Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b51fbae
move Quit command to Microsoft.DotNet.Interactive and ensure tests fo…
colombod Feb 10, 2021
91b3a70
move kernel extension to enable quit command
colombod Feb 10, 2021
262e87f
add tests for quit command behaviour
colombod Feb 10, 2021
fc79eb5
add changes to contract
colombod Feb 11, 2021
0e9ee79
ensure inflight commands are failed on quit
colombod Feb 11, 2021
e41a0d7
wiring up parent kernel event pump
colombod Feb 11, 2021
471e312
add cancel command
colombod Feb 12, 2021
8a873c5
updated typescript contract files
colombod Feb 12, 2021
73e72b2
implementing cancel command
colombod Feb 12, 2021
34b41d0
fix file
colombod Feb 12, 2021
04bea52
fix code
colombod Feb 14, 2021
bc0a1fa
Update src/Microsoft.DotNet.Interactive.Tests/LanguageKernelTests.cs
colombod Feb 16, 2021
24d2669
quit default behaviour throws if not configured
colombod Feb 16, 2021
7ca9c3e
update ncrunch settings
colombod Feb 16, 2021
23e1ff7
regroup tests for quit command
colombod Feb 16, 2021
925d26a
split tests
colombod Feb 16, 2021
5fd1b21
refactor cancel tests out to specific test class
colombod Feb 16, 2021
b770108
timeout on wait
colombod Feb 16, 2021
67b5524
remove unused namespace
colombod Feb 16, 2021
fa9b8a7
rebase quit on cancel command
colombod Feb 16, 2021
60a3853
reset handler before test
colombod Feb 16, 2021
a282d76
reflect changes in contract.ts
colombod Feb 16, 2021
2bcc44e
refactor cancelCommands
colombod Feb 16, 2021
b27cc5f
avoid double cancellation request
colombod Feb 17, 2021
47a35f3
add test to ensure commands are runing after cancel is issued
colombod Feb 17, 2021
c43018f
introduce KernelCommandScheduler
colombod Feb 17, 2021
77656f1
testing scheduler behaviours
colombod Feb 18, 2021
16d0d55
experiment
colombod Feb 18, 2021
d32c122
new scheduler api
colombod Feb 19, 2021
37e9b31
scheduled work must be awaited before completing the source
colombod Feb 22, 2021
7368e0d
cleanup
colombod Feb 22, 2021
50a9bff
cancel work on scheduler
colombod Feb 22, 2021
44713b3
refactoring
colombod Feb 22, 2021
c62ff9b
refactor test
colombod Feb 22, 2021
87de3ea
disable warning for fire and forget
colombod Feb 22, 2021
99b10e1
removed pragma
colombod Feb 22, 2021
8edf855
disposable scheduler disposed during tests
colombod Feb 22, 2021
885ab81
test parallel execution
colombod Feb 22, 2021
a8c5b86
test for parallelism
colombod Feb 23, 2021
2c470e9
test
colombod Feb 23, 2021
314e740
remove namespace
colombod Feb 23, 2021
d7c3353
change api surface
colombod Feb 23, 2021
682d49c
remove extension methods
colombod Feb 23, 2021
88cc568
all broken here
colombod Feb 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions src/Microsoft.DotNet.Interactive.CSharp/CSharpKernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,16 @@ await RunAsync(
// Publish the compilation diagnostics. This doesn't include the exception.
var kernelDiagnostics = diagnostics.Select(Diagnostic.FromCodeAnalysisDiagnostic).ToImmutableArray();

var formattedDiagnostics =
diagnostics
.Select(d => d.ToString())
.Select(text => new FormattedValue(PlainTextFormatter.MimeType, text))
.ToImmutableArray();
if (kernelDiagnostics.Length > 0)
{
var formattedDiagnostics =
diagnostics
.Select(d => d.ToString())
.Select(text => new FormattedValue(PlainTextFormatter.MimeType, text))
.ToImmutableArray();

context.Publish(new DiagnosticsProduced(kernelDiagnostics, submitCode, formattedDiagnostics));
context.Publish(new DiagnosticsProduced(kernelDiagnostics, submitCode, formattedDiagnostics));
}

// Report the compilation failure or exception
if (exception != null)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System;
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

using Microsoft.DotNet.Interactive.Server;

namespace Microsoft.DotNet.Interactive.ExtensionLab
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
// --------------------------------------------- Kernel Commands

export const AddPackageType = "AddPackage";
export const CancelType = "Cancel";
export const ChangeWorkingDirectoryType = "ChangeWorkingDirectory";
export const DisplayErrorType = "DisplayError";
export const DisplayValueType = "DisplayValue";
export const ParseNotebookType = "ParseNotebook";
export const QuitType = "Quit";
export const RequestCompletionsType = "RequestCompletions";
export const RequestDiagnosticsType = "RequestDiagnostics";
export const RequestHoverTextType = "RequestHoverText";
Expand All @@ -20,10 +22,12 @@ export const UpdateDisplayedValueType = "UpdateDisplayedValue";

export type KernelCommandType =
typeof AddPackageType
| typeof CancelType
| typeof ChangeWorkingDirectoryType
| typeof DisplayErrorType
| typeof DisplayValueType
| typeof ParseNotebookType
| typeof QuitType
| typeof RequestCompletionsType
| typeof RequestDiagnosticsType
| typeof RequestHoverTextType
Expand All @@ -40,6 +44,9 @@ export interface KernelCommand {
targetKernelName?: string;
}

export interface Cancel extends KernelCommand {
}

export interface ChangeWorkingDirectory extends KernelCommand {
workingDirectory: string;
}
Expand All @@ -58,6 +65,9 @@ export interface ParseNotebook extends KernelCommand {
rawData: Uint8Array;
}

export interface Quit extends Cancel {
}

export interface RequestCompletions extends LanguageServiceCommand {
}

Expand Down
203 changes: 203 additions & 0 deletions src/Microsoft.DotNet.Interactive.Tests/CancelCommandTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Threading.Tasks;

using FluentAssertions;
using FluentAssertions.Execution;

using Microsoft.DotNet.Interactive.Commands;
using Microsoft.DotNet.Interactive.Events;
using Microsoft.DotNet.Interactive.Tests.Utility;

using Xunit;
using Xunit.Abstractions;


namespace Microsoft.DotNet.Interactive.Tests
{
public class CancelCommandTests : LanguageKernelTestBase
{
public CancelCommandTests(ITestOutputHelper output) : base(output)
{
}

[Fact]
public async Task cancel_command_cancels_all_deferred_commands_on_composite_kernel()
{
var deferredCommandExecuted = false;

var kernel = CreateKernel();

var deferred = new SubmitCode("placeholder")
{
Handler = (command, context) =>
{
deferredCommandExecuted = true;
return Task.CompletedTask;
}
};

var cancelCommand = new Cancel();

kernel.DeferCommand(deferred);

var events = kernel.KernelEvents.ToSubscribedList();

await kernel.SendAsync(cancelCommand);

using var _ = new AssertionScope();

deferredCommandExecuted.Should().BeFalse();

events
.Should().ContainSingle<CommandSucceeded>()
.Which
.Command
.Should()
.Be(cancelCommand);
}

[Theory]
[InlineData(Language.CSharp, Skip = "requires scheduler working")]
[InlineData(Language.FSharp, Skip = "requires scheduler working")]
[InlineData(Language.PowerShell, Skip = "requires scheduler working")]
public async Task cancel_command_cancels_all_deferred_commands_on_subkernels(Language language)
{

var kernel = CreateKernel(language);

var deferred = new CancellableCommand();

var cancelCommand = new Cancel();

foreach (var subkernel in kernel.ChildKernels)
{
subkernel.DeferCommand(deferred);
}

await kernel.SendAsync(cancelCommand);

using var _ = new AssertionScope();

deferred.HasRun.Should().BeFalse();

KernelEvents
.Should().ContainSingle<CommandSucceeded>()
.Which
.Command
.Should()
.Be(cancelCommand);
}

[Theory]
[InlineData(Language.CSharp, Skip = "requires scheduler working")]
[InlineData(Language.FSharp, Skip = "requires scheduler working")]
[InlineData(Language.PowerShell, Skip = "to address later")]
public void cancel_command_cancels_the_running_command(Language language)
{

var kernel = CreateKernel(language);

var cancelCommand = new Cancel();

var submitCodeCommand = new CancellableCommand();

Task.WhenAll(
Task.Run(async () =>
{
await kernel.SendAsync(submitCodeCommand);
}),
Task.Run(async () =>
{
await Task.Delay(100);
await kernel.SendAsync(cancelCommand);
}))
.Wait(TimeSpan.FromSeconds(20));


using var _ = new AssertionScope();

submitCodeCommand.HasRun.Should().BeTrue();
submitCodeCommand.HasBeenCancelled.Should().BeTrue();

KernelEvents
.Should()
.ContainSingle<CommandFailed>(c => c.Command == submitCodeCommand)
.Which
.Exception
.Should()
.BeOfType<OperationCanceledException>();
}

[Theory]
[InlineData(Language.CSharp, Skip = "requires scheduler working")]
[InlineData(Language.FSharp, Skip = "requires scheduler working")]
[InlineData(Language.PowerShell, Skip = "to address later")]
public async Task commands_issued_after_cancel_command_are_executed(Language language)
{

var kernel = CreateKernel(language);

var cancelCommand = new Cancel();

var commandToCancel = new CancellableCommand( );

var commandToRun = new SubmitCode("1");

var _ = kernel.SendAsync(commandToCancel);
await Task.Delay(4000);
await kernel.SendAsync(cancelCommand);
await kernel.SendAsync(commandToRun);

// using var _ = new AssertionScope();

commandToCancel.HasRun.Should().BeTrue();
commandToCancel.HasBeenCancelled.Should().BeTrue();

KernelEvents
.Should()
.ContainSingle<CommandFailed>(c => c.Command == commandToCancel)
.Which
.Exception
.Should()
.BeOfType<OperationCanceledException>();
}


[Theory]
[InlineData(Language.CSharp, @"while(true){
if(Microsoft.DotNet.Interactive.KernelInvocationContext.Current.CancellationToken.IsCancellationRequested)
{
Console.WriteLine(""done c#"");
break;
}
}
", "done c#", Skip = "requires scheduler working")]
[InlineData(Language.FSharp, @"
System.Threading.Thread.Sleep(3000)
Console.WriteLine(""done c#"")", "done f#", Skip = "for the moment")]
public async Task user_code_can_react_to_cancel_command_using_cancellation_token(Language language, string code, string expectedValue)
{
var kernel = CreateKernel(language);
var cancelCommand = new Cancel();
var submitCodeCommand = new SubmitCode(code);

var _ = kernel.SendAsync(submitCodeCommand);
await Task.Delay(4000);
await kernel.SendAsync(cancelCommand);

KernelEvents
.Should()
.ContainSingle<StandardOutputValueProduced>()
.Which
.Value
.Should()
.Be(expectedValue);

}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using FluentAssertions.Execution;
using Microsoft.DotNet.Interactive.Commands;
using Microsoft.DotNet.Interactive.CSharp;
using Microsoft.DotNet.Interactive.Events;
Expand All @@ -21,7 +22,7 @@ namespace Microsoft.DotNet.Interactive.Tests
{
public class CompositeKernelTests : IDisposable
{
private readonly CompositeDisposable _disposables = new CompositeDisposable();
private readonly CompositeDisposable _disposables = new();

public CompositeKernelTests(ITestOutputHelper output)
{
Expand Down Expand Up @@ -424,6 +425,7 @@ public async Task Deferred_commands_on_composite_kernel_are_execute_on_first_sub
typeof(CompleteCodeSubmissionReceived),
typeof(CommandSucceeded));
}


[Fact]
public async Task Deferred_commands_on_composite_kernel_can_use_directives()
Expand Down
Loading