Skip to content

Commit 0468080

Browse files
committed
write tests for packaging an app in all supported configurations
1 parent 5209f49 commit 0468080

File tree

4 files changed

+77
-17
lines changed

4 files changed

+77
-17
lines changed

Microsoft.NET.Build.Containers/Registry.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,16 @@ async Task<HttpResponseMessage> GetBlob(string digest) {
7474
}
7575

7676
async Task<Image?> TryPickBestImageFromManifestList(ManifestListV2 manifestList, string runtimeIdentifier) {
77+
// TODO: we probably need to pull in actual RID parsing code and look for 'platform' here.
78+
// 'win' can take a version number and we'd break.
79+
// Also, there are more specific linux RIDs (like rhel) that we should instead be looking for the correct 'family' for?
80+
// we probably also need to look at the 'variant' field if the RID contains a version.
7781
(string os, string arch, string? variant) = runtimeIdentifier.Split('-') switch {
7882
["linux", "x64"] => ("linux", "amd64", null),
7983
["linux", "x86"] => ("linux", "386", null),
8084
["linux", "arm"] => ("linux", "arm", "v7"),
8185
["linux", "arm64"] => ("linux", "arm64", "v8"),
82-
["windows", "x64"] => ("windows", "amd64", null),
86+
["win", "x64"] => ("windows", "amd64", null),
8387
var parts => throw new ArgumentException($"Unknown OS/platform combination {String.Join(' ', parts)}")
8488
};
8589

Test.Microsoft.NET.Build.Containers.Filesystem/DockerRegistryManager.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ public class DockerRegistryManager
88
{
99
public const string BaseImage = "dotnet/runtime";
1010
public const string BaseImageSource = "mcr.microsoft.com/";
11-
public const string BaseImageTag = "6.0";
11+
public const string Net6ImageTag = "6.0";
12+
public const string Net7ImageTag = "7.0";
1213
public const string LocalRegistry = "localhost:5010";
13-
public const string FullyQualifiedBaseImageDefault = $"{BaseImageSource}{BaseImage}:{BaseImageTag}";
14+
public const string FullyQualifiedBaseImageDefault = $"{BaseImageSource}{BaseImage}:{Net6ImageTag}";
1415
private static string s_registryContainerId;
1516

1617
private static void Exec(string command, string args) {
@@ -53,9 +54,11 @@ public static void StartAndPopulateDockerRegistry(TestContext context)
5354

5455
s_registryContainerId = registryContainerId;
5556

56-
Exec("docker", $"pull {BaseImageSource}{BaseImage}:{BaseImageTag}");
57-
Exec("docker", $"tag {BaseImageSource}{BaseImage}:{BaseImageTag} {LocalRegistry}/{BaseImage}:{BaseImageTag}");
58-
Exec("docker", $"push {LocalRegistry}/{BaseImage}:{BaseImageTag}");
57+
foreach (var tag in new [] { Net6ImageTag, Net7ImageTag}) {
58+
Exec("docker", $"pull {BaseImageSource}{BaseImage}:{tag}");
59+
Exec("docker", $"tag {BaseImageSource}{BaseImage}:{tag} {LocalRegistry}/{BaseImage}:{tag}");
60+
Exec("docker", $"push {LocalRegistry}/{BaseImage}:{tag}");
61+
}
5962
LocateMSBuild();
6063
}
6164

Test.Microsoft.NET.Build.Containers.Filesystem/EndToEnd.cs

Lines changed: 63 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public async Task ApiEndToEndWithRegistryPushAndPull()
3131

3232
Registry registry = new Registry(ContainerHelpers.TryExpandRegistryToUri(DockerRegistryManager.LocalRegistry));
3333

34-
Image x = await registry.GetImageManifest(DockerRegistryManager.BaseImage, DockerRegistryManager.BaseImageTag, "linux-x64");
34+
Image x = await registry.GetImageManifest(DockerRegistryManager.BaseImage, DockerRegistryManager.Net6ImageTag, "linux-x64");
3535

3636
Layer l = Layer.FromDirectory(publishDirectory, "/app");
3737

@@ -69,7 +69,7 @@ public async Task ApiEndToEndWithLocalLoad()
6969

7070
Registry registry = new Registry(ContainerHelpers.TryExpandRegistryToUri(DockerRegistryManager.LocalRegistry));
7171

72-
Image x = await registry.GetImageManifest(DockerRegistryManager.BaseImage, DockerRegistryManager.BaseImageTag, "linux-x64");
72+
Image x = await registry.GetImageManifest(DockerRegistryManager.BaseImage, DockerRegistryManager.Net6ImageTag, "linux-x64");
7373

7474
Layer l = Layer.FromDirectory(publishDirectory, "/app");
7575

@@ -91,15 +91,15 @@ public async Task ApiEndToEndWithLocalLoad()
9191
Assert.AreEqual(0, run.ExitCode);
9292
}
9393

94-
private static async Task<string> BuildLocalApp()
94+
private static async Task<string> BuildLocalApp(string tfm = "net6.0", string rid = "linux-x64")
9595
{
9696
DirectoryInfo d = new DirectoryInfo("MinimalTestApp");
9797
if (d.Exists)
9898
{
9999
d.Delete(recursive: true);
100100
}
101101

102-
ProcessStartInfo psi = new("dotnet", "new console -f net6.0 -o MinimalTestApp")
102+
ProcessStartInfo psi = new("dotnet", $"new console -f {tfm} -o MinimalTestApp")
103103
{
104104
RedirectStandardOutput = true,
105105
RedirectStandardError = true,
@@ -109,16 +109,17 @@ private static async Task<string> BuildLocalApp()
109109

110110
Assert.IsNotNull(dotnetNew);
111111
await dotnetNew.WaitForExitAsync();
112-
Assert.AreEqual(0, dotnetNew.ExitCode, await dotnetNew.StandardOutput.ReadToEndAsync() + await dotnetNew.StandardError.ReadToEndAsync());
112+
Assert.AreEqual(0, dotnetNew.ExitCode, await dotnetNew.StandardOutput.ReadToEndAsync() + Environment.NewLine + await dotnetNew.StandardError.ReadToEndAsync());
113113

114-
// Build project
115-
116-
Process publish = Process.Start("dotnet", "publish -bl MinimalTestApp -r linux-x64");
114+
ProcessStartInfo publishPSI = rid is null ? new("dotnet", $"publish -bl MinimalTestApp") : new("dotnet", $"publish -bl MinimalTestApp -r {rid}");
115+
publishPSI.RedirectStandardOutput = true;
116+
publishPSI.RedirectStandardError = true;
117+
Process publish = Process.Start(publishPSI);
117118
Assert.IsNotNull(publish);
118119
await publish.WaitForExitAsync();
119-
Assert.AreEqual(0, publish.ExitCode);
120+
Assert.AreEqual(0, publish.ExitCode, await publish.StandardOutput.ReadToEndAsync() + Environment.NewLine + await publish.StandardError.ReadToEndAsync());
120121

121-
string publishDirectory = Path.Join("MinimalTestApp", "bin", "Debug", "net6.0", "linux-x64", "publish");
122+
string publishDirectory = Path.Join("MinimalTestApp", "bin", "Debug", tfm, rid, "publish");
122123
return publishDirectory;
123124
}
124125

@@ -274,4 +275,56 @@ public async Task EndToEnd_NoAPI()
274275
newProjectDir.Delete(true);
275276
privateNuGetAssets.Delete(true);
276277
}
278+
279+
[DataRow("linux-x86", false, "/app")] // packaging framework-dependent because missing runtime packs for x86 linux.
280+
[DataRow("linux-x64", true, "/app")]
281+
[DataRow("linux-arm", false, "/app")] // packaging framework-dependent because emulating arm on x64 Docker host doesn't work
282+
[DataRow("linux-arm64", false, "/app")] // packaging framework-dependent because emulating arm64 on x64 Docker host doesn't work
283+
[DataRow("win-x64", true, "C:\\app")]
284+
[TestMethod]
285+
public async Task CanPackageForAllSupportedContainerRIDs(string rid, bool isRIDSpecific, string workingDir) {
286+
if (rid == "win-x64") {
287+
Assert.Inconclusive("Cannot run Windows containers on Linux hosts (or at the same time as Linux containers), so skipping for now");
288+
return;
289+
}
290+
string publishDirectory = await BuildLocalApp(tfm : "net7.0", rid : (isRIDSpecific ? rid : null));
291+
292+
// Build the image
293+
Registry registry = new Registry(ContainerHelpers.TryExpandRegistryToUri(DockerRegistryManager.LocalRegistry));
294+
295+
Image x = await registry.GetImageManifest(DockerRegistryManager.BaseImage, DockerRegistryManager.Net7ImageTag, rid);
296+
297+
Layer l = Layer.FromDirectory(publishDirectory, "/app");
298+
299+
x.AddLayer(l);
300+
x.WorkingDirectory = workingDir;
301+
302+
var entryPoint = DecideEntrypoint(rid, isRIDSpecific, "MinimalTestApp", workingDir);
303+
x.SetEntrypoint(entryPoint);
304+
305+
// Load the image into the local Docker daemon
306+
307+
await LocalDocker.Load(x, NewImageName(), rid, DockerRegistryManager.BaseImage);
308+
309+
// Run the image
310+
311+
ProcessStartInfo runInfo = new("docker", $"run --rm --tty {NewImageName()}:{rid}") {
312+
RedirectStandardError = true,
313+
RedirectStandardOutput = true,
314+
};
315+
Process run = Process.Start(runInfo);
316+
Assert.IsNotNull(run);
317+
await run.WaitForExitAsync();
318+
319+
Assert.AreEqual(0, run.ExitCode, run.StandardOutput.ReadToEnd() + Environment.NewLine + run.StandardError.ReadToEnd());
320+
321+
string[] DecideEntrypoint(string rid, bool isRIDSpecific, string appName, string workingDir) {
322+
var binary = rid.StartsWith("win") ? $"{appName}.exe" : appName;
323+
if (isRIDSpecific) {
324+
return new[] { $"{workingDir}/{binary}" };
325+
} else {
326+
return new[] { "dotnet", $"{workingDir}/{binary}.dll" };
327+
}
328+
}
329+
}
277330
}

Test.Microsoft.NET.Build.Containers.Filesystem/RegistryTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public async Task GetFromRegistry()
1515
{
1616
Registry registry = new Registry(ContainerHelpers.TryExpandRegistryToUri(DockerRegistryManager.LocalRegistry));
1717

18-
Image downloadedImage = await registry.GetImageManifest(DockerRegistryManager.BaseImage, DockerRegistryManager.BaseImageTag, "linux-x64");
18+
Image downloadedImage = await registry.GetImageManifest(DockerRegistryManager.BaseImage, DockerRegistryManager.Net6ImageTag, "linux-x64");
1919

2020
Assert.IsNotNull(downloadedImage);
2121
}

0 commit comments

Comments
 (0)