From cc0d3bee87bdc1fe3921e509d4bda3498a84003d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Fri, 27 Sep 2024 16:53:47 +0200 Subject: [PATCH 01/22] Update source gen --- eng/Version.Details.xml | 2 +- eng/Versions.props | 2 +- src/Package/MSTest.Sdk/MSTest.Sdk.csproj | 2 +- src/Package/MSTest.Sdk/Sdk/Runner/NativeAOT.targets | 6 +++--- src/Package/MSTest.Sdk/Sdk/Sdk.props.template | 2 +- .../MSTest.Acceptance.IntegrationTests.csproj | 6 ++---- .../MSTest.Acceptance.IntegrationTests/NativeAotTests.cs | 6 +++--- .../Helpers/AcceptanceTestBase.cs | 6 +++--- 8 files changed, 15 insertions(+), 17 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1d7178d88e..bad312c93a 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -21,7 +21,7 @@ https://github.com/microsoft/testanywhere 14bbde521335ae458cdc613e7a4fd93d6b5cd505 - + https://github.com/microsoft/testanywhere aa2fcc8616d988b234bc1d218465b20c56d0b82f diff --git a/eng/Versions.props b/eng/Versions.props index 0d2113aec8..2658daef1f 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -11,6 +11,6 @@ 17.12.5-preview.24475.1 1.5.0-preview.24475.2 - 1.0.0-alpha.24473.2 + 1.0.0-alpha.24477.1 diff --git a/src/Package/MSTest.Sdk/MSTest.Sdk.csproj b/src/Package/MSTest.Sdk/MSTest.Sdk.csproj index 9df47c1e9a..aca0d75d36 100644 --- a/src/Package/MSTest.Sdk/MSTest.Sdk.csproj +++ b/src/Package/MSTest.Sdk/MSTest.Sdk.csproj @@ -35,7 +35,7 @@ - <_TemplateProperties>MSTestEngineVersion=$(MSTestEngineVersion);MSTestVersion=$(Version);MicrosoftTestingPlatformVersion=$(Version.Replace('$(VersionPrefix)', '$(TestingPlatformVersionPrefix)'));MicrosoftTestingEntrepriseExtensionsVersion=$(MicrosoftTestingInternalFrameworkVersion);MicrosoftNETTestSdkVersion=$(MicrosoftNETTestSdkVersion);MicrosoftTestingExtensionsCodeCoverageVersion=$(MicrosoftTestingExtensionsCodeCoverageVersion);MicrosoftPlaywrightVersion=$(MicrosoftPlaywrightVersion);AspireHostingTestingVersion=$(AspireHostingTestingVersion) + <_TemplateProperties>MSTestSourceGenerationVersion=$(MSTestSourceGenerationVersion);MSTestVersion=$(Version);MicrosoftTestingPlatformVersion=$(Version.Replace('$(VersionPrefix)', '$(TestingPlatformVersionPrefix)'));MicrosoftTestingEntrepriseExtensionsVersion=$(MicrosoftTestingInternalFrameworkVersion);MicrosoftNETTestSdkVersion=$(MicrosoftNETTestSdkVersion);MicrosoftTestingExtensionsCodeCoverageVersion=$(MicrosoftTestingExtensionsCodeCoverageVersion);MicrosoftPlaywrightVersion=$(MicrosoftPlaywrightVersion);AspireHostingTestingVersion=$(AspireHostingTestingVersion) - - + @@ -34,8 +33,7 @@ - - + diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index c0efb2bae8..ab9f5adbeb 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -23,9 +23,9 @@ public class NativeAotTests : AcceptanceTestBase - - + + @@ -101,7 +101,7 @@ public async Task NativeAotTests_WillRunWithExitCodeZero() .PatchCodeWithReplace("$MicrosoftTestingEnterpriseExtensionsVersion$", MicrosoftTestingEnterpriseExtensionsVersion) .PatchCodeWithReplace("$TargetFramework$", TargetFrameworks.NetCurrent.Arguments) .PatchCodeWithReplace("$MSTestVersion$", MSTestVersion) - .PatchCodeWithReplace("$MSTestEngineVersion$", MSTestEngineVersion), + .PatchCodeWithReplace("$MSTestSourceGenerationVersion$", MSTestSourceGenerationVersion), addPublicFeeds: true); await DotnetCli.RunAsync( diff --git a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Helpers/AcceptanceTestBase.cs b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Helpers/AcceptanceTestBase.cs index ddaf3bc633..78dbcef845 100644 --- a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Helpers/AcceptanceTestBase.cs +++ b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/Helpers/AcceptanceTestBase.cs @@ -62,12 +62,12 @@ static AcceptanceTestBase() MSTestVersion = ExtractVersionFromVersionPropsFile(versionsPropFileDoc, "MSTestVersion"); MicrosoftTestingPlatformVersion = ExtractVersionFromVersionPropsFile(versionsPropFileDoc, "MSTestVersion"); MicrosoftTestingEnterpriseExtensionsVersion = ExtractVersionFromPackage(Constants.ArtifactsPackagesShipping, "Microsoft.Testing.Extensions."); - MSTestEngineVersion = ExtractVersionFromPackage(Constants.ArtifactsPackagesShipping, "MSTest.Engine"); + MSTestSourceGenerationVersion = ExtractVersionFromPackage(Constants.ArtifactsPackagesShipping, "MSTest.SourceGeneration"); #else MSTestVersion = ExtractVersionFromPackage(Constants.ArtifactsPackagesShipping, "MSTest.TestFramework."); MicrosoftTestingPlatformVersion = ExtractVersionFromPackage(Constants.ArtifactsPackagesShipping, "Microsoft.Testing.Platform."); MicrosoftTestingEnterpriseExtensionsVersion = ExtractVersionFromVersionPropsFile(versionsPropFileDoc, "MicrosoftTestingInternalFrameworkVersion"); - MSTestEngineVersion = ExtractVersionFromVersionPropsFile(versionsPropFileDoc, "MSTestEngineVersion"); + MSTestSourceGenerationVersion = ExtractVersionFromVersionPropsFile(versionsPropFileDoc, "MSTestSourceGenerationVersion"); #endif } @@ -80,7 +80,7 @@ protected AcceptanceTestBase(ITestExecutionContext testExecutionContext) public static string MSTestVersion { get; private set; } - public static string MSTestEngineVersion { get; private set; } + public static string MSTestSourceGenerationVersion { get; private set; } public static string MicrosoftNETTestSdkVersion { get; private set; } From 990d1544b26e5315ca2caf134d077e1976487eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Mon, 30 Sep 2024 09:30:56 +0200 Subject: [PATCH 02/22] Get assembly --- eng/Versions.props | 4 ++-- .../TestingPlatformBuilderHook.cs | 13 ++++++++++++- src/Package/MSTest.Sdk/Sdk/Runner/NativeAOT.targets | 6 ++++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 2658daef1f..7ea6e5047b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,9 +1,9 @@ - 3.7.0 + 3.8.0 - 1.5.0 + 1.6.0 preview diff --git a/src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/TestingPlatformBuilderHook.cs b/src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/TestingPlatformBuilderHook.cs index befda48370..7379df8e12 100644 --- a/src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/TestingPlatformBuilderHook.cs +++ b/src/Adapter/MSTest.TestAdapter/TestingPlatformAdapter/TestingPlatformBuilderHook.cs @@ -11,6 +11,17 @@ namespace Microsoft.VisualStudio.TestTools.UnitTesting; public static class TestingPlatformBuilderHook { #pragma warning disable IDE0060 // Remove unused parameter - public static void AddExtensions(ITestApplicationBuilder testApplicationBuilder, string[] arguments) => testApplicationBuilder.AddMSTest(() => [Assembly.GetEntryAssembly()!]); + public static void AddExtensions(ITestApplicationBuilder testApplicationBuilder, string[] arguments) + { +#if NET8_0_OR_GREATER + if (!System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported) + { + // We don't have a reliable way to get reference to the entry dll when compiled as NativeAOT. So instead we do the same registration + // in source generator. + return; + } +#endif + testApplicationBuilder.AddMSTest(() => [Assembly.GetEntryAssembly()!]); + } } #endif diff --git a/src/Package/MSTest.Sdk/Sdk/Runner/NativeAOT.targets b/src/Package/MSTest.Sdk/Sdk/Runner/NativeAOT.targets index 8f658948ae..fb73f5e5f2 100644 --- a/src/Package/MSTest.Sdk/Sdk/Runner/NativeAOT.targets +++ b/src/Package/MSTest.Sdk/Sdk/Runner/NativeAOT.targets @@ -3,6 +3,10 @@ + + true + + @@ -15,8 +19,6 @@ - Date: Mon, 30 Sep 2024 10:00:32 +0200 Subject: [PATCH 03/22] Update source generation to latest --- eng/Version.Details.xml | 2 +- eng/Versions.props | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index bad312c93a..908bb477bc 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -21,7 +21,7 @@ https://github.com/microsoft/testanywhere 14bbde521335ae458cdc613e7a4fd93d6b5cd505 - + https://github.com/microsoft/testanywhere aa2fcc8616d988b234bc1d218465b20c56d0b82f diff --git a/eng/Versions.props b/eng/Versions.props index 7ea6e5047b..61b58427ef 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -11,6 +11,6 @@ 17.12.5-preview.24475.1 1.5.0-preview.24475.2 - 1.0.0-alpha.24477.1 + 1.0.0-alpha.24480.1 From acec139c0069fd136a0b38a2c1b6f221d7db5ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Tue, 1 Oct 2024 14:10:48 +0200 Subject: [PATCH 04/22] down to just trim and aot warnings from libs --- eng/Version.Details.xml | 4 +-- eng/Versions.props | 2 +- samples/Playground/Program.cs | 2 +- .../Discovery/AssemblyEnumerator.cs | 8 ++++++ .../AssemblyResolver.cs | 7 +++--- .../Services/FileOperations.cs | 5 ++-- .../Services/ReflectionOperations2.cs | 5 ++++ .../Services/TestSourceHost.cs | 5 +--- .../Utilities/DeploymentUtilityBase.cs | 4 +-- ...oft.Testing.Extensions.VSTestBridge.csproj | 2 ++ ...ngleSessionVSTestAndTestAnywhereAdapter.cs | 4 +-- .../NativeAotTests.cs | 25 ++++--------------- .../Properties/launchSettings.json | 2 +- 13 files changed, 34 insertions(+), 41 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 6bc707206f..f2024f3223 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -21,9 +21,9 @@ https://github.com/microsoft/testanywhere c13e51348015685e1ec9a71377c6e7a2ef52cfd2 - + https://github.com/microsoft/testanywhere - aa2fcc8616d988b234bc1d218465b20c56d0b82f + aef1b181cc47377cf9c381f650be704b5a8dfc44 diff --git a/eng/Versions.props b/eng/Versions.props index ad5fb2b2a7..561c7ef4cc 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -11,6 +11,6 @@ 17.12.5-preview.24477.4 1.5.0-preview.24477.3 - 1.0.0-alpha.24480.1 + 1.0.0-alpha.24501.1 diff --git a/samples/Playground/Program.cs b/samples/Playground/Program.cs index ad40e696f6..eedef3819a 100644 --- a/samples/Playground/Program.cs +++ b/samples/Playground/Program.cs @@ -25,7 +25,7 @@ public static async Task Main(string[] args) if (Environment.GetEnvironmentVariable("TESTSERVERMODE") != "1") { // To attach to the children - Microsoft.Testing.TestInfrastructure.DebuggerUtility.AttachCurrentProcessToParentVSProcess(); + // Microsoft.Testing.TestInfrastructure.DebuggerUtility.AttachCurrentProcessToParentVSProcess(); ITestApplicationBuilder testApplicationBuilder = await TestApplication.CreateBuilderAsync(args); testApplicationBuilder.AddMSTest(() => [Assembly.GetEntryAssembly()!]); diff --git a/src/Adapter/MSTest.TestAdapter/Discovery/AssemblyEnumerator.cs b/src/Adapter/MSTest.TestAdapter/Discovery/AssemblyEnumerator.cs index c820ee0e9c..e90664e2c3 100644 --- a/src/Adapter/MSTest.TestAdapter/Discovery/AssemblyEnumerator.cs +++ b/src/Adapter/MSTest.TestAdapter/Discovery/AssemblyEnumerator.cs @@ -11,6 +11,9 @@ using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Execution; using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Helpers; using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.ObjectModel; +#if NET8_0_OR_GREATER +using Microsoft.VisualStudio.TestPlatform.MSTestAdapter; +#endif using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting.Internal; @@ -300,8 +303,13 @@ private static bool DynamicDataAttached(UnitTestElement test, Lazy tests, HashSet fixtureTests) { +#if NET8_0_OR_GREATER + ApplicationStateGuard.Ensure(System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported, "Fixture tests are not supported in NativeAOT mode."); +#endif string assemblyName = testMethodInfo.Parent.Parent.Assembly.GetName().Name!; string assemblyLocation = testMethodInfo.Parent.Parent.Assembly.Location; string className = testMethodInfo.Parent.ClassType.Name; diff --git a/src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.cs b/src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.cs index 0db8b6b573..776c7f3f16 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.cs @@ -3,6 +3,7 @@ #if NETFRAMEWORK || NET using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Reflection; #if NETFRAMEWORK using System.Runtime.InteropServices.WindowsRuntime; @@ -291,16 +292,14 @@ private static #endif bool DoesFileExist(string filePath) => File.Exists(filePath); + [UnconditionalSuppressMessage("Aot", "IL2026:DoNotUseGetDefinedTypes", Justification = "The whole class is not used in source generator mode.")] + #if NETFRAMEWORK protected virtual #else private static #endif - - // This whole class is not used in source generator mode. -#pragma warning disable IL2026 // Members attributed with RequiresUnreferencedCode may break when trimming Assembly LoadAssemblyFrom(string path) => Assembly.LoadFrom(path); -#pragma warning restore IL2026 // Members attributed with RequiresUnreferencedCode may break when trimming #if NETFRAMEWORK protected virtual Assembly ReflectionOnlyLoadAssemblyFrom(string path) => Assembly.ReflectionOnlyLoadFrom(path); diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Services/FileOperations.cs b/src/Adapter/MSTestAdapter.PlatformServices/Services/FileOperations.cs index 82064d7c5b..d857acf508 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/Services/FileOperations.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/Services/FileOperations.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Reflection; #if WIN_UI @@ -81,12 +82,10 @@ public Assembly LoadAssembly(string assemblyName, bool isReflectionOnly) /// /// The assembly. /// Path to the .DLL of the assembly. + [UnconditionalSuppressMessage("Aot", "IL3000:DoNotUseLocation", Justification = "This method will never be called in source generator mode, we are providing a different provider for file operations.")] public string? GetAssemblyPath(Assembly assembly) #if NETSTANDARD || NETCOREAPP || NETFRAMEWORK - // This method will never be called in source generator mode, we are providing a different provider for file operations. -#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file => assembly.Location; -#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file #elif WINDOWS_UWP => null; // TODO: what are the options here? #endif diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations2.cs b/src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations2.cs index 8f74a3e352..d827c13945 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations2.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations2.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Diagnostics.CodeAnalysis; using System.Reflection; using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface; @@ -38,6 +39,8 @@ public IEnumerable GetDeclaredProperties(Type type) public PropertyInfo? GetDeclaredProperty(Type type, string propertyName) => type.GetTypeInfo().GetDeclaredProperty(propertyName); + [UnconditionalSuppressMessage("Aot", "IL2026:DoNotUseGetDefinedTypes", Justification = "We access all the types we need in metadata, so this is preserved and works.")] + public Type[] GetDefinedTypes(Assembly assembly) => assembly.DefinedTypes.ToArray(); @@ -50,9 +53,11 @@ public IEnumerable GetRuntimeMethods(Type type) public PropertyInfo? GetRuntimeProperty(Type classType, string testContextPropertyName) => classType.GetProperty(testContextPropertyName); + [UnconditionalSuppressMessage("Aot", "IL2026:DoNotUseGetDefinedTypes", Justification = "We access all the types we need in metadata, so this is preserved and works.")] public Type? GetType(string typeName) => Type.GetType(typeName); + [UnconditionalSuppressMessage("Aot", "IL2026:DoNotUseGetDefinedTypes", Justification = "We access all the types we need in metadata, so this is preserved and works.")] public Type? GetType(Assembly assembly, string typeName) => assembly.GetType(typeName); diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.cs b/src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.cs index 482c4f9b94..4cb8e3641f 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.cs @@ -360,6 +360,7 @@ internal virtual string GetTargetFrameworkVersionString(string sourceFileName) /// /// A list of path. /// + [UnconditionalSuppressMessage("Aot", "IL3000:DoNotUseLocation", Justification = " We check for the empty path, and in single file mode, or on source gen mode we allow loading dependencies only from the current folder, which is what the default loader handles by itself.")] internal virtual List GetResolutionPaths(string sourceFileName, bool isPortableMode) { List resolutionPaths = @@ -388,9 +389,6 @@ internal virtual List GetResolutionPaths(string sourceFileName, bool isP #endif } - // We check for the empty path, and in single file mode, or on source gen mode we don't allow - // loading dependencies than from the current folder, which is what the default loader handles by itself. -#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file if (!string.IsNullOrEmpty(typeof(TestSourceHost).Assembly.Location)) { // Adding adapter folder to resolution paths @@ -408,7 +406,6 @@ internal virtual List GetResolutionPaths(string sourceFileName, bool isP resolutionPaths.Add(Path.GetDirectoryName(typeof(AssemblyHelper).Assembly.Location)!); } } -#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file return resolutionPaths; } diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.cs b/src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.cs index 2c4d4951d1..886ecf0ec2 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.cs @@ -126,6 +126,7 @@ public static string GetTestResultsDirectory(IRunContext? runContext) => !String /// The deployment directory. /// Root results directory. /// Returns a list of deployment warnings. + [UnconditionalSuppressMessage("Aot", "IL3000:DoNotUseLocation", Justification = "Deployment feature is not available in native.")] protected IEnumerable Deploy(IList deploymentItems, string testSource, string deploymentDirectory, string resultsDirectory) { Guard.NotNullOrWhiteSpace(deploymentDirectory); @@ -186,10 +187,7 @@ protected IEnumerable Deploy(IList deploymentItems, stri // Ignore the test platform files. string tempFile = Path.GetFileName(fileToDeploy); - // We throw when we run in source gen mode. -#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string assemblyName = Path.GetFileName(GetType().Assembly.Location); -#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (tempFile.Equals(assemblyName, StringComparison.OrdinalIgnoreCase)) { continue; diff --git a/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj b/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj index a5bad74d62..f8b2f86c68 100644 --- a/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj +++ b/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj @@ -1,6 +1,8 @@ + true + true netstandard2.0;$(MicrosoftTestingTargetFrameworks) diff --git a/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.cs b/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.cs index 7cfbe47606..4ff7fe80a7 100644 --- a/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.cs +++ b/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; @@ -103,13 +104,12 @@ protected sealed override Task RunTestsAsync(VSTestRunTestExecutionRequest reque protected abstract Task SynchronizedRunTestsAsync(VSTestRunTestExecutionRequest request, IMessageBus messageBus, CancellationToken cancellationToken); + [UnconditionalSuppressMessage("Aot", "IL3000:DoNotUseLocation", Justification = "We are passing our own class that derives from Assembly and sets the Location.")] protected sealed override Task ExecuteRequestAsync(TestExecutionRequest request, IMessageBus messageBus, CancellationToken cancellationToken) => ExecuteRequestWithRequestCountGuardAsync(async () => { -#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string[] testAssemblyPaths = _getTestAssemblies().Select(x => x.Location).ToArray(); -#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file switch (request) { case DiscoverTestExecutionRequest discoverRequest: diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index ab9f5adbeb..5e02bb6b92 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -20,6 +20,11 @@ public class NativeAotTests : AcceptanceTestBase true preview true + + true @@ -29,26 +34,6 @@ public class NativeAotTests : AcceptanceTestBase -#file Program.cs -using System.Diagnostics; -using System.Reflection; -using System.Runtime.InteropServices; - -using Microsoft.Testing.Framework; -using Microsoft.Testing.Internal.Framework; -using Microsoft.Testing.Platform.Builder; -using Microsoft.Testing.Platform.Capabilities; -using Microsoft.Testing.Platform.Capabilities.TestFramework; -using Microsoft.Testing.Platform.Extensions.Messages; -using Microsoft.Testing.Platform.Extensions.TestFramework; - -using NativeAotTests; - -ITestApplicationBuilder builder = await TestApplication.CreateBuilderAsync(args); -builder.AddTestFramework(new SourceGeneratedTestNodesBuilder()); -using ITestApplication app = await builder.BuildAsync(); -return await app.RunAsync(); - #file TestClass1.cs using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/Properties/launchSettings.json b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/Properties/launchSettings.json index f422322857..628c9beaba 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/Properties/launchSettings.json +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "MSTest.Acceptance.IntegrationTests": { "commandName": "Project", - "commandLineArgs": "--treenode-filter /*/*/*/**" + "commandLineArgs": "--treenode-filter /*/*/*/NativeAotTests_WillRunWithExitCodeZero/**" } } } From b21bf50b08a16047ade022cb65118f4690779287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Tue, 1 Oct 2024 14:15:41 +0200 Subject: [PATCH 05/22] revert proj --- .../Microsoft.Testing.Extensions.VSTestBridge.csproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj b/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj index f8b2f86c68..a5bad74d62 100644 --- a/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj +++ b/src/Platform/Microsoft.Testing.Extensions.VSTestBridge/Microsoft.Testing.Extensions.VSTestBridge.csproj @@ -1,8 +1,6 @@ - true - true netstandard2.0;$(MicrosoftTestingTargetFrameworks) From 2b6ee6c1d420801bb73493a7776674df26599069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Tue, 1 Oct 2024 15:46:38 +0200 Subject: [PATCH 06/22] fixes --- src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs | 1 + src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.csproj | 2 +- .../TestFramework/Attributes/DataSource/DynamicDataAttribute.cs | 1 + src/TestFramework/TestFramework/TestFramework.csproj | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs b/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs index c3279f095b..b51781a8eb 100644 --- a/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs +++ b/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs @@ -257,6 +257,7 @@ private static bool TryGetUnescapedManagedTypeName(TestMethod testMethod, [NotNu /// The class Type. /// The test Method. /// The . + [UnconditionalSuppressMessage("Aot", "IL2070:DoNotUseGetConstructor", Justification = "We access all the types we need in metadata, so this is preserved and works.")] private TestClassInfo CreateClassInfo(Type classType, TestMethod testMethod) { IEnumerable constructors = PlatformServiceProvider.Instance.ReflectionOperations.GetDeclaredConstructors(classType); diff --git a/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.csproj b/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.csproj index b7e241b8fd..3be190d969 100644 --- a/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.csproj +++ b/src/Adapter/MSTest.TestAdapter/MSTest.TestAdapter.csproj @@ -12,7 +12,7 @@ - $(EnableIotAnalyzers) + true diff --git a/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataAttribute.cs b/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataAttribute.cs index a9040938c4..a4e600fd45 100644 --- a/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataAttribute.cs +++ b/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataAttribute.cs @@ -88,6 +88,7 @@ public DynamicDataAttribute(string dynamicDataSourceName, Type dynamicDataDeclar public IEnumerable GetData(MethodInfo methodInfo) => DynamicDataProvider.Instance.GetData(_dynamicDataDeclaringType, _dynamicDataSourceType, _dynamicDataSourceName, methodInfo); /// + [UnconditionalSuppressMessage("Aot", "IL2075:DoNotUseGetDefinedMethod", Justification = "We access all the types we need in metadata, so this is preserved and works.")] public string? GetDisplayName(MethodInfo methodInfo, object?[]? data) { if (DynamicDataDisplayName != null) diff --git a/src/TestFramework/TestFramework/TestFramework.csproj b/src/TestFramework/TestFramework/TestFramework.csproj index 8f67b0069d..4cf85dec06 100644 --- a/src/TestFramework/TestFramework/TestFramework.csproj +++ b/src/TestFramework/TestFramework/TestFramework.csproj @@ -26,7 +26,7 @@ - $(EnableIotAnalyzers) + true From 8294a2d3e8b1e2201319fb673f3ce1d6f7a59340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Tue, 1 Oct 2024 17:24:16 +0200 Subject: [PATCH 07/22] fixes --- src/Adapter/MSTest.TestAdapter/TestMethodFilter.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Adapter/MSTest.TestAdapter/TestMethodFilter.cs b/src/Adapter/MSTest.TestAdapter/TestMethodFilter.cs index 1076988370..4297ee00be 100644 --- a/src/Adapter/MSTest.TestAdapter/TestMethodFilter.cs +++ b/src/Adapter/MSTest.TestAdapter/TestMethodFilter.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Diagnostics.CodeAnalysis; using System.Reflection; using Microsoft.VisualStudio.TestPlatform.ObjectModel; @@ -118,6 +119,7 @@ internal TestProperty PropertyProvider(string propertyName) /// Discovery context. /// The logger to log exception messages too. /// Filter expression. + [UnconditionalSuppressMessage("Aot", "IL2072:DoNotUseDynamicMembers", Justification = "Tested it, it works.")] private ITestCaseFilterExpression? GetTestCaseFilterFromDiscoveryContext(IDiscoveryContext context, IMessageLogger logger) { try From c4a2bb8529ff9fface9325026b44bc8e29f7ce97 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Tue, 5 Nov 2024 13:45:45 +0100 Subject: [PATCH 08/22] Extend test with different init/cleanup attributes --- .../NativeAotTests.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index 5e02bb6b92..56ece4a038 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -42,6 +42,36 @@ namespace MyTests; [TestClass] public class UnitTest1 { + [ClassInitialize] + public static void ClassInit(TestContext testContext) + { + } + + [ClassCleanup] + public static void ClassClean(TestContext testContext) + { + } + + [TestInitialize] + public void TestInit() + { + } + + [TestCleanup] + public void TestClean() + { + } + + [AssemblyInitialize] + public static void AssemblyInit(TestContext testContext) + { + } + + [AssemblyCleanup] + public static void AssemblyClean(TestContext testContext) + { + } + [TestMethod] public void TestMethod1() { From 2520e3489e63cfd5a6f571edb3ff64045f779114 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Tue, 5 Nov 2024 16:44:25 +0100 Subject: [PATCH 09/22] Fix cleanup methods in test --- .../MSTest.Acceptance.IntegrationTests/NativeAotTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index 56ece4a038..150022bc88 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -20,6 +20,7 @@ public class NativeAotTests : AcceptanceTestBase true preview true + $(NoWarn);IL2104;IL2026;IL3053 - 3.8.0 + 3.7.0 1.6.0 preview @@ -10,7 +10,7 @@ 10.0.0-beta.24531.2 17.13.0-preview.24551.1 - 1.5.0-preview.24531.1 - 1.0.0-alpha.24501.1 + 1.5.0-preview.24554.7 + 1.0.0-alpha.24555.1 From e89c7d336ed640118cd1dc0be904b35974a33e3d Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 6 Nov 2024 08:24:58 +0100 Subject: [PATCH 11/22] Update Version.Details.xml as well --- eng/Version.Details.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a668aaa0c8..67719863af 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -21,9 +21,9 @@ https://github.com/microsoft/testanywhere 4d80102c4530845265843db1454a4abda4128ba2 - + https://github.com/microsoft/testanywhere - aef1b181cc47377cf9c381f650be704b5a8dfc44 + 3c99c34d0f99de8dacfe909073722bd8ba45f2d8 From b0ead66c28377e76e7a287abe365116b91ee6191 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 6 Nov 2024 08:26:36 +0100 Subject: [PATCH 12/22] Revert launchSettings.json change --- .../Properties/launchSettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/Properties/launchSettings.json b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/Properties/launchSettings.json index 628c9beaba..f422322857 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/Properties/launchSettings.json +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "MSTest.Acceptance.IntegrationTests": { "commandName": "Project", - "commandLineArgs": "--treenode-filter /*/*/*/NativeAotTests_WillRunWithExitCodeZero/**" + "commandLineArgs": "--treenode-filter /*/*/*/**" } } } From e298e0af54bc1c953a2a840b7c470bc35f2f02d7 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 6 Nov 2024 12:38:16 +0100 Subject: [PATCH 13/22] Add more tests for native AOT --- .../NativeAotTests.cs | 425 ++++++++++++++---- 1 file changed, 337 insertions(+), 88 deletions(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index 150022bc88..43926afa34 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -3,100 +3,256 @@ using Microsoft.Testing.Platform.Acceptance.IntegrationTests; using Microsoft.Testing.Platform.Acceptance.IntegrationTests.Helpers; +using Microsoft.Testing.Platform.Helpers; namespace MSTest.Acceptance.IntegrationTests; [TestGroup] public class NativeAotTests : AcceptanceTestBase { - private const string SourceCode = """ -#file NativeAotTests.csproj - - - $TargetFramework$ - enable - enable - Exe - true - preview - true - $(NoWarn);IL2104;IL2026;IL3053 - - true - - - - - - - - - -#file TestClass1.cs -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace MyTests; - -[TestClass] -public class UnitTest1 -{ - [ClassInitialize] - public static void ClassInit(TestContext testContext) - { - } - - [ClassCleanup] - public static void ClassClean() - { - } - - [TestInitialize] - public void TestInit() - { - } - - [TestCleanup] - public void TestClean() - { - } - - [AssemblyInitialize] - public static void AssemblyInit(TestContext testContext) - { - } - - [AssemblyCleanup] - public static void AssemblyClean() - { - } - - [TestMethod] - public void TestMethod1() - { - } - - [TestMethod] - [DataRow(0, 1)] - public void TestMethod2(int a, int b) - { - } - - [TestMethod] - [DynamicData(nameof(Data))] - public void TestMethod3(int a, int b) - { - } - - public static IEnumerable Data { get; } - = new[] + private const string SourceCodeCsproj = """ + #file NativeAotTests.csproj + + + $TargetFramework$ + enable + enable + Exe + true + preview + true + $(NoWarn);IL2104;IL2026;IL3053 + + true + + + + + + + + + """; + + private const string SourceCodeSimple = $$""" + {{SourceCodeCsproj}} + + #file TestClass1.cs + using Microsoft.VisualStudio.TestTools.UnitTesting; + + namespace MyTests; + + [TestClass] + public class UnitTest1 { - new object[] { 1, 2 } - }; -} -"""; + [ClassInitialize] + public static void ClassInit(TestContext testContext) + { + } + + [ClassCleanup] + public static void ClassClean() + { + } + + [TestInitialize] + public void TestInit() + { + } + + [TestCleanup] + public void TestClean() + { + } + + [AssemblyInitialize] + public static void AssemblyInit(TestContext testContext) + { + } + + [AssemblyCleanup] + public static void AssemblyClean() + { + } + + [TestMethod] + public void TestMethod1() + { + } + + [TestMethod] + [DataRow(0, 1)] + public void TestMethod2(int a, int b) + { + } + + [TestMethod] + [DynamicData(nameof(Data))] + public void TestMethod3(int a, int b) + { + } + + public static IEnumerable Data { get; } + = new[] + { + new object[] { 1, 2 } + }; + } + """; + + private const string SourceCodeWithFailingAssert = $$""" + {{SourceCodeCsproj}} + + #file TestClass1.cs + using Microsoft.VisualStudio.TestTools.UnitTesting; + + namespace MyTests; + + [TestClass] + public class UnitTest1 + { + [ClassInitialize] + public static void ClassInit(TestContext testContext) + { + } + + [ClassCleanup] + public static void ClassClean() + { + } + + [TestInitialize] + public void TestInit() + { + } + + [TestCleanup] + public void TestClean() + { + } + + [AssemblyInitialize] + public static void AssemblyInit(TestContext testContext) + { + } + + [AssemblyCleanup] + public static void AssemblyClean() + { + } + + [TestMethod] + public void TestMethod1() + { + Assert.Fail("Failing TestMethod1"); + } + + [TestMethod] + [DataRow(0, 1)] + [DataRow(2, 3)] + public void TestMethod2(int a, int b) + { + if (a == 2) Assert.Fail("Failing a specific case of TestMethod2"); + } + + [TestMethod] + [DynamicData(nameof(Data))] + public void TestMethod3(int a, int b) + { + if (a == 2) Assert.Fail("Failing a specific case of TestMethod3"); + } + + public static IEnumerable Data { get; } + = new[] + { + new object[] { 1, 2 }, + new object[] { 2, 3 }, + }; + } + """; + + private const string SourceCodeWithInCompatibleLibrary = $$""" + #file TestProject/NativeAotTests.csproj + + + $TargetFramework$ + enable + enable + Exe + true + preview + true + $(NoWarn);IL2104;IL2026;IL3053 + + true + + + + + + + + + + + #file TestProject/TestClass1.cs + using Microsoft.VisualStudio.TestTools.UnitTesting; + + namespace MyTests; + + [TestClass] + public class UnitTest1 + { + [TestMethod] + public void TestMethod1() + { + Assert.IsTrue(TestBadLibrary.ClassToBeTested.M()); + } + } + + #file TestBadLibrary/TestBadLibrary.csproj + + + $TargetFramework$ + enable + enable + Library + preview + + + + #file TestBadLibrary/ClassToBeTested.cs + + using System; + using System.Diagnostics.CodeAnalysis; + using System.Reflection; + + namespace TestBadLibrary; + + public static class ClassToBeTested + { + [UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Intentionally not trimmer friendly. That is what we are testing ;)")] + public static bool M() + { + var asm = Assembly.GetExecutingAssembly(); + var type = asm.GetType("TestBadLibrary.ClassToBeTested"); + var m = type!.GetMethod("CalledByReflection"); + return (bool)m!.Invoke(null, null)!; + } + + private static bool CalledByReflection() + { + return true; + } + } + + """; private readonly AcceptanceFixture _acceptanceFixture; @@ -112,7 +268,7 @@ public async Task NativeAotTests_WillRunWithExitCodeZero() { using TestAsset generator = await TestAsset.GenerateAssetAsync( "NativeAotTests", - SourceCode + SourceCodeSimple .PatchCodeWithReplace("$MicrosoftTestingPlatformVersion$", MicrosoftTestingPlatformVersion) .PatchCodeWithReplace("$MicrosoftTestingEnterpriseExtensionsVersion$", MicrosoftTestingEnterpriseExtensionsVersion) .PatchCodeWithReplace("$TargetFramework$", TargetFrameworks.NetCurrent.Arguments) @@ -127,6 +283,7 @@ await DotnetCli.RunAsync( DotnetMuxerResult compilationResult = await DotnetCli.RunAsync( $"publish -m:1 -nodeReuse:false {generator.TargetAssetPath} -r {RID}", _acceptanceFixture.NuGetGlobalPackagesFolder.Path, + timeoutInSeconds: 100, retryCount: 0); compilationResult.AssertOutputContains("Generating native code"); @@ -135,4 +292,96 @@ await DotnetCli.RunAsync( TestHostResult result = await testHost.ExecuteAsync(); result.AssertExitCodeIs(0); }, times: 15, every: TimeSpan.FromSeconds(5)); + + public async Task NativeAotTests_WillFailAsserts() + // The native AOT publication is pretty flaky and is often failing on CI with "fatal error LNK1136: invalid or corrupt file", + // or sometimes doesn't fail but the native code generation is not done. + // Retrying the restore/publish on fresh asset seems to be more effective than retrying on the same asset. + => await RetryHelper.RetryAsync( + async () => + { + using TestAsset generator = await TestAsset.GenerateAssetAsync( + "NativeAotTests", + SourceCodeWithFailingAssert + .PatchCodeWithReplace("$MicrosoftTestingPlatformVersion$", MicrosoftTestingPlatformVersion) + .PatchCodeWithReplace("$MicrosoftTestingEnterpriseExtensionsVersion$", MicrosoftTestingEnterpriseExtensionsVersion) + .PatchCodeWithReplace("$TargetFramework$", TargetFrameworks.NetCurrent.Arguments) + .PatchCodeWithReplace("$MSTestVersion$", MSTestVersion) + .PatchCodeWithReplace("$MSTestSourceGenerationVersion$", MSTestSourceGenerationVersion), + addPublicFeeds: true); + + await DotnetCli.RunAsync( + $"restore -m:1 -nodeReuse:false {generator.TargetAssetPath} -r {RID}", + _acceptanceFixture.NuGetGlobalPackagesFolder.Path, + retryCount: 0); + DotnetMuxerResult compilationResult = await DotnetCli.RunAsync( + $"publish -m:1 -nodeReuse:false {generator.TargetAssetPath} -r {RID}", + _acceptanceFixture.NuGetGlobalPackagesFolder.Path, + timeoutInSeconds: 100, + retryCount: 0); + compilationResult.AssertOutputContains("Generating native code"); + + var testHost = TestHost.LocateFrom(generator.TargetAssetPath, "NativeAotTests", TargetFrameworks.NetCurrent.Arguments, RID, Verb.publish); + + TestHostResult result = await testHost.ExecuteAsync(); + result.AssertExitCodeIs(ExitCodes.AtLeastOneTestFailed); + + result.AssertOutputContains("failed TestMethod1"); + result.AssertOutputContains("Assert.Fail failed. Failing TestMethod1"); + + result.AssertOutputContains("failed TestMethod2 (2,3)"); + result.AssertOutputContains("Assert.Fail failed. Failing a specific case of TestMethod2"); + + result.AssertOutputContains("failed TestMethod3 (2,3)"); + result.AssertOutputContains("Assert.Fail failed. Failing a specific case of TestMethod3"); + + result.AssertOutputContains("Test run summary: Failed!"); + result.AssertOutputContains("total: 5"); + result.AssertOutputContains("failed: 3"); + result.AssertOutputContains("succeeded: 2"); + result.AssertOutputContains("skipped: 0"); + }, times: 15, every: TimeSpan.FromSeconds(5)); + + public async Task NativeAotTests_WillFailBecauseTestedLibraryIsNotCompatible() + // The native AOT publication is pretty flaky and is often failing on CI with "fatal error LNK1136: invalid or corrupt file", + // or sometimes doesn't fail but the native code generation is not done. + // Retrying the restore/publish on fresh asset seems to be more effective than retrying on the same asset. + => await RetryHelper.RetryAsync( + async () => + { + using TestAsset generator = await TestAsset.GenerateAssetAsync( + "NativeAotTests", + SourceCodeWithInCompatibleLibrary + .PatchCodeWithReplace("$MicrosoftTestingPlatformVersion$", MicrosoftTestingPlatformVersion) + .PatchCodeWithReplace("$MicrosoftTestingEnterpriseExtensionsVersion$", MicrosoftTestingEnterpriseExtensionsVersion) + .PatchCodeWithReplace("$TargetFramework$", TargetFrameworks.NetCurrent.Arguments) + .PatchCodeWithReplace("$MSTestVersion$", MSTestVersion) + .PatchCodeWithReplace("$MSTestSourceGenerationVersion$", MSTestSourceGenerationVersion), + addPublicFeeds: true); + + await DotnetCli.RunAsync( + $"restore -m:1 -nodeReuse:false {Path.Combine(generator.TargetAssetPath, "TestProject")} -r {RID}", + _acceptanceFixture.NuGetGlobalPackagesFolder.Path, + retryCount: 0); + DotnetMuxerResult compilationResult = await DotnetCli.RunAsync( + $"publish -m:1 -nodeReuse:false {Path.Combine(generator.TargetAssetPath, "TestProject")} -r {RID}", + _acceptanceFixture.NuGetGlobalPackagesFolder.Path, + timeoutInSeconds: 100, + retryCount: 0); + compilationResult.AssertOutputContains("Generating native code"); + + var testHost = TestHost.LocateFrom(Path.Combine(generator.TargetAssetPath, "TestProject"), "NativeAotTests", TargetFrameworks.NetCurrent.Arguments, RID, Verb.publish); + + TestHostResult result = await testHost.ExecuteAsync(); + result.AssertExitCodeIs(ExitCodes.AtLeastOneTestFailed); + + result.AssertOutputContains("System.NullReferenceException: Object reference not set to an instance of an object."); + result.AssertOutputContains("TestBadLibrary.ClassToBeTested.M()"); + + result.AssertOutputContains("Test run summary: Failed!"); + result.AssertOutputContains("total: 1"); + result.AssertOutputContains("failed: 1"); + result.AssertOutputContains("succeeded: 0"); + result.AssertOutputContains("skipped: 0"); + }, times: 15, every: TimeSpan.FromSeconds(5)); } From def4e8b62c2b19d4568bd986ef1d97d290c09d2b Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 6 Nov 2024 13:19:47 +0100 Subject: [PATCH 14/22] Refactor tests, add more tests --- .../NativeAotTests.cs | 212 ++++++++++-------- 1 file changed, 115 insertions(+), 97 deletions(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index 43926afa34..1d17eee878 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -174,7 +174,7 @@ public void TestMethod3(int a, int b) } """; - private const string SourceCodeWithInCompatibleLibrary = $$""" + private const string SourceCodeWithIncompatibleLibrary = $$""" #file TestProject/NativeAotTests.csproj @@ -260,6 +260,84 @@ public NativeAotTests(ITestExecutionContext testExecutionContext, AcceptanceFixt : base(testExecutionContext) => _acceptanceFixture = acceptanceFixture; public async Task NativeAotTests_WillRunWithExitCodeZero() + { + TestHostResult result = await GetTestResultForCode(SourceCodeSimple); + result.AssertExitCodeIs(0); + } + + public async Task NativeAotTests_WillFailAsserts() + { + TestHostResult result = await GetTestResultForCode(SourceCodeWithFailingAssert); + result.AssertExitCodeIs(ExitCodes.AtLeastOneTestFailed); + + result.AssertOutputContains("failed TestMethod1"); + result.AssertOutputContains("Assert.Fail failed. Failing TestMethod1"); + + result.AssertOutputContains("failed TestMethod2 (2,3)"); + result.AssertOutputContains("Assert.Fail failed. Failing a specific case of TestMethod2"); + + result.AssertOutputContains("failed TestMethod3 (2,3)"); + result.AssertOutputContains("Assert.Fail failed. Failing a specific case of TestMethod3"); + + result.AssertOutputContains("Test run summary: Failed!"); + result.AssertOutputContains("total: 5"); + result.AssertOutputContains("failed: 3"); + result.AssertOutputContains("succeeded: 2"); + result.AssertOutputContains("skipped: 0"); + } + + public async Task NativeAotTests_WillFailBecauseTestedLibraryIsNotCompatible() + { + TestHostResult result = await GetTestResultForCode(SourceCodeWithIncompatibleLibrary, "TestProject"); + result.AssertExitCodeIs(ExitCodes.AtLeastOneTestFailed); + + result.AssertOutputContains("System.NullReferenceException: Object reference not set to an instance of an object."); + result.AssertOutputContains("TestBadLibrary.ClassToBeTested.M()"); + + result.AssertOutputContains("Test run summary: Failed!"); + result.AssertOutputContains("total: 1"); + result.AssertOutputContains("failed: 1"); + result.AssertOutputContains("succeeded: 0"); + result.AssertOutputContains("skipped: 0"); + } + + public async Task NativeAotTests_WillFailInTestInitialize() + { + string code = ConstructFailingFixture("TestInitialize", isStatic: false, usesTestContext: false); + await NativeAotTests_WillFailInTestFixtureCommon(code); + } + + public async Task NativeAotTests_WillFailInTestCleanup() + { + string code = ConstructFailingFixture("TestCleanup", isStatic: false, usesTestContext: false); + await NativeAotTests_WillFailInTestFixtureCommon(code); + } + + public async Task NativeAotTests_WillFailInClassInitialize() + { + string code = ConstructFailingFixture("ClassInitialize", isStatic: true, usesTestContext: true); + await NativeAotTests_WillFailInTestFixtureCommon(code); + } + + public async Task NativeAotTests_WillFailInClassCleanup() + { + string code = ConstructFailingFixture("ClassInitialize", isStatic: true, usesTestContext: false); + await NativeAotTests_WillFailInTestFixtureCommon(code); + } + + public async Task NativeAotTests_WillFailInAssemblyInitialize() + { + string code = ConstructFailingFixture("AssemblyInitialize", isStatic: true, usesTestContext: true); + await NativeAotTests_WillFailInTestFixtureCommon(code); + } + + public async Task NativeAotTests_WillFailInAssemblyCleanup() + { + string code = ConstructFailingFixture("AssemblyCleanup", isStatic: true, usesTestContext: false); + await NativeAotTests_WillFailInTestFixtureCommon(code); + } + + private async Task GetTestResultForCode(string code, string? projectDir = null) // The native AOT publication is pretty flaky and is often failing on CI with "fatal error LNK1136: invalid or corrupt file", // or sometimes doesn't fail but the native code generation is not done. // Retrying the restore/publish on fresh asset seems to be more effective than retrying on the same asset. @@ -268,7 +346,7 @@ public async Task NativeAotTests_WillRunWithExitCodeZero() { using TestAsset generator = await TestAsset.GenerateAssetAsync( "NativeAotTests", - SourceCodeSimple + code .PatchCodeWithReplace("$MicrosoftTestingPlatformVersion$", MicrosoftTestingPlatformVersion) .PatchCodeWithReplace("$MicrosoftTestingEnterpriseExtensionsVersion$", MicrosoftTestingEnterpriseExtensionsVersion) .PatchCodeWithReplace("$TargetFramework$", TargetFrameworks.NetCurrent.Arguments) @@ -276,112 +354,52 @@ public async Task NativeAotTests_WillRunWithExitCodeZero() .PatchCodeWithReplace("$MSTestSourceGenerationVersion$", MSTestSourceGenerationVersion), addPublicFeeds: true); + string targetAssetPath = projectDir is null ? generator.TargetAssetPath : Path.Combine(generator.TargetAssetPath, projectDir); + await DotnetCli.RunAsync( - $"restore -m:1 -nodeReuse:false {generator.TargetAssetPath} -r {RID}", + $"restore -m:1 -nodeReuse:false {targetAssetPath} -r {RID}", _acceptanceFixture.NuGetGlobalPackagesFolder.Path, retryCount: 0); DotnetMuxerResult compilationResult = await DotnetCli.RunAsync( - $"publish -m:1 -nodeReuse:false {generator.TargetAssetPath} -r {RID}", + $"publish -m:1 -nodeReuse:false {targetAssetPath} -r {RID}", _acceptanceFixture.NuGetGlobalPackagesFolder.Path, timeoutInSeconds: 100, retryCount: 0); compilationResult.AssertOutputContains("Generating native code"); - var testHost = TestHost.LocateFrom(generator.TargetAssetPath, "NativeAotTests", TargetFrameworks.NetCurrent.Arguments, RID, Verb.publish); + var testHost = TestHost.LocateFrom(targetAssetPath, "NativeAotTests", TargetFrameworks.NetCurrent.Arguments, RID, Verb.publish); - TestHostResult result = await testHost.ExecuteAsync(); - result.AssertExitCodeIs(0); + return await testHost.ExecuteAsync(); }, times: 15, every: TimeSpan.FromSeconds(5)); - public async Task NativeAotTests_WillFailAsserts() - // The native AOT publication is pretty flaky and is often failing on CI with "fatal error LNK1136: invalid or corrupt file", - // or sometimes doesn't fail but the native code generation is not done. - // Retrying the restore/publish on fresh asset seems to be more effective than retrying on the same asset. - => await RetryHelper.RetryAsync( - async () => - { - using TestAsset generator = await TestAsset.GenerateAssetAsync( - "NativeAotTests", - SourceCodeWithFailingAssert - .PatchCodeWithReplace("$MicrosoftTestingPlatformVersion$", MicrosoftTestingPlatformVersion) - .PatchCodeWithReplace("$MicrosoftTestingEnterpriseExtensionsVersion$", MicrosoftTestingEnterpriseExtensionsVersion) - .PatchCodeWithReplace("$TargetFramework$", TargetFrameworks.NetCurrent.Arguments) - .PatchCodeWithReplace("$MSTestVersion$", MSTestVersion) - .PatchCodeWithReplace("$MSTestSourceGenerationVersion$", MSTestSourceGenerationVersion), - addPublicFeeds: true); - - await DotnetCli.RunAsync( - $"restore -m:1 -nodeReuse:false {generator.TargetAssetPath} -r {RID}", - _acceptanceFixture.NuGetGlobalPackagesFolder.Path, - retryCount: 0); - DotnetMuxerResult compilationResult = await DotnetCli.RunAsync( - $"publish -m:1 -nodeReuse:false {generator.TargetAssetPath} -r {RID}", - _acceptanceFixture.NuGetGlobalPackagesFolder.Path, - timeoutInSeconds: 100, - retryCount: 0); - compilationResult.AssertOutputContains("Generating native code"); - - var testHost = TestHost.LocateFrom(generator.TargetAssetPath, "NativeAotTests", TargetFrameworks.NetCurrent.Arguments, RID, Verb.publish); - - TestHostResult result = await testHost.ExecuteAsync(); - result.AssertExitCodeIs(ExitCodes.AtLeastOneTestFailed); - - result.AssertOutputContains("failed TestMethod1"); - result.AssertOutputContains("Assert.Fail failed. Failing TestMethod1"); - - result.AssertOutputContains("failed TestMethod2 (2,3)"); - result.AssertOutputContains("Assert.Fail failed. Failing a specific case of TestMethod2"); - - result.AssertOutputContains("failed TestMethod3 (2,3)"); - result.AssertOutputContains("Assert.Fail failed. Failing a specific case of TestMethod3"); - - result.AssertOutputContains("Test run summary: Failed!"); - result.AssertOutputContains("total: 5"); - result.AssertOutputContains("failed: 3"); - result.AssertOutputContains("succeeded: 2"); - result.AssertOutputContains("skipped: 0"); - }, times: 15, every: TimeSpan.FromSeconds(5)); + private async Task NativeAotTests_WillFailInTestFixtureCommon(string code) + { + TestHostResult result = await GetTestResultForCode(code); + result.AssertExitCodeIs(ExitCodes.AtLeastOneTestFailed); + result.AssertOutputContains("Assert.Fail failed. Fails in fixture"); + } - public async Task NativeAotTests_WillFailBecauseTestedLibraryIsNotCompatible() - // The native AOT publication is pretty flaky and is often failing on CI with "fatal error LNK1136: invalid or corrupt file", - // or sometimes doesn't fail but the native code generation is not done. - // Retrying the restore/publish on fresh asset seems to be more effective than retrying on the same asset. - => await RetryHelper.RetryAsync( - async () => - { - using TestAsset generator = await TestAsset.GenerateAssetAsync( - "NativeAotTests", - SourceCodeWithInCompatibleLibrary - .PatchCodeWithReplace("$MicrosoftTestingPlatformVersion$", MicrosoftTestingPlatformVersion) - .PatchCodeWithReplace("$MicrosoftTestingEnterpriseExtensionsVersion$", MicrosoftTestingEnterpriseExtensionsVersion) - .PatchCodeWithReplace("$TargetFramework$", TargetFrameworks.NetCurrent.Arguments) - .PatchCodeWithReplace("$MSTestVersion$", MSTestVersion) - .PatchCodeWithReplace("$MSTestSourceGenerationVersion$", MSTestSourceGenerationVersion), - addPublicFeeds: true); - - await DotnetCli.RunAsync( - $"restore -m:1 -nodeReuse:false {Path.Combine(generator.TargetAssetPath, "TestProject")} -r {RID}", - _acceptanceFixture.NuGetGlobalPackagesFolder.Path, - retryCount: 0); - DotnetMuxerResult compilationResult = await DotnetCli.RunAsync( - $"publish -m:1 -nodeReuse:false {Path.Combine(generator.TargetAssetPath, "TestProject")} -r {RID}", - _acceptanceFixture.NuGetGlobalPackagesFolder.Path, - timeoutInSeconds: 100, - retryCount: 0); - compilationResult.AssertOutputContains("Generating native code"); - - var testHost = TestHost.LocateFrom(Path.Combine(generator.TargetAssetPath, "TestProject"), "NativeAotTests", TargetFrameworks.NetCurrent.Arguments, RID, Verb.publish); - - TestHostResult result = await testHost.ExecuteAsync(); - result.AssertExitCodeIs(ExitCodes.AtLeastOneTestFailed); - - result.AssertOutputContains("System.NullReferenceException: Object reference not set to an instance of an object."); - result.AssertOutputContains("TestBadLibrary.ClassToBeTested.M()"); - - result.AssertOutputContains("Test run summary: Failed!"); - result.AssertOutputContains("total: 1"); - result.AssertOutputContains("failed: 1"); - result.AssertOutputContains("succeeded: 0"); - result.AssertOutputContains("skipped: 0"); - }, times: 15, every: TimeSpan.FromSeconds(5)); + private static string ConstructFailingFixture(string attributeName, bool isStatic, bool usesTestContext) => $$""" + {{SourceCodeCsproj}} + + #file TestClass1.cs + using Microsoft.VisualStudio.TestTools.UnitTesting; + + namespace MyTests; + + [TestClass] + public class UnitTest1 + { + [{{attributeName}}] + public{{(isStatic ? " static" : string.Empty)}} void FixtureMethod({{(usesTestContext ? "TestContext testContext" : "")}}) + { + Assert.Fail("Fails in fixture"); + } + + [TestMethod] + public void TestMethod1() + { + } + } + """; } From ad94d29e26894fffe892ce50ff797ebc2d3330fa Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 6 Nov 2024 13:43:19 +0100 Subject: [PATCH 15/22] Fix typo --- .../MSTest.Acceptance.IntegrationTests/NativeAotTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index 1d17eee878..dd140e9f63 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -321,7 +321,7 @@ public async Task NativeAotTests_WillFailInClassInitialize() public async Task NativeAotTests_WillFailInClassCleanup() { - string code = ConstructFailingFixture("ClassInitialize", isStatic: true, usesTestContext: false); + string code = ConstructFailingFixture("ClassCleanup", isStatic: true, usesTestContext: false); await NativeAotTests_WillFailInTestFixtureCommon(code); } From 88ff2bc03d5a21ca6fcfe434cb7678ffe90947ff Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 6 Nov 2024 13:43:49 +0100 Subject: [PATCH 16/22] Address analyzer warning --- .../MSTest.Acceptance.IntegrationTests/NativeAotTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index dd140e9f63..033c862588 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -391,7 +391,7 @@ namespace MyTests; public class UnitTest1 { [{{attributeName}}] - public{{(isStatic ? " static" : string.Empty)}} void FixtureMethod({{(usesTestContext ? "TestContext testContext" : "")}}) + public{{(isStatic ? " static" : string.Empty)}} void FixtureMethod({{(usesTestContext ? "TestContext testContext" : string.Empty)}}) { Assert.Fail("Fails in fixture"); } From 947785159b10ed8b278f4142d5ca40375fee3dcf Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 6 Nov 2024 16:03:27 +0100 Subject: [PATCH 17/22] More tests --- .../NativeAotTests.cs | 140 ++++++++++++++++-- 1 file changed, 127 insertions(+), 13 deletions(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index 033c862588..f76fbfc59f 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Text.RegularExpressions; + using Microsoft.Testing.Platform.Acceptance.IntegrationTests; using Microsoft.Testing.Platform.Acceptance.IntegrationTests.Helpers; using Microsoft.Testing.Platform.Helpers; @@ -33,6 +35,7 @@ without this the dll is just copied into the output folder. + """; @@ -174,6 +177,90 @@ public void TestMethod3(int a, int b) } """; + private const string SourceCodeWithDerivedTestClass = $$""" + {{SourceCodeCsproj}} + + #file TestClass1.cs + using Microsoft.VisualStudio.TestTools.UnitTesting; + + namespace MyTests; + + public class MyTestClassAttribute : TestClassAttribute { } + + [MyTestClass] + public class UnitTest1 + { + [TestMethod] + public void TestMethod1() + { + Assert.Fail("Failing TestMethod1"); + } + } + """; + + + private const string SourceCodeWithFailingAssertClassIgnored = $$""" + {{SourceCodeCsproj}} + + #file TestClass1.cs + using Microsoft.VisualStudio.TestTools.UnitTesting; + + namespace MyTests; + + [TestClass] + [Ignore] + public class UnitTest1 + { + [TestMethod] + public void TestMethod1() + { + Assert.Fail("Failing TestMethod1"); + } + } + """; + + private const string SourceCodeWithFailingAssertMethodIgnored = $$""" + {{SourceCodeCsproj}} + + #file TestClass1.cs + using Microsoft.VisualStudio.TestTools.UnitTesting; + + namespace MyTests; + + [TestClass] + public class UnitTest1 + { + [TestMethod] + [Ignore] + public void TestMethod1() + { + Assert.Fail("Failing TestMethod1"); + } + + """; + + private const string SourceCodeWithTestContext = $$""" + {{SourceCodeCsproj}} + + #file TestClass1.cs + using Microsoft.VisualStudio.TestTools.UnitTesting; + + namespace MyTests; + + [TestClass] + public class UnitTest1 + { + public TestContext TestContext { get; set; } = default!; + + [TestMethod] + public void TestMethod1() + { + TestContext.WriteLine("Writing to TestContext"); + TestContext.AddResultFile("C:\\file.txt"); + } + } + """; + private const string SourceCodeWithIncompatibleLibrary = $$""" #file TestProject/NativeAotTests.csproj @@ -262,7 +349,7 @@ public NativeAotTests(ITestExecutionContext testExecutionContext, AcceptanceFixt public async Task NativeAotTests_WillRunWithExitCodeZero() { TestHostResult result = await GetTestResultForCode(SourceCodeSimple); - result.AssertExitCodeIs(0); + result.AssertExitCodeIs(ExitCodes.Success); } public async Task NativeAotTests_WillFailAsserts() @@ -279,11 +366,40 @@ public async Task NativeAotTests_WillFailAsserts() result.AssertOutputContains("failed TestMethod3 (2,3)"); result.AssertOutputContains("Assert.Fail failed. Failing a specific case of TestMethod3"); - result.AssertOutputContains("Test run summary: Failed!"); - result.AssertOutputContains("total: 5"); - result.AssertOutputContains("failed: 3"); - result.AssertOutputContains("succeeded: 2"); - result.AssertOutputContains("skipped: 0"); + result.AssertOutputContainsSummary(failed: 3, passed: 2, skipped: 0); + } + + public async Task NativeAotTests_WillRespectIgnoreInClass() + { + TestHostResult result = await GetTestResultForCode(SourceCodeWithFailingAssertClassIgnored); + result.AssertExitCodeIs(ExitCodes.ZeroTests); + result.AssertOutputContainsSummary(failed: 0, passed: 0, skipped: 1); + } + + public async Task NativeAotTests_WillRespectIgnoreInMethod() + { + TestHostResult result = await GetTestResultForCode(SourceCodeWithFailingAssertMethodIgnored); + result.AssertExitCodeIs(ExitCodes.ZeroTests); + result.AssertOutputContainsSummary(failed: 0, passed: 0, skipped: 1); + } + + public async Task NativeAotTests_DerivedTestClassAttribute_NotCurrentlySupported() + { + TestHostResult result = await GetTestResultForCode(SourceCodeWithDerivedTestClass); + // TODO: Add 'wrong' asserts to document the current behavior. + } + + public async Task NativeAotTests_TestContext() + { + TestHostResult result = await GetTestResultForCode(SourceCodeWithTestContext, executeBeforeDisposingTestAsset: result => + { + string trxPath = Regex.Match(result.StandardOutput, "- (.+?).trx").Value.Substring("- ".Length); + string trxContent = File.ReadAllText(trxPath); + Assert.Contains("Writing to TestContext", trxContent); + Assert.Contains(@"", trxContent); + }); + + result.AssertExitCodeIs(ExitCodes.Success); } public async Task NativeAotTests_WillFailBecauseTestedLibraryIsNotCompatible() @@ -294,11 +410,7 @@ public async Task NativeAotTests_WillFailBecauseTestedLibraryIsNotCompatible() result.AssertOutputContains("System.NullReferenceException: Object reference not set to an instance of an object."); result.AssertOutputContains("TestBadLibrary.ClassToBeTested.M()"); - result.AssertOutputContains("Test run summary: Failed!"); - result.AssertOutputContains("total: 1"); - result.AssertOutputContains("failed: 1"); - result.AssertOutputContains("succeeded: 0"); - result.AssertOutputContains("skipped: 0"); + result.AssertOutputContainsSummary(failed: 1, passed: 0, skipped: 0); } public async Task NativeAotTests_WillFailInTestInitialize() @@ -337,7 +449,7 @@ public async Task NativeAotTests_WillFailInAssemblyCleanup() await NativeAotTests_WillFailInTestFixtureCommon(code); } - private async Task GetTestResultForCode(string code, string? projectDir = null) + private async Task GetTestResultForCode(string code, string? projectDir = null, Action? executeBeforeDisposingTestAsset = null) // The native AOT publication is pretty flaky and is often failing on CI with "fatal error LNK1136: invalid or corrupt file", // or sometimes doesn't fail but the native code generation is not done. // Retrying the restore/publish on fresh asset seems to be more effective than retrying on the same asset. @@ -369,7 +481,9 @@ await DotnetCli.RunAsync( var testHost = TestHost.LocateFrom(targetAssetPath, "NativeAotTests", TargetFrameworks.NetCurrent.Arguments, RID, Verb.publish); - return await testHost.ExecuteAsync(); + TestHostResult result = await testHost.ExecuteAsync("--report-trx"); + executeBeforeDisposingTestAsset?.Invoke(result); + return result; }, times: 15, every: TimeSpan.FromSeconds(5)); private async Task NativeAotTests_WillFailInTestFixtureCommon(string code) From 873bd9751532c0354c1a717cf81d97abb959b738 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 8 Nov 2024 05:15:09 +0100 Subject: [PATCH 18/22] Formatting error --- .../MSTest.Acceptance.IntegrationTests/NativeAotTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index f76fbfc59f..83ab472dff 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -198,7 +198,6 @@ public void TestMethod1() } """; - private const string SourceCodeWithFailingAssertClassIgnored = $$""" {{SourceCodeCsproj}} From 5e41dba17a8fba19a82d6b1ae6a9e880d2d67824 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 8 Nov 2024 11:12:59 +0100 Subject: [PATCH 19/22] Move to UnconditionalSuppressMessage attribute --- .../Helpers/DataSerializationHelper.cs | 62 ++++++++++--------- .../Services/DiaSessionOperations.cs | 19 ++++-- .../Services/ReflectionOperations2.cs | 48 +++++++++++--- .../NativeAotTests.cs | 2 +- 4 files changed, 88 insertions(+), 43 deletions(-) diff --git a/src/Adapter/MSTest.TestAdapter/Helpers/DataSerializationHelper.cs b/src/Adapter/MSTest.TestAdapter/Helpers/DataSerializationHelper.cs index 0b9e1bc782..8485b1a943 100644 --- a/src/Adapter/MSTest.TestAdapter/Helpers/DataSerializationHelper.cs +++ b/src/Adapter/MSTest.TestAdapter/Helpers/DataSerializationHelper.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Collections.Concurrent; +using System.Diagnostics.CodeAnalysis; using System.Runtime.Serialization.Json; using System.Text; @@ -23,6 +24,14 @@ internal static class DataSerializationHelper /// /// Data array to serialize. /// Serialized array. + [UnconditionalSuppressMessage( + "Trimming", + "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", + Justification = "This should be safe as long as our generator mentions getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551. Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.")] + [UnconditionalSuppressMessage( + "AOT", + "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", + Justification = "This should be safe as long as our generator mentions getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551. Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.")] public static string?[]? Serialize(object?[]? data) { if (data == null) @@ -51,14 +60,7 @@ internal static class DataSerializationHelper DataContractJsonSerializer serializer = GetSerializer(type); using var memoryStream = new MemoryStream(); - // This should be safe as long as our generator mentions - // getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551 - // Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other. -#pragma warning disable IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT -#pragma warning disable IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming serializer.WriteObject(memoryStream, data[i]); -#pragma warning restore IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT -#pragma warning restore IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming byte[] serializerData = memoryStream.ToArray(); serializedData[dataIndex] = Encoding.UTF8.GetString(serializerData, 0, serializerData.Length); @@ -72,6 +74,14 @@ internal static class DataSerializationHelper /// /// Serialized data array to deserialize. /// Deserialized array. + [UnconditionalSuppressMessage( + "Trimming", + "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", + Justification = "This should be safe as long as our generator mentions getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551. Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.")] + [UnconditionalSuppressMessage( + "AOT", + "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", + Justification = "This should be safe as long as our generator mentions getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551. Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.")] public static object?[]? Deserialize(string?[]? serializedData) { if (serializedData == null || serializedData.Length % 2 != 0) @@ -98,40 +108,36 @@ internal static class DataSerializationHelper byte[] serializedDataBytes = Encoding.UTF8.GetBytes(serializedValue); using var memoryStream = new MemoryStream(serializedDataBytes); - // This should be safe as long as our generator mentions - // getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551 - // Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other. -#pragma warning disable IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT -#pragma warning disable IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming data[i] = serializer.ReadObject(memoryStream); -#pragma warning restore IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT -#pragma warning restore IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming } return data; } + [UnconditionalSuppressMessage( + "Trimming", + "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", + Justification = "This should be safe as long as our generator mentions getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551. Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.")] + [UnconditionalSuppressMessage( + "AOT", + "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", + Justification = "This should be safe as long as our generator mentions getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551. Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.")] + private static DataContractJsonSerializer GetSerializer(string assemblyQualifiedName) => SerializerCache.GetOrAdd( assemblyQualifiedName, - // This should be safe as long as our generator mentions - // getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551 - // Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other. -#pragma warning disable IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT -#pragma warning disable IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming _ => new DataContractJsonSerializer(PlatformServiceProvider.Instance.ReflectionOperations.GetType(assemblyQualifiedName) ?? typeof(object), SerializerSettings)); -#pragma warning restore IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT -#pragma warning restore IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming + [UnconditionalSuppressMessage( + "Trimming", + "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", + Justification = "This should be safe as long as our generator mentions getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551. Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.")] + [UnconditionalSuppressMessage( + "AOT", + "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", + Justification = "This should be safe as long as our generator mentions getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551. Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.")] private static DataContractJsonSerializer GetSerializer(Type type) => SerializerCache.GetOrAdd( type.AssemblyQualifiedName!, - // This should be safe as long as our generator mentions - // getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551 - // Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other. -#pragma warning disable IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT -#pragma warning disable IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming _ => new DataContractJsonSerializer(type, SerializerSettings)); -#pragma warning restore IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT -#pragma warning restore IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming } diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Services/DiaSessionOperations.cs b/src/Adapter/MSTestAdapter.PlatformServices/Services/DiaSessionOperations.cs index dd44632e3a..0e008cca6e 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/Services/DiaSessionOperations.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/Services/DiaSessionOperations.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices; @@ -33,15 +34,17 @@ static DiaSessionOperations() /// /// The source file. /// A Navigation session instance for the current platform. + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2077", + Justification = "")] internal static object? CreateNavigationSession(string source) { // Create instance only when DiaSession is found in Object Model. if (s_typeDiaSession != null && s_typeDiaNavigationData != null) { string messageFormatOnException = string.Join("MSTestDiscoverer:DiaSession: Could not create diaSession for source:", source, ". Reason:{0}"); -#pragma warning disable IL2077 // 'target parameter' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'. return SafeInvoke(() => Activator.CreateInstance(s_typeDiaSession, source)); -#pragma warning restore IL2077 // 'target parameter' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'. } return null; @@ -90,23 +93,27 @@ internal static void DisposeNavigationSession(object? navigationSession) /// /// Type name of DiaSession class. /// Type name of DiaNavigationData class. + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2057", + Justification = "")] + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2077", + Justification = "")] internal static void Initialize(string diaSession, string diaNavigationData) { // We won't reach this code, in we will generate this info in source generator, // and we won't use navigation session to get method locations from PDBs. -#pragma warning disable IL2057 // Unrecognized value passed to the typeName parameter of 'System.Type.GetType(String)' s_typeDiaSession = Type.GetType(diaSession, false); s_typeDiaNavigationData = Type.GetType(diaNavigationData, false); -#pragma warning restore IL2057 // Unrecognized value passed to the typeName parameter of 'System.Type.GetType(String)' -#pragma warning disable IL2077 // 'target parameter' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'. if (s_typeDiaSession != null && s_typeDiaNavigationData != null) { s_methodGetNavigationData = s_typeDiaSession.GetRuntimeMethod("GetNavigationData", [typeof(string), typeof(string)]); s_propertyFileName = s_typeDiaNavigationData.GetRuntimeProperty("FileName"); s_propertyMinLineNumber = s_typeDiaNavigationData.GetRuntimeProperty("MinLineNumber"); } -#pragma warning restore IL2077 // 'target parameter' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'. } private static object? SafeInvoke(Func action) diff --git a/src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations2.cs b/src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations2.cs index d827c13945..7d4275663b 100644 --- a/src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations2.cs +++ b/src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations2.cs @@ -20,22 +20,38 @@ public ReflectionOperations2() #endif } -#pragma warning disable IL2070 // this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'. -#pragma warning disable IL2026 // Members attributed with RequiresUnreferencedCode may break when trimming -#pragma warning disable IL2067 // 'target parameter' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'. -#pragma warning disable IL2057 // Unrecognized value passed to the typeName parameter of 'System.Type.GetType(String)' + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2070", + Justification = "")] public IEnumerable GetDeclaredConstructors(Type classType) => classType.GetTypeInfo().DeclaredConstructors; + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2070", + Justification = "")] public MethodInfo? GetDeclaredMethod(Type type, string methodName) => type.GetTypeInfo().GetDeclaredMethod(methodName); + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2070", + Justification = "")] public IEnumerable GetDeclaredMethods(Type classType) => classType.GetTypeInfo().DeclaredMethods; + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2070", + Justification = "")] public IEnumerable GetDeclaredProperties(Type type) => type.GetTypeInfo().DeclaredProperties; + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2070", + Justification = "")] public PropertyInfo? GetDeclaredProperty(Type type, string propertyName) => type.GetTypeInfo().GetDeclaredProperty(propertyName); @@ -44,16 +60,32 @@ public IEnumerable GetDeclaredProperties(Type type) public Type[] GetDefinedTypes(Assembly assembly) => assembly.DefinedTypes.ToArray(); + [UnconditionalSuppressMessage( + "Trimming", + "IL2067", + Justification = "")] public IEnumerable GetRuntimeMethods(Type type) => type.GetRuntimeMethods(); + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2067", + Justification = "")] public MethodInfo? GetRuntimeMethod(Type declaringType, string methodName, Type[] parameters) => declaringType.GetRuntimeMethod(methodName, parameters); + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2070", + Justification = "")] public PropertyInfo? GetRuntimeProperty(Type classType, string testContextPropertyName) => classType.GetProperty(testContextPropertyName); [UnconditionalSuppressMessage("Aot", "IL2026:DoNotUseGetDefinedTypes", Justification = "We access all the types we need in metadata, so this is preserved and works.")] + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2057", + Justification = "")] public Type? GetType(string typeName) => Type.GetType(typeName); @@ -61,10 +93,10 @@ public IEnumerable GetRuntimeMethods(Type type) public Type? GetType(Assembly assembly, string typeName) => assembly.GetType(typeName); + [UnconditionalSuppressMessage( + "ReflectionAnalysis", + "IL2067", + Justification = "")] public object? CreateInstance(Type type, object?[] parameters) => Activator.CreateInstance(type, parameters); -#pragma warning restore IL2070 // this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'. -#pragma warning restore IL2026 // Members attributed with RequiresUnreferencedCode may break when trimming -#pragma warning restore IL2067 // 'target parameter' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'. -#pragma warning restore IL2057 // Unrecognized value passed to the typeName parameter of 'System.Type.GetType(String)' } diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index 83ab472dff..ca47747563 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -235,7 +235,7 @@ public void TestMethod1() { Assert.Fail("Failing TestMethod1"); } - + } """; private const string SourceCodeWithTestContext = $$""" From 430bb08a28aef3b86359892d32eb0b42871620dc Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Tue, 12 Nov 2024 10:05:19 +0100 Subject: [PATCH 20/22] Suppress --- src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs b/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs index b51781a8eb..9863d5f885 100644 --- a/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs +++ b/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs @@ -814,6 +814,7 @@ private MethodInfo GetMethodInfoForTestMethod(TestMethod testMethod, TestClassIn return testMethodInfo; } + [UnconditionalSuppressMessage("Aot", "IL2026:DoNotUseGetConstructor", Justification = "We access all the types we need in metadata, so this is preserved and works.")] private static MethodInfo? GetMethodInfoUsingManagedNameHelper(TestMethod testMethod, TestClassInfo testClassInfo, bool discoverInternals) { MethodBase? methodBase = null; From 31001ac9d7eec8bd4bc24454d7d9c02145f0935f Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Tue, 19 Nov 2024 21:41:24 +0100 Subject: [PATCH 21/22] Avoid using #pragma warning disable ILxxxx --- samples/Playground/DebuggerUtility.cs | 2 -- .../Microsoft.Testing.Platform/Builder/TestApplication.cs | 7 +++---- .../CommandLine/CommandLineHandler.cs | 4 ++-- .../Services/CurrentTestApplicationModuleInfo.cs | 2 -- .../DebuggerUtility.cs | 2 -- 5 files changed, 5 insertions(+), 12 deletions(-) diff --git a/samples/Playground/DebuggerUtility.cs b/samples/Playground/DebuggerUtility.cs index 6b58a2a58d..71e474bd6a 100644 --- a/samples/Playground/DebuggerUtility.cs +++ b/samples/Playground/DebuggerUtility.cs @@ -121,9 +121,7 @@ private static bool AttachVs(Process vs, int pid, bool enableLog = false) IEnumMoniker? enumMoniker = null; try { -#pragma warning disable IL2050 int r = CreateBindCtx(0, out bindCtx); -#pragma warning restore IL2050 Marshal.ThrowExceptionForHR(r); if (bindCtx == null) { diff --git a/src/Platform/Microsoft.Testing.Platform/Builder/TestApplication.cs b/src/Platform/Microsoft.Testing.Platform/Builder/TestApplication.cs index 111a096a8e..3e9f5b65c8 100644 --- a/src/Platform/Microsoft.Testing.Platform/Builder/TestApplication.cs +++ b/src/Platform/Microsoft.Testing.Platform/Builder/TestApplication.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; #if NETCOREAPP @@ -113,6 +114,8 @@ public static async Task CreateBuilderAsync(string[] ar return new TestApplicationBuilder(loggingState, createBuilderStart, testApplicationOptions, s_unhandledExceptionHandler); } + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + Justification = "Only for logging, and is under IsDynamicCodeSupported check.")] private static async Task LogInformationAsync( ILogger logger, CurrentTestApplicationModuleInfo testApplicationModuleInfo, @@ -151,9 +154,7 @@ private static async Task LogInformationAsync( #if NETCOREAPP if (RuntimeFeature.IsDynamicCodeSupported) { -#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file string? runtimeLocation = typeof(object).Assembly.Location; -#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (runtimeLocation is not null) { await logger.LogInformationAsync($"Runtime location: {runtimeLocation}"); @@ -164,9 +165,7 @@ private static async Task LogInformationAsync( } } #else -#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file, this branch run only on .NET Framework string? runtimeLocation = typeof(object).Assembly?.Location; -#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file if (runtimeLocation is not null) { await logger.LogInformationAsync($"Runtime location: {runtimeLocation}"); diff --git a/src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineHandler.cs b/src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineHandler.cs index 8fb0dba1ba..f8ffb41ee3 100644 --- a/src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineHandler.cs +++ b/src/Platform/Microsoft.Testing.Platform/CommandLine/CommandLineHandler.cs @@ -51,6 +51,8 @@ public CommandLineHandler(CommandLineParseResult parseResult, IReadOnlyCollectio internal CommandLineParseResult ParseResult { get; } + [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", + Justification = "Only for logging and not under NETCOREAPP")] public async Task PrintInfoAsync(IPlatformOutputDevice platformOutputDevice, IReadOnlyList? availableTools = null) { // /!\ Info should not be localized as it serves debugging purposes. @@ -101,9 +103,7 @@ async Task DisplayPlatformInfoAsync() await platformOutputDevice.DisplayAsync(this, new TextOutputDeviceData($" Runtime information: {runtimeInformation}")); #if !NETCOREAPP -#pragma warning disable IL3000 // Avoid accessing Assembly file path when publishing as a single file, this branch run only in .NET Framework string runtimeLocation = typeof(object).Assembly?.Location ?? "Not Found"; -#pragma warning restore IL3000 // Avoid accessing Assembly file path when publishing as a single file await platformOutputDevice.DisplayAsync(this, new TextOutputDeviceData($" Runtime location: {runtimeLocation}")); #endif diff --git a/src/Platform/Microsoft.Testing.Platform/Services/CurrentTestApplicationModuleInfo.cs b/src/Platform/Microsoft.Testing.Platform/Services/CurrentTestApplicationModuleInfo.cs index 5053c18b19..68a81a7ffa 100644 --- a/src/Platform/Microsoft.Testing.Platform/Services/CurrentTestApplicationModuleInfo.cs +++ b/src/Platform/Microsoft.Testing.Platform/Services/CurrentTestApplicationModuleInfo.cs @@ -45,10 +45,8 @@ public bool IsAppHostOrSingleFileOrNativeAot #endif public string GetCurrentTestApplicationFullPath() { -#pragma warning disable IL3000 // This is empty in native app, or in single file app. string? moduleName = Assembly.GetEntryAssembly()?.Location; -#pragma warning restore IL3000 moduleName = RoslynString.IsNullOrEmpty(moduleName) ? GetProcessPath(_environment, _process) diff --git a/test/Utilities/Microsoft.Testing.TestInfrastructure/DebuggerUtility.cs b/test/Utilities/Microsoft.Testing.TestInfrastructure/DebuggerUtility.cs index ddb5ed161b..67aa959e55 100644 --- a/test/Utilities/Microsoft.Testing.TestInfrastructure/DebuggerUtility.cs +++ b/test/Utilities/Microsoft.Testing.TestInfrastructure/DebuggerUtility.cs @@ -98,9 +98,7 @@ private static bool AttachVs(Process vs, int pid, bool enableLog = false) IEnumMoniker? enumMoniker = null; try { -#pragma warning disable IL2050 int r = CreateBindCtx(0, out bindCtx); -#pragma warning restore IL2050 Marshal.ThrowExceptionForHR(r); if (bindCtx == null) { From 04f647058cb5baeb567a3ec11a3354f8a2c3f563 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Thu, 21 Nov 2024 08:42:48 +0100 Subject: [PATCH 22/22] Adjust --- .../NativeAotTests.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs index ca47747563..aebfe91310 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/NativeAotTests.cs @@ -23,7 +23,6 @@ public class NativeAotTests : AcceptanceTestBase true preview true - $(NoWarn);IL2104;IL2026;IL3053 + + """; @@ -460,7 +463,9 @@ private async Task GetTestResultForCode(string code, string? pro code .PatchCodeWithReplace("$MicrosoftTestingPlatformVersion$", MicrosoftTestingPlatformVersion) .PatchCodeWithReplace("$MicrosoftTestingEnterpriseExtensionsVersion$", MicrosoftTestingEnterpriseExtensionsVersion) - .PatchCodeWithReplace("$TargetFramework$", TargetFrameworks.NetCurrent.Arguments) + // temporarily set test to be on net9.0 as it's fixing one error that started to happen: error IL3000: System.Net.Quic.MsQuicApi..cctor + // see https://github.com/dotnet/sdk/issues/44880. + .PatchCodeWithReplace("$TargetFramework$", "net9.0"/*TODO: TargetFrameworks.NetCurrent.Arguments*/) .PatchCodeWithReplace("$MSTestVersion$", MSTestVersion) .PatchCodeWithReplace("$MSTestSourceGenerationVersion$", MSTestSourceGenerationVersion), addPublicFeeds: true); @@ -478,7 +483,7 @@ await DotnetCli.RunAsync( retryCount: 0); compilationResult.AssertOutputContains("Generating native code"); - var testHost = TestHost.LocateFrom(targetAssetPath, "NativeAotTests", TargetFrameworks.NetCurrent.Arguments, RID, Verb.publish); + var testHost = TestHost.LocateFrom(targetAssetPath, "NativeAotTests", "net9.0"/*TODO: TargetFrameworks.NetCurrent.Arguments*/, RID, Verb.publish); TestHostResult result = await testHost.ExecuteAsync("--report-trx"); executeBeforeDisposingTestAsset?.Invoke(result);