Skip to content

Commit 5f81325

Browse files
authored
Add first unit test to Traversal (#17)
* Using MSBuildLocator and MSBuildProjectCreator to abstract away projects * Fix some issues in traversal
1 parent 350d6b6 commit 5f81325

File tree

7 files changed

+254
-19
lines changed

7 files changed

+254
-19
lines changed

MSBuildSdks.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Build.NoTargets",
2020
EndProject
2121
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Build.CentralPackageVersions", "src\CentralPackageVersions\Microsoft.Build.CentralPackageVersions.csproj", "{720D8DE8-C7BA-4CD0-A00A-D8A169D7FE80}"
2222
EndProject
23+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Build.Traversal.UnitTests", "src\Traversal.UnitTests\Microsoft.Build.Traversal.UnitTests.csproj", "{48AEFD7C-4F21-4855-9EB0-75B1EB58955C}"
24+
EndProject
2325
Global
2426
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2527
Debug|Any CPU = Debug|Any CPU
@@ -38,6 +40,10 @@ Global
3840
{720D8DE8-C7BA-4CD0-A00A-D8A169D7FE80}.Debug|Any CPU.Build.0 = Debug|Any CPU
3941
{720D8DE8-C7BA-4CD0-A00A-D8A169D7FE80}.Release|Any CPU.ActiveCfg = Release|Any CPU
4042
{720D8DE8-C7BA-4CD0-A00A-D8A169D7FE80}.Release|Any CPU.Build.0 = Release|Any CPU
43+
{48AEFD7C-4F21-4855-9EB0-75B1EB58955C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44+
{48AEFD7C-4F21-4855-9EB0-75B1EB58955C}.Debug|Any CPU.Build.0 = Debug|Any CPU
45+
{48AEFD7C-4F21-4855-9EB0-75B1EB58955C}.Release|Any CPU.ActiveCfg = Release|Any CPU
46+
{48AEFD7C-4F21-4855-9EB0-75B1EB58955C}.Release|Any CPU.Build.0 = Release|Any CPU
4147
EndGlobalSection
4248
GlobalSection(SolutionProperties) = preSolution
4349
HideSolutionNode = FALSE
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.IO;
3+
4+
namespace Microsoft.Build.Traversal.UnitTests
5+
{
6+
public abstract class MSBuildSdkTestBase : MSBuildTestBase, IDisposable
7+
{
8+
private readonly string _testRootPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
9+
10+
public string TestRootPath
11+
{
12+
get
13+
{
14+
Directory.CreateDirectory(_testRootPath);
15+
return _testRootPath;
16+
}
17+
}
18+
19+
public void Dispose()
20+
{
21+
Dispose(true);
22+
GC.SuppressFinalize(this);
23+
}
24+
25+
protected virtual void Dispose(bool disposing)
26+
{
27+
if (disposing)
28+
{
29+
if (Directory.Exists(TestRootPath))
30+
{
31+
Directory.Delete(TestRootPath, recursive: true);
32+
}
33+
}
34+
}
35+
36+
protected string GetTempFile(string name)
37+
{
38+
if (name == null)
39+
{
40+
throw new ArgumentNullException(nameof(name));
41+
}
42+
43+
return Path.Combine(TestRootPath, name);
44+
}
45+
46+
protected string GetTempFileWithExtension(string extension = null)
47+
{
48+
return Path.Combine(TestRootPath, $"{Path.GetRandomFileName()}{extension ?? String.Empty}");
49+
}
50+
}
51+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using Microsoft.Build.Locator;
3+
4+
namespace Microsoft.Build.Traversal.UnitTests
5+
{
6+
public abstract class MSBuildTestBase
7+
{
8+
public static readonly VisualStudioInstance CurrentVisualStudioInstance = MSBuildLocator.RegisterDefaults();
9+
10+
protected MSBuildTestBase()
11+
{
12+
MSBuildPath = CurrentVisualStudioInstance.MSBuildPath;
13+
}
14+
15+
protected string MSBuildPath { get; }
16+
}
17+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net46</TargetFramework>
5+
<IsPackable>false</IsPackable>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<None Include="..\Traversal\Sdk\Sdk.props" Link="Sdk\Sdk.props" CopyToOutputDirectory="PreserveNewest" />
10+
<None Include="..\Traversal\Sdk\Sdk.targets" Link="Sdk\Sdk.targets" CopyToOutputDirectory="PreserveNewest" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="Microsoft.Build.Locator" Version="1.0.7-preview-ge60d679b53" />
15+
<PackageReference Include="MSBuild.ProjectCreation" Version="1.0.6" />
16+
<PackageReference Include="Microsoft.Build" Version="15.6.82" ExcludeAssets="runtime" />
17+
<PackageReference Include="Microsoft.Build.Framework" Version="15.6.82" ExcludeAssets="runtime" />
18+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.2" />
19+
<PackageReference Include="Shouldly" Version="3.0.0" />
20+
<PackageReference Include="xunit" Version="2.3.1" />
21+
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
22+
</ItemGroup>
23+
24+
<ItemGroup>
25+
<ProjectReference Include="..\Traversal\Microsoft.Build.Traversal.csproj">
26+
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
27+
</ProjectReference>
28+
</ItemGroup>
29+
30+
</Project>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Microsoft.Build.Evaluation;
2+
using Microsoft.Build.Utilities.ProjectCreation;
3+
using System;
4+
using System.IO;
5+
6+
namespace Microsoft.Build.Traversal.UnitTests
7+
{
8+
public static class CustomProjectCreatorTemplates
9+
{
10+
public static ProjectCreator TraversalProject(
11+
this ProjectCreatorTemplates templates,
12+
string[] projectReferences,
13+
string path = null,
14+
string defaultTargets = null,
15+
string initialTargets = null,
16+
string sdk = null,
17+
string toolsVersion = null,
18+
string treatAsLocalProperty = null,
19+
ProjectCollection projectCollection = null,
20+
NewProjectFileOptions? projectFileOptions = NewProjectFileOptions.None)
21+
{
22+
string currentDirectory = Environment.CurrentDirectory;
23+
24+
return ProjectCreator.Create(
25+
path,
26+
defaultTargets,
27+
initialTargets,
28+
sdk,
29+
toolsVersion,
30+
treatAsLocalProperty,
31+
projectCollection,
32+
projectFileOptions)
33+
.Import(Path.Combine(currentDirectory, "Sdk", "Sdk.props"))
34+
.ForEach(projectReferences, (projectReference, i) =>
35+
{
36+
i.ItemProjectReference(projectReference);
37+
})
38+
.Import(Path.Combine(currentDirectory, "Sdk", "Sdk.targets"));
39+
}
40+
}
41+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using Microsoft.Build.Framework;
2+
using Microsoft.Build.Utilities.ProjectCreation;
3+
using Shouldly;
4+
using System.Linq;
5+
using Xunit;
6+
7+
namespace Microsoft.Build.Traversal.UnitTests
8+
{
9+
public class TraversalTests : MSBuildSdkTestBase
10+
{
11+
[Fact(Skip = "This does not currently work, need to investigate why")]
12+
public void SkipsNonExistentTargets()
13+
{
14+
string[] projects = new[]
15+
{
16+
ProjectCreator.Templates.LogsMessage("1E70CCD4EE5741C1B0E7389E90328CD4", MessageImportance.High, targetName: "2DAB5AF89C2F47AAA618A507B2FFBA51", path: GetTempFileWithExtension(".proj"))
17+
.Save(),
18+
}.Select(i => i.FullPath).ToArray();
19+
20+
ProjectCreator
21+
.Templates
22+
.TraversalProject(
23+
projects,
24+
path: GetTempFile("dirs.proj"))
25+
.Property("SkipNonexistentTargets", "true")
26+
.Save()
27+
.TryBuild("Clean", out bool result, out BuildOutput buildOutput);
28+
29+
result.ShouldBeTrue(customMessage: () => buildOutput.GetConsoleLog());
30+
}
31+
32+
[Theory]
33+
[InlineData("Build")]
34+
[InlineData("Test")]
35+
public void TraversalTargetsRun(string target)
36+
{
37+
string[] projects = new[]
38+
{
39+
ProjectCreator.Templates.LogsMessage("BF0C6E1044514FE3AE4B78EC308D6F45", MessageImportance.High, targetName: target, path: GetTempFileWithExtension(".proj"))
40+
.Target("GetNativeManifest")
41+
.Save(),
42+
ProjectCreator.Templates.LogsMessage("40869F4000B44D75A52AB305F24E0FDB", MessageImportance.High, targetName: target, path: GetTempFileWithExtension(".proj"))
43+
.Target("GetNativeManifest")
44+
.Save(),
45+
}.Select(i => i.FullPath).ToArray();
46+
47+
ProjectCreator
48+
.Templates
49+
.TraversalProject(
50+
projects,
51+
path: GetTempFile("dirs.proj"))
52+
.Save()
53+
.TryBuild(target, out bool result, out BuildOutput buildOutput);
54+
55+
result.ShouldBeTrue(customMessage: () => buildOutput.GetConsoleLog());
56+
57+
buildOutput
58+
.MessagesHighImportance
59+
.Select(i => i.Message)
60+
.ToList()
61+
.ShouldBe(
62+
new[]
63+
{
64+
"BF0C6E1044514FE3AE4B78EC308D6F45",
65+
"40869F4000B44D75A52AB305F24E0FDB"
66+
},
67+
ignoreOrder: true,
68+
customMessage: () => buildOutput.GetConsoleLog());
69+
}
70+
}
71+
}

src/Traversal/Sdk/Sdk.targets

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
FindInvalidProjectReferences;
3333
AfterResolveReferences
3434
</ResolveReferencesDependsOn>
35+
36+
<TestDependsOn>
37+
Build
38+
</TestDependsOn>
3539
</PropertyGroup>
3640

3741
<ItemGroup Condition=" '$(TraversalTranslateProjectFileItems)' != 'false' ">
@@ -62,33 +66,38 @@
6266
Properties="$(PreTraversalGlobalProperties)"
6367
Condition=" '@(PreTraversalProject)' != '' "
6468
BuildInParallel="$(BuildInParallel)"
65-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
69+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
70+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
6671

6772
<MSBuild Projects="@(PreTraversalBuildProject)"
6873
Targets="Build"
6974
Properties="$(PreTraversalBuildGlobalProperties)"
7075
Condition=" '@(PreTraversalBuildProject)' != '' "
7176
BuildInParallel="$(BuildInParallel)"
72-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
77+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
78+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
7379

7480
<MSBuild Projects="@(_MSBuildProjectReferenceExistent)"
7581
Properties="$(TraversalGlobalProperties);$(TraversalBuildGlobalProperties)"
7682
BuildInParallel="$(BuildInParallel)"
77-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
83+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
84+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
7885

7986
<MSBuild Projects="@(PostTraversalBuildProject)"
8087
Targets="Build"
8188
Properties="$(PostTraversalBuildGlobalProperties)"
8289
Condition=" '@(PostTraversalBuildProject)' != '' "
8390
BuildInParallel="$(BuildInParallel)"
84-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
91+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
92+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
8593

8694
<MSBuild Projects="@(PostTraversalProject)"
8795
Targets="Build"
8896
Properties="$(PostTraversalGlobalProperties)"
8997
Condition=" '@(PostTraversalProject)' != '' "
9098
BuildInParallel="$(BuildInParallel)"
91-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
99+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
100+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
92101
</Target>
93102

94103
<Target Name="Clean"
@@ -99,34 +108,39 @@
99108
Properties="$(PreTraversalGlobalProperties)"
100109
Condition=" '@(PreTraversalProject)' != '' "
101110
BuildInParallel="$(BuildInParallel)"
102-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
111+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
112+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
103113

104114
<MSBuild Projects="@(PreTraversalCleanProject)"
105-
Targets="Build"
115+
Targets="Clean"
106116
Properties="$(PreTraversalCleanGlobalProperties)"
107117
Condition=" '@(PreTraversalCleanProject)' != '' "
108118
BuildInParallel="$(BuildInParallel)"
109-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
119+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
120+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
110121

111122
<MSBuild Projects="@(_MSBuildProjectReferenceExistent)"
112123
Targets="Clean"
113124
Properties="$(TraversalGlobalProperties);$(TraversalCleanGlobalProperties)"
114125
BuildInParallel="$(BuildInParallel)"
115-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
126+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
127+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
116128

117129
<MSBuild Projects="@(PostTraversalCleanProject)"
118-
Targets="Build"
130+
Targets="Clean"
119131
Properties="$(PostTraversalCleanGlobalProperties)"
120132
Condition=" '@(PostTraversalCleanProject)' != '' "
121133
BuildInParallel="$(BuildInParallel)"
122-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
134+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
135+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
123136

124137
<MSBuild Projects="@(PostTraversalProject)"
125138
Targets="Clean"
126139
Properties="$(PostTraversalGlobalProperties)"
127140
Condition=" '@(PostTraversalProject)' != '' "
128141
BuildInParallel="$(BuildInParallel)"
129-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
142+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
143+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
130144
</Target>
131145

132146
<Target Name="Test"
@@ -137,34 +151,39 @@
137151
Properties="$(PreTraversalGlobalProperties)"
138152
Condition=" '@(PreTraversalProject)' != '' "
139153
BuildInParallel="$(BuildInParallel)"
140-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
154+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
155+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
141156

142157
<MSBuild Projects="@(PreTraversalTestProject)"
143-
Targets="Build"
158+
Targets="Test"
144159
Properties="$(PreTraversalTestGlobalProperties)"
145160
Condition=" '@(PreTraversalTestProject)' != '' "
146161
BuildInParallel="$(BuildInParallel)"
147-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
162+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
163+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
148164

149165
<MSBuild Projects="@(_MSBuildProjectReferenceExistent)"
150166
Targets="Test"
151167
Properties="$(TraversalGlobalProperties);$(TraversalTestGlobalProperties)"
152168
BuildInParallel="$(BuildInParallel)"
153-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
169+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
170+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
154171

155172
<MSBuild Projects="@(PostTraversalTestProject)"
156-
Targets="Build"
173+
Targets="Test"
157174
Properties="$(PostTraversalTestGlobalProperties)"
158175
Condition=" '@(PostTraversalTestProject)' != '' "
159176
BuildInParallel="$(BuildInParallel)"
160-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
177+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
178+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
161179

162180
<MSBuild Projects="@(PostTraversalProject)"
163181
Targets="Test"
164182
Properties="$(PostTraversalGlobalProperties)"
165183
Condition=" '@(PostTraversalProject)' != '' "
166184
BuildInParallel="$(BuildInParallel)"
167-
SkipNonexistentProjects="$(SkipNonexistentProjects)" />
185+
SkipNonexistentProjects="$(SkipNonexistentProjects)"
186+
SkipNonexistentTargets="$(SkipNonexistentTargets)" />
168187
</Target>
169188

170189
<!--

0 commit comments

Comments
 (0)