From cb796ac08c6b5e49ad171a455226a0a03b0976ed Mon Sep 17 00:00:00 2001 From: Lluis Sanchez Date: Mon, 18 Sep 2017 15:23:48 +0200 Subject: Fix parallel builds Also added unit test --- .../RemoteBuildEngineManager.cs | 8 ++-- .../MonoDevelop.Projects/Project.cs | 2 +- .../MonoDevelop.Projects/BuilderManagerTests.cs | 47 ++++++++++++++++++++++ .../builder-manager-tests/Dep1/Dep1.csproj | 37 +++++++++++++++++ .../builder-manager-tests/Dep1/MyClass.cs | 10 +++++ .../builder-manager-tests/Dep2/Dep2.csproj | 37 +++++++++++++++++ .../builder-manager-tests/Dep2/MyClass.cs | 10 +++++ .../builder-manager-tests/DepMain/DepMain.csproj | 46 +++++++++++++++++++++ .../builder-manager-tests/DepMain/MyClass.cs | 10 +++++ .../builder-manager-tests.sln | 18 +++++++++ 10 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 main/tests/test-projects/builder-manager-tests/Dep1/Dep1.csproj create mode 100644 main/tests/test-projects/builder-manager-tests/Dep1/MyClass.cs create mode 100644 main/tests/test-projects/builder-manager-tests/Dep2/Dep2.csproj create mode 100644 main/tests/test-projects/builder-manager-tests/Dep2/MyClass.cs create mode 100644 main/tests/test-projects/builder-manager-tests/DepMain/DepMain.csproj create mode 100644 main/tests/test-projects/builder-manager-tests/DepMain/MyClass.cs (limited to 'main') diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteBuildEngineManager.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteBuildEngineManager.cs index b024f9b48e..2c28218fa8 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteBuildEngineManager.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/RemoteBuildEngineManager.cs @@ -172,21 +172,21 @@ namespace MonoDevelop.Projects.MSBuild // Find builders which are not being shut down - var candiateBuilders = builders.GetBuilders (builderKey).Where (b => !b.IsShuttingDown); + var candiateBuilders = builders.GetBuilders (builderKey).Where (b => !b.IsShuttingDown && (!b.IsBusy || allowBusy)); if (buildSessionId != null) { - // Look for a builder that already started the session, no matter if the builder is busy or not. + // Look for a builder that already started the session. // If there isn't one, pick builders which don't have any session assigned, so a new one // can be started. var sessionBuilders = candiateBuilders.Where (b => b.BuildSessionId == buildSessionId); if (!sessionBuilders.Any ()) - sessionBuilders = candiateBuilders.Where (b => b.BuildSessionId == null && (!b.IsBusy || allowBusy)); + sessionBuilders = candiateBuilders.Where (b => b.BuildSessionId == null); candiateBuilders = sessionBuilders; } else // Pick builders which are not bound to any session - candiateBuilders = candiateBuilders.Where (b => b.BuildSessionId == null && (!b.IsBusy || allowBusy)); + candiateBuilders = candiateBuilders.Where (b => b.BuildSessionId == null); // Prefer non-busy builders diff --git a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs index 0e8297e46f..f9ac9372f0 100644 --- a/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs +++ b/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs @@ -1228,7 +1228,7 @@ namespace MonoDevelop.Projects foreach (var err in result.Errors) { FilePath file = null; if (err.File != null) - file = Path.Combine (Path.GetDirectoryName (err.ProjectFile), err.File); + file = Path.Combine (Path.GetDirectoryName (err.ProjectFile ?? ItemDirectory.ToString ()), err.File); br.Append (new BuildError (file, err.LineNumber, err.ColumnNumber, err.Code, err.Message) { Subcategory = err.Subcategory, diff --git a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/BuilderManagerTests.cs b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/BuilderManagerTests.cs index f946e326a0..fdfdd35b2b 100644 --- a/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/BuilderManagerTests.cs +++ b/main/tests/MonoDevelop.Core.Tests/MonoDevelop.Projects/BuilderManagerTests.cs @@ -556,6 +556,53 @@ namespace MonoDevelop.Projects } } + [Test] + public async Task ParallelBuilds () + { + // Check that the project system can start two builds in parallel. + + await RemoteBuildEngineManager.RecycleAllBuilders (); + Assert.AreEqual (0, RemoteBuildEngineManager.ActiveEnginesCount); + + var currentSetting = Runtime.Preferences.ParallelBuild.Value; + try { + Runtime.Preferences.ParallelBuild.Set (true); + + FilePath solFile = Util.GetSampleProject ("builder-manager-tests", "builder-manager-tests.sln"); + using (var sol = (Solution)await Services.ProjectService.ReadWorkspaceItem (Util.GetMonitor (), solFile)) { + + // DepMain depends on both Dep1 and Dep2. + + var demMain = sol.Items.FirstOrDefault (p => p.Name == "DepMain"); + var dep1 = sol.Items.FirstOrDefault (p => p.Name == "Dep1"); + var dep2 = sol.Items.FirstOrDefault (p => p.Name == "Dep2"); + + InitBuildSyncEvent (dep1); + InitBuildSyncEvent (dep2); + + // Start the build + var build1 = demMain.Build (Util.GetMonitor (), sol.Configurations [0].Selector, true); + + // Wait for sync signal from projects Dep1 and Dep2, which will mean that + // both projects started building in parallel + + var syncAll = Task.WhenAll (WaitForBuildSyncEvent (dep1), WaitForBuildSyncEvent (dep2)); + if (await Task.WhenAny (syncAll, Task.Delay (5000)) != syncAll) + Assert.Fail ("Not all builds were started"); + + // Finish the build + SignalBuildToContinue (dep1); + SignalBuildToContinue (dep2); + + if (await Task.WhenAny (build1, Task.Delay (5000)) != build1) + Assert.Fail ("Build did not end in time"); + + Assert.AreEqual (0, build1.Result.ErrorCount); + } + } finally { + Runtime.Preferences.ParallelBuild.Set (currentSetting); + } + } void InitBuildSyncEvent (SolutionItem p) { var file = p.FileName.ParentDirectory.Combine ("sync-event"); diff --git a/main/tests/test-projects/builder-manager-tests/Dep1/Dep1.csproj b/main/tests/test-projects/builder-manager-tests/Dep1/Dep1.csproj new file mode 100644 index 0000000000..eeeeac2bfc --- /dev/null +++ b/main/tests/test-projects/builder-manager-tests/Dep1/Dep1.csproj @@ -0,0 +1,37 @@ + + + + + Debug + AnyCPU + {B515C1C3-9897-45FE-B350-037EECD0BDC7} + Library + Dep1 + Dep1 + v4.6.1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + true + bin\Release + prompt + 4 + false + + + + + + + + + \ No newline at end of file diff --git a/main/tests/test-projects/builder-manager-tests/Dep1/MyClass.cs b/main/tests/test-projects/builder-manager-tests/Dep1/MyClass.cs new file mode 100644 index 0000000000..7513c54b2a --- /dev/null +++ b/main/tests/test-projects/builder-manager-tests/Dep1/MyClass.cs @@ -0,0 +1,10 @@ +using System; +namespace Dep1 +{ + public class MyClass + { + public MyClass() + { + } + } +} diff --git a/main/tests/test-projects/builder-manager-tests/Dep2/Dep2.csproj b/main/tests/test-projects/builder-manager-tests/Dep2/Dep2.csproj new file mode 100644 index 0000000000..3307066845 --- /dev/null +++ b/main/tests/test-projects/builder-manager-tests/Dep2/Dep2.csproj @@ -0,0 +1,37 @@ + + + + + Debug + AnyCPU + {99329AC5-674A-4475-9431-43CAC8ED1CBF} + Library + Dep2 + Dep2 + v4.6.1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + true + bin\Release + prompt + 4 + false + + + + + + + + + \ No newline at end of file diff --git a/main/tests/test-projects/builder-manager-tests/Dep2/MyClass.cs b/main/tests/test-projects/builder-manager-tests/Dep2/MyClass.cs new file mode 100644 index 0000000000..b93930601e --- /dev/null +++ b/main/tests/test-projects/builder-manager-tests/Dep2/MyClass.cs @@ -0,0 +1,10 @@ +using System; +namespace Dep2 +{ + public class MyClass + { + public MyClass() + { + } + } +} diff --git a/main/tests/test-projects/builder-manager-tests/DepMain/DepMain.csproj b/main/tests/test-projects/builder-manager-tests/DepMain/DepMain.csproj new file mode 100644 index 0000000000..318f73a010 --- /dev/null +++ b/main/tests/test-projects/builder-manager-tests/DepMain/DepMain.csproj @@ -0,0 +1,46 @@ + + + + Debug + AnyCPU + {12D301E7-3AAC-4375-A6DB-E3755E9892E4} + Library + DepMain + DepMain + v4.6.1 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + true + bin\Release + prompt + 4 + false + + + + + + + + + + {B515C1C3-9897-45FE-B350-037EECD0BDC7} + Dep1 + + + {99329AC5-674A-4475-9431-43CAC8ED1CBF} + Dep2 + + + + \ No newline at end of file diff --git a/main/tests/test-projects/builder-manager-tests/DepMain/MyClass.cs b/main/tests/test-projects/builder-manager-tests/DepMain/MyClass.cs new file mode 100644 index 0000000000..f6cf0a7afd --- /dev/null +++ b/main/tests/test-projects/builder-manager-tests/DepMain/MyClass.cs @@ -0,0 +1,10 @@ +using System; +namespace DepMain +{ + public class MyClass + { + public MyClass() + { + } + } +} diff --git a/main/tests/test-projects/builder-manager-tests/builder-manager-tests.sln b/main/tests/test-projects/builder-manager-tests/builder-manager-tests.sln index 5f576d53ea..c160279f4a 100644 --- a/main/tests/test-projects/builder-manager-tests/builder-manager-tests.sln +++ b/main/tests/test-projects/builder-manager-tests/builder-manager-tests.sln @@ -7,6 +7,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyncTask", "SyncTask\SyncTa EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyncBuildProject", "TaskTest\SyncBuildProject.csproj", "{441F02A0-E0AC-4E7E-99D9-E6E516D0B35F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dep1", "Dep1\Dep1.csproj", "{B515C1C3-9897-45FE-B350-037EECD0BDC7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dep2", "Dep2\Dep2.csproj", "{99329AC5-674A-4475-9431-43CAC8ED1CBF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DepMain", "DepMain\DepMain.csproj", "{12D301E7-3AAC-4375-A6DB-E3755E9892E4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 @@ -25,5 +31,17 @@ Global {441F02A0-E0AC-4E7E-99D9-E6E516D0B35F}.Debug|x86.Build.0 = Debug|Any CPU {441F02A0-E0AC-4E7E-99D9-E6E516D0B35F}.Release|x86.ActiveCfg = Release|Any CPU {441F02A0-E0AC-4E7E-99D9-E6E516D0B35F}.Release|x86.Build.0 = Release|Any CPU + {B515C1C3-9897-45FE-B350-037EECD0BDC7}.Debug|x86.ActiveCfg = Debug|Any CPU + {B515C1C3-9897-45FE-B350-037EECD0BDC7}.Debug|x86.Build.0 = Debug|Any CPU + {B515C1C3-9897-45FE-B350-037EECD0BDC7}.Release|x86.ActiveCfg = Release|Any CPU + {B515C1C3-9897-45FE-B350-037EECD0BDC7}.Release|x86.Build.0 = Release|Any CPU + {99329AC5-674A-4475-9431-43CAC8ED1CBF}.Debug|x86.ActiveCfg = Debug|Any CPU + {99329AC5-674A-4475-9431-43CAC8ED1CBF}.Debug|x86.Build.0 = Debug|Any CPU + {99329AC5-674A-4475-9431-43CAC8ED1CBF}.Release|x86.ActiveCfg = Release|Any CPU + {99329AC5-674A-4475-9431-43CAC8ED1CBF}.Release|x86.Build.0 = Release|Any CPU + {12D301E7-3AAC-4375-A6DB-E3755E9892E4}.Debug|x86.ActiveCfg = Debug|Any CPU + {12D301E7-3AAC-4375-A6DB-E3755E9892E4}.Debug|x86.Build.0 = Debug|Any CPU + {12D301E7-3AAC-4375-A6DB-E3755E9892E4}.Release|x86.ActiveCfg = Release|Any CPU + {12D301E7-3AAC-4375-A6DB-E3755E9892E4}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection EndGlobal -- cgit v1.2.3