public void GetTargetListsAggregatesFromMultipleEdges() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, new[] { 2, 3 }, new Dictionary <string, string[]> { { "A", new[] { "B" } } }); CreateProjectFile(env, 2, new[] { 4 }, new Dictionary <string, string[]> { { "B", new[] { "C" } } }); CreateProjectFile(env, 3, new[] { 4 }, new Dictionary <string, string[]> { { "B", new[] { "D" } } }); CreateProjectFile(env, 4); var projectGraph = new ProjectGraph(entryProject.Path); projectGraph.ProjectNodes.Count.ShouldBe(4); IReadOnlyDictionary <ProjectGraphNode, ImmutableList <string> > targetLists = projectGraph.GetTargetLists(new[] { "A" }); targetLists.Count.ShouldBe(projectGraph.ProjectNodes.Count); targetLists[GetNodeForProject(projectGraph, 1)].ShouldBe(new[] { "A" }); targetLists[GetNodeForProject(projectGraph, 2)].ShouldBe(new[] { "B" }); targetLists[GetNodeForProject(projectGraph, 3)].ShouldBe(new[] { "B" }); targetLists[GetNodeForProject(projectGraph, 4)].ShouldBe(new[] { "C", "D" }); // From B => C and B => D } }
public void ConstructWithSameEffectiveProperties() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, new[] { 2, 3 }); env.CreateFile("2.proj", @" <Project> <ItemGroup> <ProjectReference Include=""4.proj"" AdditionalProperties=""Foo=Bar"" /> </ItemGroup> </Project>"); env.CreateFile("3.proj", @" <Project> <ItemGroup> <ProjectReference Include=""4.proj"" GlobalPropertiesToRemove=""DoesNotExist"" /> </ItemGroup> </Project>"); CreateProjectFile(env, 4); ProjectGraph graph = new ProjectGraph( entryProject.Path, new Dictionary <string, string> { { "Foo", "Bar" } }); // Project 4 does not require 2 nodes graph.ProjectNodes.Count.ShouldBe(4); // The project references end up using the same effective properties GetNodeForProject(graph, 2).ProjectReferences.First().ShouldBe(GetNodeForProject(graph, 3).ProjectReferences.First()); } }
public void GetTargetListsDedupesTargets() { var projectReferenceTargets = new Dictionary <string, string[]> { { "A", new[] { "B", "X", "C" } }, { "B", new[] { "X", "Y" } }, { "C", new[] { "X", "Z" } }, }; using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, new[] { 2 }, projectReferenceTargets); CreateProjectFile(env, 2, new[] { 3 }, projectReferenceTargets); CreateProjectFile(env, 3, Array.Empty <int>(), projectReferenceTargets); var projectGraph = new ProjectGraph(entryProject.Path); projectGraph.ProjectNodes.Count.ShouldBe(3); IReadOnlyDictionary <ProjectGraphNode, ImmutableList <string> > targetLists = projectGraph.GetTargetLists(new[] { "A" }); targetLists.Count.ShouldBe(projectGraph.ProjectNodes.Count); targetLists[GetNodeForProject(projectGraph, 1)].ShouldBe(new[] { "A" }); targetLists[GetNodeForProject(projectGraph, 2)].ShouldBe(new[] { "B", "X", "C" }); targetLists[GetNodeForProject(projectGraph, 3)].ShouldBe(new[] { "X", "Y", "Z" }); // Simplified from X, Y, X, Z } }
public void ConstructWithDifferentGlobalProperties() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, new[] { 2, 3 }); env.CreateFile("2.proj", @" <Project> <ItemGroup> <ProjectReference Include=""4.proj"" /> </ItemGroup> </Project>"); env.CreateFile("3.proj", @" <Project> <ItemGroup> <ProjectReference Include=""4.proj"" AdditionalProperties=""A=B"" /> </ItemGroup> </Project>"); CreateProjectFile(env, 4); ProjectGraph graph = new ProjectGraph(entryProject.Path); // Project 4 requires 2 nodes graph.ProjectNodes.Count.ShouldBe(5); // Projects 2 and 3 both reference project 4, but with different properties, so they should not point to the same node. GetNodeForProject(graph, 2).ProjectReferences.First().ShouldNotBe(GetNodeForProject(graph, 3).ProjectReferences.First()); GetNodeForProject(graph, 2).ProjectReferences.First().ProjectInstance.FullPath.ShouldEndWith("4.proj"); GetNodeForProject(graph, 2).ProjectReferences.First().GlobalProperties.ShouldBeEmpty(); GetNodeForProject(graph, 3).ProjectReferences.First().ProjectInstance.FullPath.ShouldEndWith("4.proj"); GetNodeForProject(graph, 3).ProjectReferences.First().GlobalProperties.ShouldNotBeEmpty(); } }
public void GetTargetListsDefaultComplexPropagation() { var projectReferenceTargets = new Dictionary <string, string[]> { { "Build", new[] { "A", ".default" } }, { "X", new[] { "B", ".default" } }, { "Y", new[] { "C", ".default" } }, }; using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, new[] { 2, 3, 4 }, projectReferenceTargets, defaultTargets: null); CreateProjectFile(env, 2, new[] { 5 }, projectReferenceTargets, defaultTargets: null); CreateProjectFile(env, 3, new[] { 6 }, projectReferenceTargets, defaultTargets: "X"); CreateProjectFile(env, 4, new[] { 7 }, projectReferenceTargets, defaultTargets: "Y"); CreateProjectFile(env, 5, defaultTargets: null); CreateProjectFile(env, 6, defaultTargets: null); CreateProjectFile(env, 7, defaultTargets: "Z;W"); var projectGraph = new ProjectGraph(entryProject.Path); projectGraph.ProjectNodes.Count.ShouldBe(7); IReadOnlyDictionary <ProjectGraphNode, ImmutableList <string> > targetLists = projectGraph.GetTargetLists(null); targetLists.Count.ShouldBe(projectGraph.ProjectNodes.Count); targetLists[GetNodeForProject(projectGraph, 1)].ShouldBe(new[] { "Build" }); targetLists[GetNodeForProject(projectGraph, 2)].ShouldBe(new[] { "A", "Build" }); targetLists[GetNodeForProject(projectGraph, 3)].ShouldBe(new[] { "A", "X" }); targetLists[GetNodeForProject(projectGraph, 4)].ShouldBe(new[] { "A", "Y" }); targetLists[GetNodeForProject(projectGraph, 5)].ShouldBe(new[] { "A", "Build" }); targetLists[GetNodeForProject(projectGraph, 6)].ShouldBe(new[] { "B", "Build" }); targetLists[GetNodeForProject(projectGraph, 7)].ShouldBe(new[] { "C", "Z", "W" }); } }
public void GetTargetListsForComplexGraph() { var projectReferenceTargets = new Dictionary <string, string[]> { { "A", new[] { "B" } }, { "B", new[] { "C" } }, { "C", new[] { "D" } }, { "D", new[] { "E" } }, }; using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, new[] { 2, 3, 5 }, projectReferenceTargets); CreateProjectFile(env, 2, new[] { 4, 5 }, projectReferenceTargets); CreateProjectFile(env, 3, new[] { 5, 6 }, projectReferenceTargets); CreateProjectFile(env, 4, new[] { 5 }, projectReferenceTargets); CreateProjectFile(env, 5, new[] { 6 }, projectReferenceTargets); CreateProjectFile(env, 6, Array.Empty <int>(), projectReferenceTargets); var projectGraph = new ProjectGraph(entryProject.Path); projectGraph.ProjectNodes.Count.ShouldBe(6); IReadOnlyDictionary <ProjectGraphNode, ImmutableList <string> > targetLists = projectGraph.GetTargetLists(new[] { "A" }); targetLists.Count.ShouldBe(projectGraph.ProjectNodes.Count); targetLists[GetNodeForProject(projectGraph, 1)].ShouldBe(new[] { "A" }); targetLists[GetNodeForProject(projectGraph, 2)].ShouldBe(new[] { "B" }); targetLists[GetNodeForProject(projectGraph, 3)].ShouldBe(new[] { "B" }); targetLists[GetNodeForProject(projectGraph, 4)].ShouldBe(new[] { "C" }); targetLists[GetNodeForProject(projectGraph, 5)].ShouldBe(new[] { "B", "C", "D" }); targetLists[GetNodeForProject(projectGraph, 6)].ShouldBe(new[] { "C", "D", "E" }); } }
public void LogsErrorIfReadOnlyFileCannotBeOverwitten() { using (TestEnvironment testEnvironment = TestEnvironment.Create()) { TransientTestFolder source = testEnvironment.CreateFolder(createFolder: true); TransientTestFolder destination = testEnvironment.CreateFolder(createFolder: false); TransientTestFile file1 = testEnvironment.CreateFile(source, "D6DFD219DACE48F8B86EFCDF98433333.txt", "file1"); new FileInfo(file1.Path).IsReadOnly = true; TransientZipArchive zipArchive = TransientZipArchive.Create(source, destination); Unzip unzip = new Unzip { BuildEngine = _mockEngine, DestinationFolder = new TaskItem(source.Path), OverwriteReadOnlyFiles = false, SkipUnchangedFiles = false, SourceFiles = new ITaskItem[] { new TaskItem(zipArchive.Path) } }; unzip.Execute().ShouldBeFalse(() => _mockEngine.Log); _mockEngine.Log.ShouldContain($"D6DFD219DACE48F8B86EFCDF98433333.txt{ (NativeMethodsShared.IsMono ? "\"" : "'") } is denied", () => _mockEngine.Log); } }
public void TaskNodesDieAfterBuild() { using (TestEnvironment env = TestEnvironment.Create()) { string pidTaskProject = $@" <Project> <UsingTask TaskName=""ProcessIdTask"" AssemblyName=""net.r_eg.IeXod.Engine.UnitTests"" TaskFactory=""TaskHostFactory"" /> <Target Name='AccessPID'> <ProcessIdTask> <Output PropertyName=""PID"" TaskParameter=""Pid"" /> </ProcessIdTask> </Target> </Project>"; TransientTestFile project = env.CreateFile("testProject.csproj", pidTaskProject); ProjectInstance projectInstance = new ProjectInstance(project.Path); projectInstance.Build().ShouldBeTrue(); string processId = projectInstance.GetPropertyValue("PID"); string.IsNullOrEmpty(processId).ShouldBeFalse(); Int32.TryParse(processId, out int pid).ShouldBeTrue(); Process.GetCurrentProcess().Id.ShouldNotBe <int>(pid); try { Process taskHostNode = Process.GetProcessById(pid); taskHostNode.WaitForExit(2000).ShouldBeTrue(); } // We expect the TaskHostNode to exit quickly. If it exits before Process.GetProcessById, it will throw an ArgumentException. catch (ArgumentException e) { e.Message.ShouldBe($"Process with an Id of {pid} is not running."); } } }
public void FailsToResolve() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, extraContent: @"<PropertyGroup> <EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution> <Platform>x86</Platform> <PlatformLookupTable>AnyCPU=x64</PlatformLookupTable> </PropertyGroup> <ItemGroup> <ProjectReference Include=""$(MSBuildThisFileDirectory)2.proj"" > </ProjectReference> </ItemGroup>"); var proj2 = env.CreateFile("2.proj", @" <Project> <PropertyGroup> <Platforms>x64</Platforms> </PropertyGroup> </Project>"); ProjectGraph graph = new ProjectGraph(entryProject.Path); // Here we are checking if platform is defined. in this case it should not be since Platorm would be set to the value this project defaults as // in order to avoid dual build errors we remove platform in order to avoid the edge case where a project has global platform set and does not have global platform set // yet still default to the same platform. GetFirstNodeWithProjectNumber(graph, 2).ProjectInstance.GlobalProperties.ContainsKey("Platform").ShouldBeFalse(); } }
public void TestPrecomputedCacheOutput() { using (TestEnvironment env = TestEnvironment.Create()) { TransientTestFile standardCache = env.CreateFile(".cache"); ResolveAssemblyReference t = new ResolveAssemblyReference() { _cache = new SystemState() }; t._cache.instanceLocalFileStateCache = new Dictionary <string, SystemState.FileState>() { { Path.Combine(standardCache.Path, "assembly1"), new SystemState.FileState(DateTime.Now) }, { Path.Combine(standardCache.Path, "assembly2"), new SystemState.FileState(DateTime.Now) { Assembly = new Shared.AssemblyNameExtension("hi") } } }; t._cache.IsDirty = true; t.StateFile = standardCache.Path; t.WriteStateFile(); int standardLen = File.ReadAllText(standardCache.Path).Length; File.Delete(standardCache.Path); standardLen.ShouldBeGreaterThan(0); string precomputedPath = standardCache.Path + ".cache"; t._cache.IsDirty = true; t.AssemblyInformationCacheOutputPath = precomputedPath; t.WriteStateFile(); File.Exists(standardCache.Path).ShouldBeFalse(); int preLen = File.ReadAllText(precomputedPath).Length; preLen.ShouldBeGreaterThan(0); preLen.ShouldNotBe(standardLen); } }
public void ResolvesViaSamePlatform() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, extraContent: @"<PropertyGroup> <EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution> <Platform>x86</Platform> <PlatformLookupTable>x86=AnyCPU</PlatformLookupTable> </PropertyGroup> <ItemGroup> <ProjectReference Include=""$(MSBuildThisFileDirectory)2.proj"" > </ProjectReference> </ItemGroup>"); var proj2 = env.CreateFile("2.proj", @" <Project> <PropertyGroup> <PlatformLookupTable></PlatformLookupTable> <Platforms>x86;x64;AnyCPU</Platforms> </PropertyGroup> </Project>"); ProjectGraph graph = new ProjectGraph(entryProject.Path); GetFirstNodeWithProjectNumber(graph, 2).ProjectInstance.GlobalProperties["Platform"].ShouldBe("x86"); } }
public void CanOverwriteReadOnlyFile() { using (TestEnvironment testEnvironment = TestEnvironment.Create()) { TransientTestFolder source = testEnvironment.CreateFolder(createFolder: true); TransientTestFolder destination = testEnvironment.CreateFolder(createFolder: false); TransientTestFile file1 = testEnvironment.CreateFile(source, "638AF4AE88A146E09CB69FE1CA7083DC.txt", "file1"); new FileInfo(file1.Path).IsReadOnly = true; TransientZipArchive zipArchive = TransientZipArchive.Create(source, destination); Unzip unzip = new Unzip { BuildEngine = _mockEngine, DestinationFolder = new TaskItem(source.Path), OverwriteReadOnlyFiles = true, SkipUnchangedFiles = false, SourceFiles = new ITaskItem[] { new TaskItem(zipArchive.Path) } }; unzip.Execute().ShouldBeTrue(() => _mockEngine.Log); _mockEngine.Log.ShouldContain("638AF4AE88A146E09CB69FE1CA7083DC", () => _mockEngine.Log); } }
public void SdkReferenceIsCorrect_CreatedFromOnDiskProject_SdkAttributeSet() { using (TestEnvironment testEnvironment = TestEnvironment.Create()) { TransientTestFile projectFile = testEnvironment.CreateFile( "test.proj", @" <Project> <Import Project=""Sdk.props"" Sdk=""My.Sdk"" /> </Project>"); ProjectRootElement rootElement = ProjectRootElement.Open(projectFile.Path); ProjectImportElement importElement = rootElement.Imports.First(); importElement.SdkReference.Name.ShouldBe("My.Sdk"); importElement.SdkReference.Version.ShouldBeNull(); importElement.SdkReference.MinimumVersion.ShouldBeNull(); SetPropertyAndExpectProjectXmlChangedEventToNotFire(rootElement, () => importElement.Sdk = "My.Sdk"); SetPropertyAndExpectProjectXmlChangedEventToFire(rootElement, () => importElement.Version = "1.2.0", "Set Import Version 1.2.0"); SetPropertyAndExpectProjectXmlChangedEventToNotFire(rootElement, () => importElement.Version = "1.2.0"); importElement.SdkReference.Name.ShouldBe("My.Sdk"); importElement.SdkReference.Version.ShouldBe("1.2.0"); importElement.SdkReference.MinimumVersion.ShouldBeNull(); SetPropertyAndExpectProjectXmlChangedEventToFire(rootElement, () => importElement.MinimumVersion = "1.0.0", "Set Import Minimum Version 1.0.0"); SetPropertyAndExpectProjectXmlChangedEventToNotFire(rootElement, () => importElement.MinimumVersion = "1.0.0"); importElement.SdkReference.Name.ShouldBe("My.Sdk"); importElement.SdkReference.Version.ShouldBe("1.2.0"); importElement.SdkReference.MinimumVersion.ShouldBe("1.0.0"); } }
public void TestOldNuget() { string msbuildExePath = Path.GetDirectoryName(RunnerUtilities.PathToCurrentlyRunningMsBuildExe); using TestEnvironment testEnvironment = TestEnvironment.Create(); TransientTestFolder folder = testEnvironment.CreateFolder(createFolder: true); // The content of the solution isn't known to matter, but having a custom solution makes it easier to add requirements should they become evident. TransientTestFile sln = testEnvironment.CreateFile(folder, "test.sln", @" Microsoft Visual Studio Solution File, Format Version 12.00 \# Visual Studio 15 VisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0 Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal "); RunnerUtilities.RunProcessAndGetOutput(Path.Combine(msbuildExePath, "nuget", "NuGet.exe"), "restore " + sln.Path + " -MSBuildPath \"" + msbuildExePath + "\"", out bool success, outputHelper: _output); success.ShouldBeTrue(); }
public void ParseSolutionFilter() { using (TestEnvironment testEnvironment = TestEnvironment.Create()) { TransientTestFolder folder = testEnvironment.CreateFolder(createFolder: true); TransientTestFolder src = testEnvironment.CreateFolder(Path.Combine(folder.Path, "src"), createFolder: true); TransientTestFile microsoftBuild = testEnvironment.CreateFile(src, "Microsoft.Build.csproj"); TransientTestFile msbuild = testEnvironment.CreateFile(src, "MSBuild.csproj"); TransientTestFile commandLineUnitTests = testEnvironment.CreateFile(src, "Microsoft.Build.CommandLine.UnitTests.csproj"); TransientTestFile tasksUnitTests = testEnvironment.CreateFile(src, "Microsoft.Build.Tasks.UnitTests.csproj"); // The important part of this .sln is that it has references to each of the four projects we just created. TransientTestFile sln = testEnvironment.CreateFile(folder, "Microsoft.Build.Dev.sln", @" Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.27004.2009 MinimumVisualStudioVersion = 10.0.40219.1 Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""Microsoft.Build"", """ + Path.Combine("src", Path.GetFileName(microsoftBuild.Path)) + @""", ""{69BE05E2-CBDA-4D27-9733-44E12B0F5627}"" EndProject Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""MSBuild"", """ + Path.Combine("src", Path.GetFileName(msbuild.Path)) + @""", ""{6F92CA55-1D15-4F34-B1FE-56C0B7EB455E}"" EndProject Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""Microsoft.Build.CommandLine.UnitTests"", """ + Path.Combine("src", Path.GetFileName(commandLineUnitTests.Path)) + @""", ""{0ADDBC02-0076-4159-B351-2BF33FAA46B2}"" EndProject Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""Microsoft.Build.Tasks.UnitTests"", """ + Path.Combine("src", Path.GetFileName(tasksUnitTests.Path)) + @""", ""{CF999BDE-02B3-431B-95E6-E88D621D9CBF}"" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection EndGlobal "); TransientTestFile slnf = testEnvironment.CreateFile(folder, "Dev.slnf", @" { ""solution"": { ""path"": """ + sln.Path.Replace("\\", "\\\\") + @""", ""projects"": [ """ + Path.Combine("src", Path.GetFileName(microsoftBuild.Path) !).Replace("\\", "\\\\") + @""", """ + Path.Combine("src", Path.GetFileName(tasksUnitTests.Path) !).Replace("\\", "\\\\") + @""" ] } }"); SolutionFile sp = SolutionFile.Parse(slnf.Path); sp.ProjectShouldBuild(Path.Combine("src", Path.GetFileName(microsoftBuild.Path) !)).ShouldBeTrue(); sp.ProjectShouldBuild(Path.Combine("src", Path.GetFileName(tasksUnitTests.Path) !)).ShouldBeTrue(); (sp.ProjectShouldBuild(Path.Combine("src", Path.GetFileName(commandLineUnitTests.Path) !)) || sp.ProjectShouldBuild(Path.Combine("src", Path.GetFileName(msbuild.Path) !)) || sp.ProjectShouldBuild(Path.Combine("src", "notAProject.csproj"))) .ShouldBeFalse(); } }
public void InlineTaskWithAssembly() { using (TestEnvironment env = TestEnvironment.Create()) { TransientTestFolder folder = env.CreateFolder(createFolder: true); TransientTestFile assemblyProj = env.CreateFile(folder, "5106.csproj", @$ " <Project DefaultTargets=" "Build" "> <PropertyGroup> <TargetFrameworkVersion>{MSBuildConstants.StandardTestTargetFrameworkVersion}</TargetFrameworkVersion>
public void ConstructWithSingleNode() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1); var projectGraph = new ProjectGraph(entryProject.Path); projectGraph.ProjectNodes.Count.ShouldBe(1); projectGraph.ProjectNodes.First().ProjectInstance.FullPath.ShouldBe(entryProject.Path); } }
public void ConstructWithSelfLoop() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, new[] { 2, 3 }); CreateProjectFile(env, 2, new[] { 2 }); CreateProjectFile(env, 3); Should.Throw <CircularDependencyException>(() => new ProjectGraph(entryProject.Path)); } }
public void InvalidSolutionFilters(string slnfValue, string exceptionReason) { Assert.False(File.Exists("C:\\notAPath2\\MSBuild.Dev.sln")); using (TestEnvironment testEnvironment = TestEnvironment.Create()) { TransientTestFolder folder = testEnvironment.CreateFolder(createFolder: true); TransientTestFile sln = testEnvironment.CreateFile(folder, "Dev.sln"); TransientTestFile slnf = testEnvironment.CreateFile(folder, "Dev.slnf", slnfValue.Replace(@"C:\\notAPath\\MSBuild.Dev.sln", sln.Path.Replace("\\", "\\\\"))); InvalidProjectFileException e = Should.Throw <InvalidProjectFileException>(() => SolutionFile.Parse(slnf.Path)); e.HelpKeyword.ShouldBe(exceptionReason); } }
public void TestPreComputedCacheInputMatchesOutput() { using (TestEnvironment env = TestEnvironment.Create()) { TransientTestFile precomputedCache = env.CreateFile(".cache"); ResolveAssemblyReference rarWriterTask = new ResolveAssemblyReference() { _cache = new SystemState() }; string dllName = Path.Combine(Path.GetDirectoryName(precomputedCache.Path), "randomFolder", "dll.dll"); rarWriterTask._cache.instanceLocalFileStateCache = new Dictionary <string, SystemState.FileState>() { { Path.Combine(precomputedCache.Path, "..", "assembly1", "assembly1"), new SystemState.FileState(DateTime.Now) }, { Path.Combine(precomputedCache.Path, "assembly2"), new SystemState.FileState(DateTime.Now) { Assembly = new Shared.AssemblyNameExtension("hi") } }, { dllName, new SystemState.FileState(DateTime.Now) { Assembly = null, RuntimeVersion = "v4.0.30319", FrameworkNameAttribute = new System.Runtime.Versioning.FrameworkName(".NETFramework", Version.Parse("4.7.2"), "Profile"), scatterFiles = new string[] { "first", "second" } } } }; rarWriterTask.AssemblyInformationCacheOutputPath = precomputedCache.Path; rarWriterTask._cache.IsDirty = true; // Throws an exception because precomputedCache.Path already exists. Should.Throw <InvalidOperationException>(() => rarWriterTask.WriteStateFile()); File.Delete(precomputedCache.Path); rarWriterTask.WriteStateFile(); ResolveAssemblyReference rarReaderTask = new ResolveAssemblyReference(); rarReaderTask.StateFile = precomputedCache.Path.Substring(0, precomputedCache.Path.Length - 6); // Not a real path; should not be used. rarReaderTask.AssemblyInformationCachePaths = new ITaskItem[] { new TaskItem(precomputedCache.Path) }; // At this point, the standard cache does not exist, so it defaults to reading the "precomputed" cache. // Then we verify that the information contained in that cache matches what we'd expect. rarReaderTask.ReadStateFile(p => true); rarReaderTask._cache.instanceLocalFileStateCache.ShouldContainKey(dllName); SystemState.FileState assembly3 = rarReaderTask._cache.instanceLocalFileStateCache[dllName]; assembly3.Assembly.ShouldBeNull(); assembly3.RuntimeVersion.ShouldBe("v4.0.30319"); assembly3.FrameworkNameAttribute.Version.ShouldBe(Version.Parse("4.7.2")); assembly3.scatterFiles.Length.ShouldBe(2); assembly3.scatterFiles[1].ShouldBe("second"); } }
public void ConstructWithProjectInstanceFactory_FactoryReturnsNull_Throws() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1); Should.Throw <AggregateException>(() => new ProjectGraph( entryProject.Path, ProjectCollection.GlobalProjectCollection, (projectPath, globalProperties, projectCollection) => null)).InnerException.ShouldBeOfType <InvalidOperationException>(); } }
public void ConstructWithMultipleNodes() { using (var env = TestEnvironment.Create()) { CreateProjectFile(env, 1, new[] { 4, 5 }); TransientTestFile entryProject = CreateProjectFile(env, 2, new[] { 3, 5, 6 }); CreateProjectFile(env, 3); CreateProjectFile(env, 4); CreateProjectFile(env, 5, new[] { 7 }); CreateProjectFile(env, 6, new[] { 1 }); CreateProjectFile(env, 7); ProjectGraph graph = new ProjectGraph(entryProject.Path); graph.ProjectNodes.Count.ShouldBe(7); ProjectGraphNode node1 = GetNodeForProject(graph, 1); ProjectGraphNode node2 = GetNodeForProject(graph, 2); ProjectGraphNode node3 = GetNodeForProject(graph, 3); ProjectGraphNode node4 = GetNodeForProject(graph, 4); ProjectGraphNode node5 = GetNodeForProject(graph, 5); ProjectGraphNode node6 = GetNodeForProject(graph, 6); ProjectGraphNode node7 = GetNodeForProject(graph, 7); node1.ProjectReferences.Count.ShouldBe(2); node2.ProjectReferences.Count.ShouldBe(3); node3.ProjectReferences.Count.ShouldBe(0); node4.ProjectReferences.Count.ShouldBe(0); node5.ProjectReferences.Count.ShouldBe(1); node6.ProjectReferences.Count.ShouldBe(1); node7.ProjectReferences.Count.ShouldBe(0); node1.ReferencingProjects.Count.ShouldBe(1); node2.ReferencingProjects.Count.ShouldBe(0); node3.ReferencingProjects.Count.ShouldBe(1); node4.ReferencingProjects.Count.ShouldBe(1); node5.ReferencingProjects.Count.ShouldBe(2); node6.ReferencingProjects.Count.ShouldBe(1); node7.ReferencingProjects.Count.ShouldBe(1); // confirm that there is a path from 2 -> 6 -> 1 -> 5 -> 7 node2.ProjectReferences.ShouldContain(node6); node6.ProjectReferences.ShouldContain(node1); node1.ProjectReferences.ShouldContain(node5); node5.ProjectReferences.ShouldContain(node7); // confirm that there is a path from 7 -> 5 -> 1 -> 6 -> 2 using ReferencingProjects node7.ReferencingProjects.ShouldContain(node5); node5.ReferencingProjects.ShouldContain(node1); node1.ReferencingProjects.ShouldContain(node6); node6.ReferencingProjects.ShouldContain(node2); } }
public void CodeTypeFromTaskBody() { foreach (RoslynCodeTaskFactoryCodeType codeType in Enum.GetValues(typeof(RoslynCodeTaskFactoryCodeType)).Cast <RoslynCodeTaskFactoryCodeType>()) { TryLoadTaskBodyAndExpectSuccess($"<Code Type=\"{codeType}\">code</Code>", expectedCodeType: codeType); } using (TestEnvironment testEnvironment = TestEnvironment.Create()) { TransientTestFile file = testEnvironment.CreateFile(fileName: "236D48CE30064161B31B55DBF088C8B2", contents: "6159BD98607A460AA4F11D2FA92E5436"); TryLoadTaskBodyAndExpectSuccess($"<Code Source=\"{file.Path}\"/>", expectedCodeType: RoslynCodeTaskFactoryCodeType.Class); } }
public void ConstructWithThreeNodes() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, new[] { 2, 3 }); CreateProjectFile(env, 2); CreateProjectFile(env, 3); ProjectGraph graph = new ProjectGraph(entryProject.Path); graph.ProjectNodes.Count.ShouldBe(3); GetNodeForProject(graph, 1).ProjectReferences.Count.ShouldBe(2); GetNodeForProject(graph, 2).ProjectReferences.Count.ShouldBe(0); GetNodeForProject(graph, 3).ProjectReferences.Count.ShouldBe(0); } }
public void ConstructWithCycle() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, new[] { 2 }); var proj2 = CreateProjectFile(env, 2, new[] { 3 }); var proj3 = CreateProjectFile(env, 3, new[] { 1 }); var projectsInCycle = new List <string>() { entryProject.Path, proj3.Path, proj2.Path, entryProject.Path }; string expectedErrorMessage = ProjectGraph.FormatCircularDependencyError(projectsInCycle); Should.Throw <CircularDependencyException>(() => new ProjectGraph(entryProject.Path)).Message.ShouldContain(expectedErrorMessage.ToString()); } }
public void SourceCodeFromFile() { const string sourceCodeFileContents = @" 1F214E27A13F432B9397F1733BC55929 9111DC29B0064E6994A68CFE465404D4"; using (TestEnvironment testEnvironment = TestEnvironment.Create()) { TransientTestFile file = testEnvironment.CreateFile(fileName: "CB3096DA4A454768AA9C0C4D422FC188.tmp", contents: sourceCodeFileContents); TryLoadTaskBodyAndExpectSuccess( $"<Code Source=\"{file.Path}\"/>", expectedSourceCode: sourceCodeFileContents, expectedCodeType: RoslynCodeTaskFactoryCodeType.Class); } }
public void ConstructGraphWithDifferentEntryPointsAndGraphRoots() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject1 = CreateProjectFile(env, 1, new[] { 4 }); TransientTestFile entryProject2 = CreateProjectFile(env, 2, new[] { 4, 5 }); TransientTestFile entryProject3 = CreateProjectFile(env, 3, new[] { 2, 6 }); CreateProjectFile(env, 4); CreateProjectFile(env, 5); CreateProjectFile(env, 6); var projectGraph = new ProjectGraph(new[] { entryProject1.Path, entryProject2.Path, entryProject3.Path }); projectGraph.EntryPointNodes.Count.ShouldBe(3); projectGraph.GraphRoots.Count.ShouldBe(2); projectGraph.GraphRoots.ShouldNotContain(GetNodeForProject(projectGraph, 2)); } }
public void ConstructWithInvalidProperties() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = CreateProjectFile(env, 1, new[] { 2 }); env.CreateFile("2.proj", @" <Project> <ItemGroup> <ProjectReference Include=""3.proj"" AdditionalProperties=""ThisIsntValid"" /> </ItemGroup> </Project>"); CreateProjectFile(env, 3); Should.Throw <AggregateException>(() => new ProjectGraph(entryProject.Path)).InnerException.ShouldBeOfType <InvalidProjectFileException>(); } }
public void TestGlobalPropertiesInProjectReferences() { using (var env = TestEnvironment.Create()) { TransientTestFile entryProject = env.CreateFile("1.proj", @" <Project> <ItemGroup> <ProjectReference Include=""2.proj"" AdditionalProperties=""A=B""/> </ItemGroup> </Project>"); CreateProjectFile(env, 2, new[] { 3 }); CreateProjectFile(env, 3); ProjectGraph graph = new ProjectGraph(entryProject.Path); graph.ProjectNodes.Count.ShouldBe(3); GetNodeForProject(graph, 3).GlobalProperties["A"].ShouldBe("B"); } }
public void StandardCacheTakesPrecedence() { using (TestEnvironment env = TestEnvironment.Create()) { TransientTestFile standardCache = env.CreateFile(".cache"); ResolveAssemblyReference rarWriterTask = new ResolveAssemblyReference() { _cache = new SystemState() }; rarWriterTask._cache.instanceLocalFileStateCache = new Dictionary <string, SystemState.FileState>(); rarWriterTask.StateFile = standardCache.Path; rarWriterTask._cache.IsDirty = true; // Write standard cache rarWriterTask.WriteStateFile(); string dllName = Path.Combine(Path.GetDirectoryName(standardCache.Path), "randomFolder", "dll.dll"); rarWriterTask._cache.instanceLocalFileStateCache.Add(dllName, new SystemState.FileState(DateTime.Now) { Assembly = null, RuntimeVersion = "v4.0.30319", FrameworkNameAttribute = new System.Runtime.Versioning.FrameworkName(".NETFramework", Version.Parse("4.7.2"), "Profile"), scatterFiles = new string[] { "first", "second" } }); string precomputedCachePath = standardCache.Path + ".cache"; rarWriterTask.AssemblyInformationCacheOutputPath = precomputedCachePath; rarWriterTask._cache.IsDirty = true; // Write precomputed cache rarWriterTask.WriteStateFile(); ResolveAssemblyReference rarReaderTask = new ResolveAssemblyReference(); rarReaderTask.StateFile = standardCache.Path; rarReaderTask.AssemblyInformationCachePaths = new ITaskItem[] { new TaskItem(precomputedCachePath) }; // At this point, we should have created two cache files: one "normal" one and one "precomputed" one. // When we read the state file, it should read from the caches produced in a normal build. In this case, // the normal cache does not have dll.dll, whereas the precomputed cache does, so it should not be // present when we read it. rarReaderTask.ReadStateFile(p => true); rarReaderTask._cache.instanceLocalFileStateCache.ShouldNotContainKey(dllName); } }