-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for multi-arch install locations (#53763)
* Add support for multiple architectures inside install_locations * Add install_location tests * Fallback to DOTNET_ROOT on win32
- Loading branch information
Showing
18 changed files
with
560 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
src/installer/tests/HostActivation.Tests/InstallLocationCommandResultExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
|
||
using System; | ||
using System.Runtime.InteropServices; | ||
using FluentAssertions; | ||
using Microsoft.DotNet.Cli.Build.Framework; | ||
using Microsoft.DotNet.CoreSetup.Test; | ||
using Xunit; | ||
|
||
namespace HostActivation.Tests | ||
{ | ||
internal static class InstallLocationCommandResultExtensions | ||
{ | ||
private static bool IsRunningInWoW64(string rid) => OperatingSystem.IsWindows() && Environment.Is64BitOperatingSystem && rid.Equals("win-x86"); | ||
|
||
public static AndConstraint<CommandResultAssertions> HaveUsedDotNetRootInstallLocation(this CommandResultAssertions assertion, string installLocation, string rid) | ||
{ | ||
return assertion.HaveUsedDotNetRootInstallLocation(installLocation, rid, null); | ||
} | ||
|
||
public static AndConstraint<CommandResultAssertions> HaveUsedDotNetRootInstallLocation(this CommandResultAssertions assertion, | ||
string installLocation, | ||
string rid, | ||
string arch) | ||
{ | ||
// If no arch is passed and we are on Windows, we need the used RID for determining whether or not we are running on WoW64. | ||
if (string.IsNullOrEmpty(arch)) | ||
Assert.NotNull(rid); | ||
|
||
string expectedEnvironmentVariable = !string.IsNullOrEmpty(arch) ? $"DOTNET_ROOT_{arch.ToUpper()}" : | ||
IsRunningInWoW64(rid) ? "DOTNET_ROOT(x86)" : "DOTNET_ROOT"; | ||
|
||
return assertion.HaveStdErrContaining($"Using environment variable {expectedEnvironmentVariable}=[{installLocation}] as runtime location."); | ||
} | ||
|
||
public static AndConstraint<CommandResultAssertions> HaveUsedConfigFileInstallLocation(this CommandResultAssertions assertion, string installLocation) | ||
{ | ||
return assertion.HaveStdErrContaining($"Using install location '{installLocation}'."); | ||
} | ||
|
||
public static AndConstraint<CommandResultAssertions> HaveUsedGlobalInstallLocation(this CommandResultAssertions assertion, string installLocation) | ||
{ | ||
return assertion.HaveStdErrContaining($"Using global installation location [{installLocation}]"); | ||
} | ||
|
||
public static AndConstraint<CommandResultAssertions> HaveFoundDefaultInstallLocationInConfigFile(this CommandResultAssertions assertion, string installLocation) | ||
{ | ||
return assertion.HaveStdErrContaining($"Found install location path '{installLocation}'."); | ||
} | ||
|
||
public static AndConstraint<CommandResultAssertions> HaveFoundArchSpecificInstallLocationInConfigFile(this CommandResultAssertions assertion, string installLocation, string arch) | ||
{ | ||
return assertion.HaveStdErrContaining($"Found architecture-specific install location path: '{installLocation}' ('{arch}')."); | ||
} | ||
} | ||
} |
184 changes: 184 additions & 0 deletions
184
src/installer/tests/HostActivation.Tests/MultiArchInstallLocation.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.IO; | ||
using System.Runtime.InteropServices; | ||
using Microsoft.DotNet.Cli.Build.Framework; | ||
using Microsoft.DotNet.CoreSetup.Test; | ||
using Microsoft.DotNet.CoreSetup.Test.HostActivation; | ||
using Xunit; | ||
|
||
namespace HostActivation.Tests | ||
{ | ||
public class MultiArchInstallLocation : IClassFixture<MultiArchInstallLocation.SharedTestState> | ||
{ | ||
private SharedTestState sharedTestState; | ||
|
||
public MultiArchInstallLocation(SharedTestState fixture) | ||
{ | ||
sharedTestState = fixture; | ||
} | ||
|
||
[Fact] | ||
public void EnvironmentVariable_CurrentArchitectureIsUsedIfEnvVarSet() | ||
{ | ||
var fixture = sharedTestState.PortableAppFixture | ||
.Copy(); | ||
|
||
var appExe = fixture.TestProject.AppExe; | ||
var arch = fixture.RepoDirProvider.BuildArchitecture.ToUpper(); | ||
Command.Create(appExe) | ||
.EnableTracingAndCaptureOutputs() | ||
.DotNetRoot(fixture.BuiltDotnet.BinPath, arch) | ||
.Execute() | ||
.Should().Pass() | ||
.And.HaveUsedDotNetRootInstallLocation(fixture.BuiltDotnet.BinPath, fixture.CurrentRid, arch); | ||
} | ||
|
||
[Fact] | ||
public void EnvironmentVariable_IfNoArchSpecificEnvVarIsFoundDotnetRootIsUsed() | ||
{ | ||
var fixture = sharedTestState.PortableAppFixture | ||
.Copy(); | ||
|
||
var appExe = fixture.TestProject.AppExe; | ||
var arch = fixture.RepoDirProvider.BuildArchitecture.ToUpper(); | ||
Command.Create(appExe) | ||
.EnableTracingAndCaptureOutputs() | ||
.DotNetRoot(fixture.BuiltDotnet.BinPath) | ||
.Execute() | ||
.Should().Pass() | ||
.And.HaveUsedDotNetRootInstallLocation(fixture.BuiltDotnet.BinPath, fixture.CurrentRid); | ||
} | ||
|
||
[Fact] | ||
public void EnvironmentVariable_ArchSpecificDotnetRootIsUsedOverDotnetRoot() | ||
{ | ||
var fixture = sharedTestState.PortableAppFixture | ||
.Copy(); | ||
|
||
var appExe = fixture.TestProject.AppExe; | ||
var arch = fixture.RepoDirProvider.BuildArchitecture.ToUpper(); | ||
var dotnet = fixture.BuiltDotnet.BinPath; | ||
Command.Create(appExe) | ||
.EnableTracingAndCaptureOutputs() | ||
.DotNetRoot("non_existent_path") | ||
.DotNetRoot(dotnet, arch) | ||
.Execute() | ||
.Should().Pass() | ||
.And.HaveUsedDotNetRootInstallLocation(dotnet, fixture.CurrentRid, arch) | ||
.And.NotHaveStdErrContaining("Using environment variable DOTNET_ROOT="); | ||
} | ||
|
||
[Fact] | ||
[SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")] | ||
public void InstallLocationFile_ArchSpecificLocationIsPickedFirst() | ||
{ | ||
var fixture = sharedTestState.PortableAppFixture | ||
.Copy(); | ||
|
||
var appExe = fixture.TestProject.AppExe; | ||
var arch1 = "someArch"; | ||
var path1 = "x/y/z"; | ||
var arch2 = fixture.RepoDirProvider.BuildArchitecture; | ||
var path2 = "a/b/c"; | ||
|
||
using (var registeredInstallLocationOverride = new RegisteredInstallLocationOverride(appExe)) | ||
{ | ||
registeredInstallLocationOverride.SetInstallLocation(new (string, string)[] { | ||
(string.Empty, path1), | ||
(arch1, path1), | ||
(arch2, path2) | ||
}); | ||
|
||
Command.Create(appExe) | ||
.EnableTracingAndCaptureOutputs() | ||
.ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride) | ||
.DotNetRoot(null) | ||
.Execute() | ||
.Should().HaveFoundDefaultInstallLocationInConfigFile(path1) | ||
.And.HaveFoundArchSpecificInstallLocationInConfigFile(path1, arch1) | ||
.And.HaveFoundArchSpecificInstallLocationInConfigFile(path2, arch2) | ||
.And.HaveUsedGlobalInstallLocation(path2); | ||
} | ||
} | ||
|
||
[Fact] | ||
[SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")] | ||
public void InstallLocationFile_OnlyFirstLineMayNotSpecifyArchitecture() | ||
{ | ||
var fixture = sharedTestState.PortableAppFixture | ||
.Copy(); | ||
|
||
var appExe = fixture.TestProject.AppExe; | ||
using (var registeredInstallLocationOverride = new RegisteredInstallLocationOverride(appExe)) | ||
{ | ||
registeredInstallLocationOverride.SetInstallLocation(new (string, string)[] { | ||
(string.Empty, "a/b/c"), | ||
(string.Empty, "x/y/z"), | ||
}); | ||
Command.Create(appExe) | ||
.EnableTracingAndCaptureOutputs() | ||
.ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride) | ||
.DotNetRoot(null) | ||
.Execute() | ||
.Should().HaveFoundDefaultInstallLocationInConfigFile("a/b/c") | ||
.And.HaveStdErrContaining($"Only the first line in '{registeredInstallLocationOverride.PathValueOverride}' may not have an architecture prefix.") | ||
.And.HaveUsedConfigFileInstallLocation("a/b/c"); | ||
} | ||
} | ||
|
||
[Fact] | ||
[SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")] | ||
public void InstallLocationFile_ReallyLongInstallPathIsParsedCorrectly() | ||
{ | ||
var fixture = sharedTestState.PortableAppFixture | ||
.Copy(); | ||
|
||
var appExe = fixture.TestProject.AppExe; | ||
using (var registeredInstallLocationOverride = new RegisteredInstallLocationOverride(appExe)) | ||
{ | ||
var reallyLongPath = | ||
"reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" + | ||
"reallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreallyreally" + | ||
"reallyreallyreallyreallyreallyreallyreallyreallyreallyreallylongpath"; | ||
registeredInstallLocationOverride.SetInstallLocation((string.Empty, reallyLongPath)); | ||
|
||
Command.Create(appExe) | ||
.EnableTracingAndCaptureOutputs() | ||
.ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride) | ||
.DotNetRoot(null) | ||
.Execute() | ||
.Should().HaveFoundDefaultInstallLocationInConfigFile(reallyLongPath) | ||
.And.HaveUsedConfigFileInstallLocation(reallyLongPath); | ||
} | ||
} | ||
|
||
public class SharedTestState : IDisposable | ||
{ | ||
public string BaseDirectory { get; } | ||
public TestProjectFixture PortableAppFixture { get; } | ||
public RepoDirectoriesProvider RepoDirectories { get; } | ||
public string InstallLocation { get; } | ||
|
||
public SharedTestState() | ||
{ | ||
RepoDirectories = new RepoDirectoriesProvider(); | ||
var fixture = new TestProjectFixture("PortableApp", RepoDirectories); | ||
fixture | ||
.EnsureRestored() | ||
// App Host generation is turned off by default on macOS | ||
.PublishProject(extraArgs: "/p:UseAppHost=true"); | ||
|
||
PortableAppFixture = fixture; | ||
BaseDirectory = Path.GetDirectoryName(PortableAppFixture.SdkDotnet.GreatestVersionHostFxrFilePath); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
PortableAppFixture.Dispose(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.