/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/Core/MSBuildTaskTests/RuntimeHostInfoTests.cs
128 строк
5 KB
Jan Jones
Make RuntimeHostInfoTests more robust (#81080)
11 ноя 2025, 16:59
Не верифицирован
11 ноя 2025, 16:59
a065eae
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.IO; using System.Runtime.InteropServices; using Microsoft.CodeAnalysis.CommandLine; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; using Xunit.Abstractions; namespace Microsoft.CodeAnalysis.BuildTasks.UnitTests; public sealed class RuntimeHostInfoTests(ITestOutputHelper output) : TestBase { private readonly ITestOutputHelper _output = output; /// <summary> /// Normalizes a path by resolving any symbolic links or subst drives (on Windows). /// This ensures paths can be compared even when one is a subst drive (e.g., T:\ -> D:\a\_work\1\s\artifacts\tmp\Debug). /// </summary> private static string NormalizePath(string path) { // Our test infra uses `subst` which the .NET Core's implementation of `ResolveLinkTarget` wouldn't resolve, // hence we always use our Win32 polyfill on Windows to ensure paths are fully normalized and can be compared in tests. var resolvedPath = PlatformInformation.IsWindows ? NativeMethods.ResolveLinkTargetWin32(path, returnFinalTarget: true) : File.ResolveLinkTarget(path, returnFinalTarget: true); if (resolvedPath != null) { return resolvedPath.FullName; } return path; } [Fact, WorkItem("https://github.com/dotnet/msbuild/issues/12669")] public void DotNetInPath() { using var tempRoot = new TempRoot(); var testDir = tempRoot.CreateDirectory(); var globalDotNetDir = testDir.CreateDirectory("global-dotnet"); var globalDotNetExe = globalDotNetDir.CreateFile($"dotnet{PlatformInformation.ExeExtension}"); var result = ApplyEnvironmentVariables( [ new("PATH", globalDotNetDir.Path), new(RuntimeHostInfo.DotNetHostPathEnvironmentName, ""), new(RuntimeHostInfo.DotNetExperimentalHostPathEnvironmentName, ""), ], () => RuntimeHostInfo.GetToolDotNetRoot(_output.WriteLine)); Assert.NotNull(result); AssertEx.Equal(NormalizePath(globalDotNetDir.Path), NormalizePath(result)); } [Fact, WorkItem("https://github.com/dotnet/msbuild/issues/12669")] public void DotNetInPath_None() { var result = ApplyEnvironmentVariables( [ new("PATH", ""), new(RuntimeHostInfo.DotNetHostPathEnvironmentName, ""), new(RuntimeHostInfo.DotNetExperimentalHostPathEnvironmentName, ""), ], () => RuntimeHostInfo.GetToolDotNetRoot(_output.WriteLine)); Assert.Null(result); } [Fact, WorkItem("https://github.com/dotnet/msbuild/issues/12669")] public void DotNetInPath_Symlinked() { using var tempRoot = new TempRoot(); var testDir = tempRoot.CreateDirectory(); var globalDotNetDir = testDir.CreateDirectory("global-dotnet"); var globalDotNetExe = globalDotNetDir.CreateFile($"dotnet{PlatformInformation.ExeExtension}"); var binDir = testDir.CreateDirectory("bin"); var symlinkPath = Path.Combine(binDir.Path, $"dotnet{PlatformInformation.ExeExtension}"); // Create symlink from binDir to the actual dotnet executable File.CreateSymbolicLink(path: symlinkPath, pathToTarget: globalDotNetExe.Path); var result = ApplyEnvironmentVariables( [ new("PATH", binDir.Path), new(RuntimeHostInfo.DotNetHostPathEnvironmentName, ""), new(RuntimeHostInfo.DotNetExperimentalHostPathEnvironmentName, ""), ], () => RuntimeHostInfo.GetToolDotNetRoot(_output.WriteLine)); Assert.NotNull(result); AssertEx.Equal(NormalizePath(globalDotNetDir.Path), NormalizePath(result)); } } #if !NET file static class TestNativeMethods { extension(File) { /// <remarks> /// Only used by tests currently (might need some hardening if this is to be used by production code). /// </remarks> public static void CreateSymbolicLink(string path, string pathToTarget) { bool ok = CreateSymbolicLink( lpSymlinkFileName: path, lpTargetFileName: pathToTarget, dwFlags: SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE); if (!ok) { throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); } } } [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool CreateSymbolicLink( string lpSymlinkFileName, string lpTargetFileName, uint dwFlags); private const uint SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x2; } #endif