Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 2 additions & 9 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@ on:

jobs:
build:
# Disable the MSBuild build server and node reuse for every dotnet invocation in CI. The
# solution-reference tests spawn `dotnet build` and an out-of-process MSBuildWorkspace BuildHost;
# sharing persistent MSBuild nodes across these intermittently deadlocks and hangs the test run.
env:
DOTNET_CLI_USE_MSBUILD_SERVER: 0
MSBUILDDISABLENODEREUSE: 1

strategy:
matrix:
platform: [ubuntu-latest, windows-latest]
Expand All @@ -36,11 +29,11 @@ jobs:
run: dotnet build

- name: Test
run: dotnet test --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
run: dotnet test CSharpRepl.Tests/CSharpRepl.Tests.csproj --no-build --results-directory TestResults --coverage --coverage-output-format cobertura --coverage-output coverage.cobertura.xml

- name: Report Code Coverage
if: matrix.platform == 'windows-latest' # only generate and upload code coverage once
uses: codecov/codecov-action@260aa3b4b2f265b8578bc0e721e33ebf8ff53313
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: CSharpRepl.Tests/coverage.opencover.xml
files: TestResults/coverage.cobertura.xml
20 changes: 3 additions & 17 deletions CSharpRepl.Tests/CSharpRepl.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<IsPackable>false</IsPackable>
<!-- Applies test.runsettings automatically to `dotnet test` (disables MSBuild build server /
node reuse to avoid intermittent hangs in the solution-reference tests). -->
<RunSettingsFilePath>$(MSBuildThisFileDirectory)test.runsettings</RunSettingsFilePath>
</PropertyGroup>

<ItemGroup>
Expand All @@ -17,24 +15,12 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
<PackageReference Include="NSubstitute" Version="5.3.0" />
<PackageReference Include="PrettyPrompt" Version="4.1.1" />
<PackageReference Include="Spectre.Console.Testing" Version="0.55.2" />
<PackageReference Include="System.IO.Abstractions.TestingHelpers" Version="22.1.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="10.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.msbuild" Version="10.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.v3.mtp-v2" Version="4.0.0-pre.108" />
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" Version="18.7.0" />
<!-- Keep MSBuild assemblies out of the output dir (loaded from the SDK via MSBuildLocator);
arrives transitively through the CSharpRepl.Services project reference.
See https://aka.ms/msbuild/locator/diagnostics/MSBL001 -->
Expand Down
32 changes: 16 additions & 16 deletions CSharpRepl.Tests/CompletionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,38 +25,38 @@ public CompletionTests(RoslynServicesFixture fixture)
promptCallbacks = new CSharpReplPromptCallbacks(console, services, new Configuration());
}

public Task InitializeAsync() => services.WarmUpAsync([]);
public Task DisposeAsync() => Task.CompletedTask;
public ValueTask InitializeAsync() => new(services.WarmUpAsync([]));
public ValueTask DisposeAsync() => ValueTask.CompletedTask;

[Fact]
public async Task Complete_GivenCode_ReturnsCompletions()
{
var completions = await this.services.CompleteAsync("Console.Writ", 12);
var completions = await this.services.CompleteAsync("Console.Writ", 12, TestContext.Current.CancellationToken);
var writelines = completions
.Where(c => c.Item.DisplayText.StartsWith("Write"))
.ToList();

Assert.Equal("Write", writelines[0].Item.DisplayText);
Assert.Equal("WriteLine", writelines[1].Item.DisplayText);

var writeDescription = await writelines[0].GetDescriptionAsync(cancellationToken: default);
var writeDescription = await writelines[0].GetDescriptionAsync(cancellationToken: TestContext.Current.CancellationToken);
Assert.Contains("Writes the text representation of the specified", writeDescription.Text);
var writeLineDescription = await writelines[1].GetDescriptionAsync(cancellationToken: default);
var writeLineDescription = await writelines[1].GetDescriptionAsync(cancellationToken: TestContext.Current.CancellationToken);
Assert.Contains("Writes the current line terminator to the standard output", writeLineDescription.Text);
}

[Fact]
public async Task Complete_GivenLinq_ReturnsCompletions()
{
// LINQ tends to be a good canary for whether or not our reference / implementation assemblies are correct.
var completions = await this.services.CompleteAsync("new[] { 1, 2, 3 }.Wher", 21);
var completions = await this.services.CompleteAsync("new[] { 1, 2, 3 }.Wher", 21, TestContext.Current.CancellationToken);

var whereCompletion = completions.SingleOrDefault(c => c.Item.DisplayText.StartsWith("Where"));

Assert.NotNull(whereCompletion);
Assert.Equal("Where", whereCompletion.Item.DisplayText);

var whereDescription = await whereCompletion.GetDescriptionAsync(cancellationToken: default);
var whereDescription = await whereCompletion.GetDescriptionAsync(cancellationToken: TestContext.Current.CancellationToken);
Assert.Contains("Filters a sequence of values based on a predicate", whereDescription.Text);
}

Expand All @@ -67,7 +67,7 @@ public async Task Complete_GivenLinq_ReturnsCompletions()
public async Task Complete_SyntaxHighlight_CachesAreIsolated()
{
// type "c" which triggers completion at index 1, and is cached
var completions = await this.services.CompleteAsync("c", 1);
var completions = await this.services.CompleteAsync("c", 1, TestContext.Current.CancellationToken);

// next, type the number 1, which could collide with the previous cached value if the caches
// aren't isolated, resulting in an exception
Expand All @@ -83,10 +83,10 @@ public async Task Complete_SyntaxHighlight_CachesAreIsolated()
[Fact]
public async Task Complete_GetDescriptionForShorterCompletion()
{
var completions = await this.services.CompleteAsync("datetime", 8);
var completions = await this.services.CompleteAsync("datetime", 8, TestContext.Current.CancellationToken);
var arrayCompletion = completions.SingleOrDefault(c => c.Item.DisplayText == "Array");
Assert.NotNull(arrayCompletion);
var arrayDescription = await arrayCompletion.GetDescriptionAsync(cancellationToken: default);
var arrayDescription = await arrayCompletion.GetDescriptionAsync(cancellationToken: TestContext.Current.CancellationToken);
Assert.Contains("Provides methods for creating, manipulating, searching, and sorting arrays", arrayDescription.Text);
}

Expand All @@ -96,10 +96,10 @@ public async Task Complete_GetDescriptionForShorterCompletion()
[Fact]
public async Task Complete_GetDescriptionAfterDot()
{
var completions = await this.services.CompleteAsync("\"\".Where()", 3);
var completions = await this.services.CompleteAsync("\"\".Where()", 3, TestContext.Current.CancellationToken);
var whereCompletion = completions.SingleOrDefault(c => c.Item.DisplayText == "Where");
Assert.NotNull(whereCompletion);
var whereDescription = await whereCompletion.GetDescriptionAsync(cancellationToken: default);
var whereDescription = await whereCompletion.GetDescriptionAsync(cancellationToken: TestContext.Current.CancellationToken);
Assert.Contains("Filters a sequence of values based on a predicate", whereDescription.Text);
}

Expand All @@ -118,7 +118,7 @@ public async Task Complete_ItemsFilteringAndOrder(string text, params string[] e
{
var caret = text.Length;
var span = new TextSpan(0, text.Length);
var completions = (await this.services.CompleteAsync(text, caret))
var completions = (await this.services.CompleteAsync(text, caret, TestContext.Current.CancellationToken))
.OrderByDescending(i => promptCallbacks.CreatePrettyPromptCompletionItem(i).GetCompletionItemPriority(text, caret, span));

for (int i = 0; i < expectedItems.Length; i++)
Expand All @@ -133,7 +133,7 @@ public async Task Complete_ItemsFilteringAndOrder(string text, params string[] e
[InlineData("cl", "clear")]
public async Task Complete_ReplKeywords(string source, string item)
{
var completions = await promptCallbacks.GetCompletionItemsCoreAsync(source, source.Length);
var completions = await promptCallbacks.GetCompletionItemsCoreAsync(source, source.Length, TestContext.Current.CancellationToken);
var completion = completions.SingleOrDefault(c => c.DisplayText == item);
Assert.NotNull(completion);
}
Expand All @@ -144,10 +144,10 @@ public async Task Complete_ReplKeywords(string source, string item)
[InlineData("cl", "clear", "Clear the terminal")]
public async Task Complete_ReplKeywords_HaveDescription(string source, string item, string expectedDescriptionFragment)
{
var completions = await promptCallbacks.GetCompletionItemsCoreAsync(source, source.Length);
var completions = await promptCallbacks.GetCompletionItemsCoreAsync(source, source.Length, TestContext.Current.CancellationToken);
var completion = completions.SingleOrDefault(c => c.DisplayText == item);
Assert.NotNull(completion);
var description = await completion.GetExtendedDescriptionAsync(default);
var description = await completion.GetExtendedDescriptionAsync(TestContext.Current.CancellationToken);
Assert.Contains(expectedDescriptionFragment, description.Text);
}
}
10 changes: 5 additions & 5 deletions CSharpRepl.Tests/DisassemblerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public DisassemblerTests()
this.services = new RoslynServices(console, new Configuration(), new TestTraceLogger());
}

public Task InitializeAsync() => services.WarmUpAsync([]);
public Task DisposeAsync() => Task.CompletedTask;
public ValueTask InitializeAsync() => new(services.WarmUpAsync([]));
public ValueTask DisposeAsync() => ValueTask.CompletedTask;

[Theory]
[InlineData(OptimizationLevel.Debug, "TopLevelProgram")]
Expand All @@ -47,7 +47,7 @@ public async Task Disassemble_InputCSharp_OutputILAsync(OptimizationLevel optimi
public async Task Disassemble_ImportsAcrossMultipleReplLines_CanDisassemble()
{
// import a namespace
await services.EvaluateAsync("using System.Globalization;");
await services.EvaluateAsync("using System.Globalization;", cancellationToken: TestContext.Current.CancellationToken);

// disassemble code that uses the above imported namespace.
var result = await services.ConvertToIntermediateLanguage("var x = CultureInfo.CurrentCulture;", debugMode: false);
Expand All @@ -60,7 +60,7 @@ public async Task Disassemble_ImportsAcrossMultipleReplLines_CanDisassemble()
public async Task Disassemble_InputAcrossMultipleReplLines_CanDisassemble()
{
// define a variable
await services.EvaluateAsync("var x = 5;");
await services.EvaluateAsync("var x = 5;", cancellationToken: TestContext.Current.CancellationToken);

// disassemble code that uses the above variable. This is an interesting case as the roslyn scripting will convert
// the above local variable into a field, so it can be referenced by a subsequent script.
Expand All @@ -77,7 +77,7 @@ public async Task Disassemble_InputAcrossMultipleReplLines_CanDisassemble()
public async Task Disassemble_Empty()
{
// import a namespace
await services.EvaluateAsync("using System;");
await services.EvaluateAsync("using System;", cancellationToken: TestContext.Current.CancellationToken);

// disassemble code that uses the above imported namespace.
var result = await services.ConvertToIntermediateLanguage("", debugMode: false);
Expand Down
Loading
Loading