Esempio n. 1
0
        public async Task DisposingProjectDisposesProjectBuilder()
        {
            // When a project is disposed, all project builders should be shut down

            await RemoteBuildEngineManager.RecycleAllBuilders();

            Assert.AreEqual(0, RemoteBuildEngineManager.ActiveEnginesCount);

            FilePath solFile = Util.GetSampleProject("builder-manager-tests", "builder-manager-tests.sln");
            FilePath projectFile;

            using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) {
                var project = (DotNetProject)sol.Items.FirstOrDefault(p => p.Name == "App");
                projectFile = project.FileName;
                await project.GetReferencedAssemblies(sol.Configurations [0].Selector);

                Assert.AreEqual(1, RemoteBuildEngineManager.ActiveEnginesCount);
                Assert.AreEqual(1, await RemoteBuildEngineManager.CountActiveBuildersForProject(project.FileName));

                sol.RootFolder.Items.Remove(project);
                project.Dispose();

                Assert.AreEqual(1, RemoteBuildEngineManager.ActiveEnginesCount);
                Assert.AreEqual(1, RemoteBuildEngineManager.EnginesCount);
                Assert.AreEqual(0, await RemoteBuildEngineManager.CountActiveBuildersForProject(project.FileName));
            }
            Assert.AreEqual(0, await RemoteBuildEngineManager.CountActiveBuildersForProject(projectFile));
            Assert.AreEqual(0, RemoteBuildEngineManager.ActiveEnginesCount);
            Assert.AreEqual(0, RemoteBuildEngineManager.EnginesCount);
        }
Esempio n. 2
0
        public async Task RecycleBuildersIsGraceful()
        {
            // RecycleBuilders can be called in the middle of a build and that should not interrupt
            // the build. Builders will be shut down when the build is finished.

            var currentDelay = RemoteBuildEngineManager.EngineDisposalDelay;

            try {
                RemoteBuildEngineManager.EngineDisposalDelay = 400;

                await RemoteBuildEngineManager.RecycleAllBuilders();

                Assert.AreEqual(0, RemoteBuildEngineManager.ActiveEnginesCount);

                FilePath solFile = Util.GetSampleProject("builder-manager-tests", "builder-manager-tests.sln");
                using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) {
                    var project1 = sol.Items.FirstOrDefault(p => p.Name == "SyncBuildProject");
                    var project2 = sol.Items.FirstOrDefault(p => p.Name == "App");

                    InitBuildSyncEvent(project1);

                    // Start the build
                    var build1 = project1.Build(Util.GetMonitor(), sol.Configurations [0].Selector);

                    // Wait for the build to reach the sync task
                    await WaitForBuildSyncEvent(project1);

                    Assert.AreEqual(1, RemoteBuildEngineManager.ActiveEnginesCount);
                    Assert.AreEqual(0, await RemoteBuildEngineManager.CountActiveBuildersForProject(project2.FileName));

                    // The build is now in progess. Start a new build

                    var build2 = project2.Build(Util.GetMonitor(), sol.Configurations [0].Selector);
                    if (await Task.WhenAny(build2, Task.Delay(5000)) != build2)
                    {
                        Assert.Fail("Build did not start");
                    }

                    // There should be one builder for each build

                    Assert.AreEqual(2, RemoteBuildEngineManager.ActiveEnginesCount);
                    Assert.AreEqual(2, RemoteBuildEngineManager.EnginesCount);

                    // Ask for all active builders to be shut down

                    await RemoteBuildEngineManager.RecycleAllBuilders();

                    // There is a build in progress, so there must still be one engine running

                    Assert.AreEqual(0, RemoteBuildEngineManager.ActiveEnginesCount);
                    Assert.AreEqual(1, RemoteBuildEngineManager.EnginesCount);

                    SignalBuildToContinue(project1);

                    if (await Task.WhenAny(build1, Task.Delay(5000)) != build1)
                    {
                        Assert.Fail("Build did not end in time");
                    }

                    Assert.AreEqual(0, build1.Result.ErrorCount);
                    Assert.AreEqual(0, build2.Result.ErrorCount);

                    // The builder that was running the build and was shutdown should be immediately stopped after build finishes
                    Assert.AreEqual(0, RemoteBuildEngineManager.ActiveEnginesCount);
                    Assert.AreEqual(0, RemoteBuildEngineManager.EnginesCount);
                }
            } finally {
                RemoteBuildEngineManager.EngineDisposalDelay = currentDelay;
            }
        }
Esempio n. 3
0
        public async Task AtLeastOneBuilderPersolution()
        {
            // There should always be at least one builder running per solution,
            // until the solution is explicitly disposed

            var currentDelay = RemoteBuildEngineManager.EngineDisposalDelay;

            try {
                RemoteBuildEngineManager.EngineDisposalDelay = 400;

                await RemoteBuildEngineManager.RecycleAllBuilders();

                Assert.AreEqual(0, RemoteBuildEngineManager.ActiveEnginesCount);

                FilePath solFile = Util.GetSampleProject("builder-manager-tests", "builder-manager-tests.sln");
                using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) {
                    var project1 = sol.Items.FirstOrDefault(p => p.Name == "SyncBuildProject");
                    var project2 = sol.Items.FirstOrDefault(p => p.Name == "App");

                    InitBuildSyncEvent(project1);

                    // Start the build
                    var build1 = project1.Build(Util.GetMonitor(), sol.Configurations [0].Selector);

                    // Wait for the build to reach the sync task
                    await WaitForBuildSyncEvent(project1);

                    Assert.AreEqual(1, RemoteBuildEngineManager.ActiveEnginesCount);
                    Assert.AreEqual(0, await RemoteBuildEngineManager.CountActiveBuildersForProject(project2.FileName));

                    // The build is now in progess. Start a new build

                    var build2 = project2.Build(Util.GetMonitor(), sol.Configurations [0].Selector);

                    if (await Task.WhenAny(build2, Task.Delay(5000)) != build2)
                    {
                        Assert.Fail("Build did not start");
                    }

                    Assert.AreEqual(2, RemoteBuildEngineManager.ActiveEnginesCount);
                    Assert.AreEqual(2, RemoteBuildEngineManager.EnginesCount);
                    Assert.AreEqual(1, await RemoteBuildEngineManager.CountActiveBuildersForProject(project1.FileName));
                    Assert.AreEqual(1, await RemoteBuildEngineManager.CountActiveBuildersForProject(project2.FileName));

                    SignalBuildToContinue(project1);

                    if (await Task.WhenAny(build1, Task.Delay(5000)) != build1)
                    {
                        Assert.Fail("Build did not end in time");
                    }

                    // Build engine disposal delay is set to 400ms, so unused
                    // builders should go away after a 500ms wait.

                    await Task.Delay(500);

                    // There should be at least one builder left

                    Assert.AreEqual(1, RemoteBuildEngineManager.ActiveEnginesCount);
                    Assert.AreEqual(1, RemoteBuildEngineManager.EnginesCount);
                }
            } finally {
                RemoteBuildEngineManager.EngineDisposalDelay = currentDelay;
            }

            // All builders should be gone now
            Assert.AreEqual(0, RemoteBuildEngineManager.ActiveEnginesCount);
            Assert.AreEqual(0, RemoteBuildEngineManager.EnginesCount);
        }
Esempio n. 4
0
        public async Task ExtraBuilderAutoShutdown()
        {
            // When an extra builder is created, it should be shut down when it is
            // not used anymore, after a delay

            var currentDelay = RemoteBuildEngineManager.EngineDisposalDelay;

            try {
                RemoteBuildEngineManager.EngineDisposalDelay = 400;

                await RemoteBuildEngineManager.RecycleAllBuilders();

                Assert.AreEqual(0, RemoteBuildEngineManager.ActiveEnginesCount);

                FilePath solFile = Util.GetSampleProject("builder-manager-tests", "builder-manager-tests.sln");
                using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) {
                    var project1 = sol.Items.FirstOrDefault(p => p.Name == "SyncBuildProject");
                    var project2 = sol.Items.FirstOrDefault(p => p.Name == "App");

                    InitBuildSyncEvent(project1);

                    // Start the build
                    var build1 = project1.Build(Util.GetMonitor(), sol.Configurations [0].Selector);

                    // Wait for the build to reach the sync task
                    await WaitForBuildSyncEvent(project1);

                    Assert.AreEqual(1, RemoteBuildEngineManager.ActiveEnginesCount);
                    Assert.AreEqual(0, await RemoteBuildEngineManager.CountActiveBuildersForProject(project2.FileName));

                    // The build is now in progess. Start a new build

                    var build2 = project2.Build(Util.GetMonitor(), sol.Configurations [0].Selector);
                    if (await Task.WhenAny(build2, Task.Delay(5000)) != build2)
                    {
                        Assert.Fail("Build did not start");
                    }

                    Assert.AreEqual(2, RemoteBuildEngineManager.ActiveEnginesCount);
                    Assert.AreEqual(1, await RemoteBuildEngineManager.CountActiveBuildersForProject(project2.FileName));

                    // Build engine disposal delay is set to 400ms, so it should be gone after waiting the following wait.

                    await Task.Delay(500);

                    // The second builder should now be gone

                    Assert.AreEqual(1, RemoteBuildEngineManager.ActiveEnginesCount);
                    Assert.AreEqual(1, RemoteBuildEngineManager.EnginesCount);
                    Assert.AreEqual(0, await RemoteBuildEngineManager.CountActiveBuildersForProject(project2.FileName));

                    SignalBuildToContinue(project1);

                    if (await Task.WhenAny(build1, Task.Delay(5000)) != build1)
                    {
                        Assert.Fail("Build did not end in time");
                    }
                }
            } finally {
                RemoteBuildEngineManager.EngineDisposalDelay = currentDelay;
            }
        }
Esempio n. 5
0
        public async Task ReloadProject_ProjectDisposedWhilstTargetRunning_AnotherTargetRun()
        {
            // When a long operation is running and a new one is requested, a new builder is created

            await RemoteBuildEngineManager.RecycleAllBuilders();

            Assert.AreEqual(0, RemoteBuildEngineManager.ActiveEnginesCount);

            FilePath solFile = Util.GetSampleProject("builder-manager-tests", "builder-manager-tests.sln");

            using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile)) {
                var project1 = (Project)sol.Items.FirstOrDefault(p => p.Name == "SyncBuildProject");

                InitBuildSyncEvent(project1);

                // Start the build. Use RunTarget to avoid the BindTask which will cancel the build on project dispose.
                var build1 = project1.RunTarget(Util.GetMonitor(), "Build", sol.Configurations [0].Selector);

                // Wait for the build to reach the sync task
                await WaitForBuildSyncEvent(project1);

                // The build is now in progess. Simulate reloading the project.
                using (var project2 = (Project)await sol.RootFolder.ReloadItem(Util.GetMonitor(), project1)) {
                    var builderTask = project2.GetProjectBuilder(CancellationToken.None, null, allowBusy: true);

                    // Allow second build to finish and dispose its project builder. Have to do this here otherwise
                    // GetProjectBuilder will hang waiting for a connection response back after it creates a new
                    // project builder.
                    SignalBuildToContinue(project1);
                    if (await Task.WhenAny(build1, Task.Delay(timeoutMs)) != build1)
                    {
                        Assert.Fail("Build did not end in time");
                    }

                    Assert.AreEqual(0, build1.Result.BuildResult.ErrorCount);

                    using (var builder = await builderTask) {
                        // Sanity check. We should only have one project builder and one build engine.
                        Assert.AreEqual(1, RemoteBuildEngineManager.ActiveEnginesCount);
                        Assert.AreEqual(1, RemoteBuildEngineManager.EnginesCount);
                        Assert.AreEqual(1, await RemoteBuildEngineManager.CountActiveBuildersForProject(project2.FileName));

                        var configs = project2.GetConfigurations(sol.Configurations [0].Selector, false);

                        var build2 = await Task.Run(() => {
                            // Previously this would throw a NullReferenceException since the builder has been disposed
                            // and the engine is null.
                            return(builder.Run(
                                       configs,
                                       new StringWriter(),
                                       new MSBuildLogger(),
                                       MSBuildVerbosity.Quiet,
                                       new [] { "ResolveAssemblyReferences" },
                                       new string [0],
                                       new string [0],
                                       new System.Collections.Generic.Dictionary <string, string> (),
                                       CancellationToken.None));
                        });

                        Assert.AreEqual(0, build2.Errors.Length);
                    }
                }
            }
        }