コード例 #1
0
        public async Task Queue_ProcessesNotifications_AndGoesBackToSleep()
        {
            // Arrange
            var projectManager = new TestProjectSnapshotManager(Dispatcher, Workspace);

            projectManager.HostProjectAdded(HostProject1);
            projectManager.HostProjectAdded(HostProject2);
            projectManager.WorkspaceProjectAdded(WorkspaceProject1);
            projectManager.WorkspaceProjectAdded(WorkspaceProject2);

            var projectWorker = new TestProjectSnapshotWorker();

            var queue = new ProjectSnapshotWorkerQueue(Dispatcher, projectManager, projectWorker)
            {
                Delay = TimeSpan.FromMilliseconds(1),
                BlockBackgroundWorkStart   = new ManualResetEventSlim(initialState: false),
                NotifyBackgroundWorkFinish = new ManualResetEventSlim(initialState: false),
                NotifyForegroundWorkFinish = new ManualResetEventSlim(initialState: false),
            };

            // Act & Assert
            queue.Enqueue(projectManager.GetSnapshot(HostProject1).CreateUpdateContext());

            Assert.True(queue.IsScheduledOrRunning, "Queue should be scheduled during Enqueue");
            Assert.True(queue.HasPendingNotifications, "Queue should have a notification created during Enqueue");

            // Allow the background work to proceed.
            queue.BlockBackgroundWorkStart.Set();

            // Get off the foreground thread and allow the updates to flow through.
            await Task.Run(() => queue.NotifyForegroundWorkFinish.Wait(TimeSpan.FromSeconds(1)));

            Assert.False(queue.IsScheduledOrRunning, "Queue should not have restarted");
            Assert.False(queue.HasPendingNotifications, "Queue should have processed all notifications");
        }
コード例 #2
0
        public FallbackRazorProjectHostTest()
        {
            Workspace      = new AdhocWorkspace();
            ProjectManager = new TestProjectSnapshotManager(Dispatcher, Workspace);

            ReferenceItems = new ItemCollection(ManageProjectSystemSchema.ResolvedCompilationReference.SchemaName);
        }
コード例 #3
0
        public async Task SolutionClosing_StopsActiveWork()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue);

            WorkQueueTestAccessor.BlockBackgroundWorkStart     = new ManualResetEventSlim(initialState: false);
            WorkQueueTestAccessor.NotifyBackgroundWorkStarting = new ManualResetEventSlim(initialState: false);

            Workspace.TryApplyChanges(SolutionWithTwoProjects);
            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);
            await Dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(HostProjectOne), CancellationToken.None).ConfigureAwait(false);

            workspaceStateGenerator.ClearQueue();
            WorkQueueTestAccessor.NotifyBackgroundWorkStarting.Wait();

            // Act
            await Dispatcher.RunOnDispatcherThreadAsync(() =>
            {
                projectManager.SolutionClosed();

                // Trigger a project removed event while solution is closing to clear state.
                projectManager.ProjectRemoved(HostProjectOne);
            }, CancellationToken.None).ConfigureAwait(false);

            // Assert
            //
            // The change hasn't come through yet.
            Assert.Empty(workspaceStateGenerator.UpdateQueue);

            WorkQueueTestAccessor.BlockBackgroundWorkStart.Set();
            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();

            Assert.Empty(workspaceStateGenerator.UpdateQueue);
        }
コード例 #4
0
        public async Task WorkspaceChanged_DocumentChanged_CSHTML_UpdatesProjectState_AfterDelay()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator)
            {
                EnqueueDelay = 50,
            };

            Workspace.TryApplyChanges(SolutionWithTwoProjects);
            var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace);

            projectManager.ProjectAdded(HostProjectOne);
            workspaceStateGenerator.ClearQueue();

            var solution = SolutionWithTwoProjects.WithDocumentText(CshtmlDocumentId, SourceText.From("Hello World"));
            var e        = new WorkspaceChangeEventArgs(WorkspaceChangeKind.DocumentChanged, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id, CshtmlDocumentId);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            //
            // The change hasn't come through yet.
            Assert.Empty(workspaceStateGenerator.UpdateQueue);

            await detector._deferredUpdates.Single().Value;

            var update = Assert.Single(workspaceStateGenerator.UpdateQueue);

            Assert.Equal(update.workspaceProject.Id, ProjectNumberOne.Id);
            Assert.Equal(update.projectSnapshot.FilePath, HostProjectOne.FilePath);
        }
コード例 #5
0
        public async Task Queue_ProcessesNotifications_AndRestarts()
        {
            // Arrange
            var projectManager = new TestProjectSnapshotManager(Dispatcher, Workspace);

            projectManager.HostProjectAdded(HostProject1);
            projectManager.HostProjectAdded(HostProject2);
            projectManager.WorkspaceProjectAdded(WorkspaceProject1);
            projectManager.WorkspaceProjectAdded(WorkspaceProject2);
            projectManager.DocumentAdded(HostProject1, Documents[0], null);
            projectManager.DocumentAdded(HostProject1, Documents[1], null);

            var project = projectManager.GetLoadedProject(HostProject1.FilePath);

            var queue = new BackgroundDocumentGenerator(Dispatcher)
            {
                Delay = TimeSpan.FromMilliseconds(1),
                BlockBackgroundWorkStart      = new ManualResetEventSlim(initialState: false),
                NotifyBackgroundWorkStarting  = new ManualResetEventSlim(initialState: false),
                BlockBackgroundWorkCompleting = new ManualResetEventSlim(initialState: false),
                NotifyBackgroundWorkCompleted = new ManualResetEventSlim(initialState: false),
            };

            // Act & Assert
            queue.Enqueue(project, project.GetDocument(Documents[0].FilePath));

            Assert.True(queue.IsScheduledOrRunning, "Queue should be scheduled during Enqueue");
            Assert.True(queue.HasPendingNotifications, "Queue should have a notification created during Enqueue");

            // Allow the background work to start.
            queue.BlockBackgroundWorkStart.Set();

            await Task.Run(() => queue.NotifyBackgroundWorkStarting.Wait(TimeSpan.FromSeconds(1)));

            Assert.True(queue.IsScheduledOrRunning, "Worker should be processing now");
            Assert.False(queue.HasPendingNotifications, "Worker should have taken all notifications");

            queue.Enqueue(project, project.GetDocument(Documents[1].FilePath));
            Assert.True(queue.HasPendingNotifications); // Now we should see the worker restart when it finishes.

            // Allow work to complete, which should restart the timer.
            queue.BlockBackgroundWorkCompleting.Set();

            await Task.Run(() => queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(1)));

            queue.NotifyBackgroundWorkCompleted.Reset();

            // It should start running again right away.
            Assert.True(queue.IsScheduledOrRunning, "Queue should be scheduled during Enqueue");
            Assert.True(queue.HasPendingNotifications, "Queue should have a notification created during Enqueue");

            // Allow the background work to proceed.
            queue.BlockBackgroundWorkStart.Set();

            queue.BlockBackgroundWorkCompleting.Set();
            await Task.Run(() => queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(1)));

            Assert.False(queue.IsScheduledOrRunning, "Queue should not have restarted");
            Assert.False(queue.HasPendingNotifications, "Queue should have processed all notifications");
        }
        public async Task WorkspaceChanged_DocumentChanged_Razor_UpdatesProjectState_AfterDelay()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator)
            {
                EnqueueDelay = 1,
                BlockDelayedUpdateWorkEnqueue = new ManualResetEventSlim(initialState: false),
            };

            Workspace.TryApplyChanges(SolutionWithTwoProjects);
            var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace);

            projectManager.ProjectAdded(HostProjectOne);
            workspaceStateGenerator.ClearQueue();

            var solution = SolutionWithTwoProjects.WithDocumentText(RazorDocumentId, SourceText.From("Hello World"));
            var e        = new WorkspaceChangeEventArgs(WorkspaceChangeKind.DocumentChanged, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id, RazorDocumentId);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            //
            // The change hasn't come through yet.
            Assert.Empty(workspaceStateGenerator.UpdateQueue);

            detector.BlockDelayedUpdateWorkEnqueue.Set();

            await detector._deferredUpdates.Single().Value.Task;

            var(workspaceProject, projectSnapshot) = Assert.Single(workspaceStateGenerator.UpdateQueue);
            Assert.Equal(workspaceProject.Id, ProjectNumberOne.Id);
            Assert.Equal(projectSnapshot.FilePath, HostProjectOne.FilePath);
        }
        public DefaultRazorDocumentInfoProviderTest()
        {
            ProjectSnapshotManager = new TestProjectSnapshotManager(Workspace);

            var hostProject = new HostProject("C:/path/to/project.csproj", RazorConfiguration.Default, "RootNamespace");

            ProjectSnapshotManager.ProjectAdded(hostProject);

            var hostDocument   = new HostDocument("C:/path/to/document.cshtml", "/C:/path/to/document.cshtml");
            var sourceText     = SourceText.From("Hello World");
            var textAndVersion = TextAndVersion.Create(sourceText, VersionStamp.Default, hostDocument.FilePath);

            ProjectSnapshotManager.DocumentAdded(hostProject, hostDocument, TextLoader.From(textAndVersion));

            ProjectSnapshot  = ProjectSnapshotManager.Projects[0];
            DocumentSnapshot = ProjectSnapshot.GetDocument(hostDocument.FilePath);
            var factory = new Mock <VisualStudioMacDocumentInfoFactory>();

            factory.Setup(f => f.CreateEmpty(It.IsAny <string>(), It.IsAny <ProjectId>()))
            .Returns <string, ProjectId>((razorFilePath, projectId) =>
            {
                var documentId   = DocumentId.CreateNewId(projectId);
                var documentInfo = DocumentInfo.Create(documentId, "testDoc", filePath: razorFilePath);
                return(documentInfo);
            });
            Factory = factory.Object;
        }
コード例 #8
0
        public DefaultProjectSnapshotManagerTest()
        {
            var someTagHelpers = new List <TagHelperDescriptor>();

            someTagHelpers.Add(TagHelperDescriptorBuilder.Create("Test1", "TestAssembly").Build());
            TagHelperResolver = new TestTagHelperResolver()
            {
                TagHelpers = someTagHelpers,
            };

            Documents = new HostDocument[]
            {
                TestProjectData.SomeProjectFile1,
                TestProjectData.SomeProjectFile2,

                // linked file
                TestProjectData.AnotherProjectNestedFile3,

                TestProjectData.SomeProjectComponentFile1,
                TestProjectData.SomeProjectComponentFile2,
            };

            HostProject = new HostProject(TestProjectData.SomeProject.FilePath, FallbackRazorConfiguration.MVC_2_0, TestProjectData.SomeProject.RootNamespace);
            HostProjectWithConfigurationChange = new HostProject(TestProjectData.SomeProject.FilePath, FallbackRazorConfiguration.MVC_1_0, TestProjectData.SomeProject.RootNamespace);

            ProjectManager = new TestProjectSnapshotManager(Dispatcher, Enumerable.Empty <ProjectSnapshotChangeTrigger>(), Workspace);

            ProjectWorkspaceStateWithTagHelpers = new ProjectWorkspaceState(TagHelperResolver.TagHelpers, default);

            SourceText = SourceText.From("Hello world");
        }
コード例 #9
0
        public async Task Queue_ProcessesNotifications_AndGoesBackToSleep()
        {
            // Arrange
            var projectManager = new TestProjectSnapshotManager(Dispatcher, Workspace);
            var projectWorker  = new TestProjectSnapshotWorker();

            var queue = new ProjectSnapshotWorkerQueue(Dispatcher, projectManager, projectWorker)
            {
                Delay = TimeSpan.FromMilliseconds(1),
                BlockBackgroundWorkStart   = new ManualResetEventSlim(initialState: false),
                NotifyBackgroundWorkFinish = new ManualResetEventSlim(initialState: false),
                NotifyForegroundWorkFinish = new ManualResetEventSlim(initialState: false),
            };

            // Act & Assert
            queue.Enqueue(Project1);

            Assert.True(queue.IsScheduledOrRunning);
            Assert.True(queue.HasPendingNotifications);

            // Allow the background work to proceed.
            queue.BlockBackgroundWorkStart.Set();

            // Get off the foreground thread and allow the updates to flow through.
            await Task.Run(() => queue.NotifyForegroundWorkFinish.Wait(TimeSpan.FromSeconds(1)));

            Assert.False(queue.IsScheduledOrRunning);
            Assert.False(queue.HasPendingNotifications);
        }
コード例 #10
0
        public async Task ProcessDocument_SwallowsUnauthorizedAccessExceptions()
        {
            // Arrange
            var projectManager = new TestProjectSnapshotManager(Dispatcher, Workspace);

            projectManager.ProjectAdded(HostProject1);

            var textLoader = new Mock <TextLoader>(MockBehavior.Strict);

            textLoader.Setup(loader => loader.LoadTextAndVersionAsync(It.IsAny <Workspace>(), It.IsAny <DocumentId>(), It.IsAny <CancellationToken>()))
            .Throws <UnauthorizedAccessException>();
            projectManager.DocumentAdded(HostProject1, Documents[0], textLoader.Object);

            var project = projectManager.GetLoadedProject(HostProject1.FilePath);

            var queue = new BackgroundDocumentGenerator(Dispatcher, DynamicFileInfoProvider)
            {
                Delay = TimeSpan.FromMilliseconds(1),
                NotifyBackgroundWorkCompleted = new ManualResetEventSlim(initialState: false),
                NotifyErrorBeingReported      = new ManualResetEventSlim(initialState: false),
            };

            queue.Initialize(projectManager);

            // Act & Assert
            queue.Enqueue(project, project.GetDocument(Documents[0].FilePath));

            await Task.Run(() => queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(3)));

            Assert.False(queue.NotifyErrorBeingReported.IsSet);
        }
        public DefaultProjectSnapshotManagerTest()
        {
            TagHelperResolver = new TestTagHelperResolver();

            Documents = new HostDocument[]
            {
                TestProjectData.SomeProjectFile1,
                TestProjectData.SomeProjectFile2,

                // linked file
                TestProjectData.AnotherProjectNestedFile3,

                TestProjectData.SomeProjectComponentFile1,
                TestProjectData.SomeProjectComponentFile2,
            };

            HostProject = new HostProject(TestProjectData.SomeProject.FilePath, FallbackRazorConfiguration.MVC_2_0, TestProjectData.SomeProject.RootNamespace);
            HostProjectWithConfigurationChange = new HostProject(TestProjectData.SomeProject.FilePath, FallbackRazorConfiguration.MVC_1_0, TestProjectData.SomeProject.RootNamespace);

            ProjectManager = new TestProjectSnapshotManager(Dispatcher, Enumerable.Empty <ProjectSnapshotChangeTrigger>(), Workspace);

            ProjectWorkspaceStateWithTagHelpers = new ProjectWorkspaceState(TagHelperResolver.TagHelpers);

            SourceText = SourceText.From("Hello world");
        }
コード例 #12
0
        public async Task WorkspaceChanged_ProjectRemovedEvent_QueuesProjectStateRemoval()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue)
            {
                NotifyWorkspaceChangedEventComplete = new ManualResetEventSlim(initialState: false),
            };
            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);
            await Dispatcher.RunOnDispatcherThreadAsync(() =>
            {
                projectManager.ProjectAdded(HostProjectOne);
                projectManager.ProjectAdded(HostProjectTwo);
            }, CancellationToken.None).ConfigureAwait(false);

            var solution = SolutionWithTwoProjects.RemoveProject(ProjectNumberOne.Id);
            var e        = new WorkspaceChangeEventArgs(WorkspaceChangeKind.ProjectRemoved, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);
            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();

            // Assert
            Assert.Collection(
                workspaceStateGenerator.UpdateQueue,
                p => Assert.Null(p.WorkspaceProject));
        }
コード例 #13
0
        public void WorkspaceChanged_ProjectChangeEvents_UpdatesProject(WorkspaceChangeKind kind)
        {
            // Arrange
            var trigger        = new WorkspaceProjectSnapshotChangeTrigger();
            var projectManager = new TestProjectSnapshotManager(new[] { trigger }, Workspace);

            // Initialize with some projects.
            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.SolutionAdded, oldSolution: EmptySolution, newSolution: SolutionWithTwoProjects);

            trigger.Workspace_WorkspaceChanged(Workspace, e);

            var solution = SolutionWithTwoProjects.WithProjectAssemblyName(ProjectNumberOne.Id, "Changed");

            e = new WorkspaceChangeEventArgs(kind, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id);

            // Act
            trigger.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            Assert.Collection(
                projectManager.Projects.OrderBy(p => p.UnderlyingProject.Name),
                p =>
            {
                Assert.Equal(ProjectNumberOne.Id, p.UnderlyingProject.Id);
                Assert.Equal("Changed", p.UnderlyingProject.AssemblyName);
            },
                p => Assert.Equal(ProjectNumberTwo.Id, p.UnderlyingProject.Id));
        }
コード例 #14
0
        public async Task WorkspaceChanged_SolutionEvents_EnqueuesUpdatesForProjectsInSolution(WorkspaceChangeKind kind)
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue)
            {
                NotifyWorkspaceChangedEventComplete = new ManualResetEventSlim(initialState: false),
            };
            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);
            await Dispatcher.RunOnDispatcherThreadAsync(() =>
            {
                projectManager.ProjectAdded(HostProjectOne);
                projectManager.ProjectAdded(HostProjectTwo);
            }, CancellationToken.None).ConfigureAwait(false);

            var e = new WorkspaceChangeEventArgs(kind, oldSolution: EmptySolution, newSolution: SolutionWithTwoProjects);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);
            detector.NotifyWorkspaceChangedEventComplete.Wait();
            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();

            // Assert
            Assert.Collection(
                workspaceStateGenerator.UpdateQueue,
                p => Assert.Equal(ProjectNumberOne.Id, p.WorkspaceProject.Id),
                p => Assert.Equal(ProjectNumberTwo.Id, p.WorkspaceProject.Id));
        }
        public RazorDocumentInfoProviderTest()
        {
            var serviceProviderFactory          = new DefaultRazorDocumentServiceProviderFactory();
            var lspEditorEnabledFeatureDetector = Mock.Of <LSPEditorFeatureDetector>(detector => detector.IsLSPEditorFeatureEnabled() == true, MockBehavior.Strict);

            InnerDynamicDocumentInfoProvider = new DefaultRazorDynamicFileInfoProvider(serviceProviderFactory, lspEditorEnabledFeatureDetector);
            ProjectSnapshotManager           = new TestProjectSnapshotManager(Workspace);

            var hostProject = new HostProject("C:/path/to/project.csproj", RazorConfiguration.Default, "RootNamespace");

            ProjectSnapshotManager.ProjectAdded(hostProject);

            var hostDocument   = new HostDocument("C:/path/to/document.cshtml", "/C:/path/to/document.cshtml");
            var sourceText     = SourceText.From("Hello World");
            var textAndVersion = TextAndVersion.Create(sourceText, VersionStamp.Default, hostDocument.FilePath);

            ProjectSnapshotManager.DocumentAdded(hostProject, hostDocument, TextLoader.From(textAndVersion));

            ProjectSnapshot  = ProjectSnapshotManager.Projects[0];
            DocumentSnapshot = ProjectSnapshot.GetDocument(hostDocument.FilePath);
            var factory = new Mock <VisualStudioMacDocumentInfoFactory>(MockBehavior.Strict);

            factory.Setup(f => f.CreateEmpty(It.IsAny <string>(), It.IsAny <ProjectId>()))
            .Returns <string, ProjectId>((razorFilePath, projectId) =>
            {
                var documentId   = DocumentId.CreateNewId(projectId);
                var documentInfo = DocumentInfo.Create(documentId, "testDoc", filePath: razorFilePath);
                return(documentInfo);
            });
            Factory = factory.Object;
        }
コード例 #16
0
        public async Task WorkspaceChanged_DocumentChanged_Razor_UpdatesProjectState_AfterDelay()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue);

            WorkQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false);

            Workspace.TryApplyChanges(SolutionWithTwoProjects);
            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);
            await Dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(HostProjectOne), CancellationToken.None).ConfigureAwait(false);

            workspaceStateGenerator.ClearQueue();

            var solution = SolutionWithTwoProjects.WithDocumentText(RazorDocumentId, SourceText.From("Hello World"));
            var e        = new WorkspaceChangeEventArgs(WorkspaceChangeKind.DocumentChanged, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id, RazorDocumentId);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            //
            // The change hasn't come through yet.
            Assert.Empty(workspaceStateGenerator.UpdateQueue);

            WorkQueueTestAccessor.BlockBackgroundWorkStart.Set();
            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();

            var update = Assert.Single(workspaceStateGenerator.UpdateQueue);

            Assert.Equal(update.WorkspaceProject.Id, ProjectNumberOne.Id);
            Assert.Equal(update.ProjectSnapshot.FilePath, HostProjectOne.FilePath);
        }
コード例 #17
0
        public void WorkspaceChanged_SolutionEvents_EnqueuesStateClear_EnqueuesSolutionProjectUpdates(WorkspaceChangeKind kind)
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector       = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator);
            var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace);

            projectManager.ProjectAdded(HostProjectOne);
            projectManager.ProjectAdded(HostProjectTwo);
            projectManager.ProjectAdded(HostProjectThree);

            // Initialize with a project. This will get removed.
            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.SolutionAdded, oldSolution: EmptySolution, newSolution: SolutionWithOneProject);

            detector.Workspace_WorkspaceChanged(Workspace, e);

            e = new WorkspaceChangeEventArgs(kind, oldSolution: SolutionWithOneProject, newSolution: SolutionWithTwoProjects);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            Assert.Collection(
                workspaceStateGenerator.UpdateQueue,
                p => Assert.Equal(ProjectNumberThree.Id, p.workspaceProject.Id),
                p => Assert.Null(p.workspaceProject),
                p => Assert.Equal(ProjectNumberOne.Id, p.workspaceProject.Id),
                p => Assert.Equal(ProjectNumberTwo.Id, p.workspaceProject.Id));
        }
コード例 #18
0
        public async Task WorkspaceChanged_ProjectChangeEvents_UpdatesProjectState_AfterDelay(WorkspaceChangeKind kind)
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator)
            {
                EnqueueDelay = 1,
                BlockDelayedUpdateWorkEnqueue = new ManualResetEventSlim(initialState: false),
            };

            var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace);

            projectManager.ProjectAdded(HostProjectOne);

            var solution = SolutionWithTwoProjects.WithProjectAssemblyName(ProjectNumberOne.Id, "Changed");
            var e        = new WorkspaceChangeEventArgs(kind, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            //
            // The change hasn't come through yet.
            Assert.Empty(workspaceStateGenerator.UpdateQueue);

            detector.BlockDelayedUpdateWorkEnqueue.Set();

            await detector._deferredUpdates.Single().Value;

            var update = Assert.Single(workspaceStateGenerator.UpdateQueue);

            Assert.Equal(update.workspaceProject.Id, ProjectNumberOne.Id);
            Assert.Equal(update.projectSnapshot.FilePath, HostProjectOne.FilePath);
        }
コード例 #19
0
        public void WorkspaceChanged_ProjectRemovedEvent_RemovesProject()
        {
            // Arrange
            var trigger        = new WorkspaceProjectSnapshotChangeTrigger();
            var projectManager = new TestProjectSnapshotManager(new[] { trigger }, Workspace);

            projectManager.HostProjectAdded(HostProjectOne);
            projectManager.HostProjectAdded(HostProjectTwo);

            // Initialize with some projects project.
            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.SolutionAdded, oldSolution: EmptySolution, newSolution: SolutionWithTwoProjects);

            trigger.Workspace_WorkspaceChanged(Workspace, e);

            var solution = SolutionWithTwoProjects.RemoveProject(ProjectNumberOne.Id);

            e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.ProjectRemoved, oldSolution: SolutionWithTwoProjects, newSolution: solution, projectId: ProjectNumberOne.Id);

            // Act
            trigger.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            Assert.Collection(
                projectManager.Projects.OrderBy(p => p.WorkspaceProject?.Name),
                p => Assert.Null(p.WorkspaceProject),
                p => Assert.Equal(ProjectNumberTwo.Id, p.WorkspaceProject.Id));
        }
コード例 #20
0
        public void WorkspaceChanged_SolutionEvents_ClearsExistingProjects_AddsProjectsInSolution(WorkspaceChangeKind kind)
        {
            // Arrange
            var trigger        = new WorkspaceProjectSnapshotChangeTrigger();
            var projectManager = new TestProjectSnapshotManager(new[] { trigger }, Workspace);

            projectManager.HostProjectAdded(HostProjectOne);
            projectManager.HostProjectAdded(HostProjectTwo);
            projectManager.HostProjectAdded(HostProjectThree);

            // Initialize with a project. This will get removed.
            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.SolutionAdded, oldSolution: EmptySolution, newSolution: SolutionWithOneProject);

            trigger.Workspace_WorkspaceChanged(Workspace, e);

            e = new WorkspaceChangeEventArgs(kind, oldSolution: SolutionWithOneProject, newSolution: SolutionWithTwoProjects);

            // Act
            trigger.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            Assert.Collection(
                projectManager.Projects.OrderBy(p => p.WorkspaceProject?.Name),
                p => Assert.Null(p.WorkspaceProject),
                p => Assert.Equal(ProjectNumberOne.Id, p.WorkspaceProject.Id),
                p => Assert.Equal(ProjectNumberTwo.Id, p.WorkspaceProject.Id));
        }
コード例 #21
0
        public FallbackRazorProjectHostTest()
        {
            ProjectManager = new TestProjectSnapshotManager(Dispatcher, Workspace);

            ReferenceItems = new ItemCollection(ManagedProjectSystemSchema.ResolvedCompilationReference.SchemaName);
            ContentItems   = new ItemCollection(ManagedProjectSystemSchema.ContentItem.SchemaName);
            NoneItems      = new ItemCollection(ManagedProjectSystemSchema.NoneItem.SchemaName);
        }
コード例 #22
0
        public DefaultRazorProjectHostTest()
        {
            ProjectManager = new TestProjectSnapshotManager(Dispatcher, Workspace);

            ConfigurationItems     = new ItemCollection(Rules.RazorConfiguration.SchemaName);
            ExtensionItems         = new ItemCollection(Rules.RazorExtension.SchemaName);
            DocumentItems          = new ItemCollection(Rules.RazorGenerateWithTargetPath.SchemaName);
            RazorGeneralProperties = new PropertyCollection(Rules.RazorGeneral.SchemaName);
        }
コード例 #23
0
        public async Task DocumentRemoved_ReparsesRelatedFiles()
        {
            // Arrange
            var projectManager = new TestProjectSnapshotManager(Dispatcher, Workspace)
            {
                AllowNotifyListeners = true,
            };

            projectManager.ProjectAdded(HostProject1);
            projectManager.DocumentAdded(HostProject1, TestProjectData.SomeProjectComponentFile1, null);
            projectManager.DocumentAdded(HostProject1, TestProjectData.SomeProjectImportFile, null);

            var queue = new BackgroundDocumentGenerator(Dispatcher, DynamicFileInfoProvider)
            {
                Delay = TimeSpan.FromMilliseconds(1),
                BlockBackgroundWorkStart         = new ManualResetEventSlim(initialState: false),
                NotifyBackgroundWorkStarting     = new ManualResetEventSlim(initialState: false),
                NotifyBackgroundCapturedWorkload = new ManualResetEventSlim(initialState: false),
                BlockBackgroundWorkCompleting    = new ManualResetEventSlim(initialState: false),
                NotifyBackgroundWorkCompleted    = new ManualResetEventSlim(initialState: false),
            };

            queue.Initialize(projectManager);

            // Act & Assert
            projectManager.DocumentRemoved(HostProject1, TestProjectData.SomeProjectImportFile);

            Assert.True(queue.IsScheduledOrRunning, "Queue should be scheduled during Enqueue");
            Assert.True(queue.HasPendingNotifications, "Queue should have a notification created during Enqueue");

            var kvp         = Assert.Single(queue.Work);
            var expectedKey = new DocumentKey(HostProject1.FilePath, TestProjectData.SomeProjectComponentFile1.FilePath);

            Assert.Equal(expectedKey, kvp.Key);

            // Allow the background work to start.
            queue.BlockBackgroundWorkStart.Set();

            await Task.Run(() => queue.NotifyBackgroundWorkStarting.Wait(TimeSpan.FromSeconds(1)));

            Assert.True(queue.IsScheduledOrRunning, "Worker should be processing now");

            await Task.Run(() => queue.NotifyBackgroundCapturedWorkload.Wait(TimeSpan.FromSeconds(1)));

            Assert.False(queue.HasPendingNotifications, "Worker should have taken all notifications");

            // Allow work to complete
            queue.BlockBackgroundWorkCompleting.Set();

            await Task.Run(() => queue.NotifyBackgroundWorkCompleted.Wait(TimeSpan.FromSeconds(3)));

            Assert.False(queue.HasPendingNotifications, "Queue should have processed all notifications");
            Assert.False(queue.IsScheduledOrRunning, "Queue should not have restarted");
        }
コード例 #24
0
        public async Task WorkspaceChanged_DocumentChanged_PartialComponent_UpdatesProjectState_AfterDelay()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator)
            {
                EnqueueDelay = 1,
                BlockDelayedUpdateWorkEnqueue = new ManualResetEventSlim(initialState: false),
            };

            Workspace.TryApplyChanges(SolutionWithTwoProjects);
            var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace);

            projectManager.ProjectAdded(HostProjectOne);
            workspaceStateGenerator.ClearQueue();

            var sourceText = SourceText.From(
                $@"
public partial class TestComponent : {ComponentsApi.IComponent.MetadataName} {{}}
namespace Microsoft.AspNetCore.Components
{{
    public interface IComponent {{}}
}}
");
            var syntaxTreeRoot = CSharpSyntaxTree.ParseText(sourceText).GetRoot();
            var solution       = SolutionWithTwoProjects
                                 .WithDocumentText(PartialComponentClassDocumentId, sourceText)
                                 .WithDocumentSyntaxRoot(PartialComponentClassDocumentId, syntaxTreeRoot, PreservationMode.PreserveIdentity);
            var document = solution.GetDocument(PartialComponentClassDocumentId);

            // The change detector only operates when a semantic model / syntax tree is available.
            await document.GetSyntaxRootAsync();

            await document.GetSemanticModelAsync();

            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.DocumentChanged, oldSolution: solution, newSolution: solution, projectId: ProjectNumberOne.Id, PartialComponentClassDocumentId);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            //
            // The change hasn't come through yet.
            Assert.Empty(workspaceStateGenerator.UpdateQueue);

            detector.BlockDelayedUpdateWorkEnqueue.Set();

            await detector._deferredUpdates.Single().Value;

            var update = Assert.Single(workspaceStateGenerator.UpdateQueue);

            Assert.Equal(update.workspaceProject.Id, ProjectNumberOne.Id);
            Assert.Equal(update.projectSnapshot.FilePath, HostProjectOne.FilePath);
        }
コード例 #25
0
        public async Task WorkspaceChanged_DocumentChanged_PartialComponent_UpdatesProjectState_AfterDelay()
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue);

            WorkQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false);

            Workspace.TryApplyChanges(SolutionWithTwoProjects);
            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);
            await Dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(HostProjectOne), CancellationToken.None).ConfigureAwait(false);

            workspaceStateGenerator.ClearQueue();

            var sourceText = SourceText.From(
                $@"
public partial class TestComponent : {ComponentsApi.IComponent.MetadataName} {{}}
namespace Microsoft.AspNetCore.Components
{{
    public interface IComponent {{}}
}}
");
            var syntaxTreeRoot = await CSharpSyntaxTree.ParseText(sourceText).GetRootAsync();

            var solution = SolutionWithTwoProjects
                           .WithDocumentText(PartialComponentClassDocumentId, sourceText)
                           .WithDocumentSyntaxRoot(PartialComponentClassDocumentId, syntaxTreeRoot, PreservationMode.PreserveIdentity);
            var document = solution.GetDocument(PartialComponentClassDocumentId);

            // The change detector only operates when a semantic model / syntax tree is available.
            await document.GetSyntaxRootAsync();

            await document.GetSemanticModelAsync();

            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.DocumentChanged, oldSolution: solution, newSolution: solution, projectId: ProjectNumberOne.Id, PartialComponentClassDocumentId);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);

            // Assert
            //
            // The change hasn't come through yet.
            Assert.Empty(workspaceStateGenerator.UpdateQueue);

            WorkQueueTestAccessor.BlockBackgroundWorkStart.Set();

            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();

            var update = Assert.Single(workspaceStateGenerator.UpdateQueue);

            Assert.Equal(update.WorkspaceProject.Id, ProjectNumberOne.Id);
            Assert.Equal(update.ProjectSnapshot.FilePath, HostProjectOne.FilePath);
        }
コード例 #26
0
        public FallbackRazorProjectHostTest()
        {
            ProjectManager = new TestProjectSnapshotManager(Dispatcher, Workspace);

            var projectConfigurationFilePathStore = new Mock <ProjectConfigurationFilePathStore>(MockBehavior.Strict);

            projectConfigurationFilePathStore.Setup(s => s.Remove(It.IsAny <string>())).Verifiable();
            ProjectConfigurationFilePathStore = projectConfigurationFilePathStore.Object;

            ReferenceItems = new ItemCollection(ManagedProjectSystemSchema.ResolvedCompilationReference.SchemaName);
            ContentItems   = new ItemCollection(ManagedProjectSystemSchema.ContentItem.SchemaName);
            NoneItems      = new ItemCollection(ManagedProjectSystemSchema.NoneItem.SchemaName);
        }
コード例 #27
0
        public async Task Queue_ProcessesNotifications_AndRestarts()
        {
            // Arrange
            var projectManager = new TestProjectSnapshotManager(Dispatcher, Workspace);
            var projectWorker  = new TestProjectSnapshotWorker();

            var queue = new ProjectSnapshotWorkerQueue(Dispatcher, projectManager, projectWorker)
            {
                Delay = TimeSpan.FromMilliseconds(1),
                BlockBackgroundWorkStart   = new ManualResetEventSlim(initialState: false),
                NotifyBackgroundWorkFinish = new ManualResetEventSlim(initialState: false),
                NotifyForegroundWorkFinish = new ManualResetEventSlim(initialState: false),
            };

            // Act & Assert
            queue.Enqueue(Project1);

            Assert.True(queue.IsScheduledOrRunning);
            Assert.True(queue.HasPendingNotifications);

            // Allow the background work to proceed.
            queue.BlockBackgroundWorkStart.Set();

            queue.NotifyBackgroundWorkFinish.Wait(); // Block the foreground thread so we can queue another notification.

            Assert.True(queue.IsScheduledOrRunning);
            Assert.False(queue.HasPendingNotifications);

            queue.Enqueue(Project2);

            Assert.True(queue.HasPendingNotifications); // Now we should see the worker restart when it finishes.

            // Get off the foreground thread and allow the updates to flow through.
            await Task.Run(() => queue.NotifyForegroundWorkFinish.Wait(TimeSpan.FromSeconds(1)));

            queue.NotifyBackgroundWorkFinish.Reset();
            queue.NotifyForegroundWorkFinish.Reset();

            // It should start running again right away.
            Assert.True(queue.IsScheduledOrRunning);
            Assert.True(queue.HasPendingNotifications);

            // Allow the background work to proceed.
            queue.BlockBackgroundWorkStart.Set();

            // Get off the foreground thread and allow the updates to flow through.
            await Task.Run(() => queue.NotifyForegroundWorkFinish.Wait(TimeSpan.FromSeconds(1)));

            Assert.False(queue.IsScheduledOrRunning);
            Assert.False(queue.HasPendingNotifications);
        }
コード例 #28
0
        public DefaultProjectSnapshotManagerTest()
        {
            HostProject = new HostProject("Test.csproj", FallbackRazorConfiguration.MVC_2_0);

            Workspace      = TestWorkspace.Create();
            ProjectManager = new TestProjectSnapshotManager(Dispatcher, Enumerable.Empty <ProjectSnapshotChangeTrigger>(), Workspace);

            var projectId = ProjectId.CreateNewId("Test");
            var solution  = Workspace.CurrentSolution.AddProject(ProjectInfo.Create(
                                                                     projectId,
                                                                     VersionStamp.Default,
                                                                     "Test",
                                                                     "Test",
                                                                     LanguageNames.CSharp,
                                                                     "Test.csproj"));

            WorkspaceProject = solution.GetProject(projectId);

            var vbProjectId = ProjectId.CreateNewId("VB");

            solution = solution.AddProject(ProjectInfo.Create(
                                               vbProjectId,
                                               VersionStamp.Default,
                                               "VB",
                                               "VB",
                                               LanguageNames.VisualBasic,
                                               "VB.vbproj"));
            VBWorkspaceProject = solution.GetProject(vbProjectId);

            var projectWithoutFilePathId = ProjectId.CreateNewId("NoFile");

            solution = solution.AddProject(ProjectInfo.Create(
                                               projectWithoutFilePathId,
                                               VersionStamp.Default,
                                               "NoFile",
                                               "NoFile",
                                               LanguageNames.CSharp));
            WorkspaceProjectWithoutFilePath = solution.GetProject(projectWithoutFilePathId);

            // Approximates a project with multi-targeting
            var projectIdWithDifferentTfm = ProjectId.CreateNewId("TestWithDifferentTfm");

            solution = Workspace.CurrentSolution.AddProject(ProjectInfo.Create(
                                                                projectIdWithDifferentTfm,
                                                                VersionStamp.Default,
                                                                "Test (Different TFM)",
                                                                "Test",
                                                                LanguageNames.CSharp,
                                                                "Test.csproj"));
            WorkspaceProjectWithDifferentTfm = solution.GetProject(projectIdWithDifferentTfm);
        }
コード例 #29
0
        public void Initialize_DoneInCorrectOrderBasedOnInitializePriorityPriority()
        {
            // Arrange
            var initializedOrder       = new List <string>();
            var highPriorityTrigger    = new InitializeInspectionTrigger(() => initializedOrder.Add("highPriority"), 100);
            var defaultPriorityTrigger = new InitializeInspectionTrigger(() => initializedOrder.Add("lowPriority"), 0);

            // Building this list in the wrong order so we can verify priority matters
            var triggers = new[] { defaultPriorityTrigger, highPriorityTrigger };

            // Act
            var projectManager = new TestProjectSnapshotManager(Dispatcher, triggers, Workspace);

            // Assert
            Assert.Equal(new[] { "highPriority", "lowPriority" }, initializedOrder);
        }
コード例 #30
0
        public async Task WorkspaceChanged_ProjectEvents_EnqueuesUpdatesForDependentProjects(WorkspaceChangeKind kind)
        {
            // Arrange
            var workspaceStateGenerator = new TestProjectWorkspaceStateGenerator();
            var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, Dispatcher, WorkQueue)
            {
                NotifyWorkspaceChangedEventComplete = new ManualResetEventSlim(initialState: false),
            };

            WorkQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false);

            var projectManager = new TestProjectSnapshotManager(Dispatcher, new[] { detector }, Workspace);

            await Dispatcher.RunOnDispatcherThreadAsync(() =>
            {
                projectManager.ProjectAdded(HostProjectOne);
                projectManager.ProjectAdded(HostProjectTwo);
                projectManager.ProjectAdded(HostProjectThree);
            }, CancellationToken.None).ConfigureAwait(false);

            // Initialize with a project. This will get removed.
            var e = new WorkspaceChangeEventArgs(WorkspaceChangeKind.SolutionAdded, oldSolution: EmptySolution, newSolution: SolutionWithOneProject);

            detector.Workspace_WorkspaceChanged(Workspace, e);
            detector.NotifyWorkspaceChangedEventComplete.Wait();
            detector.NotifyWorkspaceChangedEventComplete.Reset();

            e = new WorkspaceChangeEventArgs(kind, oldSolution: SolutionWithOneProject, newSolution: SolutionWithDependentProject);

            var solution = SolutionWithDependentProject.WithProjectAssemblyName(ProjectNumberThree.Id, "Changed");

            e = new WorkspaceChangeEventArgs(kind, oldSolution: SolutionWithDependentProject, newSolution: solution, projectId: ProjectNumberThree.Id);

            // Act
            detector.Workspace_WorkspaceChanged(Workspace, e);
            detector.NotifyWorkspaceChangedEventComplete.Wait();

            // Assert
            Assert.Equal(3, WorkQueueTestAccessor.Work.Count);
            Assert.Contains(WorkQueueTestAccessor.Work, u => u.Key == ProjectNumberOne.FilePath);
            Assert.Contains(WorkQueueTestAccessor.Work, u => u.Key == ProjectNumberTwo.FilePath);
            Assert.Contains(WorkQueueTestAccessor.Work, u => u.Key == ProjectNumberThree.FilePath);

            WorkQueueTestAccessor.BlockBackgroundWorkStart.Set();
            WorkQueueTestAccessor.NotifyBackgroundWorkCompleted.Wait();
            Assert.Empty(WorkQueueTestAccessor.Work);
        }