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
147
148
149
150
151
152
|
using System;
using System.Linq;
using System.Threading.Tasks;
using Mono.Cecil;
using Mono.Linker.Tests.Extensions;
using Mono.Linker.Tests.TestCases;
using NUnit.Framework;
namespace Mono.Linker.Tests.TestCasesRunner
{
public class TestRunner
{
private readonly ObjectFactory _factory;
public TestRunner (ObjectFactory factory)
{
_factory = factory;
}
public virtual LinkedTestCaseResult Run (TestCase testCase)
{
using (var fullTestCaseAssemblyDefinition = AssemblyDefinition.ReadAssembly (testCase.OriginalTestCaseAssemblyPath.ToString ())) {
var metadataProvider = _factory.CreateMetadataProvider (testCase, fullTestCaseAssemblyDefinition);
if (metadataProvider.IsIgnored (out string ignoreReason))
Assert.Ignore (ignoreReason);
var sandbox = Sandbox (testCase, metadataProvider);
var compilationResult = Compile (sandbox, metadataProvider);
PrepForLink (sandbox, compilationResult);
return Link (testCase, sandbox, compilationResult, metadataProvider);
}
}
public virtual LinkedTestCaseResult Relink (LinkedTestCaseResult result)
{
PrepForLink (result.Sandbox, result.CompilationResult);
return Link (result.TestCase, result.Sandbox, result.CompilationResult, result.MetadataProvider);
}
private TestCaseSandbox Sandbox (TestCase testCase, TestCaseMetadaProvider metadataProvider)
{
var sandbox = _factory.CreateSandbox (testCase);
sandbox.Populate (metadataProvider);
return sandbox;
}
private ManagedCompilationResult Compile (TestCaseSandbox sandbox, TestCaseMetadaProvider metadataProvider)
{
var inputCompiler = _factory.CreateCompiler (sandbox, metadataProvider);
var expectationsCompiler = _factory.CreateCompiler (sandbox, metadataProvider);
var sourceFiles = sandbox.SourceFiles.Select (s => s.ToString ()).ToArray ();
var assemblyName = metadataProvider.GetAssemblyName ();
var commonReferences = metadataProvider.GetCommonReferencedAssemblies (sandbox.InputDirectory).ToArray ();
var mainAssemblyReferences = metadataProvider.GetReferencedAssemblies (sandbox.InputDirectory).ToArray ();
var resources = sandbox.ResourceFiles.ToArray ();
var additionalArguments = metadataProvider.GetSetupCompilerArguments ().ToArray ();
var expectationsCommonReferences = metadataProvider.GetCommonReferencedAssemblies (sandbox.ExpectationsDirectory).ToArray ();
var expectationsMainAssemblyReferences = metadataProvider.GetReferencedAssemblies (sandbox.ExpectationsDirectory).ToArray ();
var inputTask = Task.Run (() => inputCompiler.CompileTestIn (sandbox.InputDirectory, assemblyName, sourceFiles, commonReferences, mainAssemblyReferences, null, resources, additionalArguments));
var expectationsTask = Task.Run (() => expectationsCompiler.CompileTestIn (sandbox.ExpectationsDirectory, assemblyName, sourceFiles, expectationsCommonReferences, expectationsMainAssemblyReferences, new[] { "INCLUDE_EXPECTATIONS" }, resources, additionalArguments));
NPath inputAssemblyPath = null;
NPath expectationsAssemblyPath = null;
try {
inputAssemblyPath = GetResultOfTaskThatMakesNUnitAssertions (inputTask);
expectationsAssemblyPath = GetResultOfTaskThatMakesNUnitAssertions (expectationsTask);
} catch (Exception) {
// If completing the input assembly task threw, we need to wait for the expectations task to complete before continuing
// otherwise we could set the next test up for a race condition with the expectations compilation over access to the sandbox directory
if (inputAssemblyPath == null && expectationsAssemblyPath == null) {
try {
expectationsTask.Wait ();
} catch (Exception) {
// Don't care, we want to throw the first exception
}
}
throw;
}
return new ManagedCompilationResult (inputAssemblyPath, expectationsAssemblyPath);
}
protected virtual void PrepForLink (TestCaseSandbox sandbox, ManagedCompilationResult compilationResult)
{
}
private LinkedTestCaseResult Link (TestCase testCase, TestCaseSandbox sandbox, ManagedCompilationResult compilationResult, TestCaseMetadaProvider metadataProvider)
{
var linker = _factory.CreateLinker ();
var linkerCustomizations = CustomizeLinker (linker, metadataProvider);
var builder = _factory.CreateLinkerArgumentBuilder (metadataProvider);
AddLinkOptions (sandbox, compilationResult, builder, metadataProvider);
LinkerTestLogger logger = new LinkerTestLogger ();
linker.Link (builder.ToArgs (), linkerCustomizations, logger);
return new LinkedTestCaseResult (testCase, compilationResult.InputAssemblyPath, sandbox.OutputDirectory.Combine (compilationResult.InputAssemblyPath.FileName), compilationResult.ExpectationsAssemblyPath, sandbox, metadataProvider, compilationResult, logger, linkerCustomizations);
}
protected virtual void AddLinkOptions (TestCaseSandbox sandbox, ManagedCompilationResult compilationResult, LinkerArgumentBuilder builder, TestCaseMetadaProvider metadataProvider)
{
var caseDefinedOptions = metadataProvider.GetLinkerOptions (sandbox.InputDirectory);
builder.AddOutputDirectory (sandbox.OutputDirectory);
foreach (var rspFile in sandbox.ResponseFiles)
builder.AddResponseFile (rspFile);
builder.AddSearchDirectory (sandbox.InputDirectory);
foreach (var extraSearchDir in metadataProvider.GetExtraLinkerSearchDirectories ())
builder.AddSearchDirectory (extraSearchDir);
builder.ProcessOptions (caseDefinedOptions);
builder.ProcessTestInputAssembly (compilationResult.InputAssemblyPath);
}
protected virtual LinkerCustomizations CustomizeLinker (LinkerDriver linker, TestCaseMetadaProvider metadataProvider)
{
LinkerCustomizations customizations = new LinkerCustomizations ();
metadataProvider.CustomizeLinker (linker, customizations);
return customizations;
}
private T GetResultOfTaskThatMakesNUnitAssertions<T> (Task<T> task)
{
try {
return task.Result;
} catch (AggregateException e) {
if (e.InnerException != null) {
if (e.InnerException is AssertionException
|| e.InnerException is SuccessException
|| e.InnerException is IgnoreException
|| e.InnerException is InconclusiveException)
throw e.InnerException;
}
throw;
}
}
}
}
|