-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
TestAssemblyInfo.cs
146 lines (117 loc) · 5.58 KB
/
TestAssemblyInfo.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Xml.Linq;
using Microsoft.Build.Shared.FileSystem;
using Microsoft.Build.UnitTests;
using Xunit;
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
// Register test framework for assembly fixture
[assembly: TestFramework("Xunit.NetCore.Extensions.XunitTestFrameworkWithAssemblyFixture", "Xunit.NetCore.Extensions")]
[assembly: AssemblyFixture(typeof(MSBuildTestAssemblyFixture))]
// Wrap a TestEnvironment around each test method and class so if invariants have changed we will know where
[assembly: AssemblyFixture(typeof(MSBuildTestEnvironmentFixture), LifetimeScope = AssemblyFixtureAttribute.Scope.Class)]
[assembly: AssemblyFixture(typeof(MSBuildTestEnvironmentFixture), LifetimeScope = AssemblyFixtureAttribute.Scope.Method)]
public class MSBuildTestAssemblyFixture : IDisposable
{
bool _disposed;
private TestEnvironment _testEnvironment;
public MSBuildTestAssemblyFixture()
{
// Set field to indicate tests are running in the TestInfo class in Microsoft.Build.Framework.
// See the comments on the TestInfo class for an explanation of why it works this way.
var frameworkAssembly = typeof(Microsoft.Build.Framework.ITask).Assembly;
var testInfoType = frameworkAssembly.GetType("Microsoft.Build.Framework.TestInfo");
var runningTestsField = testInfoType.GetField("s_runningTests", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
runningTestsField.SetValue(null, true);
_testEnvironment = TestEnvironment.Create();
// Reset the VisualStudioVersion environment variable. This will be set if tests are run from a VS command prompt. However,
// if the environment variable is set, it will interfere with tests which set the SubToolsetVersion
// (VerifySubToolsetVersionSetByConstructorOverridable), as the environment variable would take precedence.
_testEnvironment.SetEnvironmentVariable("VisualStudioVersion", string.Empty);
// Prevent test assemblies from logging any performance info.
// https://github.com/dotnet/msbuild/pull/6274
_testEnvironment.SetEnvironmentVariable("DOTNET_PERFLOG_DIR", string.Empty);
SetDotnetHostPath(_testEnvironment);
// Use a project-specific temporary path
// This is so multiple test projects can be run in parallel without sharing the same temp directory
var subdirectory = Path.GetRandomFileName();
string newTempPath = Path.Combine(Path.GetTempPath(), subdirectory);
var assemblyTempFolder = _testEnvironment.CreateFolder(newTempPath);
_testEnvironment.SetTempPath(assemblyTempFolder.Path);
_testEnvironment.CreateFile(
transientTestFolder: assemblyTempFolder,
fileName: "MSBuild_Tests.txt",
contents: $"Temporary test folder for tests from {AppContext.BaseDirectory}");
// Ensure that we stop looking for a D.B.rsp at the root of the test temp
_testEnvironment.CreateFile(
transientTestFolder: assemblyTempFolder,
fileName: "Directory.Build.rsp",
contents: string.Empty);
_testEnvironment.CreateFile(
transientTestFolder: assemblyTempFolder,
fileName: "Directory.Build.props",
contents: "<Project />");
_testEnvironment.CreateFile(
transientTestFolder: assemblyTempFolder,
fileName: "Directory.Build.targets",
contents: "<Project />");
}
/// <summary>
/// Find correct version of "dotnet", and set DOTNET_HOST_PATH so that the Roslyn tasks will use the right host
/// </summary>
/// <param name="testEnvironment"></param>
private static void SetDotnetHostPath(TestEnvironment testEnvironment)
{
var currentFolder = AppContext.BaseDirectory;
while (currentFolder != null)
{
string potentialVersionsPropsPath = Path.Combine(currentFolder, "build", "Versions.props");
if (FileSystems.Default.FileExists(potentialVersionsPropsPath))
{
var doc = XDocument.Load(potentialVersionsPropsPath);
var ns = doc.Root.Name.Namespace;
var cliVersionElement = doc.Root.Elements(ns + "PropertyGroup").Elements(ns + "DotNetCliVersion").FirstOrDefault();
if (cliVersionElement != null)
{
string cliVersion = cliVersionElement.Value;
string dotnetPath = Path.Combine(currentFolder, "artifacts", ".dotnet", cliVersion, "dotnet");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
dotnetPath += ".exe";
}
testEnvironment.SetEnvironmentVariable("DOTNET_HOST_PATH", dotnetPath);
}
break;
}
currentFolder = Directory.GetParent(currentFolder)?.FullName;
}
}
public void Dispose()
{
if (!_disposed)
{
_testEnvironment.Dispose();
_disposed = true;
}
}
}
public class MSBuildTestEnvironmentFixture : IDisposable
{
bool _disposed;
private TestEnvironment _testEnvironment;
public MSBuildTestEnvironmentFixture()
{
_testEnvironment = TestEnvironment.Create();
}
public void Dispose()
{
if (!_disposed)
{
_testEnvironment.Dispose();
_disposed = true;
}
}
}