dotnet-installer/test/dotnet.Tests/GivenThatIWantToManageMulticoreJIT.cs
Peter Huene b1f8eb1d8d
Fix crash when user home directory cannot be determined.
Currently, dotnet will crash with an `ArgumentNullException` if `USERPROFILE`
(Windows) or `HOME` (macOS and Linux) is not set in the environment.  This
is because there is a missing null check after retrieving the environment
variable's value.  Additionally, if either variable is set to an empty string,
a `.dotnet` directory is created in the current directory where dotnet is being
run.

This commit fixes this by printing a graceful error informing the user the home
directory could not be determined and to set `DOTNET_CLI_HOME` to the directory
to use.  This variable will be respected before `USERPROFILE` or `HOME`. It is
likely that CI environments where `HOME` is not set can use `DOTNET_CLI_HOME`
to specify a local temporary location; by using this variable rather than
setting `HOME`, it is guaranteed to only affect dotnet.

It was discussed that we should perhaps fallback to some temporary location if
the home directory could not be determined, but NuGet currently requires `HOME`
to be set to work.  Because of this, it was decided that we should just handle
this case gracefully and provide a way for users to override the home directory
without relying on `USERPROFILE`/`HOME` entirely.

Closes #8053.
2018-05-22 17:34:39 -07:00

115 lines
4.3 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) .NET Foundation and contributors. All rights reserved. 
// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.TestFramework;
using Microsoft.DotNet.Tools.Test.Utilities;
using System;
using System.IO;
using System.Runtime.InteropServices;
using Xunit;
using Xunit.Abstractions;
using FluentAssertions;
using Microsoft.DotNet.PlatformAbstractions;
namespace Microsoft.DotNet.Tests
{
public class GivenThatIWantToManageMulticoreJIT : TestBase
{
ITestOutputHelper _output;
private const string OptimizationProfileFileName = "dotnet";
public GivenThatIWantToManageMulticoreJIT(ITestOutputHelper output)
{
_output = output;
}
[Fact]
public void WhenInvokedThenDotnetWritesOptimizationDataToTheProfileRoot()
{
var testDirectory = TestAssets.CreateTestDirectory();
var testStartTime = GetTruncatedDateTime();
new TestCommand("dotnet")
.WithUserProfileRoot(testDirectory.FullName)
.ExecuteWithCapturedOutput("--help");
var optimizationProfileFilePath = GetOptimizationProfileFilePath(testDirectory.FullName);
new FileInfo(optimizationProfileFilePath)
.Should().Exist("Because dotnet CLI creates it after each run")
.And.HaveLastWriteTimeUtc()
.Which.Should().BeOnOrAfter(testStartTime, "Because dotnet CLI was executed after that time");
}
[Fact]
public void WhenInvokedWithMulticoreJitDisabledThenDotnetDoesNotWriteOptimizationDataToTheProfileRoot()
{
var testDirectory = TestAssets.CreateTestDirectory();
var testStartTime = GetTruncatedDateTime();
new TestCommand("dotnet")
.WithUserProfileRoot(testDirectory.FullName)
.WithEnvironmentVariable("DOTNET_DISABLE_MULTICOREJIT", "1")
.ExecuteWithCapturedOutput("--help");
var optimizationProfileFilePath = GetOptimizationProfileFilePath(testDirectory.FullName);
File.Exists(optimizationProfileFilePath)
.Should().BeFalse("Because multicore JIT is disabled");
}
[Fact]
public void WhenCliRepoBuildsThenDotnetWritesOptimizationDataToTheDefaultProfileRoot()
{
var optimizationProfileFilePath = GetOptimizationProfileFilePath();
File.Exists(optimizationProfileFilePath)
.Should().BeTrue("Because the dotnet building dotnet writes to the default root");
}
private static string GetOptimizationProfileFilePath(string userHomePath = null)
{
return Path.Combine(
GetUserProfileRoot(userHomePath),
GetOptimizationRootPath(GetDotnetVersion()),
OptimizationProfileFileName);
}
private static string GetUserProfileRoot(string overrideUserProfileRoot = null)
{
if (overrideUserProfileRoot != null)
{
return overrideUserProfileRoot;
}
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? Environment.GetEnvironmentVariable("LocalAppData")
: Environment.GetEnvironmentVariable("HOME");
}
private static string GetOptimizationRootPath(string version)
{
var rid = PlatformAbstractions.RuntimeEnvironment.GetRuntimeIdentifier();
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? $@"Microsoft\dotnet\optimizationdata\{version}\{rid}"
: $@".dotnet/optimizationdata/{version}/{rid}";
}
private static string GetDotnetVersion()
{
return new TestCommand("dotnet")
.ExecuteWithCapturedOutput("--version" )
.StdOut
.Trim();
}
private static DateTime GetTruncatedDateTime()
{
var dt = DateTime.UtcNow;
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, 0, dt.Kind);
}
}
}