예제 #1
0
        public async Task OnComplete_can_be_used_to_act_on_completion_of_commands()
        {
            using var kernel = new FakeKernel();

            using var events = kernel.KernelEvents.ToSubscribedList();

            kernel.AddDirective(new Command("#!wrap")
            {
                Handler = CommandHandler.Create(async(KernelInvocationContext c) =>
                {
                    await c.DisplayAsync("hello!");

                    c.OnComplete(async context =>
                    {
                        await context.DisplayAsync("goodbye!");
                    });
                })
            });

            await kernel.SubmitCodeAsync("#!wrap");

            events
            .OfType <DisplayedValueProduced>()
            .Select(e => e.Value)
            .Should()
            .BeEquivalentSequenceTo("hello!", "goodbye!");
        }
        public async Task When_command_handler_registered_in_child_kernel_and_command_sent_to_parent_then_handler_is_executed()
        {
            using var compositeKernel = new CompositeKernel();
            var childKernel = new FakeKernel();

            compositeKernel.Add(childKernel);

            CustomCommandTypes.FirstSubmission.MyCommand commandPassedToHandler = null;
            KernelInvocationContext contextPassedToHandler = null;

            childKernel.RegisterCommandHandler <CustomCommandTypes.FirstSubmission.MyCommand>(
                (command, context) =>
            {
                commandPassedToHandler = command;
                contextPassedToHandler = context;
                return(Task.CompletedTask);
            });

            var commandSentToCompositeKernel = new CustomCommandTypes.FirstSubmission.MyCommand("xyzzy");
            await compositeKernel.SendAsync(commandSentToCompositeKernel);

            commandPassedToHandler
            .Should()
            .BeSameAs(commandSentToCompositeKernel);
            contextPassedToHandler
            .Should()
            .NotBeNull();
        }
예제 #3
0
        public async Task Middleware_is_only_executed_once_per_command()
        {
            var middeware1Count = 0;
            var middeware2Count = 0;
            var middeware3Count = 0;

            using var kernel = new FakeKernel();

            kernel.AddMiddleware(async(command, context, next) =>
            {
                middeware1Count++;
                await next(command, context);
            }, "one");
            kernel.AddMiddleware(async(command, context, next) =>
            {
                middeware2Count++;
                await next(command, context);
            }, "two");
            kernel.AddMiddleware(async(command, context, next) =>
            {
                middeware3Count++;
                await next(command, context);
            }, "three");

            await kernel.SendAsync(new SubmitCode("123"));

            middeware1Count.Should().Be(1);
            middeware2Count.Should().Be(1);
            middeware3Count.Should().Be(1);
        }
        public async Task Handling_kernel_can_be_specified_as_a_default_via_an_alias()
        {
            var receivedOnFakeKernel = new List <KernelCommand>();

            var fakeKernel = new FakeKernel("fake")
            {
                Handle = (command, context) =>
                {
                    receivedOnFakeKernel.Add(command);
                    return(Task.CompletedTask);
                }
            };

            using var kernel = new CompositeKernel
                  {
                      new CSharpKernel()
                  };

            kernel.Add(fakeKernel, new[] { "totally-fake" });

            kernel.DefaultKernelName = "totally-fake";

            await kernel.SendAsync(
                new SubmitCode(
                    @"hello!"));

            receivedOnFakeKernel
            .Should()
            .ContainSingle(c => c is SubmitCode)
            .Which
            .As <SubmitCode>()
            .Code
            .Should()
            .Be("hello!");
        }
예제 #5
0
        public async Task Queued_initialization_command_is_executed_on_to_first_submission()
        {
            var receivedCommands = new List <IKernelCommand>();

            var kernel = new FakeKernel
            {
                Handle = (command, context) =>
                {
                    receivedCommands.Add(command);
                    return(Task.CompletedTask);
                }
            };

            using var events = kernel.KernelEvents.ToSubscribedList();

            kernel.DeferCommand(new SubmitCode("one"));
            kernel.DeferCommand(new SubmitCode("two"));

            await kernel.SendAsync(new SubmitCode("three"));

            var x = receivedCommands
                    .Select(c => c is SubmitCode submitCode ? submitCode.Code : c.ToString())
                    .Should()
                    .BeEquivalentSequenceTo("one", "two", "three");
        }
예제 #6
0
        public void When_command_type_registered_then_kernel_registers_envelope_type_for_serialization(bool withHandler)
        {
            Microsoft.DotNet.Interactive.Server.KernelCommandEnvelope.ResetToDefaults();

            using var kernel = new FakeKernel();

            if (withHandler)
            {
                kernel.RegisterCommandHandler <CustomCommandTypes.FirstSubmission.MyCommand>(
                    (_, _) => Task.CompletedTask);
            }
            else
            {
                kernel.RegisterCommandType <CustomCommandTypes.FirstSubmission.MyCommand>();
            }

            var    originalCommand             = new CustomCommandTypes.FirstSubmission.MyCommand("xyzzy");
            string envelopeJson                = Microsoft.DotNet.Interactive.Server.KernelCommandEnvelope.Serialize(originalCommand);
            var    roundTrippedCommandEnvelope = Microsoft.DotNet.Interactive.Server.KernelCommandEnvelope.Deserialize(envelopeJson);

            roundTrippedCommandEnvelope
            .Command
            .Should()
            .BeOfType <CustomCommandTypes.FirstSubmission.MyCommand>()
            .Which
            .Info
            .Should()
            .Be(originalCommand.Info);
        }
예제 #7
0
        public async Task kernelEvents_sequence_completes_when_kernel_is_disposed()
        {
            var kernel = new FakeKernel();
            var events = kernel.KernelEvents.Timeout(5.Seconds()).LastOrDefaultAsync();

            kernel.Dispose();

            var lastEvent = await events;

            lastEvent.Should().BeNull();
        }
예제 #8
0
        public void Return_the_list_of_supported_commands()
        {
            using var kernel = new FakeKernel();
            kernel.RegisterCommandType <CustomCommandTypes.FirstSubmission.MyCommand>();
            kernel.RegisterCommandType <CustomCommandTypes.SecondSubmission.MyCommand>();

            var supportedCommands = kernel.SupportedCommands();

            supportedCommands.Should().ContainInOrder(typeof(SubmitCode),
                                                      typeof(CustomCommandTypes.FirstSubmission.MyCommand),
                                                      typeof(CustomCommandTypes.SecondSubmission.MyCommand));
        }
예제 #9
0
        public async Task hover_on_unsupported_language_service_returns_nothing()
        {
            using var kernel = new FakeKernel();

            var commandResult = await SendHoverRequest(kernel, "code", 0, 0);

            commandResult
            .KernelEvents
            .ToSubscribedList()
            .Should()
            .NotContain(kv => kv.GetType().IsSubclassOf(typeof(HoverTextProduced)));
        }
예제 #10
0
        public async Task Split_non_referencing_directives_are_executed_in_textual_order()
        {
            var receivedCommands = new List <string>();

            using var kernel = new FakeKernel
                  {
                      Handle = (command, context) =>
                      {
                          receivedCommands.Add(((SubmitCode)command).Code);
                          return(Task.CompletedTask);
                      }
                  };

            kernel.AddDirective(new Command("#!one")
            {
                Handler = CommandHandler.Create(() =>
                {
                    receivedCommands.Add("#!one");
                })
            });

            kernel.AddDirective(new Command("#!two")
            {
                Handler = CommandHandler.Create(() =>
                {
                    receivedCommands.Add("#!two");
                })
            });

            var code1      = "var a = 1";
            var code2      = "var b = 2";
            var code3      = "var c = 3";
            var directive1 = "#!one";
            var directive2 = "#!two";

            await kernel.SubmitCodeAsync($@"
{code1}
{directive1}
{code2}
{directive2}
{code3}
");

            receivedCommands
            .Select(c => c.Trim())
            .Should()
            .BeEquivalentSequenceTo(
                code1,
                directive1,
                code2,
                directive2,
                code3);
        }
예제 #11
0
        public void FindKernel_finds_a_subkernel_of_a_composite_kernel_by_alias()
        {
            var one = new FakeKernel("one");
            var two = new FakeKernel("two");

            using var compositeKernel = new CompositeKernel();
            compositeKernel.Add(one, aliases: new[] { "one-alias" });
            compositeKernel.Add(two);

            var found = compositeKernel.FindKernel("one-alias");

            found.Should().BeSameAs(one);
        }
        private static Kernel CreateKernelWithConnectableFakeKernel(FakeKernel fakeKernel = null)
        {
            var compositeKernel = new CompositeKernel
            {
                new FakeKernel("x")
            };

            compositeKernel.UseKernelClientConnection(
                new ConnectFakeKernel("fake", "Connects the fake kernel")
            {
                CreateKernel = (options, context) => Task.FromResult <Kernel>(fakeKernel ?? new FakeKernel())
            });

            return(compositeKernel);
        }
예제 #13
0
        public void FindKernel_returns_null_for_unknown_kernel()
        {
            var one = new FakeKernel("one");
            var two = new FakeKernel("two");

            using var compositeKernel = new CompositeKernel
                  {
                      one,
                      two,
                  };

            var found = compositeKernel.FindKernel("three");

            found.Should().BeNull();
        }
예제 #14
0
        public void FindKernel_finds_a_subkernel_of_a_parent_composite_kernel_by_name()
        {
            var one = new FakeKernel("one");
            var two = new FakeKernel("two");

            using var compositeKernel = new CompositeKernel
                  {
                      one,
                      two,
                  };

            var found = one.FindKernel("two");

            found.Should().BeSameAs(two);
        }
        public async Task Connected_kernels_are_disposed_when_composite_kernel_is_disposed()
        {
            var disposed = false;

            var fakeKernel = new FakeKernel();

            fakeKernel.RegisterForDisposal(() => disposed = true);

            using var compositeKernel = CreateKernelWithConnectableFakeKernel(fakeKernel);

            await compositeKernel.SubmitCodeAsync("#!connect --kernel-name my-fake-kernel fake --fakeness-level 9000");

            compositeKernel.Dispose();

            disposed.Should().BeTrue();
        }
예제 #16
0
        public void Deferred_initialization_command_is_not_executed_prior_to_first_submission()
        {
            var receivedCommands = new List <IKernelCommand>();

            using var kernel = new FakeKernel
                  {
                      Handle = (command, context) =>
                      {
                          receivedCommands.Add(command);
                          return(Task.CompletedTask);
                      }
                  };

            kernel.DeferCommand(new SubmitCode("hello"));
            kernel.DeferCommand(new SubmitCode("world!"));

            receivedCommands.Should().BeEmpty();
        }
예제 #17
0
        public void When_command_type_reregistered_with_changed_type_command_then_kernel_registers_updated_envelope_type_for_serialization(bool withHandler)
        {
            // Notebook authors should be able to develop their custom commands experimentally and progressively,
            // so we don't want any "you have to restart your kernel now" situations just because you already
            // called RegisterCommandHandler once for a particular command type.
            Microsoft.DotNet.Interactive.Server.KernelCommandEnvelope.ResetToDefaults();

            using var kernel = new FakeKernel();

            if (withHandler)
            {
                kernel.RegisterCommandHandler <CustomCommandTypes.FirstSubmission.MyCommand>(
                    (_, _) => Task.CompletedTask);
                kernel.RegisterCommandHandler <CustomCommandTypes.SecondSubmission.MyCommand>(
                    (_, _) => Task.CompletedTask);
            }
            else
            {
                kernel.RegisterCommandType <CustomCommandTypes.FirstSubmission.MyCommand>();
                kernel.RegisterCommandType <CustomCommandTypes.SecondSubmission.MyCommand>();
            }

            var    originalCommand             = new CustomCommandTypes.SecondSubmission.MyCommand("xyzzy", 42);
            string envelopeJson                = Microsoft.DotNet.Interactive.Server.KernelCommandEnvelope.Serialize(originalCommand);
            var    roundTrippedCommandEnvelope = Microsoft.DotNet.Interactive.Server.KernelCommandEnvelope.Deserialize(envelopeJson);

            roundTrippedCommandEnvelope
            .Command
            .Should()
            .BeOfType <CustomCommandTypes.SecondSubmission.MyCommand>()
            .Which
            .Info
            .Should()
            .Be(originalCommand.Info);
            roundTrippedCommandEnvelope
            .Command
            .As <CustomCommandTypes.SecondSubmission.MyCommand>()
            .AdditionalProperty
            .Should()
            .Be(originalCommand.AdditionalProperty);
        }
        public async Task When_a_new_kernel_is_connected_then_it_becomes_addressable_by_name()
        {
            var wasCalled  = false;
            var fakeKernel = new FakeKernel
            {
                Handle = (command, context) =>
                {
                    wasCalled = true;
                    return(Task.CompletedTask);
                }
            };

            using var kernel = CreateKernelWithConnectableFakeKernel(fakeKernel);

            await kernel.SubmitCodeAsync("#!connect --kernel-name my-fake-kernel fake --fakeness-level 9000");

            await kernel.SubmitCodeAsync(@"
#!my-fake-kernel
hello!
");

            wasCalled.Should().BeTrue();
        }
        public async Task Action_directives_are_routed_by_kernel_chooser_directives(
            string chooseKernelCommand,
            string expectedInvokedOnKernelName)
        {
            var received = new List <string>();

            using var compositeKernel = new CompositeKernel();

            var fakeKernel1 = new FakeKernel("fake1");

            fakeKernel1.AddDirective(new Command("#!hi")
            {
                Handler = CommandHandler.Create(() => { received.Add("fake1"); })
            });

            var fakeKernel2 = new FakeKernel("fake2");

            fakeKernel2.AddDirective(new Command("#!hi")
            {
                Handler = CommandHandler.Create(() => { received.Add("fake2"); })
            });

            compositeKernel.Add(fakeKernel1, new[] { "fake1-alias" });
            compositeKernel.Add(fakeKernel2, new[] { "fake2-alias" });

            var result = await compositeKernel.SubmitCodeAsync($"{chooseKernelCommand}\n#!hi");

            result.KernelEvents.ToSubscribedList().Should().NotContainErrors();

            received
            .Should()
            .ContainSingle()
            .Which
            .Should()
            .Be(expectedInvokedOnKernelName);
        }