-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathGivenThatWeWantToVerifyNuGetReferenceCompat.cs
301 lines (244 loc) · 13.6 KB
/
GivenThatWeWantToVerifyNuGetReferenceCompat.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Runtime.CompilerServices;
namespace Microsoft.NET.Build.Tests
{
public class GivenThatWeWantToVerifyNuGetReferenceCompat : SdkTest, IClassFixture<DeleteNuGetArtifactsFixture>
{
public GivenThatWeWantToVerifyNuGetReferenceCompat(ITestOutputHelper log) : base(log)
{
}
// Reduced set of test cases that still verify the compatibility matrix
[Theory]
[InlineData("net45", "Full", "netstandard1.0 netstandard1.1 net45", true, true)]
[InlineData("net462", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netstandard2.0 net45 net451 net46 net461 net462", true, true)]
[InlineData("netstandard1.6", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6", true, true)]
[InlineData("netstandard2.0", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netstandard2.0", true, true)]
[InlineData("netcoreapp2.0", "Full", "netstandard1.0 netstandard1.1 netstandard1.2 netstandard1.3 netstandard1.4 netstandard1.5 netstandard1.6 netstandard2.0 netcoreapp1.0 netcoreapp1.1 netcoreapp2.0", true, true)]
[InlineData("netstandard2.0", "OptIn", "net45 net451 net46 net461", true, true)]
[InlineData("netcoreapp2.0", "OptIn", "net45 net451 net46 net461", true, true)]
public void Nuget_reference_compat(string referencerTarget, string testDescription, string rawDependencyTargets,
bool restoreSucceeds, bool buildSucceeds)
{
string referencerDirectoryNamePostfix = "_" + referencerTarget + "_" + testDescription;
TestProject referencerProject = GetTestProject(ConstantStringValues.ReferencerDirectoryName, referencerTarget, true);
// Skip running test if not running on Windows
// https://github.com/dotnet/sdk/issues/335
if (!(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || referencerProject.BuildsOnNonWindows))
{
return;
}
var dependencyPackageReferences = new List<TestPackageReference>();
// Process all dependencies in parallel
Parallel.ForEach(
rawDependencyTargets.Split(',', ';', ' ').Where(s => !string.IsNullOrWhiteSpace(s)),
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
dependencyTarget =>
{
// Create the dependency project and package
TestProject dependencyProject = GetTestProject(
ConstantStringValues.DependencyDirectoryNamePrefix + dependencyTarget.Replace('.', '_'),
dependencyTarget,
true);
TestPackageReference dependencyPackageReference = new(
dependencyProject.Name,
"1.0.0",
ConstantStringValues.ConstructNuGetPackageReferencePath(dependencyProject, identifier: referencerTarget + testDescription + rawDependencyTargets));
// Create package if it doesn't exist
if (!dependencyPackageReference.NuGetPackageExists() &&
(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || dependencyProject.BuildsOnNonWindows))
{
if (!dependencyPackageReference.NuGetPackageExists()) // Double-check after lock
{
var dependencyTestAsset = _testAssetsManager.CreateTestProject(
dependencyProject,
identifier: referencerTarget + testDescription + rawDependencyTargets);
dependencyTestAsset.GetRestoreCommand(Log, relativePath: dependencyProject.Name)
.Execute().Should().Pass();
var dependencyProjectDirectory = Path.Combine(
dependencyTestAsset.TestRoot,
dependencyProject.Name);
new PackCommand(Log, dependencyProjectDirectory)
.Execute().Should().Pass();
}
}
});
// Add all references to the referencer project
foreach (var dependencyPackageReference in dependencyPackageReferences)
{
referencerProject.PackageReferences.Add(dependencyPackageReference);
}
// Skip running tests if no NuGet packages are referenced
// https://github.com/dotnet/sdk/issues/335
if (referencerProject.PackageReferences == null)
{
return;
}
// Set the referencer project as an Exe unless it targets .NET Standard
if (!referencerProject.TargetFrameworkIdentifiers.Contains(ConstantStringValues.NetstandardTargetFrameworkIdentifier))
{
referencerProject.IsExe = true;
}
// Create the referencing app and run the compat test
var referencerTestAsset = _testAssetsManager.CreateTestProject(referencerProject, ConstantStringValues.TestDirectoriesNamePrefix, referencerDirectoryNamePostfix);
var referencerRestoreCommand = referencerTestAsset.GetRestoreCommand(Log, relativePath: referencerProject.Name);
List<string> referencerRestoreSources = new();
// Modify the restore command to refer to the created NuGet packages
foreach (TestPackageReference packageReference in referencerProject.PackageReferences)
{
var source = Path.Combine(packageReference.NupkgPath, packageReference.ID, "bin", "Debug");
referencerRestoreSources.Add(source);
}
NuGetConfigWriter.Write(referencerTestAsset.TestRoot, referencerRestoreSources);
if (restoreSucceeds)
{
referencerRestoreCommand.Execute().Should().Pass();
}
else
{
referencerRestoreCommand.Execute().Should().Fail();
}
var referencerBuildCommand = new BuildCommand(referencerTestAsset);
var referencerBuildResult = referencerBuildCommand.Execute();
if (buildSucceeds)
{
referencerBuildResult.Should().Pass();
}
else
{
referencerBuildResult.Should().Fail().And.HaveStdOutContaining("It cannot be referenced by a project that targets");
}
}
[WindowsOnlyTheory]
[InlineData("netstandard2.0")]
[InlineData("netcoreapp2.0")]
public void Netfx_is_implicit_for_Netstandard_and_Netcore_20(string targetFramework)
{
var testProjectName = targetFramework.Replace(".", "_") + "implicit_atf";
var (testProjectTestAsset, testPackageReference) = CreateTestAsset(testProjectName, targetFramework, "net461", identifer: targetFramework);
var restoreCommand = testProjectTestAsset.GetRestoreCommand(Log, relativePath: testProjectName);
var source = Path.Combine(testPackageReference.NupkgPath, testPackageReference.ID, "bin", "Debug");
NuGetConfigWriter.Write(testProjectTestAsset.TestRoot, source);
restoreCommand.Execute().Should().Pass();
var buildCommand = new BuildCommand(testProjectTestAsset);
buildCommand.Execute().Should().Pass();
}
[WindowsOnlyTheory]
[InlineData("netstandard1.6")]
[InlineData("netcoreapp1.1")]
public void Netfx_is_not_implicit_for_Netstandard_and_Netcore_less_than_20(string targetFramework)
{
var testProjectName = targetFramework.Replace(".", "_") + "non_implicit_atf";
var (testProjectTestAsset, testPackageReference) = CreateTestAsset(testProjectName, targetFramework, "net461", identifer: targetFramework);
var restoreCommand = testProjectTestAsset.GetRestoreCommand(Log, relativePath: testProjectName);
NuGetConfigWriter.Write(testProjectTestAsset.TestRoot, Path.GetDirectoryName(testPackageReference.NupkgPath));
restoreCommand.Execute().Should().Fail();
}
[WindowsOnlyFact]
public void It_is_possible_to_disable_netfx_implicit_asset_target_fallback()
{
const string testProjectName = "netstandard20_disabled_atf";
var (testProjectTestAsset, testPackageReference) = CreateTestAsset(
testProjectName,
"netstandard2.0",
"net461",
new Dictionary<string, string> { { "DisableImplicitAssetTargetFallback", "true" } });
var restoreCommand = testProjectTestAsset.GetRestoreCommand(Log, relativePath: testProjectName);
NuGetConfigWriter.Write(testProjectTestAsset.TestRoot, Path.GetDirectoryName(testPackageReference.NupkgPath));
restoreCommand.Execute().Should().Fail();
}
[WindowsOnlyFact]
public void It_chooses_lowest_netfx_in_default_atf()
{
var testProjectName = $"{ToolsetInfo.CurrentTargetFramework.Replace(".", "")}_multiple_atf";
var (testProjectTestAsset, testPackageReference) = CreateTestAsset(
testProjectName,
ToolsetInfo.CurrentTargetFramework,
"net462;net472",
new Dictionary<string, string> { ["CopyLocalLockFileAssemblies"] = "true" });
var source = Path.Combine(testPackageReference.NupkgPath, testPackageReference.ID, "bin", "Debug");
NuGetConfigWriter.Write(testProjectTestAsset.TestRoot, source);
var restoreCommand = testProjectTestAsset.GetRestoreCommand(Log, relativePath: testProjectName);
restoreCommand.Execute().Should().Pass();
var buildCommand = new BuildCommand(testProjectTestAsset);
buildCommand.Execute().Should().Pass();
var referencedDll = buildCommand.GetOutputDirectory().File("net462_net472_pkg.dll").FullName;
var referencedTargetFramework = AssemblyInfo.Get(referencedDll)["TargetFrameworkAttribute"];
referencedTargetFramework.Should().Be(".NETFramework,Version=v4.6.2");
}
private (TestAsset, TestPackageReference) CreateTestAsset(
string testProjectName,
string callerTargetFramework,
string calleeTargetFrameworks,
Dictionary<string, string> additionalProperties = null,
[CallerMemberName] string testName = null,
string identifer = null)
{
var testPackageReference = CreateTestPackage(calleeTargetFrameworks, testName, identifer);
var testProject =
new TestProject
{
Name = testProjectName,
TargetFrameworks = callerTargetFramework,
};
if (additionalProperties != null)
{
foreach (var additionalProperty in additionalProperties)
{
testProject.AdditionalProperties.Add(additionalProperty.Key, additionalProperty.Value);
}
}
testProject.PackageReferences.Add(testPackageReference);
var testProjectTestAsset = _testAssetsManager.CreateTestProject(
testProject,
string.Empty,
$"{testProjectName}_{calleeTargetFrameworks}");
return (testProjectTestAsset, testPackageReference);
}
private TestPackageReference CreateTestPackage(string targetFrameworks, string identifier, [CallerMemberName] string callingMethod = "")
{
var project =
new TestProject
{
Name = $"{targetFrameworks.Replace(';', '_')}_pkg",
TargetFrameworks = targetFrameworks,
};
var packageReference =
new TestPackageReference(
project.Name,
"1.0.0",
ConstantStringValues.ConstructNuGetPackageReferencePath(project, identifier, callingMethod));
if (!packageReference.NuGetPackageExists())
{
var testAsset =
_testAssetsManager.CreateTestProject(
project,
callingMethod,
identifier);
var packageRestoreCommand =
testAsset.GetRestoreCommand(Log, relativePath: project.Name).Execute().Should().Pass();
var dependencyProjectDirectory = Path.Combine(testAsset.TestRoot, project.Name);
var packagePackCommand =
new PackCommand(Log, dependencyProjectDirectory).Execute().Should().Pass();
}
return packageReference;
}
TestProject GetTestProject(string name, string target, bool isSdkProject)
{
TestProject ret = new()
{
Name = name,
IsSdkProject = isSdkProject
};
if (isSdkProject)
{
ret.TargetFrameworks = target;
}
else
{
ret.TargetFrameworkVersion = target;
}
return ret;
}
}
}