diff --git a/Directory.Build.targets b/Directory.Build.targets
index 1b047230fe58..c5d5576ee337 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -25,16 +25,6 @@
-
-
-
-
- false
- false
-
-
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 2cb60d612604..0f4331677215 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -54,7 +54,7 @@
-
+
@@ -75,11 +75,11 @@
-
+
-
+
-
+
@@ -144,10 +144,9 @@
-
-
-
+
+
+ 3.2.2
8.0.0-beta.23607.1
0.15.6
0.14.0
diff --git a/eng/dependabot/Packages.props b/eng/dependabot/Packages.props
index 76181ba6cfc0..6128e5be0b3d 100644
--- a/eng/dependabot/Packages.props
+++ b/eng/dependabot/Packages.props
@@ -7,7 +7,7 @@
-
+
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/DoNotUseCountWhenAnyCanBeUsedTests.Data.cs b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/DoNotUseCountWhenAnyCanBeUsedTests.Data.cs
index 1df929f8c851..baee2c842362 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/DoNotUseCountWhenAnyCanBeUsedTests.Data.cs
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.NetCore.Analyzers/Performance/DoNotUseCountWhenAnyCanBeUsedTests.Data.cs
@@ -3,6 +3,7 @@
using Microsoft.CodeAnalysis.Operations;
using Xunit;
+using Xunit.Sdk;
namespace Microsoft.NetCore.Analyzers.Performance.UnitTests
{
@@ -31,7 +32,7 @@ private static TheoryData Build_LeftCount_NoDiagn
var theoryData = new TheoryData();
foreach (var withPredicate in new[] { false, true })
{
- foreach (var fixerData in LeftCount_NoDiagnostic_TheoryData)
+ foreach (var fixerData in LeftCount_NoDiagnostic_TheoryData.Select(r => ((ITheoryDataRow)r).GetData()))
{
theoryData.Add((BinaryOperatorKind)fixerData[0], (int)fixerData[1], withPredicate);
}
@@ -63,7 +64,7 @@ private static TheoryData Build_RightCount_NoDiag
var theoryData = new TheoryData();
foreach (var withPredicate in new[] { false, true })
{
- foreach (var fixerData in RightCount_NoDiagnostic_TheoryData)
+ foreach (var fixerData in RightCount_NoDiagnostic_TheoryData.Select(r => ((ITheoryDataRow)r).GetData()))
{
theoryData.Add((int)fixerData[0], (BinaryOperatorKind)fixerData[1], withPredicate);
}
@@ -89,7 +90,7 @@ private static TheoryData Build_LeftCount_F
var theoryData = new TheoryData();
foreach (var withPredicate in new[] { false, true })
{
- foreach (var fixerData in LeftCount_Fixer_TheoryData)
+ foreach (var fixerData in LeftCount_Fixer_TheoryData.Select(r => ((ITheoryDataRow)r).GetData()))
{
theoryData.Add((BinaryOperatorKind)fixerData[0], (int)fixerData[1], withPredicate, (bool)fixerData[2]);
}
@@ -103,7 +104,7 @@ private static TheoryData Build_LeftCount_F
private static TheoryData Build_LeftCount_Diagnostic_TheoryData()
{
var theoryData = new TheoryData();
- foreach (var fixerData in LeftCount_Fixer_TheoryData)
+ foreach (var fixerData in LeftCount_Fixer_TheoryData.Select(r => ((ITheoryDataRow)r).GetData()))
{
theoryData.Add((BinaryOperatorKind)fixerData[0], (int)fixerData[1]);
}
@@ -128,7 +129,7 @@ private static TheoryData Build_RightCount_
var theoryData = new TheoryData();
foreach (var withPredicate in new[] { false, true })
{
- foreach (var fixerData in RightCount_Fixer_TheoryData)
+ foreach (var fixerData in RightCount_Fixer_TheoryData.Select(r => ((ITheoryDataRow)r).GetData()))
{
theoryData.Add((int)fixerData[0], (BinaryOperatorKind)fixerData[1], withPredicate, (bool)fixerData[2]);
}
@@ -142,7 +143,7 @@ private static TheoryData Build_RightCount_
private static TheoryData Build_RightCount_Diagnostic_TheoryData()
{
var theoryData = new TheoryData();
- foreach (var fixerData in RightCount_Fixer_TheoryData)
+ foreach (var fixerData in RightCount_Fixer_TheoryData.Select(r => ((ITheoryDataRow)r).GetData()))
{
theoryData.Add((int)fixerData[0], (BinaryOperatorKind)fixerData[1]);
}
diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Test.Utilities/Test.Utilities.csproj b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Test.Utilities/Test.Utilities.csproj
index 5f6dff4ac8e9..9cde946facb9 100644
--- a/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Test.Utilities/Test.Utilities.csproj
+++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Test.Utilities/Test.Utilities.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/test/Common/Program.cs b/test/Common/Program.cs
deleted file mode 100644
index 472ba48088b4..000000000000
--- a/test/Common/Program.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace Microsoft.NET.TestFramework;
-
-#pragma warning disable SA1205 // Partial elements should declare access
-partial class Program
-#pragma warning restore SA1205 // Partial elements should declare access
-{
- public static int Main(string[] args)
- {
- var newArgs = new List(args);
- newArgs.Insert(0, typeof(Program).Assembly.Location);
-
- var xunitReturnCode = Xunit.ConsoleClient.Program.Main(newArgs.ToArray());
-
- int returnCode;
- if (Environment.GetEnvironmentVariable("HELIX_WORKITEM_PAYLOAD") != null)
- {
- // If we are running in Helix, we want the test work item to return 0 unless there's a crash
- Console.WriteLine($"Xunit return code: {xunitReturnCode}");
- returnCode = 0;
- }
- else
- {
- // If we are running locally, we to return the xunit return code
- returnCode = xunitReturnCode;
- }
-
- return returnCode;
- }
-}
diff --git a/test/Directory.Build.props b/test/Directory.Build.props
index cff60a43a07d..66a00f061c87 100644
--- a/test/Directory.Build.props
+++ b/test/Directory.Build.props
@@ -14,9 +14,12 @@
- $(NoWarn);NU5125;NU5123
+
+ $(NoWarn);NU5125;NU5123;xUnit1051
- false
+
+ false
embedded
diff --git a/test/Directory.Build.targets b/test/Directory.Build.targets
index edd1cbc3f09a..28bd22c5cdb6 100644
--- a/test/Directory.Build.targets
+++ b/test/Directory.Build.targets
@@ -5,6 +5,8 @@
+ XUnitV3
+ Exe
true
@@ -17,11 +19,6 @@
-
-
-
-
-
diff --git a/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs b/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs
index a3e8eb3e64e4..c8bfa9ef0dc4 100644
--- a/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs
+++ b/test/HelixTasks/SDKCustomCreateXUnitWorkItemsWithTestExclusion.cs
@@ -36,6 +36,11 @@ public class SDKCustomCreateXUnitWorkItemsWithTestExclusion : Build.Utilities.Ta
[Required]
public bool IsPosixShell { get; set; }
+ ///
+ /// The runtime identifier of the target Helix queue (e.g. osx-arm64, linux-x64).
+ ///
+ public string TargetRid { get; set; } = "";
+
///
/// Optional timeout for all created workitems
/// Defaults to 300s
@@ -158,7 +163,15 @@ private async Task ExecuteAsync()
var testFilter = string.IsNullOrEmpty(assemblyPartitionInfo.ClassListArgumentString) ? "" : $"--filter \"{assemblyPartitionInfo.ClassListArgumentString}\"";
- string command = $"{driver} test {assemblyName} -e HELIX_WORK_ITEM_TIMEOUT={timeout} {testExecutionDirectory} {msbuildAdditionalSdkResolverFolder} " +
+ // xUnit v3 tests run out-of-process: the VSTest adapter launches the AppHost executable.
+ // On POSIX, the execute bit is lost when the Helix SDK packages the payload as a zip archive,
+ // so we need to restore it before running.
+ string exeName = Path.GetFileNameWithoutExtension(assemblyName);
+ string chmodPrefix = IsPosixShell ? $"chmod +x {exeName} && " : "";
+ // On macOS, ad-hoc sign the test exe with get-task-allow entitlement so createdump can attach via task_for_pid for crash dumps.
+ string codesignPrefix = IsPosixShell && TargetRid.StartsWith("osx") ? $"codesign -s - -f --entitlements $HELIX_CORRELATION_PAYLOAD/t/helix-debug-entitlements.plist {exeName} && " : "";
+
+ string command = $"{chmodPrefix}{codesignPrefix}{driver} test {assemblyName} -e HELIX_WORK_ITEM_TIMEOUT={timeout} {testExecutionDirectory} {msbuildAdditionalSdkResolverFolder} " +
$"{(XUnitArguments != null ? " " + XUnitArguments : "")} --results-directory .{Path.DirectorySeparatorChar} --logger trx --logger \"console;verbosity=detailed\" --blame-hang --blame-hang-timeout 60m {testFilter} {enableDiagLogging} {arguments}";
Log.LogMessage($"Creating work item with properties Identity: {assemblyName}, PayloadDirectory: {publishDirectory}, Command: {command}");
diff --git a/test/Microsoft.DotNet.HotReload.Test.Utilities/DebugTestOutputLogger.cs b/test/Microsoft.DotNet.HotReload.Test.Utilities/DebugTestOutputLogger.cs
index 411cbb360967..dd5cd0d09508 100644
--- a/test/Microsoft.DotNet.HotReload.Test.Utilities/DebugTestOutputLogger.cs
+++ b/test/Microsoft.DotNet.HotReload.Test.Utilities/DebugTestOutputLogger.cs
@@ -3,19 +3,35 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
-using Xunit.Abstractions;
+using Xunit;
namespace Microsoft.DotNet.Watch.UnitTests;
public class DebugTestOutputLogger(ITestOutputHelper logger) : ITestOutputHelper
{
+ private readonly StringBuilder _output = new();
+
public event Action? OnMessage;
+ public string Output => _output.ToString();
+
public void Log(string message, [CallerFilePath] string? testPath = null, [CallerLineNumber] int testLine = 0)
=> WriteLine($"[TEST {Path.GetFileName(testPath)}:{testLine}] {message}");
+ public void Write(string message)
+ {
+ _output.Append(message);
+ Debug.Write(message);
+ logger.Write(message);
+ OnMessage?.Invoke(message);
+ }
+
+ public void Write(string format, params object[] args)
+ => Write(string.Format(format, args));
+
public void WriteLine(string message)
{
+ _output.AppendLine(message);
Debug.WriteLine(message);
try
diff --git a/test/Microsoft.DotNet.HotReload.Test.Utilities/Microsoft.DotNet.HotReload.Test.Utilities.csproj b/test/Microsoft.DotNet.HotReload.Test.Utilities/Microsoft.DotNet.HotReload.Test.Utilities.csproj
index f267d2070886..113689abef9a 100644
--- a/test/Microsoft.DotNet.HotReload.Test.Utilities/Microsoft.DotNet.HotReload.Test.Utilities.csproj
+++ b/test/Microsoft.DotNet.HotReload.Test.Utilities/Microsoft.DotNet.HotReload.Test.Utilities.csproj
@@ -13,6 +13,7 @@
+
diff --git a/test/Microsoft.DotNet.HotReload.Test.Utilities/TestLogger.cs b/test/Microsoft.DotNet.HotReload.Test.Utilities/TestLogger.cs
index be7b5f747c80..0b8e8b83f2d1 100644
--- a/test/Microsoft.DotNet.HotReload.Test.Utilities/TestLogger.cs
+++ b/test/Microsoft.DotNet.HotReload.Test.Utilities/TestLogger.cs
@@ -3,7 +3,7 @@
using System.Collections.Immutable;
using Microsoft.Extensions.Logging;
-using Xunit.Abstractions;
+using Xunit;
namespace Microsoft.DotNet.Watch.UnitTests;
diff --git a/test/Microsoft.DotNet.HotReload.Test.Utilities/WatchSdkTest.cs b/test/Microsoft.DotNet.HotReload.Test.Utilities/WatchSdkTest.cs
index ece62d264dac..eb58e192490a 100644
--- a/test/Microsoft.DotNet.HotReload.Test.Utilities/WatchSdkTest.cs
+++ b/test/Microsoft.DotNet.HotReload.Test.Utilities/WatchSdkTest.cs
@@ -3,7 +3,7 @@
using System.Runtime.CompilerServices;
using Microsoft.NET.TestFramework;
-using Xunit.Abstractions;
+using Xunit;
namespace Microsoft.DotNet.Watch.UnitTests;
diff --git a/test/Microsoft.DotNet.HotReload.Test.Utilities/WatchableApp.cs b/test/Microsoft.DotNet.HotReload.Test.Utilities/WatchableApp.cs
index 2dacad1cb33a..8fa474f5caac 100644
--- a/test/Microsoft.DotNet.HotReload.Test.Utilities/WatchableApp.cs
+++ b/test/Microsoft.DotNet.HotReload.Test.Utilities/WatchableApp.cs
@@ -7,7 +7,6 @@
using Microsoft.DotNet.Cli.Utils;
using Microsoft.NET.TestFramework;
using Xunit;
-using Xunit.Abstractions;
namespace Microsoft.DotNet.Watch.UnitTests
{
diff --git a/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerIsAvailableAndSupportsArchFact.cs b/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerIsAvailableAndSupportsArchFact.cs
index ae0e76f3c153..404b99624234 100644
--- a/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerIsAvailableAndSupportsArchFact.cs
+++ b/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerIsAvailableAndSupportsArchFact.cs
@@ -1,11 +1,18 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Runtime.CompilerServices;
+
namespace Microsoft.NET.Build.Containers.IntegrationTests;
public class DockerIsAvailableAndSupportsArchFactAttribute : FactAttribute
{
- public DockerIsAvailableAndSupportsArchFactAttribute(string arch, bool checkContainerdStoreAvailability = false)
+ public DockerIsAvailableAndSupportsArchFactAttribute(
+ string arch,
+ bool checkContainerdStoreAvailability = false,
+ [CallerFilePath] string? sourceFilePath = null,
+ [CallerLineNumber] int sourceLineNumber = 0)
+ : base(sourceFilePath, sourceLineNumber)
{
if (!DockerSupportsArchHelper.DaemonIsAvailable)
{
diff --git a/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerIsAvailableAndSupportsArchTheory.cs b/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerIsAvailableAndSupportsArchTheory.cs
index 382e57604fab..dffff31792da 100644
--- a/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerIsAvailableAndSupportsArchTheory.cs
+++ b/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerIsAvailableAndSupportsArchTheory.cs
@@ -1,11 +1,18 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Runtime.CompilerServices;
+
namespace Microsoft.NET.Build.Containers.IntegrationTests;
public class DockerIsAvailableAndSupportsArchTheoryAttribute : TheoryAttribute
{
- public DockerIsAvailableAndSupportsArchTheoryAttribute(string arch, bool checkContainerdStoreAvailability = false)
+ public DockerIsAvailableAndSupportsArchTheoryAttribute(
+ string arch,
+ bool checkContainerdStoreAvailability = false,
+ [CallerFilePath] string? sourceFilePath = null,
+ [CallerLineNumber] int sourceLineNumber = 0)
+ : base(sourceFilePath, sourceLineNumber)
{
if (!DockerSupportsArchHelper.DaemonIsAvailable)
{
@@ -20,4 +27,4 @@ public DockerIsAvailableAndSupportsArchTheoryAttribute(string arch, bool checkCo
base.Skip = $"Skipping test because Docker daemon does not support {arch}.";
}
}
-}
\ No newline at end of file
+}
diff --git a/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryManager.cs b/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryManager.cs
index 5e3de400ddc3..e5b1de42ad57 100644
--- a/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryManager.cs
+++ b/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerRegistryManager.cs
@@ -3,7 +3,6 @@
using Microsoft.DotNet.Cli.Utils;
using Microsoft.Extensions.Logging;
-using Xunit.Sdk;
namespace Microsoft.NET.Build.Containers.IntegrationTests;
diff --git a/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerSupportsArchInlineData.cs b/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerSupportsArchInlineData.cs
index 7944436b39c9..502bc3c98e22 100644
--- a/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerSupportsArchInlineData.cs
+++ b/test/Microsoft.NET.Build.Containers.IntegrationTests/DockerSupportsArchInlineData.cs
@@ -3,7 +3,7 @@
using System.Reflection;
using System.Text.Json;
-using Xunit.Sdk;
+using Xunit.v3;
namespace Microsoft.NET.Build.Containers.IntegrationTests;
@@ -18,17 +18,19 @@ public DockerSupportsArchInlineData(string arch, params object[] data)
_data = data;
}
- public override IEnumerable
public string? Reason { get; set; }
- public RequiresMSBuildVersionFactAttribute(string version)
+ public RequiresMSBuildVersionFactAttribute(string version, [CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = 0)
+ : base(sourceFilePath, sourceLineNumber)
{
RequiresMSBuildVersionTheoryAttribute.CheckForRequiredMSBuildVersion(this, version);
}
diff --git a/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionTheoryAttribute.cs b/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionTheoryAttribute.cs
index b09480505f59..23f9bd6138ac 100644
--- a/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionTheoryAttribute.cs
+++ b/test/Microsoft.NET.TestFramework/Attributes/RequiresMSBuildVersionTheoryAttribute.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Runtime.CompilerServices;
+
namespace Microsoft.NET.TestFramework
{
public class RequiresMSBuildVersionTheoryAttribute : TheoryAttribute
@@ -10,7 +12,8 @@ public class RequiresMSBuildVersionTheoryAttribute : TheoryAttribute
///
public string? Reason { get; set; }
- public RequiresMSBuildVersionTheoryAttribute(string version)
+ public RequiresMSBuildVersionTheoryAttribute(string version, [CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = 0)
+ : base(sourceFilePath, sourceLineNumber)
{
CheckForRequiredMSBuildVersion(this, version);
}
diff --git a/test/Microsoft.NET.TestFramework/Attributes/RequiresSpecificFrameworkFactAttribute.cs b/test/Microsoft.NET.TestFramework/Attributes/RequiresSpecificFrameworkFactAttribute.cs
index 8bbd151553f6..d3a76dcd5e97 100644
--- a/test/Microsoft.NET.TestFramework/Attributes/RequiresSpecificFrameworkFactAttribute.cs
+++ b/test/Microsoft.NET.TestFramework/Attributes/RequiresSpecificFrameworkFactAttribute.cs
@@ -3,11 +3,14 @@
#if NETCOREAPP
+using System.Runtime.CompilerServices;
+
namespace Microsoft.NET.TestFramework
{
public class RequiresSpecificFrameworkFactAttribute : FactAttribute
{
- public RequiresSpecificFrameworkFactAttribute(string framework)
+ public RequiresSpecificFrameworkFactAttribute(string framework, [CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = 0)
+ : base(sourceFilePath, sourceLineNumber)
{
if (!EnvironmentInfo.SupportsTargetFramework(framework))
{
diff --git a/test/Microsoft.NET.TestFramework/Attributes/RequiresSpecificFrameworkTheoryAttribute.cs b/test/Microsoft.NET.TestFramework/Attributes/RequiresSpecificFrameworkTheoryAttribute.cs
index 65550cdb8879..95d563362313 100644
--- a/test/Microsoft.NET.TestFramework/Attributes/RequiresSpecificFrameworkTheoryAttribute.cs
+++ b/test/Microsoft.NET.TestFramework/Attributes/RequiresSpecificFrameworkTheoryAttribute.cs
@@ -1,15 +1,17 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
#if NETCOREAPP
+using System.Runtime.CompilerServices;
using Microsoft.DotNet.Tools.Test.Utilities;
namespace Microsoft.NET.TestFramework
{
public class RequiresSpecificFrameworkTheoryAttribute : TheoryAttribute
{
- public RequiresSpecificFrameworkTheoryAttribute(string framework)
+ public RequiresSpecificFrameworkTheoryAttribute(string framework, [CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = 0)
+ : base(sourceFilePath, sourceLineNumber)
{
if (!EnvironmentInfo.SupportsTargetFramework(framework))
{
diff --git a/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionFactAttribute.cs b/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionFactAttribute.cs
index 73121c780841..55df869206e1 100644
--- a/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionFactAttribute.cs
+++ b/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionFactAttribute.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Runtime.CompilerServices;
+
namespace Microsoft.NET.TestFramework
{
public class WindowsOnlyRequiresMSBuildVersionFactAttribute : FactAttribute
@@ -9,8 +11,9 @@ public class WindowsOnlyRequiresMSBuildVersionFactAttribute : FactAttribute
/// Gets or sets the reason for potentially skipping the test if conditions are not met.
///
public string? Reason { get; set; }
-
- public WindowsOnlyRequiresMSBuildVersionFactAttribute(string version)
+
+ public WindowsOnlyRequiresMSBuildVersionFactAttribute(string version, [CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = 0)
+ : base(sourceFilePath, sourceLineNumber)
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
diff --git a/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionTheoryAttribute.cs b/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionTheoryAttribute.cs
index f9c43590585e..2b8664843cfe 100644
--- a/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionTheoryAttribute.cs
+++ b/test/Microsoft.NET.TestFramework/Attributes/WindowsOnlyRequiresMSBuildVersionTheoryAttribute.cs
@@ -1,11 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Runtime.CompilerServices;
+
namespace Microsoft.NET.TestFramework
{
public class WindowsOnlyRequiresMSBuildVersionTheoryAttribute : TheoryAttribute
{
- public WindowsOnlyRequiresMSBuildVersionTheoryAttribute(string version)
+ public WindowsOnlyRequiresMSBuildVersionTheoryAttribute(string version, [CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = 0)
+ : base(sourceFilePath, sourceLineNumber)
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
diff --git a/test/Microsoft.NET.TestFramework/Commands/SdkCommandSpec.cs b/test/Microsoft.NET.TestFramework/Commands/SdkCommandSpec.cs
index 9bc513f6ff6c..6ae759d32a0e 100644
--- a/test/Microsoft.NET.TestFramework/Commands/SdkCommandSpec.cs
+++ b/test/Microsoft.NET.TestFramework/Commands/SdkCommandSpec.cs
@@ -3,6 +3,9 @@
using System.Diagnostics;
using Microsoft.DotNet.Cli.Utils;
+#if NET
+using System.Runtime.InteropServices;
+#endif
namespace Microsoft.NET.TestFramework.Commands
{
@@ -21,6 +24,8 @@ public class SdkCommandSpec
public bool DisableOutputAndErrorRedirection { get; set; }
+ public bool CreateNewProcessGroup { get; set; }
+
private string EscapeArgs()
{
// Note: this doesn't handle invoking .cmd files via "cmd /c" on Windows, which probably won't be necessary here
@@ -61,6 +66,13 @@ public ProcessStartInfo ToProcessStartInfo(bool doNotEscapeArguments = false)
ret.WorkingDirectory = WorkingDirectory;
}
+#if NET
+ if (CreateNewProcessGroup && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ ret.CreateNewProcessGroup = true;
+ }
+#endif
+
return ret;
}
}
diff --git a/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs b/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs
index 56cf1002d2ae..6bb45283efe5 100644
--- a/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs
+++ b/test/Microsoft.NET.TestFramework/Commands/TestCommand.cs
@@ -24,6 +24,12 @@ public abstract class TestCommand
public bool DisableOutputAndErrorRedirection { get; set; }
+ ///
+ /// When true, the child process is launched in a new process group so that
+ /// console signals (e.g. Ctrl+C) sent to it do not propagate to the test host.
+ ///
+ public bool CreateNewProcessGroup { get; set; }
+
// These only work via Execute(), not when using GetProcessStartInfo()
public Action? CommandOutputHandler { get; set; }
public Action? ProcessStartedHandler { get; set; }
@@ -116,6 +122,7 @@ private SdkCommandSpec CreateCommandSpec(IEnumerable args)
commandSpec.RedirectStandardInput = RedirectStandardInput;
commandSpec.DisableOutputAndErrorRedirection = DisableOutputAndErrorRedirection;
+ commandSpec.CreateNewProcessGroup = CreateNewProcessGroup;
return commandSpec;
}
@@ -203,7 +210,7 @@ public virtual CommandResult Execute(IEnumerable args)
public static void LogCommandResult(ITestOutputHelper log, CommandResult result)
{
log.WriteLine($"> {result.StartInfo.FileName} {result.StartInfo.Arguments}");
- log.WriteLine(result.StdOut);
+ log.WriteLine(result.StdOut ?? string.Empty);
if (!string.IsNullOrEmpty(result.StdErr))
{
diff --git a/test/Microsoft.NET.TestFramework/Microsoft.NET.TestFramework.csproj b/test/Microsoft.NET.TestFramework/Microsoft.NET.TestFramework.csproj
index 6751b7251938..0d63310bd9f1 100644
--- a/test/Microsoft.NET.TestFramework/Microsoft.NET.TestFramework.csproj
+++ b/test/Microsoft.NET.TestFramework/Microsoft.NET.TestFramework.csproj
@@ -60,12 +60,13 @@
-->
-
+
-
+
+
@@ -75,7 +76,6 @@
-
diff --git a/test/Microsoft.NET.TestFramework/SharedTestOutputHelper.cs b/test/Microsoft.NET.TestFramework/SharedTestOutputHelper.cs
index d3591610f624..c7f1a510fbbd 100644
--- a/test/Microsoft.NET.TestFramework/SharedTestOutputHelper.cs
+++ b/test/Microsoft.NET.TestFramework/SharedTestOutputHelper.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Xunit.Sdk;
+using Xunit.v3;
namespace Microsoft.NET.TestFramework;
@@ -12,19 +13,38 @@ namespace Microsoft.NET.TestFramework;
public class SharedTestOutputHelper : ITestOutputHelper
{
private readonly IMessageSink _sink;
+ private readonly StringBuilder _output = new();
public SharedTestOutputHelper(IMessageSink sink)
{
_sink = sink;
}
+ public string Output => _output.ToString();
+
+ public void Write(string message)
+ {
+ _output.Append(message);
+ _sink.OnMessage(new DiagnosticMessage(message));
+ }
+
+ public void Write(string format, params object[] args)
+ {
+ var formatted = string.Format(format, args);
+ _output.Append(formatted);
+ _sink.OnMessage(new DiagnosticMessage(formatted));
+ }
+
public void WriteLine(string message)
{
+ _output.AppendLine(message);
_sink.OnMessage(new DiagnosticMessage(message));
}
public void WriteLine(string format, params object[] args)
{
- _sink.OnMessage(new DiagnosticMessage(format, args));
+ var formatted = string.Format(format, args);
+ _output.AppendLine(formatted);
+ _sink.OnMessage(new DiagnosticMessage(formatted));
}
}
diff --git a/test/Microsoft.NET.TestFramework/StringTestLogger.cs b/test/Microsoft.NET.TestFramework/StringTestLogger.cs
index a5323123fba4..1d08f176332b 100644
--- a/test/Microsoft.NET.TestFramework/StringTestLogger.cs
+++ b/test/Microsoft.NET.TestFramework/StringTestLogger.cs
@@ -7,6 +7,18 @@ public class StringTestLogger : ITestOutputHelper
{
StringBuilder _stringBuilder = new();
+ public string Output => _stringBuilder.ToString();
+
+ public void Write(string message)
+ {
+ _stringBuilder.Append(message);
+ }
+
+ public void Write(string format, params object[] args)
+ {
+ _stringBuilder.Append(string.Format(format, args));
+ }
+
public void WriteLine(string message)
{
_stringBuilder.AppendLine(message);
diff --git a/test/Microsoft.NET.TestFramework/TestLoggerFactory.cs b/test/Microsoft.NET.TestFramework/TestLoggerFactory.cs
index 40ec82ed3041..02982eb098a9 100644
--- a/test/Microsoft.NET.TestFramework/TestLoggerFactory.cs
+++ b/test/Microsoft.NET.TestFramework/TestLoggerFactory.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Extensions.Logging;
+using Xunit.Sdk;
namespace Microsoft.NET.TestFramework
{
diff --git a/test/Microsoft.TemplateEngine.Cli.UnitTests/Microsoft.TemplateEngine.Cli.UnitTests.csproj b/test/Microsoft.TemplateEngine.Cli.UnitTests/Microsoft.TemplateEngine.Cli.UnitTests.csproj
index bf6139c9af64..b1e1394cf095 100644
--- a/test/Microsoft.TemplateEngine.Cli.UnitTests/Microsoft.TemplateEngine.Cli.UnitTests.csproj
+++ b/test/Microsoft.TemplateEngine.Cli.UnitTests/Microsoft.TemplateEngine.Cli.UnitTests.csproj
@@ -16,10 +16,10 @@
-
+
-
-
+
+
diff --git a/test/Microsoft.Win32.Msi.Manual.Tests/Microsoft.Win32.Msi.Manual.Tests.csproj b/test/Microsoft.Win32.Msi.Manual.Tests/Microsoft.Win32.Msi.Manual.Tests.csproj
index a1465b5f3026..c13835ee50fe 100644
--- a/test/Microsoft.Win32.Msi.Manual.Tests/Microsoft.Win32.Msi.Manual.Tests.csproj
+++ b/test/Microsoft.Win32.Msi.Manual.Tests/Microsoft.Win32.Msi.Manual.Tests.csproj
@@ -22,6 +22,5 @@
-
diff --git a/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj b/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj
index 9df4924b8ce4..889e80b3c357 100644
--- a/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj
+++ b/test/Msbuild.Tests.Utilities/Msbuild.Tests.Utilities.csproj
@@ -16,7 +16,6 @@
-
diff --git a/test/System.CommandLine.StaticCompletions.Tests/System.CommandLine.StaticCompletions.Tests.csproj b/test/System.CommandLine.StaticCompletions.Tests/System.CommandLine.StaticCompletions.Tests.csproj
index b5959c334766..349ac13587c3 100644
--- a/test/System.CommandLine.StaticCompletions.Tests/System.CommandLine.StaticCompletions.Tests.csproj
+++ b/test/System.CommandLine.StaticCompletions.Tests/System.CommandLine.StaticCompletions.Tests.csproj
@@ -10,8 +10,7 @@
-
-
+
diff --git a/test/UnitTests.proj b/test/UnitTests.proj
index b3037317f63f..289858317516 100644
--- a/test/UnitTests.proj
+++ b/test/UnitTests.proj
@@ -114,6 +114,7 @@
+
@@ -141,7 +142,7 @@
. $HELIX_CORRELATION_PAYLOAD/t/SetupHelixEnvironment.sh;$(HelixPreCommands)
PowerShell -ExecutionPolicy ByPass "dotnet nuget locals all -l | ForEach-Object { $_.Split(' ')[1]} | Where-Object{$_ -like '*cache'} | Get-ChildItem -Recurse -File -Filter '*.dat' | Measure";$(HelixPostCommands)
PowerShell -ExecutionPolicy ByPass "Get-ChildItem -Recurse -File -Filter '*hangdump.dmp' | Copy-Item -Destination $env:HELIX_WORKITEM_UPLOAD_ROOT";$(HelixPostCommands)
- find "$HELIX_WORKITEM_UPLOAD_ROOT/../../.." -name '*hangdump.dmp' -exec cp {} "$HELIX_WORKITEM_UPLOAD_ROOT" \;;$(HelixPostCommands)
+ find "$HELIX_WORKITEM_UPLOAD_ROOT/../../.." -name '*hangdump.dmp' -print0 | xargs -0 -I@ cp @ "$HELIX_WORKITEM_UPLOAD_ROOT";$(HelixPostCommands)
$(Version)
$(RepoRoot)artifacts\bin\Microsoft.DotNet.MSBuildSdkResolver
$(RepoRoot)artifacts\tmp\HelixStage0.tar.gz
diff --git a/test/dotnet-format.UnitTests/Analyzers/ThirdPartyAnalyzerFormatterTests.cs b/test/dotnet-format.UnitTests/Analyzers/ThirdPartyAnalyzerFormatterTests.cs
index 07fae27e9946..939463a91d90 100644
--- a/test/dotnet-format.UnitTests/Analyzers/ThirdPartyAnalyzerFormatterTests.cs
+++ b/test/dotnet-format.UnitTests/Analyzers/ThirdPartyAnalyzerFormatterTests.cs
@@ -26,7 +26,7 @@ public ThirdPartyAnalyzerFormatterTests(ITestOutputHelper output)
TestOutputHelper = output;
}
- public async Task InitializeAsync()
+ public async ValueTask InitializeAsync()
{
var logger = new TestLogger();
@@ -52,11 +52,11 @@ public async Task InitializeAsync()
}
}
- public Task DisposeAsync()
+ public ValueTask DisposeAsync()
{
_analyzerReferencesProject = null;
- return Task.CompletedTask;
+ return ValueTask.CompletedTask;
}
private IEnumerable GetAnalyzerReferences(string prefix)
diff --git a/test/dotnet-format.UnitTests/XUnit/ConditionalFactAttribute.cs b/test/dotnet-format.UnitTests/XUnit/ConditionalFactAttribute.cs
index e887376ef1cf..c7434c6c9d1e 100644
--- a/test/dotnet-format.UnitTests/XUnit/ConditionalFactAttribute.cs
+++ b/test/dotnet-format.UnitTests/XUnit/ConditionalFactAttribute.cs
@@ -1,6 +1,8 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Runtime.CompilerServices;
+
namespace Microsoft.CodeAnalysis.Tools.Tests.XUnit
{
public class ConditionalFactAttribute : FactAttribute
@@ -11,7 +13,7 @@ public class ConditionalFactAttribute : FactAttribute
/// skipped vs. conditionally skipped which is the entire point of this attribute.
///
[Obsolete("ConditionalFact should use Reason or AlwaysSkip", error: true)]
- public new string Skip
+ public new string? Skip
{
get => base.Skip;
set => base.Skip = value;
@@ -21,7 +23,7 @@ public class ConditionalFactAttribute : FactAttribute
/// Used to unconditionally Skip a test. For the rare occasion when a conditional test needs to be
/// unconditionally skipped (typically short term for a bug to be fixed).
///
- public string AlwaysSkip
+ public string? AlwaysSkip
{
get => base.Skip;
set => base.Skip = value;
@@ -29,7 +31,8 @@ public string AlwaysSkip
public string? Reason { get; set; }
- public ConditionalFactAttribute(params Type[] skipConditions)
+ public ConditionalFactAttribute(Type[] skipConditions, [CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = 0)
+ : base(sourceFilePath, sourceLineNumber)
{
foreach (var skipCondition in skipConditions)
{
@@ -51,7 +54,7 @@ public class ConditionalTheoryAttribute : TheoryAttribute
/// skipped vs. conditionally skipped which is the entire point of this attribute.
///
[Obsolete("ConditionalTheory should use Reason or AlwaysSkip")]
- public new string Skip
+ public new string? Skip
{
get => base.Skip;
set => base.Skip = value;
@@ -61,7 +64,7 @@ public class ConditionalTheoryAttribute : TheoryAttribute
/// Used to unconditionally Skip a test. For the rare occasion when a conditional test needs to be
/// unconditionally skipped (typically short term for a bug to be fixed).
///
- public string AlwaysSkip
+ public string? AlwaysSkip
{
get => base.Skip;
set => base.Skip = value;
@@ -69,7 +72,8 @@ public string AlwaysSkip
public string? Reason { get; set; }
- public ConditionalTheoryAttribute(params Type[] skipConditions)
+ public ConditionalTheoryAttribute(Type[] skipConditions, [CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = 0)
+ : base(sourceFilePath, sourceLineNumber)
{
foreach (var skipCondition in skipConditions)
{
diff --git a/test/dotnet-format.UnitTests/XUnit/MSBuildFactAttribute.cs b/test/dotnet-format.UnitTests/XUnit/MSBuildFactAttribute.cs
index 384f87887586..97caeb8011b7 100644
--- a/test/dotnet-format.UnitTests/XUnit/MSBuildFactAttribute.cs
+++ b/test/dotnet-format.UnitTests/XUnit/MSBuildFactAttribute.cs
@@ -1,17 +1,34 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Xunit.Sdk;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.CodeAnalysis.Tools.Workspaces;
+using Xunit.v3;
namespace Microsoft.CodeAnalysis.Tools.Tests.XUnit
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
- [XunitTestCaseDiscoverer("Microsoft.CodeAnalysis.Tools.Tests.XUnit.MSBuildFactDiscoverer", "dotnet-format.UnitTests")]
- public sealed class MSBuildFactAttribute : ConditionalFactAttribute
+ public sealed class MSBuildFactAttribute : ConditionalFactAttribute, IBeforeAfterTestAttribute
{
public MSBuildFactAttribute(params Type[] skipConditions)
: base(skipConditions)
{
}
+
+ public MSBuildFactAttribute([CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = 0)
+ : base(Array.Empty(), sourceFilePath, sourceLineNumber)
+ {
+ }
+
+ public void Before(MethodInfo methodUnderTest, IXunitTest test)
+ {
+ MSBuildWorkspaceLoader.Guard.Wait();
+ }
+
+ public void After(MethodInfo methodUnderTest, IXunitTest test)
+ {
+ MSBuildWorkspaceLoader.Guard.Release();
+ }
}
}
diff --git a/test/dotnet-format.UnitTests/XUnit/MSBuildFactDiscoverer.cs b/test/dotnet-format.UnitTests/XUnit/MSBuildFactDiscoverer.cs
deleted file mode 100644
index 6262d6d78a66..000000000000
--- a/test/dotnet-format.UnitTests/XUnit/MSBuildFactDiscoverer.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Xunit.Sdk;
-
-namespace Microsoft.CodeAnalysis.Tools.Tests.XUnit
-{
-
- public sealed class MSBuildFactDiscoverer : IXunitTestCaseDiscoverer
- {
- private readonly FactDiscoverer _factDiscoverer;
-
- public MSBuildFactDiscoverer(IMessageSink diagnosticMessageSink)
- {
- _factDiscoverer = new FactDiscoverer(diagnosticMessageSink);
- }
-
- public IEnumerable Discover(
- ITestFrameworkDiscoveryOptions discoveryOptions,
- ITestMethod testMethod,
- IAttributeInfo factAttribute)
- {
- return _factDiscoverer
- .Discover(discoveryOptions, testMethod, factAttribute)
- .Select(testCase => new MSBuildTestCase(testCase));
- }
- }
-}
diff --git a/test/dotnet-format.UnitTests/XUnit/MSBuildTestCase.cs b/test/dotnet-format.UnitTests/XUnit/MSBuildTestCase.cs
deleted file mode 100644
index 0104480fdff9..000000000000
--- a/test/dotnet-format.UnitTests/XUnit/MSBuildTestCase.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable disable
-
-using System.Diagnostics;
-using Microsoft.CodeAnalysis.Tools.Workspaces;
-using Xunit.Sdk;
-
-namespace Microsoft.CodeAnalysis.Tools.Tests.XUnit
-{
- [DebuggerDisplay(@"\{ class = {TestMethod.TestClass.Class.Name}, method = {TestMethod.Method.Name}, display = {DisplayName}, skip = {SkipReason} \}")]
- public sealed class MSBuildTestCase : Xunit.LongLivedMarshalByRefObject, IXunitTestCase
- {
- private IXunitTestCase _testCase;
-
- public string DisplayName => _testCase.DisplayName;
- public IMethodInfo Method => _testCase.Method;
- public string SkipReason => _testCase.SkipReason;
- public ITestMethod TestMethod => _testCase.TestMethod;
- public object[] TestMethodArguments => _testCase.TestMethodArguments;
- public Dictionary> Traits => _testCase.Traits;
- public string UniqueID => _testCase.UniqueID;
-
- public ISourceInformation SourceInformation
- {
- get => _testCase.SourceInformation;
- set => _testCase.SourceInformation = value;
- }
-
- public Exception InitializationException => _testCase.InitializationException;
-
- public int Timeout => _testCase.Timeout;
-
- public MSBuildTestCase(IXunitTestCase testCase)
- {
- _testCase = testCase ?? throw new ArgumentNullException(nameof(testCase));
- }
-
- [Obsolete("Called by the deserializer", error: true)]
- public MSBuildTestCase() { }
-
- public async Task RunAsync(
- IMessageSink diagnosticMessageSink,
- IMessageBus messageBus,
- object[] constructorArguments,
- ExceptionAggregator aggregator,
- CancellationTokenSource cancellationTokenSource)
- {
- await MSBuildWorkspaceLoader.Guard.WaitAsync();
- try
- {
- var runner = new XunitTestCaseRunner(this, DisplayName, SkipReason, constructorArguments, TestMethodArguments, messageBus, aggregator, cancellationTokenSource);
- return await runner.RunAsync();
- }
- finally
- {
- MSBuildWorkspaceLoader.Guard.Release();
- }
- }
-
- public void Deserialize(IXunitSerializationInfo info)
- {
- _testCase = info.GetValue("InnerTestCase");
- }
-
- public void Serialize(IXunitSerializationInfo info)
- {
- info.AddValue("InnerTestCase", _testCase);
- }
- }
-}
diff --git a/test/dotnet-format.UnitTests/XUnit/MSBuildTheoryAttribute.cs b/test/dotnet-format.UnitTests/XUnit/MSBuildTheoryAttribute.cs
index 27b9f39b4d44..abf7c371c024 100644
--- a/test/dotnet-format.UnitTests/XUnit/MSBuildTheoryAttribute.cs
+++ b/test/dotnet-format.UnitTests/XUnit/MSBuildTheoryAttribute.cs
@@ -1,17 +1,33 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Xunit.Sdk;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Microsoft.CodeAnalysis.Tools.Workspaces;
+using Xunit.v3;
namespace Microsoft.CodeAnalysis.Tools.Tests.XUnit
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
- [XunitTestCaseDiscoverer("Microsoft.CodeAnalysis.Tools.Tests.XUnit.MSBuildTheoryDiscoverer", "dotnet-format.UnitTests")]
- public sealed class MSBuildTheoryAttribute : ConditionalTheoryAttribute
+ public sealed class MSBuildTheoryAttribute : ConditionalTheoryAttribute, IBeforeAfterTestAttribute
{
- public MSBuildTheoryAttribute(params Type[] skipConditions)
- : base(skipConditions)
+ public MSBuildTheoryAttribute(params Type[] skipConditions) : base(skipConditions)
{
}
+
+ public MSBuildTheoryAttribute([CallerFilePath] string? sourceFilePath = null, [CallerLineNumber] int sourceLineNumber = 0)
+ : base(Array.Empty(), sourceFilePath, sourceLineNumber)
+ {
+ }
+
+ public void Before(MethodInfo methodUnderTest, IXunitTest test)
+ {
+ MSBuildWorkspaceLoader.Guard.Wait();
+ }
+
+ public void After(MethodInfo methodUnderTest, IXunitTest test)
+ {
+ MSBuildWorkspaceLoader.Guard.Release();
+ }
}
}
diff --git a/test/dotnet-format.UnitTests/XUnit/MSBuildTheoryDiscoverer.cs b/test/dotnet-format.UnitTests/XUnit/MSBuildTheoryDiscoverer.cs
deleted file mode 100644
index 22ce8042aaf7..000000000000
--- a/test/dotnet-format.UnitTests/XUnit/MSBuildTheoryDiscoverer.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Xunit.Sdk;
-
-namespace Microsoft.CodeAnalysis.Tools.Tests.XUnit
-{
-
- public sealed class MSBuildTheoryDiscoverer : IXunitTestCaseDiscoverer
- {
- private readonly TheoryDiscoverer _theoryDiscoverer;
-
- public MSBuildTheoryDiscoverer(IMessageSink diagnosticMessageSink)
- {
- _theoryDiscoverer = new TheoryDiscoverer(diagnosticMessageSink);
- }
-
- public IEnumerable Discover(
- ITestFrameworkDiscoveryOptions discoveryOptions,
- ITestMethod testMethod,
- IAttributeInfo factAttribute)
- {
- return _theoryDiscoverer
- .Discover(discoveryOptions, testMethod, factAttribute)
- .Select(testCase => new MSBuildTestCase(testCase));
- }
- }
-}
diff --git a/test/dotnet-new.IntegrationTests/Diagnostic/DiagnosticFixture.cs b/test/dotnet-new.IntegrationTests/Diagnostic/DiagnosticFixture.cs
index df772d9846de..2eab6d6d2b9f 100644
--- a/test/dotnet-new.IntegrationTests/Diagnostic/DiagnosticFixture.cs
+++ b/test/dotnet-new.IntegrationTests/Diagnostic/DiagnosticFixture.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using Xunit.Sdk;
+
namespace Microsoft.DotNet.Cli.New.IntegrationTests
{
public class DiagnosticFixture
diff --git a/test/dotnet-new.IntegrationTests/Diagnostic/XunitNuGetLogger.cs b/test/dotnet-new.IntegrationTests/Diagnostic/XunitNuGetLogger.cs
index b25feb42326f..af6202fb527b 100644
--- a/test/dotnet-new.IntegrationTests/Diagnostic/XunitNuGetLogger.cs
+++ b/test/dotnet-new.IntegrationTests/Diagnostic/XunitNuGetLogger.cs
@@ -2,7 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using NuGet.Common;
-using DiagnosticMessage = Xunit.Sdk.DiagnosticMessage;
+using Xunit.Sdk;
+using DiagnosticMessage = Xunit.v3.DiagnosticMessage;
namespace Microsoft.DotNet.Cli.New.IntegrationTests
{
diff --git a/test/dotnet-new.IntegrationTests/DotnetNewDetailsTest.cs b/test/dotnet-new.IntegrationTests/DotnetNewDetailsTest.cs
index 80fa07d8d410..364e95c6580c 100644
--- a/test/dotnet-new.IntegrationTests/DotnetNewDetailsTest.cs
+++ b/test/dotnet-new.IntegrationTests/DotnetNewDetailsTest.cs
@@ -1,6 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using Xunit.Sdk;
+
namespace Microsoft.DotNet.Cli.New.IntegrationTests
{
public partial class DotnetNewDetailsTest : BaseIntegrationTest, IClassFixture
diff --git a/test/dotnet-new.IntegrationTests/DotnetNewHelpTests.Approval.cs b/test/dotnet-new.IntegrationTests/DotnetNewHelpTests.Approval.cs
index 464fc117c1c4..974ef1352b55 100644
--- a/test/dotnet-new.IntegrationTests/DotnetNewHelpTests.Approval.cs
+++ b/test/dotnet-new.IntegrationTests/DotnetNewHelpTests.Approval.cs
@@ -208,12 +208,16 @@ public Task CannotShowHelpForTemplate_FullNameMatch()
[Fact]
public Task CannotShowHelpForTemplate_WhenAmbiguousLanguageChoice()
{
+ // Use a dedicated home directory to avoid conflicts with other tests that install
+ // templates with the same 'basic' short name. Tests are not guaranteed to execute
+ // in declared order.
string workingDirectory = CreateTemporaryFolder();
- InstallTestTemplate("TemplateResolution/DifferentLanguagesGroup/BasicFSharp", _log, _fixture.HomeDirectory, workingDirectory);
- InstallTestTemplate("TemplateResolution/DifferentLanguagesGroup/BasicVB", _log, _fixture.HomeDirectory, workingDirectory);
+ string homeDirectory = CreateTemporaryFolder("Home");
+ InstallTestTemplate("TemplateResolution/DifferentLanguagesGroup/BasicFSharp", _log, homeDirectory, workingDirectory);
+ InstallTestTemplate("TemplateResolution/DifferentLanguagesGroup/BasicVB", _log, homeDirectory, workingDirectory);
CommandResult commandResult = new DotnetNewCommand(_log, "basic", "--help")
- .WithCustomHive(_fixture.HomeDirectory)
+ .WithCustomHive(homeDirectory)
.WithWorkingDirectory(workingDirectory)
.Execute();
@@ -393,11 +397,15 @@ public Task CanShowHelpForTemplate_ConditionalParams()
[Fact]
public Task CanShowHelpForTemplateWhenRequiredParamIsMissed()
{
+ // Use a dedicated home directory to avoid conflicts with other tests that install
+ // templates with the same 'basic' short name. Tests are not guaranteed to execute
+ // in declared order.
string workingDirectory = CreateTemporaryFolder();
- InstallTestTemplate($"TemplateResolution/MissedRequiredParameter/BasicTemplate1", _log, _fixture.HomeDirectory, workingDirectory);
+ string homeDirectory = CreateTemporaryFolder("Home");
+ InstallTestTemplate($"TemplateResolution/MissedRequiredParameter/BasicTemplate1", _log, homeDirectory, workingDirectory);
CommandResult commandResult = new DotnetNewCommand(_log, "basic", "--help")
- .WithCustomHive(_fixture.HomeDirectory)
+ .WithCustomHive(homeDirectory)
.WithWorkingDirectory(workingDirectory)
.Execute();
diff --git a/test/dotnet-new.IntegrationTests/DotnetNewInstallTests.cs b/test/dotnet-new.IntegrationTests/DotnetNewInstallTests.cs
index c88f7e31f49b..d8c4a5d28d58 100644
--- a/test/dotnet-new.IntegrationTests/DotnetNewInstallTests.cs
+++ b/test/dotnet-new.IntegrationTests/DotnetNewInstallTests.cs
@@ -5,7 +5,8 @@
using System.Text.RegularExpressions;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.TemplateEngine.TestHelper;
-using DiagnosticMessage = Xunit.Sdk.DiagnosticMessage;
+using Xunit.Sdk;
+using DiagnosticMessage = Xunit.v3.DiagnosticMessage;
namespace Microsoft.DotNet.Cli.New.IntegrationTests
{
diff --git a/test/dotnet-new.IntegrationTests/DotnetNewTestTemplatesTests.cs b/test/dotnet-new.IntegrationTests/DotnetNewTestTemplatesTests.cs
index 2e6128de171b..a61bbcc94336 100644
--- a/test/dotnet-new.IntegrationTests/DotnetNewTestTemplatesTests.cs
+++ b/test/dotnet-new.IntegrationTests/DotnetNewTestTemplatesTests.cs
@@ -48,6 +48,12 @@ public static class Languages
private class NullTestOutputHelper : ITestOutputHelper
{
+ public string Output => string.Empty;
+
+ public void Write(string message) { }
+
+ public void Write(string format, params object[] args) { }
+
public void WriteLine(string message) { }
public void WriteLine(string format, params object[] args) { }
diff --git a/test/dotnet-new.IntegrationTests/SharedHomeDirectory.cs b/test/dotnet-new.IntegrationTests/SharedHomeDirectory.cs
index e7b91db01f32..fd946bf2aa4d 100644
--- a/test/dotnet-new.IntegrationTests/SharedHomeDirectory.cs
+++ b/test/dotnet-new.IntegrationTests/SharedHomeDirectory.cs
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using SharedTestOutputHelper = Microsoft.TemplateEngine.TestHelper.SharedTestOutputHelper;
+using Xunit.Sdk;
namespace Microsoft.DotNet.Cli.New.IntegrationTests
{
diff --git a/test/dotnet-new.IntegrationTests/TemplateDiscoveryTests.cs b/test/dotnet-new.IntegrationTests/TemplateDiscoveryTests.cs
index a87b0fc3cbc2..c65e813bd950 100644
--- a/test/dotnet-new.IntegrationTests/TemplateDiscoveryTests.cs
+++ b/test/dotnet-new.IntegrationTests/TemplateDiscoveryTests.cs
@@ -17,7 +17,7 @@ public TemplateDiscoveryTests(ITestOutputHelper log, TemplateDiscoveryTool templ
}
#pragma warning disable xUnit1004 // Test methods should not be skipped
- [PlatformSpecificFact(SkipPlatforms = TestPlatforms.OSX, SkipArchitecture = Architecture.Arm64, SkipReason = "https://github.com/dotnet/sdk/issues/53569")]
+ [PlatformSpecificFact(skipPlatforms: TestPlatforms.OSX, skipArchitecture: Architecture.Arm64, skipReason: "https://github.com/dotnet/sdk/issues/53569")]
#pragma warning restore xUnit1004 // Test methods should not be skipped
public async Task CanRunDiscoveryTool()
{
diff --git a/test/dotnet-new.IntegrationTests/TemplateDiscoveryTool.cs b/test/dotnet-new.IntegrationTests/TemplateDiscoveryTool.cs
index 48034a63a83c..9d2d0a86a677 100644
--- a/test/dotnet-new.IntegrationTests/TemplateDiscoveryTool.cs
+++ b/test/dotnet-new.IntegrationTests/TemplateDiscoveryTool.cs
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using SharedTestOutputHelper = Microsoft.TemplateEngine.TestHelper.SharedTestOutputHelper;
+using Xunit.Sdk;
namespace Microsoft.DotNet.Cli.New.IntegrationTests
{
diff --git a/test/dotnet-new.IntegrationTests/WebProjectsTests.cs b/test/dotnet-new.IntegrationTests/WebProjectsTests.cs
index 7cd274107a21..59cc08e55c0c 100644
--- a/test/dotnet-new.IntegrationTests/WebProjectsTests.cs
+++ b/test/dotnet-new.IntegrationTests/WebProjectsTests.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.DotNet.Cli.Utils;
+using Xunit.Sdk;
namespace Microsoft.DotNet.Cli.New.IntegrationTests
{
diff --git a/test/dotnet-new.IntegrationTests/dotnet-new.IntegrationTests.csproj b/test/dotnet-new.IntegrationTests/dotnet-new.IntegrationTests.csproj
index 06014f7dfcda..e87d35c501b9 100644
--- a/test/dotnet-new.IntegrationTests/dotnet-new.IntegrationTests.csproj
+++ b/test/dotnet-new.IntegrationTests/dotnet-new.IntegrationTests.csproj
@@ -13,10 +13,10 @@
-
+
-
-
+
+
diff --git a/test/dotnet-watch.Tests/TestUtilities/DotNetWatchTestBase.cs b/test/dotnet-watch.Tests/TestUtilities/DotNetWatchTestBase.cs
index 3bbbeddb34d3..00e66f1f7762 100644
--- a/test/dotnet-watch.Tests/TestUtilities/DotNetWatchTestBase.cs
+++ b/test/dotnet-watch.Tests/TestUtilities/DotNetWatchTestBase.cs
@@ -19,10 +19,10 @@ public DotNetWatchTestBase(ITestOutputHelper logger)
TestAssets = new TestAssetsManager(App.Logger);
}
- public Task InitializeAsync()
- => Task.CompletedTask;
+ public ValueTask InitializeAsync()
+ => default;
- public async Task DisposeAsync()
+ public async ValueTask DisposeAsync()
{
Log("Disposing test");
await App.DisposeAsync();
diff --git a/test/dotnet-watch.Tests/TestUtilities/ModuleInitializer.cs b/test/dotnet-watch.Tests/TestUtilities/MSBuildFixture.cs
similarity index 84%
rename from test/dotnet-watch.Tests/TestUtilities/ModuleInitializer.cs
rename to test/dotnet-watch.Tests/TestUtilities/MSBuildFixture.cs
index 84836479d581..71a39705de97 100644
--- a/test/dotnet-watch.Tests/TestUtilities/ModuleInitializer.cs
+++ b/test/dotnet-watch.Tests/TestUtilities/MSBuildFixture.cs
@@ -2,16 +2,20 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Runtime.Loader;
using Microsoft.Build.Locator;
+[assembly: AssemblyFixture(typeof(Microsoft.DotNet.Watch.UnitTests.MSBuildFixture))]
+
namespace Microsoft.DotNet.Watch.UnitTests;
-public static class ModuleInitializer
+///
+/// Assembly fixture that registers MSBuild and sets up assembly resolution for dotnet-watch tests.
+/// A fixture is preferred over a [ModuleInitializer] because it doesn't get invoked for test discovery.
+///
+public class MSBuildFixture
{
- [ModuleInitializer]
- public static void Initialize()
+ public MSBuildFixture()
{
// Ensure that we load the msbuild binaries from redist deployment. Otherwise, msbuild might use target files
// that do not match the implementations of the core tasks.
diff --git a/test/dotnet.Tests/CommandTests/Package/Add/GivenDotnetPackageAdd.cs b/test/dotnet.Tests/CommandTests/Package/Add/GivenDotnetPackageAdd.cs
index 744f8bcd9856..102640211fe5 100644
--- a/test/dotnet.Tests/CommandTests/Package/Add/GivenDotnetPackageAdd.cs
+++ b/test/dotnet.Tests/CommandTests/Package/Add/GivenDotnetPackageAdd.cs
@@ -3,7 +3,6 @@
using System.Runtime.CompilerServices;
using Microsoft.DotNet.Cli.Commands;
-using Xunit.Runners;
namespace Microsoft.DotNet.Cli.Package.Add.Tests
{
@@ -379,7 +378,7 @@ public void FileBasedApp_NoVersion(string[] inputVersions, string? expectedVersi
var file = Path.Join(testInstance.Path, "Program.cs");
var source = $"""
- #:property RestoreSources=$(RestoreSources);{restoreSources}
+ #:property RestoreAdditionalProjectSources={restoreSources}
Console.WriteLine();
""";
File.WriteAllText(file, source);
@@ -416,7 +415,7 @@ public void FileBasedApp_NoVersion_Prerelease(string[] inputVersions, string? _,
var file = Path.Join(testInstance.Path, "Program.cs");
var source = $"""
- #:property RestoreSources=$(RestoreSources);{restoreSources}
+ #:property RestoreAdditionalProjectSources={restoreSources}
Console.WriteLine();
""";
File.WriteAllText(file, source);
@@ -637,7 +636,7 @@ public void FileBasedApp_CentralPackageManagement_NoVersionSpecified(bool legacy
var file = Path.Join(testInstance.Path, "Program.cs");
var source = $"""
- #:property RestoreSources=$(RestoreSources);{restoreSources}
+ #:property RestoreAdditionalProjectSources={restoreSources}
Console.WriteLine();
""";
File.WriteAllText(file, source);
@@ -687,7 +686,7 @@ public void FileBasedApp_CentralPackageManagement_NoVersionSpecified_KeepExistin
var file = Path.Join(testInstance.Path, "Program.cs");
var source = $"""
- #:property RestoreSources=$(RestoreSources);{restoreSources}
+ #:property RestoreAdditionalProjectSources={restoreSources}
#:package A
Console.WriteLine();
""";
diff --git a/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunIsInterrupted.cs b/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunIsInterrupted.cs
index a7a188e14648..7ebdcd079eb9 100644
--- a/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunIsInterrupted.cs
+++ b/test/dotnet.Tests/CommandTests/Run/GivenDotnetRunIsInterrupted.cs
@@ -27,6 +27,10 @@ public void ItTerminatesWinExeAppWithCloseMainWindow()
var command = new DotnetCommand(Log, "run")
.WithWorkingDirectory(asset.Path);
+ // Launch dotnet run in a new process group so that GenerateConsoleCtrlEvent
+ // targets only the child group and does not propagate to the test host.
+ command.CreateNewProcessGroup = true;
+
bool signaled = false;
bool sawClosingGracefully = false;
Process child = null;
diff --git a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
index ba7d612f3596..3a83bbafcba6 100644
--- a/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
+++ b/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
@@ -20,6 +20,9 @@ namespace Microsoft.DotNet.Cli.Run.Tests;
public sealed class RunFileTests(ITestOutputHelper log) : SdkTest(log)
{
+ // Ensure OutOfTreeBaseDirectory (and its NuGet cache warm-up) runs before any test.
+ static RunFileTests() => _ = OutOfTreeBaseDirectory;
+
internal static string s_includeExcludeDefaultKnownExtensions
=> field ??= string.Join(", ", CSharpDirective.IncludeOrExclude.DefaultMapping.Select(static e => e.Extension));
@@ -133,6 +136,8 @@ private static string PrepareOutOfTreeBaseDirectory()
var targetNuGetConfig = Path.Join(outOfTreeBaseDirectory, "NuGet.config");
File.Copy(sourceNuGetConfig, targetNuGetConfig, overwrite: true);
+ WarmUpNuGetCache(outOfTreeBaseDirectory);
+
// Check there are no implicit build files that would prevent testing optimizations.
VirtualProjectBuildingCommand.CollectImplicitBuildFiles(new DirectoryInfo(outOfTreeBaseDirectory), [], out var exampleMSBuildFile);
exampleMSBuildFile.Should().BeNull(because: "there should not be any implicit build files in the temp directory or its parents " +
@@ -141,6 +146,44 @@ private static string PrepareOutOfTreeBaseDirectory()
return outOfTreeBaseDirectory;
}
+ ///
+ /// Runs a full MSBuild build of a trivial file-based app to pull CSC dependencies
+ /// (e.g., ILLink analyzer DLLs from microsoft.net.illink.tasks) into the NuGet cache.
+ /// Without this, falls back to
+ /// because the NuGet-provided DLLs checked by
+ /// are missing,
+ /// causing tests that assert CSC-only behavior to fail depending on the order they run in.
+ ///
+ private static void WarmUpNuGetCache(string outOfTreeBaseDirectory)
+ {
+ var warmUpDir = Path.Join(outOfTreeBaseDirectory, ".warmup");
+ Directory.CreateDirectory(warmUpDir);
+ var warmUpFile = Path.Join(warmUpDir, "WarmUp.cs");
+
+ try
+ {
+ File.WriteAllText(warmUpFile, """System.Console.Write("ok");""");
+
+ var result = new DotnetCommand(NullOutputHelper.Instance, "build", "WarmUp.cs")
+ .WithWorkingDirectory(warmUpDir)
+ .Execute();
+
+ if (result.ExitCode != 0)
+ {
+ throw new InvalidOperationException(
+ $"NuGet cache warm-up failed with exit code {result.ExitCode}.{Environment.NewLine}" +
+ $"stdout: {result.StdOut}{Environment.NewLine}" +
+ $"stderr: {result.StdErr}");
+ }
+ }
+ finally
+ {
+ try { Directory.Delete(warmUpDir, true); } catch { }
+ try { Directory.Delete(VirtualProjectBuilder.GetArtifactsPath(warmUpFile), true); } catch { }
+ }
+
+ }
+
internal static string DirectiveError(string path, int line, string messageFormat, params ReadOnlySpan args)
{
return $"{path}({line}): {FileBasedProgramsResources.DirectiveError}: {string.Format(messageFormat, args)}";
@@ -2533,7 +2576,7 @@ public void Publish_In_SubDir()
public void Pack()
{
var testInstance = TestAssetsManager.CreateTestDirectory();
- var programFile = Path.Join(testInstance.Path, "MyFileBasedTool.cs");
+ var programFile = Path.Join(testInstance.Path, "PackTool.cs");
File.WriteAllText(programFile, """
Console.WriteLine($"Hello; EntryPointFilePath set? {AppContext.GetData("EntryPointFilePath") is string}");
#if !DEBUG
@@ -2542,7 +2585,7 @@ public void Pack()
""");
// Run unpacked.
- new DotnetCommand(Log, "run", "MyFileBasedTool.cs")
+ new DotnetCommand(Log, "run", "PackTool.cs")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
@@ -2555,17 +2598,17 @@ public void Pack()
if (Directory.Exists(outputDir)) Directory.Delete(outputDir, recursive: true);
// Pack.
- new DotnetCommand(Log, "pack", "MyFileBasedTool.cs")
+ new DotnetCommand(Log, "pack", "PackTool.cs")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass();
- var packageDir = new DirectoryInfo(outputDir).Sub("MyFileBasedTool");
- packageDir.File("MyFileBasedTool.1.0.0.nupkg").Should().Exist();
+ var packageDir = new DirectoryInfo(outputDir).Sub("PackTool");
+ packageDir.File("PackTool.1.0.0.nupkg").Should().Exist();
new DirectoryInfo(artifactsDir).Sub("package").Should().NotExist();
// Run the packed tool.
- new DotnetCommand(Log, "tool", "exec", "MyFileBasedTool", "--yes", "--add-source", packageDir.FullName)
+ new DotnetCommand(Log, "tool", "exec", "PackTool", "--yes", "--add-source", packageDir.FullName)
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
@@ -2579,14 +2622,14 @@ Release config
public void Pack_CustomPath()
{
var testInstance = TestAssetsManager.CreateTestDirectory();
- var programFile = Path.Join(testInstance.Path, "MyFileBasedTool.cs");
+ var programFile = Path.Join(testInstance.Path, "PackCustomPathTool.cs");
File.WriteAllText(programFile, """
#:property PackageOutputPath=custom
Console.WriteLine($"Hello; EntryPointFilePath set? {AppContext.GetData("EntryPointFilePath") is string}");
""");
// Run unpacked.
- new DotnetCommand(Log, "run", "MyFileBasedTool.cs")
+ new DotnetCommand(Log, "run", "PackCustomPathTool.cs")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
@@ -2599,16 +2642,16 @@ public void Pack_CustomPath()
if (Directory.Exists(outputDir)) Directory.Delete(outputDir, recursive: true);
// Pack.
- new DotnetCommand(Log, "pack", "MyFileBasedTool.cs")
+ new DotnetCommand(Log, "pack", "PackCustomPathTool.cs")
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass();
- new DirectoryInfo(outputDir).File("MyFileBasedTool.1.0.0.nupkg").Should().Exist();
+ new DirectoryInfo(outputDir).File("PackCustomPathTool.1.0.0.nupkg").Should().Exist();
new DirectoryInfo(artifactsDir).Sub("package").Should().NotExist();
// Run the packed tool.
- new DotnetCommand(Log, "tool", "exec", "MyFileBasedTool", "--yes", "--add-source", outputDir)
+ new DotnetCommand(Log, "tool", "exec", "PackCustomPathTool", "--yes", "--add-source", outputDir)
.WithWorkingDirectory(testInstance.Path)
.Execute()
.Should().Pass()
@@ -6300,4 +6343,17 @@ Dictionary ReadFiles()
return result;
}
}
+
+ ///
+ /// No-op for use in static contexts where no test logger is available.
+ ///
+ private sealed class NullOutputHelper : ITestOutputHelper
+ {
+ public static readonly NullOutputHelper Instance = new();
+ public string Output => string.Empty;
+ public void Write(string message) { }
+ public void Write(string format, params object[] args) { }
+ public void WriteLine(string message) { }
+ public void WriteLine(string format, params object[] args) { }
+ }
}
diff --git a/test/dotnet.Tests/CommandTests/Test/GivenDotnetTestBuildsAndRunsTestfromCsproj.cs b/test/dotnet.Tests/CommandTests/Test/GivenDotnetTestBuildsAndRunsTestfromCsproj.cs
index 6bc213d4a4e4..ac056bcb2fbe 100644
--- a/test/dotnet.Tests/CommandTests/Test/GivenDotnetTestBuildsAndRunsTestfromCsproj.cs
+++ b/test/dotnet.Tests/CommandTests/Test/GivenDotnetTestBuildsAndRunsTestfromCsproj.cs
@@ -716,7 +716,9 @@ public void EnsureOutputPathEscaped(string flag)
{
var testProjectDirectory = CopyAndRestoreVSTestDotNetCoreTestApp([flag]);
- var pathWithComma = Path.Combine(AppContext.BaseDirectory, "a,b");
+ // Use a unique subdirectory per flag to avoid conflicts between theory data rows.
+ // --diag creates a file, while --output and --results-directory create directories.
+ var pathWithComma = Path.Combine(AppContext.BaseDirectory, "a,b", flag.TrimStart('-'));
// Call test
CommandResult result = new DotnetTestCommand(Log, disableNewOutput: true)
diff --git a/test/dotnet.Tests/dotnet.Tests.csproj b/test/dotnet.Tests/dotnet.Tests.csproj
index e98c47fdf6a2..70bebf3082df 100644
--- a/test/dotnet.Tests/dotnet.Tests.csproj
+++ b/test/dotnet.Tests/dotnet.Tests.csproj
@@ -89,9 +89,9 @@
-
-
-
+
+
+
diff --git a/test/xunit-runner/XUnitRunner.targets b/test/xunit-runner/XUnitRunner.targets
index 03897ea63aab..dce3fb456e8d 100644
--- a/test/xunit-runner/XUnitRunner.targets
+++ b/test/xunit-runner/XUnitRunner.targets
@@ -4,12 +4,20 @@
$(SdkTargetFramework)
$(SdkTargetFramework)
- 2.4.1
+ $(XUnitV3Version)
<_SDKCustomXUnitPublishTargetsPath>$(MSBuildThisFileDirectory)XUnitPublish.targets
-nocolor
+
+ <_TestPublishRidProperties Condition="'$(TargetRid)' != ''">RuntimeIdentifier=$(TargetRid);SelfContained=false;ErrorOnDuplicatePublishOutputFiles=false
+
$(ArtifactsBinDir)HelixTasks\$(Configuration)\HelixTasks.dll
@@ -37,7 +45,7 @@
Outputs="%(SDKCustomXUnitProject.Identity)%(SDKCustomXUnitProject.TargetFramework)%(SDKCustomXUnitProject.RuntimeTargetFramework)%(SDKCustomXUnitProject.AdditionalProperties)">
+ Properties="CustomAfterMicrosoftCommonTargets=$(_SDKCustomXUnitPublishTargetsPath);RuntimeIdentifiers=$(TargetRid);%(SDKCustomXUnitProject.AdditionalProperties)">
@@ -53,7 +61,16 @@
<_CurrentRuntimeTargetFramework Condition="'$(_CurrentRuntimeTargetFramework)' == ''">$(SDKCustomXUnitRuntimeTargetFramework)
<_CurrentAdditionalProperties>%(SDKCustomXUnitProject.AdditionalProperties)
-
+
+
+
+
@@ -77,6 +94,7 @@
diff --git a/test/xunit.runner.json b/test/xunit.runner.json
index 1fca20845e33..650eda816f3b 100644
--- a/test/xunit.runner.json
+++ b/test/xunit.runner.json
@@ -1,5 +1,5 @@
{
- "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
+ "$schema": "https://xunit.net/schema/v3.1/xunit.runner.schema.json",
"diagnosticMessages": true,
"longRunningTestSeconds": 20,
"showLiveOutput": true,