Exemple #1
0
        public async Task WhenBaseIntermediateOutputPathNotSet_DoesNotAttemptToAdviseFileChange()
        {
            var spMock            = new IAsyncServiceProviderMoq();
            var fileChangeService = IVsFileChangeExFactory.CreateWithAdviseUnadviseFileChange(100);

            spMock.AddService(typeof(SVsFileChangeEx), fileChangeService);
            var tasksService = IUnconfiguredProjectTasksServiceFactory.ImplementLoadedProjectAsync <ConfiguredProject>(t => t());

            var watcher = new ProjectAssetFileWatcher(spMock,
                                                      IProjectTreeProviderFactory.Create(),
                                                      IUnconfiguredProjectCommonServicesFactory.Create(threadingService: new IProjectThreadingServiceMock()),
                                                      tasksService,
                                                      IActiveConfiguredProjectSubscriptionServiceFactory.Create());

            var tree          = ProjectTreeParser.Parse(@"Root (flags: {ProjectRoot}), FilePath: ""C:\Foo\foo.proj""");
            var projectUpdate = IProjectSubscriptionUpdateFactory.FromJson(@"{
    ""CurrentState"": {
        ""ConfigurationGeneral"": {
            ""Properties"": {
               ""MSBuildProjectFullPath"": ""C:\\Foo\\foo.proj""
            }
        }
    }
}");

            watcher.Load();
            await watcher.DataFlow_ChangedAsync(IProjectVersionedValueFactory <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > .Create((Tuple.Create(IProjectTreeSnapshotFactory.Create(tree), projectUpdate))));

            var  fileChangeServiceMock = Mock.Get(fileChangeService);
            uint cookie;

            fileChangeServiceMock.Verify(s => s.AdviseFileChange(It.IsAny <string>(), It.IsAny <uint>(), watcher, out cookie),
                                         Times.Never());
        }
Exemple #2
0
        public async Task VerifyFileWatcherRegistrationOnTreeChange(string inputTree, string changedTree, int numRegisterCalls, int numUnregisterCalls)
        {
            uint adviseCookie      = 100;
            var  fileChangeService = IVsFileChangeExFactory.CreateWithAdviseUnadviseFileChange(adviseCookie);

            var tasksService = IUnconfiguredProjectTasksServiceFactory.ImplementLoadedProjectAsync <ConfiguredProject>(t => t());

            using var watcher = new ProjectAssetFileWatcherInstance(
                      IVsServiceFactory.Create <SVsFileChangeEx, IVsAsyncFileChangeEx>(fileChangeService),
                      IProjectTreeProviderFactory.Create(),
                      IUnconfiguredProjectCommonServicesFactory.Create(threadingService: IProjectThreadingServiceFactory.Create()),
                      tasksService,
                      IActiveConfiguredProjectSubscriptionServiceFactory.Create());
            await watcher.InitializeAsync();

            var projectUpdate = IProjectSubscriptionUpdateFactory.FromJson(ProjectCurrentStateJson);

            var firstTree = ProjectTreeParser.Parse(inputTree);
            await watcher.DataFlow_ChangedAsync(IProjectVersionedValueFactory.Create(Tuple.Create(IProjectTreeSnapshotFactory.Create(firstTree), projectUpdate)));

            var secondTree = ProjectTreeParser.Parse(changedTree);
            await watcher.DataFlow_ChangedAsync(IProjectVersionedValueFactory.Create(Tuple.Create(IProjectTreeSnapshotFactory.Create(secondTree), projectUpdate)));

            // If fileToWatch is null then we expect to not register any filewatcher.
            var fileChangeServiceMock = Mock.Get(fileChangeService);

            fileChangeServiceMock.Verify(s => s.AdviseFileChangeAsync(It.IsAny <string>(), It.IsAny <_VSFILECHANGEFLAGS>(), watcher, CancellationToken.None),
                                         Times.Exactly(numRegisterCalls));
            fileChangeServiceMock.Verify(s => s.UnadviseFileChangeAsync(adviseCookie, CancellationToken.None), Times.Exactly(numUnregisterCalls));
        }
        internal async Task OnProjectChangedAsync_WhenProjectUnloaded_TriggersCancellation(WorkspaceContextHandlerType handlerType)
        {
            var unloadSource = new CancellationTokenSource();
            var tasksService = IUnconfiguredProjectTasksServiceFactory.ImplementUnloadCancellationToken(unloadSource.Token);

            void ApplyProjectBuild(IProjectVersionedValue <IProjectSubscriptionUpdate> _, IProjectBuildSnapshot projectBuildSnapshot, ContextState __, CancellationToken cancellationToken)
            {
                // Unload project
                unloadSource.Cancel();

                cancellationToken.ThrowIfCancellationRequested();
            }

            void ApplyProjectEvaluation(IProjectVersionedValue <IProjectSubscriptionUpdate> _, ContextState __, CancellationToken cancellationToken)
            {
                // Unload project
                unloadSource.Cancel();

                cancellationToken.ThrowIfCancellationRequested();
            }

            var applyChangesToWorkspaceContext = handlerType switch
            {
                WorkspaceContextHandlerType.Evaluation => IApplyChangesToWorkspaceContextFactory.ImplementApplyProjectEvaluationAsync(ApplyProjectEvaluation),
                WorkspaceContextHandlerType.ProjectBuild => IApplyChangesToWorkspaceContextFactory.ImplementApplyProjectBuildAsync(ApplyProjectBuild),
                WorkspaceContextHandlerType.SourceItems => IApplyChangesToWorkspaceContextFactory.ImplementApplySourceItemsAsync(ApplyProjectEvaluation), // ApplyProjectEvaluation works for source items as they share a signature
                _ => throw new NotImplementedException()
            };

            var instance = await CreateInitializedInstanceAsync(tasksService : tasksService, applyChangesToWorkspaceContext : applyChangesToWorkspaceContext);

            var update = IProjectVersionedValueFactory.Create <(ConfiguredProject, IProjectSubscriptionUpdate, IProjectBuildSnapshot)>((default !, default !, Mock.Of <IProjectBuildSnapshot>()));
        internal async Task OnProjectChangedAsync_WhenProjectUnloaded_TriggersCancellation()
        {
            var unloadSource = new CancellationTokenSource();

            var instance = await CreateInitializedInstanceAsync(
                tasksService : IUnconfiguredProjectTasksServiceFactory.ImplementUnloadCancellationToken(unloadSource.Token));

            var registration            = IDataProgressTrackerServiceRegistrationFactory.Create();
            var activeConfiguredProject = ConfiguredProjectFactory.Create();
            var update = IProjectVersionedValueFactory.CreateEmpty();

            await Assert.ThrowsAsync <OperationCanceledException>(() =>
            {
                return(instance.OnProjectChangedAsync(
                           registration,
                           activeConfiguredProject,
                           update,
                           hasChange: _ => true,
                           applyFunc: (_, _, _, token) =>
                {
                    // Simulate project unload during callback
                    unloadSource.Cancel();

                    token.ThrowIfCancellationRequested();
                }));
            });
        }
Exemple #5
0
        public async Task WhenBaseIntermediateOutputPathNotSet_DoesNotAttemptToAdviseFileChange()
        {
            var fileChangeService = IVsFileChangeExFactory.CreateWithAdviseUnadviseFileChange(100);

            var tasksService = IUnconfiguredProjectTasksServiceFactory.ImplementLoadedProjectAsync <ConfiguredProject>(t => t());

            using var watcher = new ProjectAssetFileWatcherInstance(
                      IVsServiceFactory.Create <SVsFileChangeEx, IVsAsyncFileChangeEx>(fileChangeService),
                      IProjectTreeProviderFactory.Create(),
                      IUnconfiguredProjectCommonServicesFactory.Create(threadingService: IProjectThreadingServiceFactory.Create()),
                      tasksService,
                      IActiveConfiguredProjectSubscriptionServiceFactory.Create());
            var tree          = ProjectTreeParser.Parse(@"Root (flags: {ProjectRoot}), FilePath: ""C:\Foo\foo.proj""");
            var projectUpdate = IProjectSubscriptionUpdateFactory.FromJson(@"{
    ""CurrentState"": {
        ""ConfigurationGeneral"": {
            ""Properties"": {
               ""MSBuildProjectFullPath"": ""C:\\Foo\\foo.proj""
            }
        }
    }
}");

            await watcher.InitializeAsync();

            await watcher.DataFlow_ChangedAsync(IProjectVersionedValueFactory.Create(Tuple.Create(IProjectTreeSnapshotFactory.Create(tree), projectUpdate)));

            var fileChangeServiceMock = Mock.Get(fileChangeService);

            fileChangeServiceMock.Verify(s => s.AdviseFileChangeAsync(It.IsAny <string>(), It.IsAny <_VSFILECHANGEFLAGS>(), watcher, CancellationToken.None),
                                         Times.Never());
        }
        [InlineData(false)]     // Project Build
        public async Task OnProjectChangedAsync_WhenProjectUnloaded_TriggersCancellation(bool evaluation)
        {
            var unloadSource = new CancellationTokenSource();
            var tasksService = IUnconfiguredProjectTasksServiceFactory.ImplementUnloadCancellationToken(unloadSource.Token);

            void ApplyProjectBuild(IProjectVersionedValue <IProjectSubscriptionUpdate> _, IProjectBuildSnapshot projectBuildSnapshot, ContextState __, CancellationToken cancellationToken)
            {
                // Unload project
                unloadSource.Cancel();

                cancellationToken.ThrowIfCancellationRequested();
            }

            void ApplyProjectEvaluation(IProjectVersionedValue <IProjectSubscriptionUpdate> _, ContextState __, CancellationToken cancellationToken)
            {
                // Unload project
                unloadSource.Cancel();

                cancellationToken.ThrowIfCancellationRequested();
            }

            var applyChangesToWorkspaceContext = evaluation ? IApplyChangesToWorkspaceContextFactory.ImplementApplyProjectEvaluationAsync(ApplyProjectEvaluation) : IApplyChangesToWorkspaceContextFactory.ImplementApplyProjectBuildAsync(ApplyProjectBuild);

            var instance = await CreateInitializedInstanceAsync(tasksService : tasksService, applyChangesToWorkspaceContext : applyChangesToWorkspaceContext);

            var update = IProjectVersionedValueFactory.Create <(ConfiguredProject, IProjectSubscriptionUpdate, IProjectBuildSnapshot)>(default);
Exemple #7
0
        public async Task VerifyFileWatcherRegistrationOnTreeChange(string inputTree, string changedTree, int numRegisterCalls, int numUnregisterCalls)
        {
            var  spMock            = new IAsyncServiceProviderMoq();
            uint adviseCookie      = 100;
            var  fileChangeService = IVsFileChangeExFactory.CreateWithAdviseUnadviseFileChange(adviseCookie);

            spMock.AddService(typeof(SVsFileChangeEx), fileChangeService);
            var tasksService = IUnconfiguredProjectTasksServiceFactory.ImplementLoadedProjectAsync <ConfiguredProject>(t => t());

            var watcher = new ProjectAssetFileWatcher(spMock,
                                                      IProjectTreeProviderFactory.Create(),
                                                      IUnconfiguredProjectCommonServicesFactory.Create(threadingService: new IProjectThreadingServiceMock()),
                                                      tasksService,
                                                      IActiveConfiguredProjectSubscriptionServiceFactory.Create());

            watcher.Load();
            var projectUpdate = IProjectSubscriptionUpdateFactory.FromJson(ProjectCurrentStateJson);

            var firstTree = ProjectTreeParser.Parse(inputTree);
            await watcher.DataFlow_ChangedAsync(IProjectVersionedValueFactory <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > .Create((Tuple.Create(IProjectTreeSnapshotFactory.Create(firstTree), projectUpdate))));

            var secondTree = ProjectTreeParser.Parse(changedTree);
            await watcher.DataFlow_ChangedAsync(IProjectVersionedValueFactory <Tuple <IProjectTreeSnapshot, IProjectSubscriptionUpdate> > .Create((Tuple.Create(IProjectTreeSnapshotFactory.Create(secondTree), projectUpdate))));

            // If fileToWatch is null then we expect to not register any filewatcher.
            var fileChangeServiceMock = Mock.Get(fileChangeService);

            fileChangeServiceMock.Verify(s => s.AdviseFileChange(It.IsAny <string>(), It.IsAny <uint>(), watcher, out adviseCookie),
                                         Times.Exactly(numRegisterCalls));
            fileChangeServiceMock.Verify(s => s.UnadviseFileChange(adviseCookie), Times.Exactly(numUnregisterCalls));
        }
Exemple #8
0
        private static VsSafeProjectGuidService CreateInstance(IUnconfiguredProjectTasksService tasksService = null)
        {
            var project = UnconfiguredProjectFactory.Create();

            tasksService = tasksService ?? IUnconfiguredProjectTasksServiceFactory.ImplementPrioritizedProjectLoadedInHost(() => Task.CompletedTask);

            return(new VsSafeProjectGuidService(project, tasksService));
        }
Exemple #9
0
        public void GetProjectGuidAsync_WhenProjectAlreadyUnloaded_ReturnsCancelledTask()
        {
            var tasksService = IUnconfiguredProjectTasksServiceFactory.CreateWithUnloadedProject <string>();

            var accessor = CreateInstance(tasksService);

            var result = accessor.GetProjectGuidAsync();

            Assert.True(result.IsCanceled);
        }
        private static SDKVersionTelemetryServiceComponent CreateComponent(Guid guid, Action <TelemetryParameters> onTelemetryLogged, string?version)
        {
            var projectVsServices  = CreateProjectServices(version);
            var projectGuidService = CreateISafeProjectGuidService(guid);
            var telemetryService   = CreateITelemetryService(onTelemetryLogged);
            var unconfiguredProjectTasksService = IUnconfiguredProjectTasksServiceFactory.ImplementLoadedProjectAsync(async t => await t());

            return(new SDKVersionTelemetryServiceComponent(
                       projectVsServices,
                       projectGuidService,
                       telemetryService,
                       unconfiguredProjectTasksService));
        }
Exemple #11
0
        public async Task OpenContextForWriteAsync_WhenProjectUnloaded_ThrowsOperationCanceled()
        {
            var tasksService = IUnconfiguredProjectTasksServiceFactory.ImplementUnloadCancellationToken(new CancellationToken(canceled: true));
            var accessor     = IWorkspaceProjectContextAccessorFactory.Create();
            var workspaceProjectContextProvider = IWorkspaceProjectContextProviderFactory.ImplementCreateProjectContextAsync(accessor);

            var instance = await CreateInitializedInstanceAsync(workspaceProjectContextProvider : workspaceProjectContextProvider, tasksService : tasksService);

            int callCount = 0;

            await Assert.ThrowsAnyAsync <OperationCanceledException>(() =>
            {
                return(instance.OpenContextForWriteAsync(c => { callCount++; return Task.CompletedTask; }));
            });

            Assert.Equal(0, callCount);
        }
Exemple #12
0
        private WorkspaceProjectContextHostInstance CreateInstance(ConfiguredProject project = null, IProjectThreadingService threadingService = null, IUnconfiguredProjectTasksService tasksService = null, IProjectSubscriptionService projectSubscriptionService = null, IActiveEditorContextTracker activeWorkspaceProjectContextTracker = null, IWorkspaceProjectContextProvider workspaceProjectContextProvider = null, IApplyChangesToWorkspaceContext applyChangesToWorkspaceContext = null)
        {
            project                              = project ?? ConfiguredProjectFactory.Create();
            threadingService                     = threadingService ?? IProjectThreadingServiceFactory.Create();
            tasksService                         = tasksService ?? IUnconfiguredProjectTasksServiceFactory.Create();
            projectSubscriptionService           = projectSubscriptionService ?? IProjectSubscriptionServiceFactory.Create();
            activeWorkspaceProjectContextTracker = activeWorkspaceProjectContextTracker ?? IActiveEditorContextTrackerFactory.Create();
            workspaceProjectContextProvider      = workspaceProjectContextProvider ?? IWorkspaceProjectContextProviderFactory.ImplementCreateProjectContextAsync(IWorkspaceProjectContextAccessorFactory.Create());
            applyChangesToWorkspaceContext       = applyChangesToWorkspaceContext ?? IApplyChangesToWorkspaceContextFactory.Create();

            return(new WorkspaceProjectContextHostInstance(project,
                                                           threadingService,
                                                           tasksService,
                                                           projectSubscriptionService,
                                                           workspaceProjectContextProvider,
                                                           activeWorkspaceProjectContextTracker,
                                                           ExportFactoryFactory.ImplementCreateValueWithAutoDispose(() => applyChangesToWorkspaceContext)));
        }
Exemple #13
0
        public async Task GetProjectGuidAsync_WhenProjectUnloads_CancelsTask()
        {
            var projectUnloaded = new TaskCompletionSource <object>();
            var tasksService    = IUnconfiguredProjectTasksServiceFactory.ImplementPrioritizedProjectLoadedInHost(() => projectUnloaded.Task);

            var accessor = CreateInstance(tasksService);

            var result = accessor.GetProjectGuidAsync();

            Assert.False(result.IsCanceled);

            // Now "unload" the project
            projectUnloaded.SetCanceled();

            await Assert.ThrowsAnyAsync <OperationCanceledException>(() =>
            {
                return(result);
            });
        }
        private static StartupProjectRegistrar CreateInstance(
            IVsStartupProjectsListService?vsStartupProjectsListService = null,
            IProjectThreadingService?threadingService  = null,
            ISafeProjectGuidService?projectGuidService = null,
            IActiveConfiguredProjectSubscriptionService?projectSubscriptionService = null,
            IActiveConfiguredValues <IDebugLaunchProvider>?launchProviders         = null)
        {
            var project  = UnconfiguredProjectFactory.Create();
            var instance = new StartupProjectRegistrar(
                project,
                IUnconfiguredProjectTasksServiceFactory.Create(),
                IVsServiceFactory.Create <SVsStartupProjectsListService, IVsStartupProjectsListService?>(vsStartupProjectsListService !),
                threadingService ?? IProjectThreadingServiceFactory.Create(),
                projectGuidService ?? ISafeProjectGuidServiceFactory.ImplementGetProjectGuidAsync(Guid.NewGuid()),
                projectSubscriptionService ?? IActiveConfiguredProjectSubscriptionServiceFactory.Create(),
                launchProviders !);

            return(instance);
        }
Exemple #15
0
        public async Task VerifyFileWatcherRegistration(string inputTree, string fileToWatch)
        {
            uint adviseCookie      = 100;
            var  fileChangeService = IVsFileChangeExFactory.CreateWithAdviseUnadviseFileChange(adviseCookie);

            var tasksService = IUnconfiguredProjectTasksServiceFactory.ImplementLoadedProjectAsync <ConfiguredProject>(t => t());

            using (var watcher = new ProjectAssetFileWatcher(IVsServiceFactory.Create <SVsFileChangeEx, Shell.IVsAsyncFileChangeEx>(fileChangeService), IProjectTreeProviderFactory.Create(), IUnconfiguredProjectCommonServicesFactory.Create(threadingService: IProjectThreadingServiceFactory.Create()), tasksService, IActiveConfiguredProjectSubscriptionServiceFactory.Create()))
            {
                var tree          = ProjectTreeParser.Parse(inputTree);
                var projectUpdate = IProjectSubscriptionUpdateFactory.FromJson(ProjectCurrentStateJson);
                watcher.Load();
                await watcher.DataFlow_ChangedAsync(IProjectVersionedValueFactory.Create(Tuple.Create(IProjectTreeSnapshotFactory.Create(tree), projectUpdate)));

                // If fileToWatch is null then we expect to not register any filewatcher.
                var times = fileToWatch == null?Times.Never() : Times.Once();

                Mock.Get(fileChangeService).Verify(s => s.AdviseFileChangeAsync(fileToWatch ?? It.IsAny <string>(), It.IsAny <_VSFILECHANGEFLAGS>(), watcher, CancellationToken.None), times);
            }
        }
Exemple #16
0
        internal async Task RenameAsync(string sourceCode, string oldFilePath, string newFilePath, IUserNotificationServices userNotificationServices, IRoslynServices roslynServices, IVsOnlineServices vsOnlineServices, string language)
        {
            using var ws = new AdhocWorkspace();
            ws.AddSolution(InitializeWorkspace(ProjectId.CreateNewId(), newFilePath, sourceCode, language));

            var unconfiguredProject = UnconfiguredProjectFactory.Create(filePath: $@"C:\project1.{ProjectFileExtension}");
            var projectServices     = IUnconfiguredProjectVsServicesFactory.Implement(
                threadingServiceCreator: () => IProjectThreadingServiceFactory.Create(),
                unconfiguredProjectCreator: () => unconfiguredProject);
            var unconfiguredProjectTasksService = IUnconfiguredProjectTasksServiceFactory.Create();
            var environmentOptionsFactory       = IEnvironmentOptionsFactory.Implement((string category, string page, string property, bool defaultValue) => { return(true); });
            var waitIndicator         = (new Mock <IWaitIndicator>()).Object;
            var refactorNotifyService = (new Mock <IRefactorNotifyService>()).Object;

            var dte = IVsUIServiceFactory.Create <Shell.Interop.SDTE, EnvDTE.DTE>(null !);

            var renamer = new Renamer(projectServices, unconfiguredProjectTasksService, ws, dte, environmentOptionsFactory, userNotificationServices, roslynServices, waitIndicator, refactorNotifyService, vsOnlineServices);
            await renamer.HandleRenameAsync(oldFilePath, newFilePath)
            .TimeoutAfter(TimeSpan.FromSeconds(1));
        }
        private static WorkspaceProjectContextHostInstance CreateInstance(ConfiguredProject?project = null, IProjectThreadingService?threadingService = null, IUnconfiguredProjectTasksService?tasksService = null, IProjectSubscriptionService?projectSubscriptionService = null, IActiveEditorContextTracker?activeWorkspaceProjectContextTracker = null, IWorkspaceProjectContextProvider?workspaceProjectContextProvider = null, IApplyChangesToWorkspaceContext?applyChangesToWorkspaceContext = null)
        {
            project ??= ConfiguredProjectFactory.Create();
            threadingService ??= IProjectThreadingServiceFactory.Create();
            tasksService ??= IUnconfiguredProjectTasksServiceFactory.Create();
            projectSubscriptionService ??= IProjectSubscriptionServiceFactory.Create();
            activeWorkspaceProjectContextTracker ??= IActiveEditorContextTrackerFactory.Create();
            workspaceProjectContextProvider ??= IWorkspaceProjectContextProviderFactory.ImplementCreateProjectContextAsync(IWorkspaceProjectContextAccessorFactory.Create());
            applyChangesToWorkspaceContext ??= IApplyChangesToWorkspaceContextFactory.Create();
            IDataProgressTrackerService dataProgressTrackerService = IDataProgressTrackerServiceFactory.Create();

            return(new WorkspaceProjectContextHostInstance(project,
                                                           threadingService,
                                                           tasksService,
                                                           projectSubscriptionService,
                                                           workspaceProjectContextProvider,
                                                           activeWorkspaceProjectContextTracker,
                                                           ExportFactoryFactory.ImplementCreateValueWithAutoDispose(() => applyChangesToWorkspaceContext),
                                                           dataProgressTrackerService));
        }
Exemple #18
0
        [InlineData(false)]     // Project Build
        public async Task OnProjectChangedAsync_WhenProjectUnloaded_TriggersCancellation(bool evaluation)
        {
            var unloadSource = new CancellationTokenSource();
            var tasksService = IUnconfiguredProjectTasksServiceFactory.ImplementUnloadCancellationToken(unloadSource.Token);

            void applyChanges(IProjectVersionedValue <IProjectSubscriptionUpdate> _, bool __, CancellationToken cancellationToken)
            {
                // Unload project
                unloadSource.Cancel();

                cancellationToken.ThrowIfCancellationRequested();
            }

            var applyChangesToWorkspaceContext = evaluation ? IApplyChangesToWorkspaceContextFactory.ImplementApplyProjectEvaluationAsync(applyChanges) : IApplyChangesToWorkspaceContextFactory.ImplementApplyProjectBuildAsync(applyChanges);

            var instance = await CreateInitializedInstanceAsync(tasksService : tasksService, applyChangesToWorkspaceContext : applyChangesToWorkspaceContext);

            var update = IProjectVersionedValueFactory.CreateEmpty();
            await Assert.ThrowsAsync <OperationCanceledException>(() =>
            {
                return(instance.OnProjectChangedAsync(update, evaluation));
            });
        }
        public async Task WhenProjectUnloading_DoesNotLoadConfiguredProject()
        {
            var tasksService      = IUnconfiguredProjectTasksServiceFactory.CreateWithUnloadedProject <ConfiguredProject>();
            var configuredProject = ConfiguredProjectFactory.Create();

            int callCount = 0;
            UnconfiguredProject project = UnconfiguredProjectFactory.ImplementLoadConfiguredProjectAsync(configuration =>
            {
                callCount++;
                return(Task.FromResult(configuredProject));
            });

            var loader = CreateInstance(project, tasksService, out ProjectValueDataSource <IConfigurationGroup <ProjectConfiguration> > source);
            await loader.InitializeAsync();

            var configurationGroups = IConfigurationGroupFactory.CreateFromConfigurationNames("Debug|AnyCPU");

            // Change the active configurations
            await source.SendAndCompleteAsync(configurationGroups, loader.TargetBlock);

            // Should not be listening
            Assert.Equal(0, callCount);
        }
        private static ActiveConfiguredProjectsLoader CreateInstance(UnconfiguredProject project, IActiveConfigurationGroupService activeConfigurationGroupService, IUnconfiguredProjectTasksService?tasksService)
        {
            tasksService ??= IUnconfiguredProjectTasksServiceFactory.ImplementLoadedProjectAsync <ConfiguredProject>(t => t());

            return(new ActiveConfiguredProjectsLoader(project, activeConfigurationGroupService, tasksService));
        }