Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move EnC workspace tests down to Features layer #73660

Merged
merged 5 commits into from
May 23, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.Scripting.UnitTests" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.Scripting.Desktop.UnitTests" />
<InternalsVisibleTo Include="InteractiveHost.UnitTests" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.Features.UnitTests" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.EditorFeatures.UnitTests" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.Features.UnitTests" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
Expand All @@ -12,10 +16,10 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.EditAndContinue;
using Microsoft.CodeAnalysis.EditAndContinue.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.UnitTests;
Expand All @@ -24,10 +28,10 @@
using Xunit;
using DebuggerContracts = Microsoft.VisualStudio.Debugger.Contracts.HotReload;

namespace Roslyn.VisualStudio.Next.UnitTests.EditAndContinue;
namespace Microsoft.CodeAnalysis.Editor.UnitTests.EditAndContinue;

[UseExportProvider]
public class EditAndContinueLanguageServiceTests
public class EditAndContinueLanguageServiceTests : EditAndContinueWorkspaceTestBase
{
private static string Inspect(DiagnosticData d)
=> $"{d.Severity} {d.Id}:" +
Expand All @@ -39,6 +43,43 @@ private static string Inspect(DebuggerContracts.ManagedHotReloadDiagnostic d)
(!string.IsNullOrWhiteSpace(d.FilePath) ? $" {d.FilePath}({d.Span.StartLine}, {d.Span.StartColumn}, {d.Span.EndLine}, {d.Span.EndColumn}):" : "") +
$" {d.Message}";

private TestWorkspace CreateEditorWorkspace(out Solution solution, out EditAndContinueService service, out EditAndContinueLanguageService languageService, Type[] additionalParts = null)
{
var composition = EditorTestCompositions.EditorFeatures
.RemoveParts(typeof(MockWorkspaceEventListenerProvider))
.AddParts(
typeof(MockHostWorkspaceProvider),
typeof(MockManagedHotReloadService),
typeof(MockServiceBrokerProvider))
.AddParts(additionalParts);

var workspace = new TestWorkspace(composition: composition, solutionTelemetryId: s_solutionTelemetryId);

((MockServiceBroker)workspace.GetService<IServiceBrokerProvider>().ServiceBroker).CreateService = t => t switch
{
_ when t == typeof(Microsoft.VisualStudio.Debugger.Contracts.HotReload.IHotReloadLogger) => new MockHotReloadLogger(),
_ => throw ExceptionUtilities.UnexpectedValue(t)
};

((MockHostWorkspaceProvider)workspace.GetService<IHostWorkspaceProvider>()).Workspace = workspace;

solution = workspace.CurrentSolution;
service = GetEditAndContinueService(workspace);
languageService = workspace.GetService<EditAndContinueLanguageService>();
return workspace;
}

private class TestSourceTextContainer : SourceTextContainer
{
public SourceText Text { get; set; }

public override SourceText CurrentText => Text;

#pragma warning disable CS0067
public override event EventHandler<TextChangeEventArgs> TextChanged;
#pragma warning restore
}

[Theory, CombinatorialData]
public async Task Test(bool commitChanges)
{
Expand Down Expand Up @@ -118,9 +159,9 @@ await localWorkspace.ChangeSolutionAsync(localWorkspace.CurrentSolution
{
var syntaxTree = solution.GetRequiredDocument(documentId).GetSyntaxTreeSynchronously(CancellationToken.None)!;

var documentDiagnostic = Diagnostic.Create(diagnosticDescriptor1, Location.Create(syntaxTree, TextSpan.FromBounds(1, 2)), ["doc", "error 1"]);
var projectDiagnostic = Diagnostic.Create(diagnosticDescriptor1, Location.None, ["proj", "error 2"]);
var syntaxError = Diagnostic.Create(diagnosticDescriptor1, Location.Create(syntaxTree, TextSpan.FromBounds(1, 2)), ["doc", "syntax error 3"]);
var documentDiagnostic = CodeAnalysis.Diagnostic.Create(diagnosticDescriptor1, Location.Create(syntaxTree, TextSpan.FromBounds(1, 2)), ["doc", "error 1"]);
var projectDiagnostic = CodeAnalysis.Diagnostic.Create(diagnosticDescriptor1, Location.None, ["proj", "error 2"]);
var syntaxError = CodeAnalysis.Diagnostic.Create(diagnosticDescriptor1, Location.Create(syntaxTree, TextSpan.FromBounds(1, 2)), ["doc", "syntax error 3"]);

return new()
{
Expand Down Expand Up @@ -179,4 +220,64 @@ await localWorkspace.ChangeSolutionAsync(localWorkspace.CurrentSolution
Assert.Empty(sessionState.ApplyChangesDiagnostics);
Assert.False(sessionState.IsSessionActive);
}

[Fact]
public async Task DefaultPdbMatchingSourceTextProvider()
{
var source1 = "class C1 { void M() { System.Console.WriteLine(\"a\"); } }";
var source2 = "class C1 { void M() { System.Console.WriteLine(\"b\"); } }";
var source3 = "class C1 { void M() { System.Console.WriteLine(\"c\"); } }";

var dir = Temp.CreateDirectory();
var sourceFile = dir.CreateFile("test.cs").WriteAllText(source1, Encoding.UTF8);

using var workspace = CreateEditorWorkspace(out var solution, out var service, out var languageService);
var sourceTextProvider = workspace.GetService<PdbMatchingSourceTextProvider>();

var projectId = ProjectId.CreateNewId();
var documentId = DocumentId.CreateNewId(projectId);

solution = solution.
AddProject(projectId, "test", "test", LanguageNames.CSharp).
WithProjectChecksumAlgorithm(projectId, SourceHashAlgorithms.Default).
AddMetadataReferences(projectId, TargetFrameworkUtil.GetReferences(TargetFramework.Mscorlib40)).
AddDocument(DocumentInfo.Create(
documentId,
name: "test.cs",
loader: new WorkspaceFileTextLoader(workspace.Services.SolutionServices, sourceFile.Path, Encoding.UTF8),
filePath: sourceFile.Path));

Assert.True(workspace.SetCurrentSolution(_ => solution, WorkspaceChangeKind.SolutionAdded));
solution = workspace.CurrentSolution;

var moduleId = EmitAndLoadLibraryToDebuggee(source1, sourceFilePath: sourceFile.Path);

// hydrate document text and overwrite file content:
var document1 = await solution.GetDocument(documentId).GetTextAsync();
File.WriteAllText(sourceFile.Path, source2, Encoding.UTF8);

await languageService.StartSessionAsync(CancellationToken.None);
await languageService.EnterBreakStateAsync(CancellationToken.None);

workspace.OnDocumentOpened(documentId, new TestSourceTextContainer()
{
Text = SourceText.From(source3, Encoding.UTF8, SourceHashAlgorithm.Sha1)
});

await workspace.GetService<AsynchronousOperationListenerProvider>().GetWaiter(FeatureAttribute.Workspace).ExpeditedWaitAsync();

var (key, (documentState, version)) = sourceTextProvider.GetTestAccessor().GetDocumentsWithChangedLoaderByPath().Single();
Assert.Equal(sourceFile.Path, key);
Assert.Equal(solution.WorkspaceVersion, version);
Assert.Equal(source1, (await documentState.GetTextAsync(CancellationToken.None)).ToString());

// check committed document status:
var debuggingSession = service.GetTestAccessor().GetActiveDebuggingSessions().Single();
var (document, state) = await debuggingSession.LastCommittedSolution.GetDocumentAndStateAsync(documentId, currentDocument: null, CancellationToken.None);
var text = await document.GetTextAsync();
Assert.Equal(CommittedSolution.DocumentState.MatchesBuildOutput, state);
Assert.Equal(source1, (await document.GetTextAsync(CancellationToken.None)).ToString());

await languageService.EndSessionAsync(CancellationToken.None);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1087,7 +1087,7 @@ class Goo
[
SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Goo..ctor"), preserveLocalVariables: true)
],
capabilities: EditAndContinueTestHelpers.Net6RuntimeCapabilities);
capabilities: EditAndContinueTestVerifier.Net6RuntimeCapabilities);
}

[Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/742334")]
Expand Down Expand Up @@ -9860,7 +9860,7 @@ static void Main(string[] args)
var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);

edits.VerifySemanticDiagnostics(active, capabilities: EditAndContinueTestHelpers.Net6RuntimeCapabilities);
edits.VerifySemanticDiagnostics(active, capabilities: EditAndContinueTestVerifier.Net6RuntimeCapabilities);
}

[Fact]
Expand Down Expand Up @@ -12333,7 +12333,7 @@ public static void H(int x)

var edits = GetTopEdits(src1, src2);
var active = GetActiveStatements(src1, src2);
var validator = new CSharpEditAndContinueTestHelpers(faultInjector: node =>
var validator = new CSharpEditAndContinueTestVerifier(faultInjector: node =>
{
if (node.Parent is MethodDeclarationSyntax methodDecl && methodDecl.Identifier.Text == "G")
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ private static async Task<DocumentAnalysisResults> AnalyzeDocumentAsync(
Project oldProject,
Document newDocument,
ActiveStatementsMap activeStatementMap = null,
EditAndContinueCapabilities capabilities = EditAndContinueTestHelpers.Net5RuntimeCapabilities,
EditAndContinueCapabilities capabilities = EditAndContinueTestVerifier.Net5RuntimeCapabilities,
ImmutableArray<ActiveStatementLineSpan> newActiveStatementSpans = default)
{
var analyzer = new CSharpEditAndContinueAnalyzer();
Expand Down Expand Up @@ -747,7 +747,7 @@ public async Task AnalyzeDocumentAsync_InternalError(bool outOfMemory)
var newSyntaxTree = await newDocument.GetSyntaxTreeAsync().ConfigureAwait(false);

var baseActiveStatements = AsyncLazy.Create(ActiveStatementsMap.Empty);
var capabilities = AsyncLazy.Create(EditAndContinueTestHelpers.Net5RuntimeCapabilities);
var capabilities = AsyncLazy.Create(EditAndContinueTestVerifier.Net5RuntimeCapabilities);

var analyzer = new CSharpEditAndContinueAnalyzer(node =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,9 @@

namespace Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests;

internal sealed class CSharpEditAndContinueTestHelpers : EditAndContinueTestHelpers
internal sealed class CSharpEditAndContinueTestVerifier(Action<SyntaxNode>? faultInjector = null) : EditAndContinueTestVerifier
{
private readonly CSharpEditAndContinueAnalyzer _analyzer;

public CSharpEditAndContinueTestHelpers(Action<SyntaxNode>? faultInjector = null)
{
_analyzer = new CSharpEditAndContinueAnalyzer(faultInjector);
}
private readonly CSharpEditAndContinueAnalyzer _analyzer = new(faultInjector);

public override AbstractEditAndContinueAnalyzer Analyzer => _analyzer;
public override string LanguageName => LanguageNames.CSharp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ internal static void VerifyLineEdits(
RudeEditDiagnosticDescription[]? diagnostics = null,
EditAndContinueCapabilities? capabilities = null)
{
new CSharpEditAndContinueTestHelpers().VerifyLineEdits(
new CSharpEditAndContinueTestVerifier().VerifyLineEdits(
editScript,
lineEdits,
semanticEdits,
Expand Down Expand Up @@ -129,7 +129,7 @@ internal static void VerifySemantics(
{
foreach (var targetFramework in targetFrameworks ?? [TargetFramework.NetCoreApp, TargetFramework.NetFramework])
{
new CSharpEditAndContinueTestHelpers().VerifySemantics(editScripts, targetFramework, results, capabilities);
new CSharpEditAndContinueTestVerifier().VerifySemantics(editScripts, targetFramework, results, capabilities);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,14 @@ internal static Match<SyntaxNode> GetMethodMatch(string src1, string src2, Metho
internal static IEnumerable<KeyValuePair<SyntaxNode, SyntaxNode>> GetMethodMatches(string src1, string src2, MethodKind kind = MethodKind.Regular)
{
var methodMatch = GetMethodMatch(src1, src2, kind);
return EditAndContinueTestHelpers.GetMethodMatches(CreateAnalyzer(), methodMatch);
return EditAndContinueTestVerifier.GetMethodMatches(CreateAnalyzer(), methodMatch);
}

public static MatchingPairs ToMatchingPairs(Match<SyntaxNode> match)
=> EditAndContinueTestHelpers.ToMatchingPairs(match);
=> EditAndContinueTestVerifier.ToMatchingPairs(match);

public static MatchingPairs ToMatchingPairs(IEnumerable<KeyValuePair<SyntaxNode, SyntaxNode>> matches)
=> EditAndContinueTestHelpers.ToMatchingPairs(matches);
=> EditAndContinueTestVerifier.ToMatchingPairs(matches);

internal static MemberBody MakeMethodBody(
string bodySource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6406,7 +6406,7 @@ static void Main(int y, int x)
[
SemanticEdit(SemanticEditKind.Update, c => c.GetMember("Program.Main"), preserveLocalVariables: true)
],
capabilities: EditAndContinueTestHelpers.Net6RuntimeCapabilities);
capabilities: EditAndContinueTestVerifier.Net6RuntimeCapabilities);
}

[Fact]
Expand Down
Loading