From 34e4dc7bec5aca4dfccede2b11c851f680a1c001 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Mon, 27 Jan 2025 09:58:00 +0100 Subject: [PATCH 1/4] Add tests for Polyfill type forwarding --- .../WinUITests.cs | 84 +++++++++++++++++++ .../TypeForwardingTests.cs | 79 +++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs create mode 100644 test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs new file mode 100644 index 0000000000..483587b123 --- /dev/null +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.Testing.Platform.Acceptance.IntegrationTests; +using Microsoft.Testing.Platform.Acceptance.IntegrationTests.Helpers; +using Microsoft.Testing.Platform.Helpers; + +namespace MSTest.Acceptance.IntegrationTests; + +[TestClass] +public sealed class WinUITests : AcceptanceTestBase +{ + private static readonly string WinUITargetFramework = $"{TargetFrameworks.NetCurrent}-windows10.0.19041.0"; + + [TestMethod] + public async Task SimpleWinUITestCase() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // WinUI is Windows-only :) + return; + } + + var testHost = TestHost.LocateFrom(AssetFixture.ProjectPath, TestAssetFixture.ProjectName, WinUITargetFramework); + TestHostResult testHostResult = await testHost.ExecuteAsync(); + + // Assert + testHostResult.AssertExitCodeIs(ExitCodes.Success); + testHostResult.AssertOutputContainsSummary(failed: 0, passed: 1, skipped: 0); + } + + public sealed class TestAssetFixture() : TestAssetFixtureBase(AcceptanceFixture.NuGetGlobalPackagesFolder) + { + public const string ProjectName = "WinUITests"; + + public string ProjectPath => GetAssetPath(ProjectName); + + public override IEnumerable<(string ID, string Name, string Code)> GetAssetsToGenerate() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // WinUI is Windows-only :) + yield break; + } + + yield return (ProjectName, ProjectName, + SourceCode + .PatchCodeWithReplace("$TargetFramework$", WinUITargetFramework) + .PatchCodeWithReplace("$MSTestVersion$", MSTestVersion)); + } + + private const string SourceCode = """ +#file WinUITests.csproj + + + + Exe + true + $TargetFramework$ + true + + + + + + + + + +#file UnitTest1.cs +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +[TestClass] +public class TestClass1 +{ + [TestMethod] + public void TestMethod1() + { + } +} +"""; + } +} diff --git a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs new file mode 100644 index 0000000000..ecee677dd6 --- /dev/null +++ b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.Testing.Platform.Acceptance.IntegrationTests; + +[TestClass] +public class TypeForwardingTests : AcceptanceTestBase +{ + private const string AssetName = "TypeForwardingTests"; + + // The idea of this test is to have a netstandard2.0 library that sets an init-only property. + // The library is compiled against netstandard2.0 API of MTP. So, IsExternalInit is coming through Polyfill. + // Then, console app is consuming the library and uses the latest TFM for MTP, which has IsExternalInit from BCL. + // What happens now is: + // At IL-level (compile-time), IsExternalInit from Polyfill is accessed. + // At runtime, IsExternalInit doesn't exist from Polyfill and exists only through BCL. + // For this situation to work, a TypeForwardedTo(typeof(IsExternalInit)) is needed in MTP when + // compiling for a TFM that has IsExternalInit from BCL. + // See https://github.com/SimonCropp/Polyfill/issues/290 + private const string Sources = """ + #file ClassLib/ClassLib.csproj + + + netstandard2.0 + Library + enable + preview + + + + + + + #file ClassLib/MyClassCompiledAgainstNetStandardBinary.cs + using Microsoft.Testing.Platform.Extensions.Messages; + + public static class MyClassCompiledAgainstNetStandardBinary + { + public static TestNode M() + => new TestNode() { DisplayName = "MyDisplayName", Uid = new("MyUid") }; + } + + #file ConsoleApp/ConsoleApp.csproj + + + + $TargetFrameworks$ + Exe + enable + preview + + + + + + + #file ConsoleApp/Program.cs + using System; + + Console.WriteLine(MyClassCompiledAgainstNetStandardBinary.M().DisplayName); + """; + + [TestMethod] + public async Task SettingDisplayNameFromNetStandardLibraryDuringNetCurrentRuntimeExecutionShouldNotCrash() + { + string patchedSources = Sources + .PatchTargetFrameworks(TargetFrameworks.NetCurrent) + .PatchCodeWithReplace("$MicrosoftTestingPlatformVersion$", MicrosoftTestingPlatformVersion); + + TestAsset testAsset = await TestAsset.GenerateAssetAsync(AssetName, patchedSources); + await DotnetCli.RunAsync($"build -m:1 -nodeReuse:false {testAsset.TargetAssetPath}/ConsoleApp -c Release", AcceptanceFixture.NuGetGlobalPackagesFolder.Path); + + var testHost = TestInfrastructure.TestHost.LocateFrom($"{testAsset.TargetAssetPath}/ConsoleApp", "ConsoleApp", TargetFrameworks.NetCurrent); + TestHostResult testHostResult = await testHost.ExecuteAsync(); + + testHostResult.AssertExitCodeIs(ExitCodes.Success); + testHostResult.AssertOutputContains("MyDisplayName"); + } +} From 81b3721544000a88c173271a0b55502b815d84da Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Mon, 27 Jan 2025 10:19:12 +0100 Subject: [PATCH 2/4] Adjust tests for TA --- .../WinUITests.cs | 16 +++++++++++----- .../TypeForwardingTests.cs | 10 +++++++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs index 483587b123..a2e3fbc709 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs @@ -1,18 +1,23 @@ // 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.Runtime.InteropServices; + using Microsoft.Testing.Platform.Acceptance.IntegrationTests; using Microsoft.Testing.Platform.Acceptance.IntegrationTests.Helpers; using Microsoft.Testing.Platform.Helpers; namespace MSTest.Acceptance.IntegrationTests; -[TestClass] -public sealed class WinUITests : AcceptanceTestBase +[TestGroup] +public sealed class WinUITests : AcceptanceTestBase { private static readonly string WinUITargetFramework = $"{TargetFrameworks.NetCurrent}-windows10.0.19041.0"; + private readonly TestAssetFixture _testAssetFixture; + + public WinUITests(ITestExecutionContext testExecutionContext, TestAssetFixture testAssetFixture) + : base(testExecutionContext) => _testAssetFixture = testAssetFixture; - [TestMethod] public async Task SimpleWinUITestCase() { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -21,7 +26,7 @@ public async Task SimpleWinUITestCase() return; } - var testHost = TestHost.LocateFrom(AssetFixture.ProjectPath, TestAssetFixture.ProjectName, WinUITargetFramework); + var testHost = TestHost.LocateFrom(_testAssetFixture.ProjectPath, TestAssetFixture.ProjectName, WinUITargetFramework); TestHostResult testHostResult = await testHost.ExecuteAsync(); // Assert @@ -29,7 +34,8 @@ public async Task SimpleWinUITestCase() testHostResult.AssertOutputContainsSummary(failed: 0, passed: 1, skipped: 0); } - public sealed class TestAssetFixture() : TestAssetFixtureBase(AcceptanceFixture.NuGetGlobalPackagesFolder) + [TestFixture(TestFixtureSharingStrategy.PerTestGroup)] + public sealed class TestAssetFixture(AcceptanceFixture acceptanceFixture) : TestAssetFixtureBase(acceptanceFixture.NuGetGlobalPackagesFolder) { public const string ProjectName = "WinUITests"; diff --git a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs index ecee677dd6..0ace8b85df 100644 --- a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs +++ b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs @@ -3,8 +3,8 @@ namespace Microsoft.Testing.Platform.Acceptance.IntegrationTests; -[TestClass] -public class TypeForwardingTests : AcceptanceTestBase +[TestGroup] +public class TypeForwardingTests : AcceptanceTestBase { private const string AssetName = "TypeForwardingTests"; @@ -60,7 +60,11 @@ public static TestNode M() Console.WriteLine(MyClassCompiledAgainstNetStandardBinary.M().DisplayName); """; - [TestMethod] + public TypeForwardingTests(ITestExecutionContext testExecutionContext) + : base(testExecutionContext) + { + } + public async Task SettingDisplayNameFromNetStandardLibraryDuringNetCurrentRuntimeExecutionShouldNotCrash() { string patchedSources = Sources From 4e24ff82952090cc637ac6a381cbf1a44a8e69f1 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Mon, 27 Jan 2025 10:21:06 +0100 Subject: [PATCH 3/4] Fix errors --- .../TypeForwardingTests.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs index 0ace8b85df..0a4383b407 100644 --- a/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs +++ b/test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/TypeForwardingTests.cs @@ -1,6 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using Microsoft.Testing.Platform.Acceptance.IntegrationTests.Helpers; +using Microsoft.Testing.Platform.Helpers; + namespace Microsoft.Testing.Platform.Acceptance.IntegrationTests; [TestGroup] @@ -8,6 +11,8 @@ public class TypeForwardingTests : AcceptanceTestBase { private const string AssetName = "TypeForwardingTests"; + private readonly AcceptanceFixture _acceptanceFixture; + // The idea of this test is to have a netstandard2.0 library that sets an init-only property. // The library is compiled against netstandard2.0 API of MTP. So, IsExternalInit is coming through Polyfill. // Then, console app is consuming the library and uses the latest TFM for MTP, which has IsExternalInit from BCL. @@ -60,10 +65,8 @@ public static TestNode M() Console.WriteLine(MyClassCompiledAgainstNetStandardBinary.M().DisplayName); """; - public TypeForwardingTests(ITestExecutionContext testExecutionContext) - : base(testExecutionContext) - { - } + public TypeForwardingTests(ITestExecutionContext testExecutionContext, AcceptanceFixture acceptanceFixture) + : base(testExecutionContext) => _acceptanceFixture = acceptanceFixture; public async Task SettingDisplayNameFromNetStandardLibraryDuringNetCurrentRuntimeExecutionShouldNotCrash() { @@ -72,9 +75,9 @@ public async Task SettingDisplayNameFromNetStandardLibraryDuringNetCurrentRuntim .PatchCodeWithReplace("$MicrosoftTestingPlatformVersion$", MicrosoftTestingPlatformVersion); TestAsset testAsset = await TestAsset.GenerateAssetAsync(AssetName, patchedSources); - await DotnetCli.RunAsync($"build -m:1 -nodeReuse:false {testAsset.TargetAssetPath}/ConsoleApp -c Release", AcceptanceFixture.NuGetGlobalPackagesFolder.Path); + await DotnetCli.RunAsync($"build -m:1 -nodeReuse:false {testAsset.TargetAssetPath}/ConsoleApp -c Release", _acceptanceFixture.NuGetGlobalPackagesFolder.Path); - var testHost = TestInfrastructure.TestHost.LocateFrom($"{testAsset.TargetAssetPath}/ConsoleApp", "ConsoleApp", TargetFrameworks.NetCurrent); + var testHost = TestInfrastructure.TestHost.LocateFrom($"{testAsset.TargetAssetPath}/ConsoleApp", "ConsoleApp", TargetFrameworks.NetCurrent.Arguments); TestHostResult testHostResult = await testHost.ExecuteAsync(); testHostResult.AssertExitCodeIs(ExitCodes.Success); From 6fc3cc3acd51728711630db6c1b50a4d3611a630 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Mon, 27 Jan 2025 11:16:24 +0100 Subject: [PATCH 4/4] Fix TFM --- .../MSTest.Acceptance.IntegrationTests/WinUITests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs index a2e3fbc709..cb42f35d87 100644 --- a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/WinUITests.cs @@ -12,7 +12,7 @@ namespace MSTest.Acceptance.IntegrationTests; [TestGroup] public sealed class WinUITests : AcceptanceTestBase { - private static readonly string WinUITargetFramework = $"{TargetFrameworks.NetCurrent}-windows10.0.19041.0"; + private static readonly string WinUITargetFramework = $"{TargetFrameworks.NetCurrent.Arguments}-windows10.0.19041.0"; private readonly TestAssetFixture _testAssetFixture; public WinUITests(ITestExecutionContext testExecutionContext, TestAssetFixture testAssetFixture)