There can be only one... TestProjectSnapshotManager

The testing infrastructure contains no fewer than six TestProjectSnapshotManager classes. This change merges five of them into one and converts the sixth into a mock.
This commit is contained in:
Dustin Campbell 2024-03-07 10:04:02 -08:00
Родитель 8a402bac3e
Коммит af0eee6871
28 изменённых файлов: 235 добавлений и 265 удалений

Просмотреть файл

@ -5,3 +5,5 @@ cshtml
microsoft
Metacode
hresult
csproj
vsls

Просмотреть файл

@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts;
using Microsoft.AspNetCore.Razor.LanguageServer.Formatting;
using Microsoft.AspNetCore.Razor.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.Workspaces;
using Microsoft.AspNetCore.Razor.Utilities;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;

Просмотреть файл

@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;

Просмотреть файл

@ -13,7 +13,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem;
using Microsoft.AspNetCore.Razor.LanguageServer.Tooltip;
using Microsoft.AspNetCore.Razor.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Roslyn.Test.Utilities;
using Xunit;
using Xunit.Abstractions;

Просмотреть файл

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.Workspaces;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor;

Просмотреть файл

@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Utilities;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Moq;

Просмотреть файл

@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.CodeAnalysis;
using Xunit;
using Xunit.Abstractions;

Просмотреть файл

@ -5,6 +5,7 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.Workspaces;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;

Просмотреть файл

@ -4,6 +4,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;
using Xunit;

Просмотреть файл

@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Tooltip;
using Microsoft.AspNetCore.Razor.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.Mef;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Razor.Workspaces.Protocol;

Просмотреть файл

@ -9,6 +9,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.Workspaces;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Razor;

Просмотреть файл

@ -23,7 +23,7 @@ using Moq;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
using TestProjectSnapshotManager = Microsoft.AspNetCore.Razor.Test.Common.LanguageServer.TestProjectSnapshotManager;
using TestProjectSnapshotManager = Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem.TestProjectSnapshotManager;
namespace Microsoft.AspNetCore.Razor.LanguageServer;

Просмотреть файл

@ -20,6 +20,7 @@ using Microsoft.AspNetCore.Razor.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.Mef;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Utilities;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Workspaces;

Просмотреть файл

@ -5,6 +5,7 @@ using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Utilities;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Xunit;

Просмотреть файл

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
namespace Microsoft.AspNetCore.Razor.LanguageServer;

Просмотреть файл

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Xunit;
using Xunit.Abstractions;

Просмотреть файл

@ -4,6 +4,7 @@
using System;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.Workspaces;

Просмотреть файл

@ -1,56 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.LanguageServer;
using Microsoft.AspNetCore.Razor.ProjectEngineHost;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Workspaces;
namespace Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
internal class TestProjectSnapshotManager : DefaultProjectSnapshotManager
{
private TestProjectSnapshotManager(
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher,
IErrorReporter errorReporter)
: base(triggers: [], projectEngineFactoryProvider, dispatcher, errorReporter)
{
}
public static TestProjectSnapshotManager Create(ProjectSnapshotManagerDispatcher dispatcher, IErrorReporter errorReporter)
=> new TestProjectSnapshotManager(ProjectEngineFactories.DefaultProvider, dispatcher, errorReporter);
public bool AllowNotifyListeners { get; set; }
public TestDocumentSnapshot CreateAndAddDocument(ProjectSnapshot projectSnapshot, string filePath)
{
var documentSnapshot = TestDocumentSnapshot.Create(projectSnapshot, filePath);
DocumentAdded(projectSnapshot.Key, documentSnapshot.HostDocument, new DocumentSnapshotTextLoader(documentSnapshot));
return documentSnapshot;
}
internal TestProjectSnapshot CreateAndAddProject(string filePath)
{
var projectSnapshot = TestProjectSnapshot.Create(filePath);
ProjectAdded(projectSnapshot.HostProject);
return projectSnapshot;
}
protected override void NotifyListeners(ProjectChangeEventArgs e)
{
if (AllowNotifyListeners)
{
base.NotifyListeners(e);
}
}
private sealed class TestWorkspaceProvider(Workspace workspace) : IWorkspaceProvider
{
public Workspace GetWorkspace() => workspace;
}
}

Просмотреть файл

@ -0,0 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Moq;
namespace Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
internal static class MockExtensions
{
public static void RaiseChanged(this Mock<IProjectSnapshotManager> mock, ProjectChangeEventArgs e)
{
mock.Raise(x => x.Changed += delegate { }, e);
}
}

Просмотреть файл

@ -2,7 +2,6 @@
// Licensed under the MIT license. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
@ -12,7 +11,7 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
namespace Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
internal class TestDocumentSnapshot : DocumentSnapshot
{

Просмотреть файл

@ -11,7 +11,7 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
namespace Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
internal class TestProjectSnapshot : ProjectSnapshot
{

Просмотреть файл

@ -1,46 +1,91 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Linq;
using Microsoft.AspNetCore.Razor.LanguageServer;
using Microsoft.AspNetCore.Razor.ProjectEngineHost;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Workspaces;
namespace Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
internal class TestProjectSnapshotManager(
IProjectSnapshotChangeTrigger[] changeTriggers,
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher,
IErrorReporter errorReporter)
: DefaultProjectSnapshotManager(changeTriggers, projectEngineFactoryProvider, dispatcher, errorReporter)
internal class TestProjectSnapshotManager : DefaultProjectSnapshotManager
{
public TestProjectSnapshotManager(ProjectSnapshotManagerDispatcher dispatcher)
: this(changeTriggers: [], ProjectEngineFactories.DefaultProvider, dispatcher, StrictMock.Of<IErrorReporter>())
{
}
public TestProjectSnapshotManager(
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher)
: this(changeTriggers: [], projectEngineFactoryProvider, dispatcher, StrictMock.Of<IErrorReporter>())
{
}
public TestProjectSnapshotManager(
IProjectSnapshotChangeTrigger[] changeTriggers,
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher)
: this(changeTriggers, projectEngineFactoryProvider, dispatcher, StrictMock.Of<IErrorReporter>())
{
}
public bool AllowNotifyListeners { get; set; }
public ProjectChangeKind? ListenersNotifiedOf { get; private set; }
public TestProjectSnapshotManager(ProjectSnapshotManagerDispatcher dispatcher)
: this(triggers: [], ProjectEngineFactories.DefaultProvider, dispatcher, StrictMock.Of<IErrorReporter>())
{
}
public TestProjectSnapshotManager(
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher)
: this(triggers: [], projectEngineFactoryProvider, dispatcher, StrictMock.Of<IErrorReporter>())
{
}
public TestProjectSnapshotManager(
IProjectSnapshotChangeTrigger[] triggers,
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher)
: this(triggers, projectEngineFactoryProvider, dispatcher, StrictMock.Of<IErrorReporter>())
{
}
public TestProjectSnapshotManager(
IProjectSnapshotChangeTrigger[] triggers,
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher,
IErrorReporter errorReporter)
: base(triggers, projectEngineFactoryProvider, dispatcher, errorReporter)
{
}
public static TestProjectSnapshotManager Create(ProjectSnapshotManagerDispatcher dispatcher, IErrorReporter errorReporter)
=> new TestProjectSnapshotManager(triggers: [], ProjectEngineFactories.DefaultProvider, dispatcher, errorReporter);
public TestDocumentSnapshot CreateAndAddDocument(ProjectSnapshot projectSnapshot, string filePath)
{
var documentSnapshot = TestDocumentSnapshot.Create(projectSnapshot, filePath);
DocumentAdded(projectSnapshot.Key, documentSnapshot.HostDocument, new DocumentSnapshotTextLoader(documentSnapshot));
return documentSnapshot;
}
internal TestProjectSnapshot CreateAndAddProject(string filePath)
{
var projectSnapshot = TestProjectSnapshot.Create(filePath);
ProjectAdded(projectSnapshot.HostProject);
return projectSnapshot;
}
public IProjectSnapshot? FindProject(HostProject hostProject)
{
return GetProjects().FirstOrDefault(s => s.FilePath == hostProject.FilePath);
}
public void Reset()
{
ListenersNotifiedOf = null;
}
protected override void NotifyListeners(ProjectChangeEventArgs e)
{
ListenersNotifiedOf = e.Kind;
if (AllowNotifyListeners)
{
base.NotifyListeners(e);
}
}
private sealed class TestWorkspaceProvider(Workspace workspace) : IWorkspaceProvider
{
public Workspace GetWorkspace() => workspace;
}
}

Просмотреть файл

@ -5,7 +5,7 @@ using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio;
using Microsoft.AspNetCore.Razor.Test.Common.Workspaces;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;

Просмотреть файл

@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Text;

Просмотреть файл

@ -3,7 +3,6 @@
using System;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor;
@ -11,6 +10,7 @@ using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.ProjectEngineHost;
using Microsoft.AspNetCore.Razor.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
using Microsoft.VisualStudio.LiveShare.Razor.Test;
@ -22,6 +22,14 @@ namespace Microsoft.VisualStudio.LiveShare.Razor.Host;
public class ProjectSnapshotManagerProxyTest : VisualStudioTestBase
{
private const string ProjectName1 = "project1";
private const string ProjectName2 = "project2";
private const string ProjectFilePath1 = $"/host/path/to/{ProjectName1}.csproj";
private const string ProjectFilePath2 = $"/host/path/to/{ProjectName2}.csproj";
private const string IntermediateOutputPath = "/host/path/to/obj";
private const string LspProjectFilePath1 = $"vsls:/path/to/{ProjectName1}.csproj";
private const string LspProjectFilePath2 = $"vsls:/path/to/{ProjectName2}.csproj";
private readonly IProjectSnapshot _projectSnapshot1;
private readonly IProjectSnapshot _projectSnapshot2;
@ -30,30 +38,25 @@ public class ProjectSnapshotManagerProxyTest : VisualStudioTestBase
{
var projectEngineFactoryProvider = StrictMock.Of<IProjectEngineFactoryProvider>();
var projectWorkspaceState1 = ProjectWorkspaceState.Create(
[TagHelperDescriptorBuilder.Create("test1", "TestAssembly1").Build()]);
_projectSnapshot1 = new ProjectSnapshot(
ProjectState.Create(
projectEngineFactoryProvider,
new HostProject("/host/path/to/project1.csproj", "/host/path/to/obj", RazorConfiguration.Default, "project1"),
projectWorkspaceState1));
var projectWorkspaceState2 = ProjectWorkspaceState.Create(
[TagHelperDescriptorBuilder.Create("test2", "TestAssembly2").Build()]);
new HostProject(ProjectFilePath1, IntermediateOutputPath, RazorConfiguration.Default, ProjectName1),
ProjectWorkspaceState.Create([TagHelperDescriptorBuilder.Create("test1", "TestAssembly1").Build()])));
_projectSnapshot2 = new ProjectSnapshot(
ProjectState.Create(
projectEngineFactoryProvider,
new HostProject("/host/path/to/project2.csproj", "/host/path/to/obj", RazorConfiguration.Default, "project2"),
projectWorkspaceState2));
new HostProject(ProjectFilePath2, IntermediateOutputPath, RazorConfiguration.Default, ProjectName2),
ProjectWorkspaceState.Create([TagHelperDescriptorBuilder.Create("test2", "TestAssembly2").Build()])));
}
[UIFact]
public async Task CalculateUpdatedStateAsync_ReturnsStateForAllProjects()
{
// Arrange
var projectManager = new TestProjectSnapshotManager(_projectSnapshot1, _projectSnapshot2);
var projectManagerMock = CreateProjectSnapshotManager(_projectSnapshot1, _projectSnapshot2);
var projectManager = projectManagerMock.Object;
using var proxy = new ProjectSnapshotManagerProxy(
new TestCollaborationSession(true),
projectManager,
@ -69,44 +72,39 @@ public class ProjectSnapshotManagerProxyTest : VisualStudioTestBase
Assert.Collection(
state.ProjectHandles,
handle =>
{
Assert.Equal("vsls:/path/to/project1.csproj", handle.FilePath.ToString());
Assert.Equal<TagHelperDescriptor>(project1TagHelpers, handle.ProjectWorkspaceState.TagHelpers);
},
handle =>
{
Assert.Equal("vsls:/path/to/project2.csproj", handle.FilePath.ToString());
Assert.Equal<TagHelperDescriptor>(project2TagHelpers, handle.ProjectWorkspaceState.TagHelpers);
});
AssertProjectSnapshotHandle(LspProjectFilePath1, project1TagHelpers),
AssertProjectSnapshotHandle(LspProjectFilePath2, project2TagHelpers));
}
[UIFact]
public async Task Changed_TriggersOnSnapshotManagerChanged()
{
// Arrange
var projectManager = new TestProjectSnapshotManager(_projectSnapshot1);
var projectManagerMock = CreateProjectSnapshotManager(_projectSnapshot1);
var projectManager = projectManagerMock.Object;
using var proxy = new ProjectSnapshotManagerProxy(
new TestCollaborationSession(true),
projectManager,
Dispatcher,
JoinableTaskFactory);
var proxyAccessor = proxy.GetTestAccessor();
var changedArgs = new ProjectChangeEventArgs(_projectSnapshot1, _projectSnapshot1, ProjectChangeKind.ProjectChanged);
var called = false;
proxy.Changed += (sender, args) =>
{
called = true;
Assert.Equal($"vsls:/path/to/project1.csproj", args.ProjectFilePath.ToString());
Assert.Equal(LspProjectFilePath1, args.ProjectFilePath.ToString());
Assert.Equal(ProjectProxyChangeKind.ProjectChanged, args.Kind);
Assert.NotNull(args.Newer);
Assert.Equal("vsls:/path/to/project1.csproj", args.Newer.FilePath.ToString());
Assert.Equal(LspProjectFilePath1, args.Newer.FilePath.ToString());
};
// Act
await RunOnDispatcherAsync(() =>
{
projectManager.TriggerChanged(changedArgs);
projectManagerMock.RaiseChanged(
new ProjectChangeEventArgs(_projectSnapshot1, _projectSnapshot1, ProjectChangeKind.ProjectChanged));
});
await proxyAccessor.ProcessingChangedEventTestTask.AssumeNotNull().JoinAsync();
@ -116,22 +114,25 @@ public class ProjectSnapshotManagerProxyTest : VisualStudioTestBase
}
[UIFact]
public void Changed_NoopsIfProxyDisposed()
public void Changed_DoesNotFireIfProxyIsDisposed()
{
// Arrange
var projectManager = new TestProjectSnapshotManager(_projectSnapshot1);
var projectManagerMock = CreateProjectSnapshotManager(_projectSnapshot1);
var projectManager = projectManagerMock.Object;
var proxy = new ProjectSnapshotManagerProxy(
new TestCollaborationSession(true),
projectManager,
Dispatcher,
JoinableTaskFactory);
var proxyAccessor = proxy.GetTestAccessor();
var changedArgs = new ProjectChangeEventArgs(_projectSnapshot1, _projectSnapshot1, ProjectChangeKind.ProjectChanged);
proxy.Changed += (sender, args) => throw new InvalidOperationException("Should not have been called.");
proxy.Dispose();
// Act
projectManager.TriggerChanged(changedArgs);
projectManagerMock.RaiseChanged(
new ProjectChangeEventArgs(_projectSnapshot1, _projectSnapshot1, ProjectChangeKind.ProjectChanged));
// Assert
Assert.Null(proxyAccessor.ProcessingChangedEventTestTask);
@ -141,7 +142,8 @@ public class ProjectSnapshotManagerProxyTest : VisualStudioTestBase
public async Task GetLatestProjectsAsync_ReturnsSnapshotManagerProjects()
{
// Arrange
var projectManager = new TestProjectSnapshotManager(_projectSnapshot1);
var projectManagerMock = CreateProjectSnapshotManager(_projectSnapshot1);
var projectManager = projectManagerMock.Object;
using var proxy = new ProjectSnapshotManagerProxy(
new TestCollaborationSession(true),
projectManager,
@ -160,7 +162,8 @@ public class ProjectSnapshotManagerProxyTest : VisualStudioTestBase
public async Task GetStateAsync_ReturnsProjectState()
{
// Arrange
var projectManager = new TestProjectSnapshotManager(_projectSnapshot1, _projectSnapshot2);
var projectManagerMock = CreateProjectSnapshotManager(_projectSnapshot1, _projectSnapshot2);
var projectManager = projectManagerMock.Object;
using var proxy = new ProjectSnapshotManagerProxy(
new TestCollaborationSession(true),
projectManager,
@ -176,23 +179,16 @@ public class ProjectSnapshotManagerProxyTest : VisualStudioTestBase
Assert.Collection(
state.ProjectHandles,
handle =>
{
Assert.Equal("vsls:/path/to/project1.csproj", handle.FilePath.ToString());
Assert.Equal<TagHelperDescriptor>(project1TagHelpers, handle.ProjectWorkspaceState.TagHelpers);
},
handle =>
{
Assert.Equal("vsls:/path/to/project2.csproj", handle.FilePath.ToString());
Assert.Equal<TagHelperDescriptor>(project2TagHelpers, handle.ProjectWorkspaceState.TagHelpers);
});
AssertProjectSnapshotHandle(LspProjectFilePath1, project1TagHelpers),
AssertProjectSnapshotHandle(LspProjectFilePath2, project2TagHelpers));
}
[UIFact]
public async Task GetStateAsync_CachesState()
{
// Arrange
var projectManager = new TestProjectSnapshotManager(_projectSnapshot1);
var projectManagerMock = CreateProjectSnapshotManager(_projectSnapshot1);
var projectManager = projectManagerMock.Object;
using var proxy = new ProjectSnapshotManagerProxy(
new TestCollaborationSession(true),
projectManager,
@ -207,29 +203,22 @@ public class ProjectSnapshotManagerProxyTest : VisualStudioTestBase
Assert.Same(state1, state2);
}
private sealed class TestProjectSnapshotManager(params IProjectSnapshot[] projects) : IProjectSnapshotManager
private static StrictMock<IProjectSnapshotManager> CreateProjectSnapshotManager(params IProjectSnapshot[] projects)
{
private readonly ImmutableArray<IProjectSnapshot> _projects = [.. projects];
var mock = new StrictMock<IProjectSnapshotManager>();
public ImmutableArray<IProjectSnapshot> GetProjects() => _projects;
mock.Setup(x => x.GetProjects())
.Returns([.. projects]);
public event EventHandler<ProjectChangeEventArgs>? Changed;
public void TriggerChanged(ProjectChangeEventArgs args)
{
Changed?.Invoke(this, args);
}
public IProjectSnapshot GetLoadedProject(ProjectKey projectKey)
=> throw new NotImplementedException();
public ImmutableArray<ProjectKey> GetAllProjectKeys(string projectFileName)
=> throw new NotImplementedException();
public bool IsDocumentOpen(string documentFilePath)
=> throw new NotImplementedException();
public bool TryGetLoadedProject(ProjectKey projectKey, [NotNullWhen(true)] out IProjectSnapshot project)
=> throw new NotImplementedException();
return mock;
}
private static Action<ProjectSnapshotHandleProxy> AssertProjectSnapshotHandle(
string expectedFilePath,
ImmutableArray<TagHelperDescriptor> expectedTagHelpers)
=> handle =>
{
Assert.Equal(expectedFilePath, handle.FilePath.ToString());
Assert.Equal<TagHelperDescriptor>(expectedTagHelpers, handle.ProjectWorkspaceState.TagHelpers);
};
}

Просмотреть файл

@ -9,9 +9,9 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.ProjectEngineHost;
using Microsoft.AspNetCore.Razor.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio;
using Microsoft.CodeAnalysis.Text;
using Moq;
@ -99,8 +99,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var snapshot = _projectManager.GetSnapshot(s_hostProject);
Assert.Single(snapshot.DocumentFilePaths,
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
Assert.Single(project.DocumentFilePaths,
filePath => filePath == s_documents[0].FilePath);
Assert.Equal(ProjectChangeKind.DocumentAdded, _projectManager.ListenersNotifiedOf);
@ -124,11 +125,12 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
Assert.Single(
snapshot.DocumentFilePaths,
project.DocumentFilePaths,
filePath => filePath == s_documents[0].FilePath &&
snapshot.GetDocument(filePath).AssumeNotNull().FileKind == FileKinds.Legacy);
project.GetDocument(filePath).AssumeNotNull().FileKind == FileKinds.Legacy);
Assert.Equal(ProjectChangeKind.DocumentAdded, _projectManager.ListenersNotifiedOf);
}
@ -151,11 +153,12 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
Assert.Single(
snapshot.DocumentFilePaths,
project.DocumentFilePaths,
filePath => filePath == s_documents[3].FilePath &&
snapshot.GetDocument(filePath).AssumeNotNull().FileKind == FileKinds.Component);
project.GetDocument(filePath).AssumeNotNull().FileKind == FileKinds.Component);
Assert.Equal(ProjectChangeKind.DocumentAdded, _projectManager.ListenersNotifiedOf);
}
@ -179,8 +182,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var snapshot = _projectManager.GetSnapshot(s_hostProject);
Assert.Single(snapshot.DocumentFilePaths,
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
Assert.Single(project.DocumentFilePaths,
filePath => filePath == s_documents[0].FilePath);
Assert.Null(_projectManager.ListenersNotifiedOf);
@ -195,8 +199,8 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
_projectManager.DocumentAdded(s_hostProject.Key, s_documents[0], null!);
// Assert
var snapshot = _projectManager.GetSnapshot(s_hostProject);
Assert.Null(snapshot);
var project = _projectManager.FindProject(s_hostProject);
Assert.Null(project);
}
[UIFact]
@ -217,8 +221,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var document = snapshot.GetDocument(snapshot.DocumentFilePaths.Single());
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
var document = project.GetDocument(project.DocumentFilePaths.Single());
Assert.NotNull(document);
var text = await document.GetTextAsync();
@ -245,9 +250,10 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var filePath = Assert.Single(snapshot.DocumentFilePaths);
var document = snapshot.GetDocument(filePath);
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
var filePath = Assert.Single(project.DocumentFilePaths);
var document = project.GetDocument(filePath);
Assert.NotNull(document);
var actual = await document.GetTextAsync();
@ -266,7 +272,7 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
_projectManager.Reset();
var originalTagHelpers = await _projectManager.GetSnapshot(s_hostProject).GetTagHelpersAsync(DisposalToken);
var originalTagHelpers = await _projectManager.FindProject(s_hostProject).AssumeNotNull().GetTagHelpersAsync(DisposalToken);
// Act
await RunOnDispatcherAsync(() =>
@ -275,7 +281,7 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var newTagHelpers = await _projectManager.GetSnapshot(s_hostProject).GetTagHelpersAsync(DisposalToken);
var newTagHelpers = await _projectManager.FindProject(s_hostProject).AssumeNotNull().GetTagHelpersAsync(DisposalToken);
Assert.Equal(originalTagHelpers.Length, newTagHelpers.Length);
for (var i = 0; i < originalTagHelpers.Length; i++)
@ -295,8 +301,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
_projectManager.Reset();
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var projectEngine = snapshot.GetProjectEngine();
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
var projectEngine = project.GetProjectEngine();
// Act
await RunOnDispatcherAsync(() =>
@ -305,8 +312,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
snapshot = _projectManager.GetSnapshot(s_hostProject);
Assert.Same(projectEngine, snapshot.GetProjectEngine());
project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
Assert.Same(projectEngine, project.GetProjectEngine());
}
[UIFact]
@ -330,9 +338,10 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
Assert.Collection(
snapshot.DocumentFilePaths.OrderBy(f => f),
project.DocumentFilePaths.OrderBy(f => f),
f => Assert.Equal(s_documents[2].FilePath, f),
f => Assert.Equal(s_documents[0].FilePath, f));
@ -357,8 +366,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var snapshot = _projectManager.GetSnapshot(s_hostProject);
Assert.Empty(snapshot.DocumentFilePaths);
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
Assert.Empty(project.DocumentFilePaths);
Assert.Null(_projectManager.ListenersNotifiedOf);
}
@ -375,8 +385,8 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var snapshot = _projectManager.GetSnapshot(s_hostProject);
Assert.Null(snapshot);
var project = _projectManager.FindProject(s_hostProject);
Assert.Null(project);
}
[UIFact]
@ -394,7 +404,7 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
_projectManager.Reset();
var originalTagHelpers = await _projectManager.GetSnapshot(s_hostProject).GetTagHelpersAsync(CancellationToken.None);
var originalTagHelpers = await _projectManager.FindProject(s_hostProject).AssumeNotNull().GetTagHelpersAsync(CancellationToken.None);
// Act
await RunOnDispatcherAsync(() =>
@ -403,7 +413,7 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
var newTagHelpers = await _projectManager.GetSnapshot(s_hostProject).GetTagHelpersAsync(CancellationToken.None);
var newTagHelpers = await _projectManager.FindProject(s_hostProject).AssumeNotNull().GetTagHelpersAsync(CancellationToken.None);
Assert.Equal(originalTagHelpers.Length, newTagHelpers.Length);
for (var i = 0; i < originalTagHelpers.Length; i++)
@ -426,8 +436,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
_projectManager.Reset();
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var projectEngine = snapshot.GetProjectEngine();
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
var projectEngine = project.GetProjectEngine();
// Act
await RunOnDispatcherAsync(() =>
@ -436,8 +447,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
snapshot = _projectManager.GetSnapshot(s_hostProject);
Assert.Same(projectEngine, snapshot.GetProjectEngine());
project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
Assert.Same(projectEngine, project.GetProjectEngine());
}
[UIFact]
public async Task DocumentOpened_UpdatesDocument()
@ -460,8 +472,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Assert
Assert.Equal(ProjectChangeKind.DocumentChanged, _projectManager.ListenersNotifiedOf);
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var text = await snapshot.GetDocument(s_documents[0].FilePath)!.GetTextAsync();
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
var text = await project.GetDocument(s_documents[0].FilePath)!.GetTextAsync();
Assert.Same(_sourceText, text);
Assert.True(_projectManager.IsDocumentOpen(s_documents[0].FilePath));
@ -494,8 +507,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Assert
Assert.Equal(ProjectChangeKind.DocumentChanged, _projectManager.ListenersNotifiedOf);
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var text = await snapshot.GetDocument(s_documents[0].FilePath)!.GetTextAsync();
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
var text = await project.GetDocument(s_documents[0].FilePath)!.GetTextAsync();
Assert.Same(expected, text);
Assert.False(_projectManager.IsDocumentOpen(s_documents[0].FilePath));
}
@ -524,8 +538,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Assert
Assert.Equal(ProjectChangeKind.DocumentChanged, _projectManager.ListenersNotifiedOf);
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var text = await snapshot.GetDocument(s_documents[0].FilePath)!.GetTextAsync();
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
var text = await project.GetDocument(s_documents[0].FilePath)!.GetTextAsync();
Assert.Same(expected, text);
}
@ -553,8 +568,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Assert
Assert.Equal(ProjectChangeKind.DocumentChanged, _projectManager.ListenersNotifiedOf);
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var text = await snapshot.GetDocument(s_documents[0].FilePath)!.GetTextAsync();
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
var text = await project.GetDocument(s_documents[0].FilePath)!.GetTextAsync();
Assert.Same(expected, text);
}
@ -583,8 +599,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Assert
Assert.Equal(ProjectChangeKind.DocumentChanged, _projectManager.ListenersNotifiedOf);
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var text = await snapshot.GetDocument(s_documents[0].FilePath)!.GetTextAsync();
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
var text = await project.GetDocument(s_documents[0].FilePath)!.GetTextAsync();
Assert.Same(expected, text);
}
@ -657,8 +674,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
_projectManager.Reset();
var snapshot = _projectManager.GetSnapshot(s_hostProject);
var projectEngine = snapshot.GetProjectEngine();
var project = _projectManager.FindProject(s_hostProject);
Assert.NotNull(project);
var projectEngine = project.GetProjectEngine();
// Act
await RunOnDispatcherAsync(() =>
@ -667,8 +685,9 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
});
// Assert
snapshot = _projectManager.GetSnapshot(s_hostProjectWithConfigurationChange);
Assert.NotSame(projectEngine, snapshot.GetProjectEngine());
project = _projectManager.FindProject(s_hostProjectWithConfigurationChange);
Assert.NotNull(project);
Assert.NotSame(projectEngine, project.GetProjectEngine());
}
[UIFact]
@ -795,7 +814,7 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
};
_projectManager.Changed += (sender, args) => listenerNotifications.Add(args.Kind);
_projectManager.NotifyChangedEvents = true;
_projectManager.AllowNotifyListeners = true;
// Act
await RunOnDispatcherAsync(() =>
@ -819,7 +838,7 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
_projectManager.Reset();
_projectManager.Changed += (sender, args) => Assert.True(args.SolutionIsClosing);
_projectManager.NotifyChangedEvents = true;
_projectManager.AllowNotifyListeners = true;
var textLoader = new Mock<TextLoader>(MockBehavior.Strict);
@ -835,42 +854,6 @@ public class DefaultProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
textLoader.Verify(d => d.LoadTextAndVersionAsync(It.IsAny<LoadTextOptions>(), It.IsAny<CancellationToken>()), Times.Never());
}
private class TestProjectSnapshotManager(
IEnumerable<IProjectSnapshotChangeTrigger> triggers,
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher)
: DefaultProjectSnapshotManager(triggers, projectEngineFactoryProvider, dispatcher, Mock.Of<IErrorReporter>(MockBehavior.Strict))
{
public ProjectChangeKind? ListenersNotifiedOf { get; private set; }
public bool NotifyChangedEvents { get; set; }
public ProjectSnapshot GetSnapshot(HostProject hostProject)
{
return GetProjects().Cast<ProjectSnapshot>().FirstOrDefault(s => s.FilePath == hostProject.FilePath);
}
public ProjectSnapshot GetSnapshot(Project workspaceProject)
{
return GetProjects().Cast<ProjectSnapshot>().FirstOrDefault(s => s.FilePath == workspaceProject.FilePath);
}
public void Reset()
{
ListenersNotifiedOf = null;
}
protected override void NotifyListeners(ProjectChangeEventArgs e)
{
ListenersNotifiedOf = e.Kind;
if (NotifyChangedEvents)
{
base.NotifyListeners(e);
}
}
}
private class InitializeInspectionTrigger(Action initializeNotification) : IProjectSnapshotChangeTrigger
{
private readonly Action _initializeNotification = initializeNotification;

Просмотреть файл

@ -9,8 +9,8 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.ProjectEngineHost;
using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.VisualStudio.ProjectSystem;
@ -1381,15 +1381,4 @@ public class DefaultWindowsRazorProjectHostTest : VisualStudioWorkspaceTestBase
await Task.Run(async () => await host.DisposeAsync());
Assert.Empty(_projectManager.GetProjects());
}
private class TestProjectSnapshotManager(
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher)
: DefaultProjectSnapshotManager(
triggers: [],
projectEngineFactoryProvider,
dispatcher,
Mock.Of<IErrorReporter>(MockBehavior.Strict))
{
}
}

Просмотреть файл

@ -10,7 +10,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.ProjectEngineHost;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.VisualStudio.ProjectSystem;
@ -672,14 +672,4 @@ public class FallbackWindowsRazorProjectHostTest : VisualStudioWorkspaceTestBase
return true;
}
}
private class TestProjectSnapshotManager(
IProjectEngineFactoryProvider projectEngineFactoryProvider,
ProjectSnapshotManagerDispatcher dispatcher) : DefaultProjectSnapshotManager(
triggers: [],
projectEngineFactoryProvider,
dispatcher,
Mock.Of<IErrorReporter>(MockBehavior.Strict))
{
}
}