Skip to content

Commit 072cbae

Browse files
authored
Split install_location to file-per-architecture (#59404)
On non-Windows we used install_location file with multiple lines which contained locations per-architecture (and the default). This changes the host to use separate file for each architecture: * `install_location_<arch>` for the architecture specific * `install_location` for the "legacy" file This is a much easier format for installers to handle (and it also simplifies the apphost code a little bit). Adapted tests to the new behavior. Removed some tests which don't make sense anymore. Some small test cleanup to deduplicate code. Changed the test-only env. variable to point to the directory with configuration files instead of to the configuration file itself.
1 parent 12183cb commit 072cbae

6 files changed

Lines changed: 96 additions & 140 deletions

File tree

src/installer/tests/HostActivation.Tests/Constants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public static class TestOnlyEnvironmentVariables
5353
public const string DefaultInstallPath = "_DOTNET_TEST_DEFAULT_INSTALL_PATH";
5454
public const string RegistryPath = "_DOTNET_TEST_REGISTRY_PATH";
5555
public const string GloballyRegisteredPath = "_DOTNET_TEST_GLOBALLY_REGISTERED_PATH";
56-
public const string InstallLocationFilePath = "_DOTNET_TEST_INSTALL_LOCATION_FILE_PATH";
56+
public const string InstallLocationPath = "_DOTNET_TEST_INSTALL_LOCATION_PATH";
5757
}
5858

5959
public static class RuntimeId

src/installer/tests/HostActivation.Tests/InstallLocationCommandResultExtensions.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44

55
using System;
6+
using System.IO;
67
using System.Runtime.InteropServices;
78
using FluentAssertions;
89
using Microsoft.DotNet.Cli.Build.Framework;
@@ -45,14 +46,14 @@ public static AndConstraint<CommandResultAssertions> HaveUsedGlobalInstallLocati
4546
return assertion.HaveStdErrContaining($"Using global installation location [{installLocation}]");
4647
}
4748

48-
public static AndConstraint<CommandResultAssertions> HaveFoundDefaultInstallLocationInConfigFile(this CommandResultAssertions assertion, string installLocation)
49+
public static AndConstraint<CommandResultAssertions> HaveLookedForDefaultInstallLocation(this CommandResultAssertions assertion, string installLocationPath)
4950
{
50-
return assertion.HaveStdErrContaining($"Found install location path '{installLocation}'.");
51+
return assertion.HaveStdErrContaining($"Looking for install_location file in '{Path.Combine(installLocationPath, "install_location")}'.");
5152
}
5253

53-
public static AndConstraint<CommandResultAssertions> HaveFoundArchSpecificInstallLocationInConfigFile(this CommandResultAssertions assertion, string installLocation, string arch)
54+
public static AndConstraint<CommandResultAssertions> HaveLookedForArchitectureSpecificInstallLocation(this CommandResultAssertions assertion, string installLocationPath, string architecture)
5455
{
55-
return assertion.HaveStdErrContaining($"Found architecture-specific install location path: '{installLocation}' ('{arch}').");
56+
return assertion.HaveStdErrContaining($"Looking for architecture specific install_location file in '{Path.Combine(installLocationPath, "install_location_" + architecture.ToLowerInvariant())}'.");
5657
}
5758
}
5859
}

src/installer/tests/HostActivation.Tests/MultiArchInstallLocation.cs

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -174,40 +174,14 @@ public void InstallLocationFile_ArchSpecificLocationIsPickedFirst()
174174

175175
if (!OperatingSystem.IsWindows())
176176
{
177-
result.Should().HaveFoundDefaultInstallLocationInConfigFile(path1)
178-
.And.HaveFoundArchSpecificInstallLocationInConfigFile(path1, arch1)
179-
.And.HaveFoundArchSpecificInstallLocationInConfigFile(path2, arch2);
177+
result.Should()
178+
.HaveLookedForArchitectureSpecificInstallLocation(registeredInstallLocationOverride.PathValueOverride, arch2);
180179
}
181180

182181
result.Should().HaveUsedGlobalInstallLocation(path2);
183182
}
184183
}
185184

186-
[Fact]
187-
[SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")]
188-
public void InstallLocationFile_OnlyFirstLineMayNotSpecifyArchitecture()
189-
{
190-
var fixture = sharedTestState.PortableAppFixture
191-
.Copy();
192-
193-
var appExe = fixture.TestProject.AppExe;
194-
using (var registeredInstallLocationOverride = new RegisteredInstallLocationOverride(appExe))
195-
{
196-
registeredInstallLocationOverride.SetInstallLocation(new (string, string)[] {
197-
(string.Empty, "a/b/c"),
198-
(string.Empty, "x/y/z"),
199-
});
200-
Command.Create(appExe)
201-
.EnableTracingAndCaptureOutputs()
202-
.ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride)
203-
.DotNetRoot(null)
204-
.Execute()
205-
.Should().HaveFoundDefaultInstallLocationInConfigFile("a/b/c")
206-
.And.HaveStdErrContaining($"Only the first line in '{registeredInstallLocationOverride.PathValueOverride}' may not have an architecture prefix.")
207-
.And.HaveUsedConfigFileInstallLocation("a/b/c");
208-
}
209-
}
210-
211185
[Fact]
212186
[SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")]
213187
public void InstallLocationFile_ReallyLongInstallPathIsParsedCorrectly()
@@ -229,7 +203,7 @@ public void InstallLocationFile_ReallyLongInstallPathIsParsedCorrectly()
229203
.ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride)
230204
.DotNetRoot(null)
231205
.Execute()
232-
.Should().HaveFoundDefaultInstallLocationInConfigFile(reallyLongPath)
206+
.Should().HaveLookedForDefaultInstallLocation(registeredInstallLocationOverride.PathValueOverride)
233207
.And.HaveUsedConfigFileInstallLocation(reallyLongPath);
234208
}
235209
}
@@ -247,16 +221,15 @@ public void InstallLocationFile_MissingFile()
247221
{
248222
Directory.CreateDirectory(testArtifactsPath);
249223

250-
string directory = Path.Combine(testArtifactsPath, "installLocationOverride");
251-
Directory.CreateDirectory(directory);
252-
string nonExistentLocationFile = Path.Combine(directory, "install_location");
224+
string installLocationDirectory = Path.Combine(testArtifactsPath, "installLocationOverride");
225+
Directory.CreateDirectory(installLocationDirectory);
253226
string defaultInstallLocation = Path.Combine(testArtifactsPath, "defaultInstallLocation");
254227

255228
Command.Create(appExe)
256229
.CaptureStdErr()
257230
.EnvironmentVariable(
258-
Constants.TestOnlyEnvironmentVariables.InstallLocationFilePath,
259-
nonExistentLocationFile)
231+
Constants.TestOnlyEnvironmentVariables.InstallLocationPath,
232+
installLocationDirectory)
260233
.EnvironmentVariable(
261234
Constants.TestOnlyEnvironmentVariables.DefaultInstallPath,
262235
defaultInstallLocation)

src/installer/tests/HostActivation.Tests/NativeHosting/Nethost.cs

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using HostActivation.Tests;
45
using Microsoft.DotNet.Cli.Build.Framework;
56
using System;
67
using System.IO;
@@ -216,12 +217,21 @@ public void GetHostFxrPath_InstallLocationFile(string value, bool shouldUseArchS
216217
.DotNetRoot(null)
217218
.Execute();
218219

219-
result.Should().HaveStdErrContaining($"Looking for install_location file in '{registeredInstallLocationOverride.PathValueOverride}'.");
220+
if (shouldUseArchSpecificInstallLocation)
221+
{
222+
result.Should().HaveLookedForArchitectureSpecificInstallLocation(
223+
registeredInstallLocationOverride.PathValueOverride,
224+
sharedState.RepoDirectories.BuildArchitecture);
225+
}
226+
else
227+
{
228+
result.Should().HaveLookedForDefaultInstallLocation(registeredInstallLocationOverride.PathValueOverride);
229+
}
220230

221231
if (shouldPass)
222232
{
223233
result.Should().Pass()
224-
.And.HaveStdErrContaining($"Using install location '{installLocation}'.")
234+
.And.HaveUsedConfigFileInstallLocation(installLocation)
225235
.And.HaveStdOutContaining($"hostfxr_path: {sharedState.HostFxrPath}".ToLower());
226236
}
227237
else
@@ -234,35 +244,6 @@ public void GetHostFxrPath_InstallLocationFile(string value, bool shouldUseArchS
234244
}
235245
}
236246

237-
[Fact]
238-
[SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")]
239-
public void GetHostFxrPath_GlobalInstallation_HasMoreThanOneDefaultInstallationPath()
240-
{
241-
string installLocation = Path.Combine(sharedState.ValidInstallRoot, "dotnet");
242-
using (var registeredInstallLocationOverride = new RegisteredInstallLocationOverride(sharedState.NethostPath))
243-
{
244-
registeredInstallLocationOverride.SetInstallLocation(new (string, string)[] {
245-
(string.Empty, installLocation), (string.Empty, installLocation)
246-
});
247-
248-
CommandResult result = Command.Create(sharedState.NativeHostPath, GetHostFxrPath)
249-
.EnableTracingAndCaptureOutputs()
250-
.ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride)
251-
.EnvironmentVariable( // Redirect the default install location to an invalid location so that it doesn't cause the test to pass
252-
Constants.TestOnlyEnvironmentVariables.DefaultInstallPath,
253-
sharedState.InvalidInstallRoot)
254-
.DotNetRoot(null)
255-
.Execute();
256-
257-
result.Should().Pass()
258-
.And.HaveStdErrContaining($"Looking for install_location file in '{registeredInstallLocationOverride.PathValueOverride}'.")
259-
.And.HaveStdErrContaining($"Found install location path '{installLocation}'.")
260-
.And.HaveStdErrContaining($"Only the first line in '{registeredInstallLocationOverride.PathValueOverride}' may not have an architecture prefix.")
261-
.And.HaveStdErrContaining($"Using install location '{installLocation}'.")
262-
.And.HaveStdOutContaining($"hostfxr_path: {sharedState.HostFxrPath}".ToLower());
263-
}
264-
}
265-
266247
[Fact]
267248
[SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")]
268249
public void GetHostFxrPath_GlobalInstallation_HasNoDefaultInstallationPath()
@@ -285,9 +266,10 @@ public void GetHostFxrPath_GlobalInstallation_HasNoDefaultInstallationPath()
285266
.Execute();
286267

287268
result.Should().Pass()
288-
.And.HaveStdErrContaining($"Looking for install_location file in '{registeredInstallLocationOverride.PathValueOverride}'.")
289-
.And.HaveStdErrContaining($"Found architecture-specific install location path: '{installLocation}' ('{sharedState.RepoDirectories.BuildArchitecture.ToLower()}').")
290-
.And.HaveStdErrContaining($"Using install location '{installLocation}'.")
269+
.And.HaveLookedForArchitectureSpecificInstallLocation(
270+
registeredInstallLocationOverride.PathValueOverride,
271+
sharedState.RepoDirectories.BuildArchitecture)
272+
.And.HaveUsedConfigFileInstallLocation(installLocation)
291273
.And.HaveStdOutContaining($"hostfxr_path: {sharedState.HostFxrPath}".ToLower());
292274
}
293275
}
@@ -314,10 +296,10 @@ public void GetHostFxrPath_GlobalInstallation_ArchitectureSpecificPathIsPickedOv
314296
.Execute();
315297

316298
result.Should().Pass()
317-
.And.HaveStdErrContaining($"Looking for install_location file in '{registeredInstallLocationOverride.PathValueOverride}'.")
318-
.And.HaveStdErrContaining($"Found install location path '{installLocation}/a/b/c'.")
319-
.And.HaveStdErrContaining($"Found architecture-specific install location path: '{installLocation}' ('{sharedState.RepoDirectories.BuildArchitecture.ToLower()}').")
320-
.And.HaveStdErrContaining($"Using install location '{installLocation}'.")
299+
.And.HaveLookedForArchitectureSpecificInstallLocation(
300+
registeredInstallLocationOverride.PathValueOverride,
301+
sharedState.RepoDirectories.BuildArchitecture)
302+
.And.HaveUsedConfigFileInstallLocation(installLocation)
321303
.And.HaveStdOutContaining($"hostfxr_path: {sharedState.HostFxrPath}".ToLower());
322304
}
323305
}

src/installer/tests/HostActivation.Tests/RegisteredInstallLocationOverride.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,11 @@ public RegisteredInstallLocationOverride(string productBinaryPath)
5656
// On Linux/macOS the install location is registered in a file which is normally
5757
// located in /etc/dotnet/install_location
5858
// So we need to redirect it to a different place here.
59-
string directory = Path.Combine(TestArtifact.TestArtifactsPath, "installLocationOverride");
59+
string directory = Path.Combine(TestArtifact.TestArtifactsPath, "installLocationOverride" + Process.GetCurrentProcess().Id.ToString());
60+
if (Directory.Exists(directory))
61+
Directory.Delete(directory, true);
6062
Directory.CreateDirectory(directory);
61-
PathValueOverride = Path.Combine(directory, "install_location." + Process.GetCurrentProcess().Id.ToString());
62-
File.WriteAllText(PathValueOverride, "");
63+
PathValueOverride = directory;
6364
}
6465
}
6566

@@ -78,9 +79,12 @@ public void SetInstallLocation(params (string Architecture, string Path)[] locat
7879
}
7980
else
8081
{
81-
File.WriteAllText(PathValueOverride, string.Join(Environment.NewLine,
82-
locations.Select(l => string.Format("{0}{1}",
83-
(!string.IsNullOrWhiteSpace(l.Architecture) ? l.Architecture + "=" : ""), l.Path))));
82+
foreach (var location in locations)
83+
{
84+
string installLocationFileName = "install_location" +
85+
(!string.IsNullOrWhiteSpace(location.Architecture) ? ("_" + location.Architecture) : string.Empty);
86+
File.WriteAllText(Path.Combine(PathValueOverride, installLocationFileName), location.Path);
87+
}
8488
}
8589
}
8690

@@ -127,7 +131,7 @@ public static Command ApplyRegisteredInstallLocationOverride(
127131
else
128132
{
129133
return command.EnvironmentVariable(
130-
Constants.TestOnlyEnvironmentVariables.InstallLocationFilePath,
134+
Constants.TestOnlyEnvironmentVariables.InstallLocationPath,
131135
registeredInstallLocationOverride.PathValueOverride);
132136
}
133137
}

0 commit comments

Comments
 (0)