diff --git a/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs b/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs index cc0202e573..224a5dfce8 100644 --- a/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs +++ b/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs @@ -31,7 +31,7 @@ public static void AddMSBuild(this ITestApplicationBuilder builder) serviceProvider.GetConfiguration(), serviceProvider.GetCommandLineOptions())); - ((TestApplicationBuilder)builder).TestHostOrchestrator.AddTestHostOrchestratorApplicationLifetime( + builder.TestHostOrchestrator.AddTestHostOrchestratorApplicationLifetime( serviceProvider => new MSBuildOrchestratorLifetime( serviceProvider.GetConfiguration(), serviceProvider.GetCommandLineOptions())); diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/ExtensionResources.resx b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/ExtensionResources.resx index a8757886f1..8179e3290f 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/ExtensionResources.resx +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/ExtensionResources.resx @@ -149,9 +149,6 @@ Moving last attempt asset files to the default result directory Retry failed tests - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - The retry extension is not supported on browser platform. Browser-based tests cannot be retried due to platform limitations. diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.cs.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.cs.xlf index 2b2ad0c92d..0ec43e125a 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.cs.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.cs.xlf @@ -60,11 +60,6 @@ Přesouvání souborů prostředků posledního pokusu do výchozího adresáře Opakovat neúspěšné testy - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - Opakování neúspěšných testů funguje pouze s tvůrci typu Microsoft.Testing.Platform.Builder.TestApplicationBuilder. - - Disable retry mechanism if the percentage of failed tests is greater than the specified value Zakázat mechanismus opakování, pokud je procento neúspěšných testů větší než zadaná hodnota diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.de.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.de.xlf index 787a8ed11e..54f48e40b8 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.de.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.de.xlf @@ -60,11 +60,6 @@ Medienobjektdateien des letzten Versuchs werden in das Standardergebnisverzeichn Tests mit Wiederholungsfehlern - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - Das Wiederholen fehlerhafter Tests funktioniert nur mit Generatoren vom Typ "Microsoft.Testing.Platform.Builder.TestApplicationBuilder". - - Disable retry mechanism if the percentage of failed tests is greater than the specified value Wiederholungsmechanismus deaktivieren, wenn der Prozentsatz fehlerhafter Tests größer als der angegebene Wert ist diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.es.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.es.xlf index f3a7637822..55edc18d71 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.es.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.es.xlf @@ -60,11 +60,6 @@ Moviendo los archivos de recursos del último intento al directorio de resultado Reintentar pruebas con errores - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - Reintentar pruebas con errores solo funciona con generadores de tipo "Microsoft.Testing.Platform.Builder.TestApplicationBuilder" - - Disable retry mechanism if the percentage of failed tests is greater than the specified value Deshabilitar el mecanismo de reintento si el porcentaje de pruebas con errores es mayor que el valor especificado diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.fr.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.fr.xlf index ed59580e56..2fc7921866 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.fr.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.fr.xlf @@ -60,11 +60,6 @@ Déplacement des fichiers de ressources de la dernière tentative vers le réper Nouvelle tentative de tests ayant échoué - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - Les nouvelles tentatives de tests ayant échoué fonctionnent uniquement avec les générateurs de type « Microsoft.Testing.Platform.Builder.TestApplicationBuilder » - - Disable retry mechanism if the percentage of failed tests is greater than the specified value Désactiver le mécanisme de nouvelle tentative si le pourcentage de tests ayant échoué est supérieur à la valeur spécifiée diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.it.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.it.xlf index 7d9750754b..a55bf502da 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.it.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.it.xlf @@ -60,11 +60,6 @@ Spostamento dei file di asset dell'ultimo tentativo nella directory dei risultat Ripeti i test non riusciti - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - La ripetizione dei test non riusciti funziona solo con i generatori di tipo 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder'. - - Disable retry mechanism if the percentage of failed tests is greater than the specified value Disabilita il meccanismo di ripetizione dei tentativi se la percentuale di test non riusciti è maggiore del valore specificato. diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ja.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ja.xlf index a30363058f..23d77b2232 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ja.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ja.xlf @@ -60,11 +60,6 @@ Moving last attempt asset files to the default result directory 失敗したテストの再試行 - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - 失敗したテストの再試行は、'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' 型のビルダーでのみ機能します - - Disable retry mechanism if the percentage of failed tests is greater than the specified value 失敗したテストの割合が指定した値を超える場合は再試行メカニズムを無効にする diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ko.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ko.xlf index 7187c103d4..df4c3290dd 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ko.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ko.xlf @@ -60,11 +60,6 @@ Moving last attempt asset files to the default result directory 실패한 테스트 다시 시도 - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - 실패한 테스트 다시 시도는 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' 유형의 작성기에서만 작동합니다. - - Disable retry mechanism if the percentage of failed tests is greater than the specified value 실패한 테스트의 비율이 지정된 값보다 큰 경우 다시 시도 메커니즘을 사용하지 않도록 설정 diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pl.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pl.xlf index 63ff3a2680..cde119184e 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pl.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pl.xlf @@ -60,11 +60,6 @@ Przeniesienie plików zasobów ostatniej próby do domyślnego katalogu wyników Ponów próbę testów zakończonych niepowodzeniem - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - Ponawianie testów zakończonych niepowodzeniem działa tylko z konstruktorami typu „Microsoft.Testing.Platform.Builder.TestApplicationBuilder” - - Disable retry mechanism if the percentage of failed tests is greater than the specified value Wyłącz mechanizm ponawiania prób, jeśli procent testów zakończonych niepowodzeniem jest większy niż określona wartość diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pt-BR.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pt-BR.xlf index ea1cb27f27..e7b749064a 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pt-BR.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pt-BR.xlf @@ -60,11 +60,6 @@ Movendo arquivos de ativo da última tentativa para o diretório de resultados p Repetir testes com falha - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - A repetição de testes com falha funciona somente com construtores do tipo ''Microsoft.Testing.Platform.Builder.TestApplicationBuilder'' - - Disable retry mechanism if the percentage of failed tests is greater than the specified value Desabilitar o mecanismo de repetição se a porcentagem de testes com falha for maior que o valor especificado diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ru.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ru.xlf index fe066e3d9a..eecf000105 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ru.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ru.xlf @@ -60,11 +60,6 @@ Moving last attempt asset files to the default result directory Включить повтор неудачных тестов - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - Повтор неудачных тестов работает только с построителями типа "Microsoft.Testing.Platform.Builder.TestApplicationBuilder" - - Disable retry mechanism if the percentage of failed tests is greater than the specified value Отключить механизм повторных попыток, если процент неудачных тестов превышает указанное значение diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.tr.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.tr.xlf index deaaa7765c..8879edbaee 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.tr.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.tr.xlf @@ -60,11 +60,6 @@ Son deneme varlık dosyaları, varsayılan sonuç dizinine taşınıyor Başarısız testleri yeniden deneyin - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - Başarısız testleri yeniden deneme yalnızca 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' türündeki oluşturucularla çalışır - - Disable retry mechanism if the percentage of failed tests is greater than the specified value Başarısız testlerin yüzdesi belirtilen değerden büyükse yeniden deneme mekanizmasını devre dışı bırak diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hans.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hans.xlf index 19baf236ed..643ff90857 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hans.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hans.xlf @@ -60,11 +60,6 @@ Moving last attempt asset files to the default result directory 重试失败的测试 - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - 重试失败的测试仅适用于“Microsoft.Testing.Platform.Builder.TestApplicationBuilder”类型的生成器 - - Disable retry mechanism if the percentage of failed tests is greater than the specified value 如果失败的测试百分比大于指定值,则禁用重试机制 diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hant.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hant.xlf index b3a54c8afe..417569a8bc 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hant.xlf +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hant.xlf @@ -60,11 +60,6 @@ Moving last attempt asset files to the default result directory 重試失敗的測試 - - Retry failed tests only works with builders of type 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' - 重試失敗的測試僅適用於類型為 'Microsoft.Testing.Platform.Builder.TestApplicationBuilder' 的建立器 - - Disable retry mechanism if the percentage of failed tests is greater than the specified value 如果失敗的測試百分比大於指定的值,則停用重試機制 diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs index 61525c5b6c..44c492c009 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs @@ -5,7 +5,6 @@ using Microsoft.Testing.Extensions.Policy.Resources; using Microsoft.Testing.Platform.Builder; using Microsoft.Testing.Platform.Extensions; -using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; using Microsoft.Testing.Platform.TestHost; namespace Microsoft.Testing.Extensions; @@ -37,13 +36,7 @@ CompositeExtensionFactory compositeExtensionFactory builder.TestHost.AddDataConsumer(compositeExtensionFactory); builder.TestHost.AddTestSessionLifetimeHandler(compositeExtensionFactory); - if (builder is not TestApplicationBuilder testApplicationBuilder) - { - throw new InvalidOperationException(ExtensionResources.RetryFailedTestsInvalidTestApplicationBuilderErrorMessage); - } - - // Net yet exposed extension points - ((TestHostOrchestratorManager)testApplicationBuilder.TestHostOrchestrator) + builder.TestHostOrchestrator .AddTestHostOrchestrator(serviceProvider => new RetryOrchestrator(serviceProvider)); ((TestHostManager)builder.TestHost) .AddTestExecutionFilterFactory(serviceProvider => new RetryExecutionFilterFactory(serviceProvider)); diff --git a/src/Platform/Microsoft.Testing.Platform/Builder/ITestApplicationBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Builder/ITestApplicationBuilder.cs index d17fca33e1..7ad9101abb 100644 --- a/src/Platform/Microsoft.Testing.Platform/Builder/ITestApplicationBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Builder/ITestApplicationBuilder.cs @@ -8,6 +8,7 @@ using Microsoft.Testing.Platform.Logging; using Microsoft.Testing.Platform.TestHost; using Microsoft.Testing.Platform.TestHostControllers; +using Microsoft.Testing.Platform.TestHostOrchestrator; namespace Microsoft.Testing.Platform.Builder; @@ -26,6 +27,12 @@ public interface ITestApplicationBuilder /// ITestHostControllersManager TestHostControllers { get; } + /// + /// Gets the test host orchestrator manager. + /// + [Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] + ITestHostOrchestratorManager TestHostOrchestrator { get; } + /// /// Gets the command line manager. /// diff --git a/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs index 7b7d7a2791..851e7feb3b 100644 --- a/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs @@ -7,7 +7,6 @@ using Microsoft.Testing.Platform.CommandLine; using Microsoft.Testing.Platform.Configurations; using Microsoft.Testing.Platform.Extensions.TestFramework; -using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; using Microsoft.Testing.Platform.Helpers; using Microsoft.Testing.Platform.Hosts; using Microsoft.Testing.Platform.Logging; @@ -16,6 +15,7 @@ using Microsoft.Testing.Platform.Telemetry; using Microsoft.Testing.Platform.TestHost; using Microsoft.Testing.Platform.TestHostControllers; +using Microsoft.Testing.Platform.TestHostOrchestrator; using Microsoft.Testing.Platform.Tools; namespace Microsoft.Testing.Platform.Builder; @@ -53,9 +53,13 @@ internal TestApplicationBuilder( public ITestHostControllersManager TestHostControllers => _testHostBuilder.TestHostControllers; - public ICommandLineManager CommandLine => _testHostBuilder.CommandLine; + [Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] + ITestHostOrchestratorManager ITestApplicationBuilder.TestHostOrchestrator => _testHostBuilder.TestHostOrchestrator; - internal ITestHostOrchestratorManager TestHostOrchestrator => _testHostBuilder.TestHostOrchestratorManager; + // Binary backward compatibility: old extensions access this property on the concrete class. + internal Extensions.TestHostOrchestrator.ITestHostOrchestratorManager TestHostOrchestrator => (Extensions.TestHostOrchestrator.ITestHostOrchestratorManager)_testHostBuilder.TestHostOrchestrator; + + public ICommandLineManager CommandLine => _testHostBuilder.CommandLine; [Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] public IConfigurationManager Configuration => _testHostBuilder.Configuration; diff --git a/src/Platform/Microsoft.Testing.Platform/Hosts/ITestHostBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Hosts/ITestHostBuilder.cs index 12cc02f5a6..b21500548c 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/ITestHostBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/ITestHostBuilder.cs @@ -5,12 +5,12 @@ using Microsoft.Testing.Platform.Builder; using Microsoft.Testing.Platform.CommandLine; using Microsoft.Testing.Platform.Configurations; -using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; using Microsoft.Testing.Platform.Helpers; using Microsoft.Testing.Platform.Logging; using Microsoft.Testing.Platform.Telemetry; using Microsoft.Testing.Platform.TestHost; using Microsoft.Testing.Platform.TestHostControllers; +using Microsoft.Testing.Platform.TestHostOrchestrator; using Microsoft.Testing.Platform.Tools; namespace Microsoft.Testing.Platform.Hosts; @@ -29,7 +29,7 @@ internal interface ITestHostBuilder ITestHostControllersManager TestHostControllers { get; } - ITestHostOrchestratorManager TestHostOrchestratorManager { get; } + ITestHostOrchestratorManager TestHostOrchestrator { get; } ITelemetryManager Telemetry { get; } diff --git a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs index beb17eeeea..1d5b12cb7a 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs @@ -10,7 +10,6 @@ using Microsoft.Testing.Platform.Extensions; using Microsoft.Testing.Platform.Extensions.TestFramework; using Microsoft.Testing.Platform.Extensions.TestHost; -using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; using Microsoft.Testing.Platform.Helpers; using Microsoft.Testing.Platform.IPC; using Microsoft.Testing.Platform.IPC.Models; @@ -26,6 +25,7 @@ using Microsoft.Testing.Platform.Telemetry; using Microsoft.Testing.Platform.TestHost; using Microsoft.Testing.Platform.TestHostControllers; +using Microsoft.Testing.Platform.TestHostOrchestrator; using Microsoft.Testing.Platform.Tools; namespace Microsoft.Testing.Platform.Hosts; @@ -55,7 +55,7 @@ internal sealed class TestHostBuilder(IFileSystem fileSystem, IRuntimeFeature ru public IToolsManager Tools { get; } = new ToolsManager(); - public ITestHostOrchestratorManager TestHostOrchestratorManager { get; } = new TestHostOrchestratorManager(); + public ITestHostOrchestratorManager TestHostOrchestrator { get; } = new Extensions.TestHostOrchestrator.TestHostOrchestratorManager(); public async Task BuildAsync( ApplicationLoggingState loggingState, @@ -407,15 +407,15 @@ await LogTestHostCreatedAsync( } // ======= TEST HOST ORCHESTRATOR ======== // - TestHostOrchestratorConfiguration testHostOrchestratorConfiguration = await TestHostOrchestratorManager.BuildAsync(serviceProvider).ConfigureAwait(false); + TestHostOrchestratorConfiguration testHostOrchestratorConfiguration = await ((TestHostOrchestratorManager)TestHostOrchestrator).BuildAsync(serviceProvider).ConfigureAwait(false); if (testHostOrchestratorConfiguration.TestHostOrchestrators.Length > 0 && !commandLineHandler.IsOptionSet(PlatformCommandLineProvider.DiscoverTestsOptionKey)) { policiesService.ProcessRole = TestProcessRole.TestHostOrchestrator; await proxyOutputDevice.HandleProcessRoleAsync(TestProcessRole.TestHostOrchestrator, testApplicationCancellationTokenSource.CancellationToken).ConfigureAwait(false); // Build and register the test application lifecycle callbacks. - ITestHostOrchestratorApplicationLifetime[] orchestratorLifetimes = - await ((TestHostOrchestratorManager)TestHostOrchestratorManager).BuildTestHostOrchestratorApplicationLifetimesAsync(serviceProvider).ConfigureAwait(false); + Extensions.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime[] orchestratorLifetimes = + await ((TestHostOrchestratorManager)TestHostOrchestrator).BuildTestHostOrchestratorApplicationLifetimesAsync(serviceProvider).ConfigureAwait(false); serviceProvider.AddServices(orchestratorLifetimes); builderActivity?.SetTag(BuilderHostTypeOTelKey, nameof(TestHostOrchestratorHost)); diff --git a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs index da8ff57ef0..80e9fad19e 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs @@ -6,6 +6,7 @@ using Microsoft.Testing.Platform.Logging; using Microsoft.Testing.Platform.Services; using Microsoft.Testing.Platform.Telemetry; +using Microsoft.Testing.Platform.TestHostOrchestrator; namespace Microsoft.Testing.Platform.Hosts; diff --git a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt index 80ae5857e1..59fdfa7acf 100644 --- a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt @@ -5,3 +5,13 @@ Microsoft.Testing.Platform.Extensions.TestHost.ITestHostApplicationLifetime.AfterRunAsync(int exitCode, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! Microsoft.Testing.Platform.Extensions.TestHostControllers.ITestHostProcessLifetimeHandler.OnTestHostProcessExitedAsync(Microsoft.Testing.Platform.Extensions.TestHostControllers.ITestHostProcessInformation! testHostProcessInformation, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! Microsoft.Testing.Platform.Extensions.TestHostControllers.ITestHostProcessLifetimeHandler.OnTestHostProcessStartedAsync(Microsoft.Testing.Platform.Extensions.TestHostControllers.ITestHostProcessInformation! testHostProcessInformation, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! +[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestrator +[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestrator.OrchestrateTestHostExecutionAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! +Microsoft.Testing.Platform.Builder.ITestApplicationBuilder.TestHostOrchestrator.get -> Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestratorManager! +[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestratorManager +[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestratorManager.AddTestHostOrchestrator(System.Func! factory) -> void +[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestratorManager.AddTestHostOrchestratorApplicationLifetime(System.Func! testHostOrchestratorApplicationLifetimeFactory) -> void +[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime +[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime.AfterRunAsync(int exitCode, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! +[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime.BeforeRunAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! +[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorExtension diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs index 02c81a5fee..84046d93b2 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs @@ -6,4 +6,5 @@ namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; /// /// Represents an extension for test host orchestrators. /// -internal interface ITestHostOrchestratorExtension : IExtension; +[Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] +public interface ITestHostOrchestratorExtension : IExtension; diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs index 036b994b5b..e0dce2a842 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs @@ -3,7 +3,16 @@ namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; -internal interface ITestHostOrchestrator : IExtension +/// +/// Represents an extension that orchestrates test host execution. +/// +[Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] +public interface ITestHostOrchestrator : IExtension { + /// + /// Orchestrates test host execution. + /// + /// The cancellation token. + /// A task representing the asynchronous operation that returns the test host exit code. Task OrchestrateTestHostExecutionAsync(CancellationToken cancellationToken); } diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs index 815b128fba..0e98bb36e2 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs @@ -3,7 +3,11 @@ namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; -internal interface ITestHostOrchestratorApplicationLifetime : ITestHostOrchestratorExtension +/// +/// Represents the application lifetime for a test host orchestrator. +/// +[Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] +public interface ITestHostOrchestratorApplicationLifetime : ITestHostOrchestratorExtension { /// /// Executes before the orchestrator runs. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs index 7f4d5c0827..52d80d3f86 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs @@ -1,18 +1,25 @@ // 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.Services; +using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; -namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; +namespace Microsoft.Testing.Platform.TestHostOrchestrator; -internal interface ITestHostOrchestratorManager +/// +/// Represents a manager for test host orchestrators. +/// +[Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] +public interface ITestHostOrchestratorManager { + /// + /// Adds a test host orchestrator. + /// + /// The factory method for creating the test host orchestrator. void AddTestHostOrchestrator(Func factory); - // NOTE: In ITestHostManager, we have AddTestApplicationLifecycleCallbacks, which is an unfortunate naming. - // If we ever open orchestration before MTP v2 (https://github.com/microsoft/testfx/issues/5733), we should - // consider if we are okay with this kinda inconsistent naming between test host and test host orchestrator. + /// + /// Adds a test host orchestrator application lifetime. + /// + /// The factory method for creating the test host orchestrator application lifetime. void AddTestHostOrchestratorApplicationLifetime(Func testHostOrchestratorApplicationLifetimeFactory); - - Task BuildAsync(ServiceProvider serviceProvider); } diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs new file mode 100644 index 0000000000..e26bc0c863 --- /dev/null +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +// These types provide binary backward compatibility for extensions compiled +// against older platform versions where the orchestrator manager type lived in the +// Microsoft.Testing.Platform.Extensions.TestHostOrchestrator namespace. +namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; + +internal interface ITestHostOrchestratorManager +{ + void AddTestHostOrchestrator(Func factory); +} + +// Kept for binary backward compatibility with extensions that cast to this concrete type. +internal sealed class TestHostOrchestratorManager : global::Microsoft.Testing.Platform.TestHostOrchestrator.TestHostOrchestratorManager; diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs index 095f30e6a2..a9ab7a918c 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs @@ -1,7 +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. -namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; +using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; + +namespace Microsoft.Testing.Platform.TestHostOrchestrator; internal sealed class TestHostOrchestratorConfiguration(ITestHostOrchestrator[] testHostOrchestrators) { diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs index 30094f9ed1..a7d47706e4 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs @@ -1,12 +1,14 @@ // 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.Extensions; +using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; using Microsoft.Testing.Platform.Helpers; using Microsoft.Testing.Platform.Services; -namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; +namespace Microsoft.Testing.Platform.TestHostOrchestrator; -internal sealed class TestHostOrchestratorManager : ITestHostOrchestratorManager +internal class TestHostOrchestratorManager : ITestHostOrchestratorManager, Extensions.TestHostOrchestrator.ITestHostOrchestratorManager { private readonly List> _testHostOrchestratorApplicationLifetimeFactories = []; private List>? _factories; @@ -18,7 +20,14 @@ public void AddTestHostOrchestrator(Func BuildAsync(ServiceProvider serviceProvider) + void Extensions.TestHostOrchestrator.ITestHostOrchestratorManager.AddTestHostOrchestrator(Func factory) + { + Ensure.NotNull(factory); + _factories ??= []; + _factories.Add(sp => factory(sp)); + } + + internal async Task BuildAsync(ServiceProvider serviceProvider) { if (_factories is null) { diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs new file mode 100644 index 0000000000..73f4f8b4e5 --- /dev/null +++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs @@ -0,0 +1,186 @@ +// 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.Helpers; +using Microsoft.Testing.Platform.Services; + +using BackCompat = Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; +using PublicApi = Microsoft.Testing.Platform.TestHostOrchestrator; + +namespace Microsoft.Testing.Platform.UnitTests; + +[TestClass] +public sealed class TestHostOrchestratorManagerTests +{ + private readonly ServiceProvider _serviceProvider = new(); + + [TestMethod] + public async Task AddTestHostOrchestrator_ViaPublicInterface_RegistersAndBuildsOrchestrator() + { + PublicApi.TestHostOrchestratorManager manager = new(); + + PublicApi.ITestHostOrchestratorManager publicManager = manager; + publicManager.AddTestHostOrchestrator(_ => new FakeOrchestrator("orch1")); + + PublicApi.TestHostOrchestratorConfiguration config = await manager.BuildAsync(_serviceProvider); + + Assert.HasCount(1, config.TestHostOrchestrators); + Assert.AreEqual("orch1", config.TestHostOrchestrators[0].Uid); + } + + [TestMethod] + public async Task AddTestHostOrchestrator_ViaBackCompatInterface_RegistersAndBuildsOrchestrator() + { + PublicApi.TestHostOrchestratorManager manager = new(); + + // Simulate what old extensions compiled against the old namespace do: + // they cast to the back-compat ITestHostOrchestratorManager interface. + BackCompat.ITestHostOrchestratorManager backCompatManager = manager; + backCompatManager.AddTestHostOrchestrator(_ => new FakeOrchestrator("orch-backcompat")); + + PublicApi.TestHostOrchestratorConfiguration config = await manager.BuildAsync(_serviceProvider); + + Assert.HasCount(1, config.TestHostOrchestrators); + Assert.AreEqual("orch-backcompat", config.TestHostOrchestrators[0].Uid); + } + + [TestMethod] + public async Task AddTestHostOrchestrator_BothPublicAndBackCompat_RegistersBoth() + { + PublicApi.TestHostOrchestratorManager manager = new(); + + PublicApi.ITestHostOrchestratorManager publicManager = manager; + publicManager.AddTestHostOrchestrator(_ => new FakeOrchestrator("public")); + + BackCompat.ITestHostOrchestratorManager backCompatManager = manager; + backCompatManager.AddTestHostOrchestrator(_ => new FakeOrchestrator("backcompat")); + + PublicApi.TestHostOrchestratorConfiguration config = await manager.BuildAsync(_serviceProvider); + + Assert.HasCount(2, config.TestHostOrchestrators); + } + + [TestMethod] + public async Task AddTestHostOrchestratorApplicationLifetime_RegistersAndBuilds() + { + PublicApi.TestHostOrchestratorManager manager = new(); + + PublicApi.ITestHostOrchestratorManager publicManager = manager; + publicManager.AddTestHostOrchestratorApplicationLifetime(_ => new FakeOrchestratorLifetime("lifetime1")); + + BackCompat.ITestHostOrchestratorApplicationLifetime[] lifetimes = await manager.BuildTestHostOrchestratorApplicationLifetimesAsync(_serviceProvider); + + Assert.HasCount(1, lifetimes); + Assert.AreEqual("lifetime1", lifetimes[0].Uid); + } + + [TestMethod] + public async Task BuildAsync_NoOrchestrators_ReturnsEmptyConfiguration() + { + PublicApi.TestHostOrchestratorManager manager = new(); + + PublicApi.TestHostOrchestratorConfiguration config = await manager.BuildAsync(_serviceProvider); + + Assert.HasCount(0, config.TestHostOrchestrators); + } + + [TestMethod] + public async Task AddTestHostOrchestrator_DuplicatedId_ShouldFail() + { + PublicApi.TestHostOrchestratorManager manager = new(); + + PublicApi.ITestHostOrchestratorManager publicManager = manager; + publicManager.AddTestHostOrchestrator(_ => new FakeOrchestrator("duplicatedId")); + publicManager.AddTestHostOrchestrator(_ => new FakeOrchestrator("duplicatedId")); + + InvalidOperationException exception = await Assert.ThrowsExactlyAsync(() => manager.BuildAsync(_serviceProvider)); + + Assert.IsTrue(exception.Message.Contains("duplicatedId") && exception.Message.Contains(typeof(FakeOrchestrator).ToString())); + } + + [TestMethod] + public async Task AddTestHostOrchestratorApplicationLifetime_DuplicatedId_ShouldFail() + { + PublicApi.TestHostOrchestratorManager manager = new(); + + PublicApi.ITestHostOrchestratorManager publicManager = manager; + publicManager.AddTestHostOrchestratorApplicationLifetime(_ => new FakeOrchestratorLifetime("duplicatedId")); + publicManager.AddTestHostOrchestratorApplicationLifetime(_ => new FakeOrchestratorLifetime("duplicatedId")); + + InvalidOperationException exception = await Assert.ThrowsExactlyAsync(() => manager.BuildTestHostOrchestratorApplicationLifetimesAsync(_serviceProvider)); + + Assert.IsTrue(exception.Message.Contains("duplicatedId") && exception.Message.Contains(typeof(FakeOrchestratorLifetime).ToString())); + } + + [TestMethod] + public void BackCompatTestHostOrchestratorManager_IsAssignableToPublicManager() + { + // The back-compat subclass should be a valid TestHostOrchestratorManager + BackCompat.TestHostOrchestratorManager backCompatManager = new(); + Assert.IsInstanceOfType(backCompatManager); + } + + [TestMethod] + public void TestHostBuilder_TestHostOrchestrator_ImplementsBackCompatInterface() + { + // TestHostBuilder creates a BackCompat.TestHostOrchestratorManager + // which must implement both the public and back-compat interfaces. + var manager = new BackCompat.TestHostOrchestratorManager(); + + Assert.IsInstanceOfType(manager); + Assert.IsInstanceOfType(manager); + } + + [TestMethod] + public async Task BackCompatTestHostOrchestratorManager_AddViaBackCompat_BuildsViaBase() + { + // End-to-end test: use the back-compat subclass and register through the back-compat interface, + // then build through the base class method. + var backCompatManager = new BackCompat.TestHostOrchestratorManager(); + + BackCompat.ITestHostOrchestratorManager backCompatInterface = backCompatManager; + backCompatInterface.AddTestHostOrchestrator(_ => new FakeOrchestrator("e2e-compat")); + + PublicApi.TestHostOrchestratorConfiguration config = await backCompatManager.BuildAsync(_serviceProvider); + + Assert.HasCount(1, config.TestHostOrchestrators); + Assert.AreEqual("e2e-compat", config.TestHostOrchestrators[0].Uid); + } + + private sealed class FakeOrchestrator : BackCompat.ITestHostOrchestrator + { + public FakeOrchestrator(string uid) => Uid = uid; + + public string Uid { get; } + + public string Version => AppVersion.DefaultSemVer; + + public string DisplayName => Uid; + + public string Description => Uid; + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Task OrchestrateTestHostExecutionAsync(CancellationToken cancellationToken) + => Task.FromResult(0); + } + + private sealed class FakeOrchestratorLifetime : BackCompat.ITestHostOrchestratorApplicationLifetime + { + public FakeOrchestratorLifetime(string uid) => Uid = uid; + + public string Uid { get; } + + public string Version => AppVersion.DefaultSemVer; + + public string DisplayName => Uid; + + public string Description => Uid; + + public Task IsEnabledAsync() => Task.FromResult(true); + + public Task BeforeRunAsync(CancellationToken cancellationToken) => Task.CompletedTask; + + public Task AfterRunAsync(int exitCode, CancellationToken cancellationToken) => Task.CompletedTask; + } +}