From 004278108b5613215a37436c3eabab46cf9aa818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Sat, 14 Feb 2026 16:43:01 +0100 Subject: [PATCH 01/13] Open up orchestrator experimentally --- .../RetryExtensions.cs | 9 +-------- .../Builder/ITestApplicationBuilder.cs | 7 +++++++ .../Builder/TestApplicationBuilder.cs | 5 +++-- .../Hosts/ITestHostBuilder.cs | 2 +- .../Hosts/TestHostBuilder.cs | 2 +- .../PublicAPI/PublicAPI.Unshipped.txt | 5 +++++ .../TestHostOrcherstrator/ITestHostOrchestrator.cs | 11 ++++++++++- .../ITestHostOrchestratorManager.cs | 13 ++++++++++++- .../TestHostOrchestratorManager.cs | 2 +- 9 files changed, 41 insertions(+), 15 deletions(-) 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..a8f8c67f4d 100644 --- a/src/Platform/Microsoft.Testing.Platform/Builder/ITestApplicationBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Builder/ITestApplicationBuilder.cs @@ -5,6 +5,7 @@ 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.Logging; using Microsoft.Testing.Platform.TestHost; using Microsoft.Testing.Platform.TestHostControllers; @@ -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..523f70b61a 100644 --- a/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs @@ -53,9 +53,10 @@ internal TestApplicationBuilder( public ITestHostControllersManager TestHostControllers => _testHostBuilder.TestHostControllers; - public ICommandLineManager CommandLine => _testHostBuilder.CommandLine; + [Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] + public ITestHostOrchestratorManager TestHostOrchestrator => _testHostBuilder.TestHostOrchestratorManager; - internal ITestHostOrchestratorManager TestHostOrchestrator => _testHostBuilder.TestHostOrchestratorManager; + 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..781ecfa0b2 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/ITestHostBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/ITestHostBuilder.cs @@ -29,7 +29,7 @@ internal interface ITestHostBuilder ITestHostControllersManager TestHostControllers { get; } - ITestHostOrchestratorManager TestHostOrchestratorManager { get; } + IInternalTestHostOrchestratorManager TestHostOrchestratorManager { 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..d7660352bd 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs @@ -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 IInternalTestHostOrchestratorManager TestHostOrchestratorManager { get; } = new TestHostOrchestratorManager(); public async Task BuildAsync( ApplicationLoggingState loggingState, diff --git a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt index 80ae5857e1..3ff72fee2c 100644 --- a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt @@ -5,3 +5,8 @@ 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.Extensions.TestHostOrchestrator.ITestHostOrchestratorManager! +[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorManager +[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorManager.AddTestHostOrchestrator(System.Func! factory) -> void 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/ITestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs index 7f4d5c0827..a724d41e72 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs @@ -5,10 +5,21 @@ namespace Microsoft.Testing.Platform.Extensions.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); +} +internal interface IInternalTestHostOrchestratorManager : ITestHostOrchestratorManager +{ // 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. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs index 30094f9ed1..ae92fc444c 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs @@ -6,7 +6,7 @@ namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; -internal sealed class TestHostOrchestratorManager : ITestHostOrchestratorManager +internal sealed class TestHostOrchestratorManager : IInternalTestHostOrchestratorManager { private readonly List> _testHostOrchestratorApplicationLifetimeFactories = []; private List>? _factories; From 7aee1d7e36a7f6e8a8afa70150921f6ec590619d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Sat, 14 Feb 2026 21:38:34 +0100 Subject: [PATCH 02/13] Fix --- .../Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs b/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs index cc0202e573..c054ae845a 100644 --- a/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs +++ b/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs @@ -4,6 +4,7 @@ using Microsoft.Testing.Extensions.MSBuild; using Microsoft.Testing.Platform.Builder; using Microsoft.Testing.Platform.Extensions; +using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; using Microsoft.Testing.Platform.Services; namespace Microsoft.Testing.Platform.MSBuild; @@ -31,7 +32,7 @@ public static void AddMSBuild(this ITestApplicationBuilder builder) serviceProvider.GetConfiguration(), serviceProvider.GetCommandLineOptions())); - ((TestApplicationBuilder)builder).TestHostOrchestrator.AddTestHostOrchestratorApplicationLifetime( + ((IInternalTestHostOrchestratorManager)((TestApplicationBuilder)builder).TestHostOrchestrator).AddTestHostOrchestratorApplicationLifetime( serviceProvider => new MSBuildOrchestratorLifetime( serviceProvider.GetConfiguration(), serviceProvider.GetCommandLineOptions())); From 33d4cc2e6f9dd5e9816ccb9426dcffc51916767b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Mon, 16 Feb 2026 10:01:43 +0100 Subject: [PATCH 03/13] Address review comments --- .../MSBuildExtensions.cs | 3 +-- .../Resources/ExtensionResources.resx | 3 --- .../Resources/xlf/ExtensionResources.cs.xlf | 5 ----- .../Resources/xlf/ExtensionResources.de.xlf | 5 ----- .../Resources/xlf/ExtensionResources.es.xlf | 5 ----- .../Resources/xlf/ExtensionResources.fr.xlf | 5 ----- .../Resources/xlf/ExtensionResources.it.xlf | 5 ----- .../Resources/xlf/ExtensionResources.ja.xlf | 5 ----- .../Resources/xlf/ExtensionResources.ko.xlf | 5 ----- .../Resources/xlf/ExtensionResources.pl.xlf | 6 +----- .../Resources/xlf/ExtensionResources.pt-BR.xlf | 5 ----- .../Resources/xlf/ExtensionResources.ru.xlf | 5 ----- .../Resources/xlf/ExtensionResources.tr.xlf | 5 ----- .../Resources/xlf/ExtensionResources.zh-Hans.xlf | 6 +----- .../Resources/xlf/ExtensionResources.zh-Hant.xlf | 5 ----- .../Hosts/ITestHostBuilder.cs | 2 +- .../Hosts/TestHostBuilder.cs | 4 ++-- .../PublicAPI/PublicAPI.Unshipped.txt | 5 +++++ .../ITestHostControllersExtension.cs | 3 ++- .../ITestHostOrchestratorApplicationLifetime.cs | 6 +++++- .../ITestHostOrchestratorManager.cs | 14 ++++---------- .../TestHostOrchestratorManager.cs | 4 ++-- 22 files changed, 24 insertions(+), 87 deletions(-) diff --git a/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs b/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs index c054ae845a..224a5dfce8 100644 --- a/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs +++ b/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildExtensions.cs @@ -4,7 +4,6 @@ using Microsoft.Testing.Extensions.MSBuild; using Microsoft.Testing.Platform.Builder; using Microsoft.Testing.Platform.Extensions; -using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; using Microsoft.Testing.Platform.Services; namespace Microsoft.Testing.Platform.MSBuild; @@ -32,7 +31,7 @@ public static void AddMSBuild(this ITestApplicationBuilder builder) serviceProvider.GetConfiguration(), serviceProvider.GetCommandLineOptions())); - ((IInternalTestHostOrchestratorManager)((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..a079921d02 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,7 @@ 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..6b31f884d1 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,7 @@ 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.Platform/Hosts/ITestHostBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Hosts/ITestHostBuilder.cs index 781ecfa0b2..12cc02f5a6 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/ITestHostBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/ITestHostBuilder.cs @@ -29,7 +29,7 @@ internal interface ITestHostBuilder ITestHostControllersManager TestHostControllers { get; } - IInternalTestHostOrchestratorManager TestHostOrchestratorManager { get; } + ITestHostOrchestratorManager TestHostOrchestratorManager { 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 d7660352bd..6e42f1ef03 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs @@ -55,7 +55,7 @@ internal sealed class TestHostBuilder(IFileSystem fileSystem, IRuntimeFeature ru public IToolsManager Tools { get; } = new ToolsManager(); - public IInternalTestHostOrchestratorManager TestHostOrchestratorManager { get; } = new TestHostOrchestratorManager(); + public ITestHostOrchestratorManager TestHostOrchestratorManager { get; } = new TestHostOrchestratorManager(); public async Task BuildAsync( ApplicationLoggingState loggingState, @@ -407,7 +407,7 @@ await LogTestHostCreatedAsync( } // ======= TEST HOST ORCHESTRATOR ======== // - TestHostOrchestratorConfiguration testHostOrchestratorConfiguration = await TestHostOrchestratorManager.BuildAsync(serviceProvider).ConfigureAwait(false); + TestHostOrchestratorConfiguration testHostOrchestratorConfiguration = await ((TestHostOrchestratorManager)TestHostOrchestratorManager).BuildAsync(serviceProvider).ConfigureAwait(false); if (testHostOrchestratorConfiguration.TestHostOrchestrators.Length > 0 && !commandLineHandler.IsOptionSet(PlatformCommandLineProvider.DiscoverTestsOptionKey)) { policiesService.ProcessRole = TestProcessRole.TestHostOrchestrator; diff --git a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt index 3ff72fee2c..e480ada588 100644 --- a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt @@ -10,3 +10,8 @@ Microsoft.Testing.Platform.Extensions.TestHostControllers.ITestHostProcessLifeti Microsoft.Testing.Platform.Builder.ITestApplicationBuilder.TestHostOrchestrator.get -> Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorManager! [TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorManager [TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorManager.AddTestHostOrchestrator(System.Func! factory) -> void +[TPEXP]Microsoft.Testing.Platform.Extensions.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/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 a724d41e72..d3d104ff38 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs @@ -1,8 +1,6 @@ // 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; - namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; /// @@ -16,14 +14,10 @@ public interface ITestHostOrchestratorManager /// /// The factory method for creating the test host orchestrator. void AddTestHostOrchestrator(Func factory); -} -internal interface IInternalTestHostOrchestratorManager : ITestHostOrchestratorManager -{ - // 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/TestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs index ae92fc444c..7a0f40b6ab 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs @@ -6,7 +6,7 @@ namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; -internal sealed class TestHostOrchestratorManager : IInternalTestHostOrchestratorManager +internal sealed class TestHostOrchestratorManager : ITestHostOrchestratorManager { private readonly List> _testHostOrchestratorApplicationLifetimeFactories = []; private List>? _factories; @@ -18,7 +18,7 @@ public void AddTestHostOrchestrator(Func BuildAsync(ServiceProvider serviceProvider) + internal async Task BuildAsync(ServiceProvider serviceProvider) { if (_factories is null) { From d503956a6cdde442f23514f993c187a86df753bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Tue, 17 Feb 2026 20:30:49 +0100 Subject: [PATCH 04/13] Address review comments --- .../MSBuildOrchestratorLifecycleCallbacks.cs | 2 +- .../RetryOrchestrator.cs | 2 +- .../Builder/ITestApplicationBuilder.cs | 2 +- .../Builder/TestApplicationBuilder.cs | 4 ++-- .../Hosts/ITestHostBuilder.cs | 4 ++-- .../Hosts/TestHostBuilder.cs | 8 ++++---- .../Hosts/TestHostOchestratorHost.cs | 2 +- .../PublicAPI/PublicAPI.Unshipped.txt | 20 +++++++++---------- .../ITestHostControllersExtension.cs | 4 +++- .../ITestHostOrchestrator.cs | 4 +++- ...TestHostOrchestratorApplicationLifetime.cs | 2 +- .../ITestHostOrchestratorManager.cs | 2 +- .../TestHostOrchestratorConfiguration.cs | 2 +- .../TestHostOrchestratorManager.cs | 3 ++- 14 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildOrchestratorLifecycleCallbacks.cs b/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildOrchestratorLifecycleCallbacks.cs index e8b4b37ff2..ceddb9512f 100644 --- a/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildOrchestratorLifecycleCallbacks.cs +++ b/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildOrchestratorLifecycleCallbacks.cs @@ -4,11 +4,11 @@ using Microsoft.Testing.Extensions.MSBuild.Serializers; 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.IPC; using Microsoft.Testing.Platform.IPC.Models; using Microsoft.Testing.Platform.IPC.Serializers; +using Microsoft.Testing.Platform.TestHostOrchestrator; namespace Microsoft.Testing.Extensions.MSBuild; diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs index 44b8dd7109..b57c9cfcac 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs @@ -5,11 +5,11 @@ using Microsoft.Testing.Platform.CommandLine; using Microsoft.Testing.Platform.Configurations; using Microsoft.Testing.Platform.Extensions.OutputDevice; -using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; using Microsoft.Testing.Platform.Helpers; using Microsoft.Testing.Platform.Logging; using Microsoft.Testing.Platform.OutputDevice; using Microsoft.Testing.Platform.Services; +using Microsoft.Testing.Platform.TestHostOrchestrator; namespace Microsoft.Testing.Extensions.Policy; diff --git a/src/Platform/Microsoft.Testing.Platform/Builder/ITestApplicationBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Builder/ITestApplicationBuilder.cs index a8f8c67f4d..7ad9101abb 100644 --- a/src/Platform/Microsoft.Testing.Platform/Builder/ITestApplicationBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Builder/ITestApplicationBuilder.cs @@ -5,10 +5,10 @@ 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.Logging; using Microsoft.Testing.Platform.TestHost; using Microsoft.Testing.Platform.TestHostControllers; +using Microsoft.Testing.Platform.TestHostOrchestrator; namespace Microsoft.Testing.Platform.Builder; diff --git a/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs index 523f70b61a..13b6f85cce 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; @@ -54,7 +54,7 @@ internal TestApplicationBuilder( public ITestHostControllersManager TestHostControllers => _testHostBuilder.TestHostControllers; [Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] - public ITestHostOrchestratorManager TestHostOrchestrator => _testHostBuilder.TestHostOrchestratorManager; + public ITestHostOrchestratorManager TestHostOrchestrator => _testHostBuilder.TestHostOrchestrator; public ICommandLineManager CommandLine => _testHostBuilder.CommandLine; 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 6e42f1ef03..23d3c62e4e 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 TestHostOrchestratorManager(); public async Task BuildAsync( ApplicationLoggingState loggingState, @@ -407,7 +407,7 @@ await LogTestHostCreatedAsync( } // ======= TEST HOST ORCHESTRATOR ======== // - TestHostOrchestratorConfiguration testHostOrchestratorConfiguration = await ((TestHostOrchestratorManager)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; @@ -415,7 +415,7 @@ await LogTestHostCreatedAsync( // Build and register the test application lifecycle callbacks. ITestHostOrchestratorApplicationLifetime[] orchestratorLifetimes = - await ((TestHostOrchestratorManager)TestHostOrchestratorManager).BuildTestHostOrchestratorApplicationLifetimesAsync(serviceProvider).ConfigureAwait(false); + 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..a4cdd8e731 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs @@ -1,11 +1,11 @@ // 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.TestHostOrchestrator; using Microsoft.Testing.Platform.Helpers; 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 e480ada588..e651e71677 100644 --- a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt @@ -5,13 +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.Extensions.TestHostOrchestrator.ITestHostOrchestratorManager! -[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorManager -[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostOrchestratorManager.AddTestHostOrchestrator(System.Func! factory) -> void -[TPEXP]Microsoft.Testing.Platform.Extensions.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 +[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestrator +[TPEXP]Microsoft.Testing.Platform.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.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime +[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime.AfterRunAsync(int exitCode, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! +[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime.BeforeRunAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! +[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestratorExtension diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs index 84046d93b2..131f44e098 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.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; + +namespace Microsoft.Testing.Platform.TestHostOrchestrator; /// /// Represents an extension for test host orchestrators. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs index e0dce2a842..90dee90375 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.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; + +namespace Microsoft.Testing.Platform.TestHostOrchestrator; /// /// Represents an extension that orchestrates test host execution. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs index 0e98bb36e2..96d5328cf7 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs @@ -1,7 +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. -namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; +namespace Microsoft.Testing.Platform.TestHostOrchestrator; /// /// Represents the application lifetime for a test host orchestrator. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs index d3d104ff38..f0e52295dd 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs @@ -1,7 +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. -namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; +namespace Microsoft.Testing.Platform.TestHostOrchestrator; /// /// Represents a manager for test host orchestrators. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs index 095f30e6a2..06ef62848e 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs @@ -1,7 +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. -namespace 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 7a0f40b6ab..f6d302b5c7 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs @@ -1,10 +1,11 @@ // 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.Helpers; using Microsoft.Testing.Platform.Services; -namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; +namespace Microsoft.Testing.Platform.TestHostOrchestrator; internal sealed class TestHostOrchestratorManager : ITestHostOrchestratorManager { From 04aef205c1dd5079c4ce4c38c0709dec5fd24248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Wed, 18 Feb 2026 13:44:14 +0100 Subject: [PATCH 05/13] Fix compat issues --- .../Builder/TestApplicationBuilder.cs | 5 ++++- .../Hosts/TestHostBuilder.cs | 2 +- .../OrchestratorBackCompat.cs | 22 +++++++++++++++++++ .../TestHostOrchestratorManager.cs | 9 +++++++- 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs diff --git a/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs index 13b6f85cce..851e7feb3b 100644 --- a/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Builder/TestApplicationBuilder.cs @@ -54,7 +54,10 @@ internal TestApplicationBuilder( public ITestHostControllersManager TestHostControllers => _testHostBuilder.TestHostControllers; [Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] - public ITestHostOrchestratorManager TestHostOrchestrator => _testHostBuilder.TestHostOrchestrator; + ITestHostOrchestratorManager ITestApplicationBuilder.TestHostOrchestrator => _testHostBuilder.TestHostOrchestrator; + + // 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; diff --git a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs index 23d3c62e4e..8fce853d03 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs @@ -55,7 +55,7 @@ internal sealed class TestHostBuilder(IFileSystem fileSystem, IRuntimeFeature ru public IToolsManager Tools { get; } = new ToolsManager(); - public ITestHostOrchestratorManager TestHostOrchestrator { get; } = new TestHostOrchestratorManager(); + public ITestHostOrchestratorManager TestHostOrchestrator { get; } = new Extensions.TestHostOrchestrator.TestHostOrchestratorManager(); public async Task BuildAsync( ApplicationLoggingState loggingState, 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..0c84dd2db7 --- /dev/null +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs @@ -0,0 +1,22 @@ +// 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 types lived in the +// Microsoft.Testing.Platform.Extensions.TestHostOrchestrator namespace. +namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; + +// Extends the new public interface so internal code can use this type everywhere. +internal interface ITestHostOrchestrator : global::Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestrator; + +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 +{ + internal void AddTestHostOrchestrator(Func factory) + => ((ITestHostOrchestratorManager)this).AddTestHostOrchestrator(factory); +} diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs index f6d302b5c7..11669f7202 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs @@ -7,7 +7,7 @@ namespace Microsoft.Testing.Platform.TestHostOrchestrator; -internal sealed class TestHostOrchestratorManager : ITestHostOrchestratorManager +internal class TestHostOrchestratorManager : ITestHostOrchestratorManager, Extensions.TestHostOrchestrator.ITestHostOrchestratorManager { private readonly List> _testHostOrchestratorApplicationLifetimeFactories = []; private List>? _factories; @@ -19,6 +19,13 @@ public void AddTestHostOrchestrator(Func factory) + { + Ensure.NotNull(factory); + _factories ??= []; + _factories.Add(sp => factory(sp)); + } + internal async Task BuildAsync(ServiceProvider serviceProvider) { if (_factories is null) From 49d71a9e8d844b1436da0dd03a00bbafad316910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Fri, 20 Feb 2026 12:39:49 +0100 Subject: [PATCH 06/13] Apply suggestions from code review Co-authored-by: Youssef Victor --- .../Resources/xlf/ExtensionResources.pl.xlf | 1 - .../Resources/xlf/ExtensionResources.zh-Hans.xlf | 1 - 2 files changed, 2 deletions(-) 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 a079921d02..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,7 +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 - 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.zh-Hans.xlf b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hans.xlf index 6b31f884d1..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,7 +60,6 @@ Moving last attempt asset files to the default result directory 重试失败的测试 - Disable retry mechanism if the percentage of failed tests is greater than the specified value 如果失败的测试百分比大于指定值,则禁用重试机制 From aeaa25b2bcd3a628ba0654f5eefd19930a315ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Sun, 22 Feb 2026 09:58:34 +0100 Subject: [PATCH 07/13] Fixes --- .../MSBuildOrchestratorLifecycleCallbacks.cs | 2 +- .../RetryOrchestrator.cs | 2 +- .../Hosts/TestHostBuilder.cs | 2 +- .../Hosts/TestHostOchestratorHost.cs | 1 + .../PublicAPI/PublicAPI.Unshipped.txt | 16 +- .../ITestHostControllersExtension.cs | 4 +- .../ITestHostOrchestrator.cs | 4 +- ...TestHostOrchestratorApplicationLifetime.cs | 2 +- .../ITestHostOrchestratorManager.cs | 2 + .../OrchestratorBackCompat.cs | 11 +- .../TestHostOrchestratorConfiguration.cs | 2 + .../TestHostOrchestratorManager.cs | 1 + .../TestHostOrchestratorManagerTests.cs | 186 ++++++++++++++++++ 13 files changed, 208 insertions(+), 27 deletions(-) create mode 100644 test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs diff --git a/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildOrchestratorLifecycleCallbacks.cs b/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildOrchestratorLifecycleCallbacks.cs index ceddb9512f..e8b4b37ff2 100644 --- a/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildOrchestratorLifecycleCallbacks.cs +++ b/src/Platform/Microsoft.Testing.Extensions.MSBuild/MSBuildOrchestratorLifecycleCallbacks.cs @@ -4,11 +4,11 @@ using Microsoft.Testing.Extensions.MSBuild.Serializers; 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.IPC; using Microsoft.Testing.Platform.IPC.Models; using Microsoft.Testing.Platform.IPC.Serializers; -using Microsoft.Testing.Platform.TestHostOrchestrator; namespace Microsoft.Testing.Extensions.MSBuild; diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs index b57c9cfcac..44b8dd7109 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs @@ -5,11 +5,11 @@ using Microsoft.Testing.Platform.CommandLine; using Microsoft.Testing.Platform.Configurations; using Microsoft.Testing.Platform.Extensions.OutputDevice; +using Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; using Microsoft.Testing.Platform.Helpers; using Microsoft.Testing.Platform.Logging; using Microsoft.Testing.Platform.OutputDevice; using Microsoft.Testing.Platform.Services; -using Microsoft.Testing.Platform.TestHostOrchestrator; namespace Microsoft.Testing.Extensions.Policy; diff --git a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs index 8fce853d03..1d5b12cb7a 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs @@ -414,7 +414,7 @@ await LogTestHostCreatedAsync( await proxyOutputDevice.HandleProcessRoleAsync(TestProcessRole.TestHostOrchestrator, testApplicationCancellationTokenSource.CancellationToken).ConfigureAwait(false); // Build and register the test application lifecycle callbacks. - ITestHostOrchestratorApplicationLifetime[] orchestratorLifetimes = + Extensions.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime[] orchestratorLifetimes = await ((TestHostOrchestratorManager)TestHostOrchestrator).BuildTestHostOrchestratorApplicationLifetimesAsync(serviceProvider).ConfigureAwait(false); serviceProvider.AddServices(orchestratorLifetimes); diff --git a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs index a4cdd8e731..80e9fad19e 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.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 Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; using Microsoft.Testing.Platform.Helpers; using Microsoft.Testing.Platform.Logging; using Microsoft.Testing.Platform.Services; diff --git a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt index e651e71677..59fdfa7acf 100644 --- a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt @@ -5,13 +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.TestHostOrchestrator.ITestHostOrchestrator -[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestrator.OrchestrateTestHostExecutionAsync(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.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime -[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime.AfterRunAsync(int exitCode, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! -[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime.BeforeRunAsync(System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! -[TPEXP]Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestratorExtension +[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 131f44e098..84046d93b2 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs @@ -1,9 +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 Microsoft.Testing.Platform.Extensions; - -namespace Microsoft.Testing.Platform.TestHostOrchestrator; +namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; /// /// Represents an extension for test host orchestrators. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs index 90dee90375..e0dce2a842 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs @@ -1,9 +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 Microsoft.Testing.Platform.Extensions; - -namespace Microsoft.Testing.Platform.TestHostOrchestrator; +namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; /// /// Represents an extension that orchestrates test host execution. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs index 96d5328cf7..0e98bb36e2 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs @@ -1,7 +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. -namespace Microsoft.Testing.Platform.TestHostOrchestrator; +namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; /// /// Represents the application lifetime for a test host orchestrator. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs index f0e52295dd..52d80d3f86 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.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 Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; + namespace Microsoft.Testing.Platform.TestHostOrchestrator; /// diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs index 0c84dd2db7..e26bc0c863 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs @@ -2,21 +2,14 @@ // 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 types lived in the +// against older platform versions where the orchestrator manager type lived in the // Microsoft.Testing.Platform.Extensions.TestHostOrchestrator namespace. namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; -// Extends the new public interface so internal code can use this type everywhere. -internal interface ITestHostOrchestrator : global::Microsoft.Testing.Platform.TestHostOrchestrator.ITestHostOrchestrator; - 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 -{ - internal void AddTestHostOrchestrator(Func factory) - => ((ITestHostOrchestratorManager)this).AddTestHostOrchestrator(factory); -} +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 06ef62848e..a9ab7a918c 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.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 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 11669f7202..a7d47706e4 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs @@ -2,6 +2,7 @@ // 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; 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; + } +} From c36e2ded668c5837279a36b2cee046933aedddd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Thu, 5 Mar 2026 15:37:10 +0100 Subject: [PATCH 08/13] Rename + fix typo on folder --- .../RetryOrchestrator.cs | 2 +- .../Hosts/TestHostOchestratorHost.cs | 2 +- .../PublicAPI/PublicAPI.Unshipped.txt | 6 +++--- .../ITestHostExecutionOrchestrator.cs} | 2 +- .../ITestHostOrchestratorApplicationLifetime.cs | 0 .../ITestHostOrchestratorExtension.cs} | 0 .../ITestHostOrchestratorManager.cs | 2 +- .../OrchestratorBackCompat.cs | 2 +- .../TestHostOrchestratorConfiguration.cs | 4 ++-- .../TestHostOrchestratorManager.cs | 12 ++++++------ .../TestHostOrchestratorManagerTests.cs | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) rename src/Platform/Microsoft.Testing.Platform/{TestHostOrcherstrator/ITestHostOrchestrator.cs => TestHostOrchestrator/ITestHostExecutionOrchestrator.cs} (90%) rename src/Platform/Microsoft.Testing.Platform/{TestHostOrcherstrator => TestHostOrchestrator}/ITestHostOrchestratorApplicationLifetime.cs (100%) rename src/Platform/Microsoft.Testing.Platform/{TestHostOrcherstrator/ITestHostControllersExtension.cs => TestHostOrchestrator/ITestHostOrchestratorExtension.cs} (100%) rename src/Platform/Microsoft.Testing.Platform/{TestHostOrcherstrator => TestHostOrchestrator}/ITestHostOrchestratorManager.cs (97%) rename src/Platform/Microsoft.Testing.Platform/{TestHostOrcherstrator => TestHostOrchestrator}/OrchestratorBackCompat.cs (96%) rename src/Platform/Microsoft.Testing.Platform/{TestHostOrcherstrator => TestHostOrchestrator}/TestHostOrchestratorConfiguration.cs (70%) rename src/Platform/Microsoft.Testing.Platform/{TestHostOrcherstrator => TestHostOrchestrator}/TestHostOrchestratorManager.cs (88%) diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs index 44b8dd7109..5aeb86304a 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs @@ -14,7 +14,7 @@ namespace Microsoft.Testing.Extensions.Policy; [UnsupportedOSPlatform("browser")] -internal sealed class RetryOrchestrator : ITestHostOrchestrator, IOutputDeviceDataProducer +internal sealed class RetryOrchestrator : ITestHostExecutionOrchestrator, IOutputDeviceDataProducer { private readonly IServiceProvider _serviceProvider; private readonly ICommandLineOptions _commandLineOptions; diff --git a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs index 80e9fad19e..0b8dc8105b 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostOchestratorHost.cs @@ -24,7 +24,7 @@ public async Task RunAsync() throw new NotSupportedException("Multiple test orchestrator not supported"); } - ITestHostOrchestrator testHostOrchestrator = _testHostOrchestratorConfiguration.TestHostOrchestrators[0]; + ITestHostExecutionOrchestrator testHostOrchestrator = _testHostOrchestratorConfiguration.TestHostOrchestrators[0]; ITestApplicationCancellationTokenSource applicationCancellationToken = _serviceProvider.GetTestApplicationCancellationTokenSource(); int exitCode; await logger.LogInformationAsync($"Running test orchestrator '{testHostOrchestrator.Uid}'").ConfigureAwait(false); diff --git a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt index 59fdfa7acf..05eaa9f07e 100644 --- a/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt +++ b/src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt @@ -5,11 +5,11 @@ 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! +[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostExecutionOrchestrator +[TPEXP]Microsoft.Testing.Platform.Extensions.TestHostOrchestrator.ITestHostExecutionOrchestrator.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.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! diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostExecutionOrchestrator.cs similarity index 90% rename from src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs rename to src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostExecutionOrchestrator.cs index e0dce2a842..382f43ee0b 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestrator.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostExecutionOrchestrator.cs @@ -7,7 +7,7 @@ namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; /// Represents an extension that orchestrates test host execution. /// [Experimental("TPEXP", UrlFormat = "https://aka.ms/testingplatform/diagnostics#{0}")] -public interface ITestHostOrchestrator : IExtension +public interface ITestHostExecutionOrchestrator : ITestHostOrchestratorExtension { /// /// Orchestrates test host execution. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestratorApplicationLifetime.cs similarity index 100% rename from src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorApplicationLifetime.cs rename to src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestratorApplicationLifetime.cs diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestratorExtension.cs similarity index 100% rename from src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostControllersExtension.cs rename to src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestratorExtension.cs diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestratorManager.cs similarity index 97% rename from src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs rename to src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestratorManager.cs index 52d80d3f86..86a9163699 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/ITestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestratorManager.cs @@ -15,7 +15,7 @@ public interface ITestHostOrchestratorManager /// Adds a test host orchestrator. /// /// The factory method for creating the test host orchestrator. - void AddTestHostOrchestrator(Func factory); + void AddTestHostOrchestrator(Func factory); /// /// Adds a test host orchestrator application lifetime. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs similarity index 96% rename from src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs rename to src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs index e26bc0c863..6c14780b5e 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/OrchestratorBackCompat.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs @@ -8,7 +8,7 @@ namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; internal interface ITestHostOrchestratorManager { - void AddTestHostOrchestrator(Func factory); + void AddTestHostOrchestrator(Func factory); } // Kept for binary backward compatibility with extensions that cast to this concrete type. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostOrchestratorConfiguration.cs similarity index 70% rename from src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs rename to src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostOrchestratorConfiguration.cs index a9ab7a918c..92a4669958 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorConfiguration.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostOrchestratorConfiguration.cs @@ -5,7 +5,7 @@ namespace Microsoft.Testing.Platform.TestHostOrchestrator; -internal sealed class TestHostOrchestratorConfiguration(ITestHostOrchestrator[] testHostOrchestrators) +internal sealed class TestHostOrchestratorConfiguration(ITestHostExecutionOrchestrator[] testHostOrchestrators) { - public ITestHostOrchestrator[] TestHostOrchestrators { get; } = testHostOrchestrators; + public ITestHostExecutionOrchestrator[] TestHostOrchestrators { get; } = testHostOrchestrators; } diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostOrchestratorManager.cs similarity index 88% rename from src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs rename to src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostOrchestratorManager.cs index a7d47706e4..f672055eef 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrcherstrator/TestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostOrchestratorManager.cs @@ -11,16 +11,16 @@ namespace Microsoft.Testing.Platform.TestHostOrchestrator; internal class TestHostOrchestratorManager : ITestHostOrchestratorManager, Extensions.TestHostOrchestrator.ITestHostOrchestratorManager { private readonly List> _testHostOrchestratorApplicationLifetimeFactories = []; - private List>? _factories; + private List>? _factories; - public void AddTestHostOrchestrator(Func factory) + public void AddTestHostOrchestrator(Func factory) { Ensure.NotNull(factory); _factories ??= []; _factories.Add(factory); } - void Extensions.TestHostOrchestrator.ITestHostOrchestratorManager.AddTestHostOrchestrator(Func factory) + void Extensions.TestHostOrchestrator.ITestHostOrchestratorManager.AddTestHostOrchestrator(Func factory) { Ensure.NotNull(factory); _factories ??= []; @@ -34,10 +34,10 @@ internal async Task BuildAsync(ServiceProvide return new TestHostOrchestratorConfiguration([]); } - List orchestrators = []; - foreach (Func factory in _factories) + List orchestrators = []; + foreach (Func factory in _factories) { - ITestHostOrchestrator orchestrator = factory(serviceProvider); + ITestHostExecutionOrchestrator orchestrator = factory(serviceProvider); // Check if we have already extensions of the same type with same id registered orchestrators.ValidateUniqueExtension(orchestrator); diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs index 73f4f8b4e5..35615ab8bf 100644 --- a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs +++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs @@ -147,7 +147,7 @@ public async Task BackCompatTestHostOrchestratorManager_AddViaBackCompat_BuildsV Assert.AreEqual("e2e-compat", config.TestHostOrchestrators[0].Uid); } - private sealed class FakeOrchestrator : BackCompat.ITestHostOrchestrator + private sealed class FakeOrchestrator : BackCompat.ITestHostExecutionOrchestrator { public FakeOrchestrator(string uid) => Uid = uid; From f4d3236c5f6841fabe77631b553ff961f966fa02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Thu, 5 Mar 2026 16:33:34 +0100 Subject: [PATCH 09/13] Fix backcompat --- .../TestHostOrchestrator/ITestHostOrchestrator.cs | 7 +++++++ .../TestHostOrchestrator/OrchestratorBackCompat.cs | 4 +++- .../TestHostOrchestrator/TestHostOrchestratorManager.cs | 5 ++++- 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestrator.cs diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestrator.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestrator.cs new file mode 100644 index 0000000000..339e559366 --- /dev/null +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/ITestHostOrchestrator.cs @@ -0,0 +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. + +// Back-compat shim: the old ITestHostOrchestrator was renamed to ITestHostExecutionOrchestrator. +namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; + +internal interface ITestHostOrchestrator : ITestHostExecutionOrchestrator; diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs index 6c14780b5e..0796c4e7b0 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs @@ -8,7 +8,9 @@ namespace Microsoft.Testing.Platform.Extensions.TestHostOrchestrator; internal interface ITestHostOrchestratorManager { - void AddTestHostOrchestrator(Func factory); + void AddTestHostOrchestrator(Func factory); + + void AddTestHostOrchestratorApplicationLifetime(Func testHostOrchestratorApplicationLifetimeFactory); } // Kept for binary backward compatibility with extensions that cast to this concrete type. diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostOrchestratorManager.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostOrchestratorManager.cs index f672055eef..e76b966f2e 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostOrchestratorManager.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/TestHostOrchestratorManager.cs @@ -20,13 +20,16 @@ public void AddTestHostOrchestrator(Func factory) + void Extensions.TestHostOrchestrator.ITestHostOrchestratorManager.AddTestHostOrchestrator(Func factory) { Ensure.NotNull(factory); _factories ??= []; _factories.Add(sp => factory(sp)); } + void Extensions.TestHostOrchestrator.ITestHostOrchestratorManager.AddTestHostOrchestratorApplicationLifetime(Func testHostOrchestratorApplicationLifetimeFactory) + => AddTestHostOrchestratorApplicationLifetime(testHostOrchestratorApplicationLifetimeFactory); + internal async Task BuildAsync(ServiceProvider serviceProvider) { if (_factories is null) From c59f5ff31c95ca94fbf95ca2532ad84d56aef441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Fri, 6 Mar 2026 11:04:18 +0100 Subject: [PATCH 10/13] Fix --- .../TestHostOrchestratorManagerTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs index 35615ab8bf..73f4f8b4e5 100644 --- a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs +++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/TestHostOrchestratorManagerTests.cs @@ -147,7 +147,7 @@ public async Task BackCompatTestHostOrchestratorManager_AddViaBackCompat_BuildsV Assert.AreEqual("e2e-compat", config.TestHostOrchestrators[0].Uid); } - private sealed class FakeOrchestrator : BackCompat.ITestHostExecutionOrchestrator + private sealed class FakeOrchestrator : BackCompat.ITestHostOrchestrator { public FakeOrchestrator(string uid) => Uid = uid; From 9f08b631dc69d1a7f5ebe8039e45f9dbd21ae4a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Fri, 6 Mar 2026 14:35:24 +0100 Subject: [PATCH 11/13] Address review comments --- .../RetryExtensions.cs | 9 ++++++++- .../Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs | 8 +++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs index 44c492c009..f95c9e6f5d 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs @@ -38,7 +38,14 @@ CompositeExtensionFactory compositeExtensionFactory builder.TestHostOrchestrator .AddTestHostOrchestrator(serviceProvider => new RetryOrchestrator(serviceProvider)); - ((TestHostManager)builder.TestHost) + + if (builder.TestHost is not TestHostManager testHostManager) + { + throw new InvalidOperationException( + "The retry provider requires the default TestHostManager implementation."); + } + + testHostManager .AddTestExecutionFilterFactory(serviceProvider => new RetryExecutionFilterFactory(serviceProvider)); } } diff --git a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs index 1d5b12cb7a..bd69e72c36 100644 --- a/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs +++ b/src/Platform/Microsoft.Testing.Platform/Hosts/TestHostBuilder.cs @@ -55,7 +55,9 @@ internal sealed class TestHostBuilder(IFileSystem fileSystem, IRuntimeFeature ru public IToolsManager Tools { get; } = new ToolsManager(); - public ITestHostOrchestratorManager TestHostOrchestrator { get; } = new Extensions.TestHostOrchestrator.TestHostOrchestratorManager(); + private readonly TestHostOrchestratorManager _testHostOrchestratorManager = new Extensions.TestHostOrchestrator.TestHostOrchestratorManager(); + + public ITestHostOrchestratorManager TestHostOrchestrator => _testHostOrchestratorManager; public async Task BuildAsync( ApplicationLoggingState loggingState, @@ -407,7 +409,7 @@ await LogTestHostCreatedAsync( } // ======= TEST HOST ORCHESTRATOR ======== // - TestHostOrchestratorConfiguration testHostOrchestratorConfiguration = await ((TestHostOrchestratorManager)TestHostOrchestrator).BuildAsync(serviceProvider).ConfigureAwait(false); + TestHostOrchestratorConfiguration testHostOrchestratorConfiguration = await _testHostOrchestratorManager.BuildAsync(serviceProvider).ConfigureAwait(false); if (testHostOrchestratorConfiguration.TestHostOrchestrators.Length > 0 && !commandLineHandler.IsOptionSet(PlatformCommandLineProvider.DiscoverTestsOptionKey)) { policiesService.ProcessRole = TestProcessRole.TestHostOrchestrator; @@ -415,7 +417,7 @@ await LogTestHostCreatedAsync( // Build and register the test application lifecycle callbacks. Extensions.TestHostOrchestrator.ITestHostOrchestratorApplicationLifetime[] orchestratorLifetimes = - await ((TestHostOrchestratorManager)TestHostOrchestrator).BuildTestHostOrchestratorApplicationLifetimesAsync(serviceProvider).ConfigureAwait(false); + await _testHostOrchestratorManager.BuildTestHostOrchestratorApplicationLifetimesAsync(serviceProvider).ConfigureAwait(false); serviceProvider.AddServices(orchestratorLifetimes); builderActivity?.SetTag(BuilderHostTypeOTelKey, nameof(TestHostOrchestratorHost)); From e776b0be0291577fc309ce04f795c17b8984beeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Fri, 6 Mar 2026 15:14:24 +0100 Subject: [PATCH 12/13] Fix --- .../Resources/ExtensionResources.resx | 3 +++ .../Resources/xlf/ExtensionResources.cs.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.de.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.es.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.fr.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.it.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.ja.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.ko.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.pl.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.pt-BR.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.ru.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.tr.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.zh-Hans.xlf | 5 +++++ .../Resources/xlf/ExtensionResources.zh-Hant.xlf | 5 +++++ .../Microsoft.Testing.Extensions.Retry/RetryExtensions.cs | 2 +- 15 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/ExtensionResources.resx b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/ExtensionResources.resx index 8179e3290f..089fc89eed 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/ExtensionResources.resx +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/Resources/ExtensionResources.resx @@ -149,6 +149,9 @@ Moving last attempt asset files to the default result directory Retry failed tests + + The retry provider requires the default TestHostManager implementation. + 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 0ec43e125a..30cdad2767 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 @@ -100,6 +100,11 @@ Přesouvání souborů prostředků posledního pokusu do výchozího adresáře Možnost {0} nelze používat společně s možností {1}. + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} Hostitelský proces testu byl ukončen dříve, než se k němu mohla služba opakování připojit. Ukončovací kód: {0} 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 54f48e40b8..cce9e67a21 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 @@ -100,6 +100,11 @@ Medienobjektdateien des letzten Versuchs werden in das Standardergebnisverzeichn Optionen "{0}" und "{1}" können nicht zusammen verwendet werden + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} Der Testhostprozess wurde beendet, bevor der Wiederholungsdienst eine Verbindung herstellen konnte. Exitcode: {0} 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 55edc18d71..f6d738cc4f 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 @@ -100,6 +100,11 @@ Moviendo los archivos de recursos del último intento al directorio de resultado Las opciones '{0}' y '{1}' no se pueden usar juntas + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} El proceso de host de prueba se cerró antes de que el servicio de reintento pudiera conectarse a él. Código de salida: {0} 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 2fc7921866..eff9d1d0a0 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 @@ -100,6 +100,11 @@ Déplacement des fichiers de ressources de la dernière tentative vers le réper Les options «{0}» et «{1}» ne peuvent pas être utilisées ensemble + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} Le processus hôte de test s’est arrêté avant que le service de nouvelle tentative puisse s’y connecter. Code de sortie : {0} 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 a55bf502da..b39bc19951 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 @@ -100,6 +100,11 @@ Spostamento dei file di asset dell'ultimo tentativo nella directory dei risultat Le opzioni '{0}' e '{1}' non possono essere usate insieme + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} Il processo host di test è stato chiuso prima che il servizio di ripetizione potesse connettersi ad esso. Codice di uscita: {0} 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 23d77b2232..e7388256f2 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 @@ -100,6 +100,11 @@ Moving last attempt asset files to the default result directory オプション '{0}' と '{1}' を一緒に使用することはできません + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} 再試行サービスが接続する前に、テスト ホスト プロセスが終了しました。終了コード: {0} 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 df4c3290dd..e6b757ebdb 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 @@ -100,6 +100,11 @@ Moving last attempt asset files to the default result directory '{0}' 및 '{1}' 옵션은 함께 사용할 수 없습니다. + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} 다시 시도 서비스가 연결되기 전에 테스트 호스트 프로세스가 종료되었습니다. 종료 코드: {0} 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 cde119184e..3ad94b710e 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 @@ -100,6 +100,11 @@ Przeniesienie plików zasobów ostatniej próby do domyślnego katalogu wyników Opcji „{0}” i „{1}” nie można używać razem + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} Proces hosta testowego zakończył się, zanim usługa ponawiania próby mogła nawiązać z nim połączenie. Kod zakończenia: {0} 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 e7b749064a..7cf9450007 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 @@ -100,6 +100,11 @@ Movendo arquivos de ativo da última tentativa para o diretório de resultados p As opções ''{0}'' e ''{1}'' não podem ser usadas juntas + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} O processo de host de teste foi encerrado antes que o serviço de repetição pudesse se conectar a ele. Código de saída: {0} 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 eecf000105..e7cefd251f 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 @@ -100,6 +100,11 @@ Moving last attempt asset files to the default result directory Параметры "{0}" и "{1}" не могут использоваться вместе + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} Тестовый хост-процесс завершился прежде, чем к нему смогла подключиться служба повторной попытки. Код выхода: {0} 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 8879edbaee..e6f139efaa 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 @@ -100,6 +100,11 @@ Son deneme varlık dosyaları, varsayılan sonuç dizinine taşınıyor '{0}' ve '{1}' seçenekleri birlikte kullanılamaz + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} Yeniden deneme hizmeti ona bağlanamadan test ana makinesi işleminden çıkıldı. Çıkış kodu: {0} 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 643ff90857..8b13bb86c9 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 @@ -100,6 +100,11 @@ Moving last attempt asset files to the default result directory 选项“{0}”和“{1}”不能一起使用 + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} 测试主机进程已在重试服务可以连接到它之前退出。退出代码: {0} 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 417569a8bc..86598a1d9e 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 @@ -100,6 +100,11 @@ Moving last attempt asset files to the default result directory 選項 '{0}' 和 '{1}' 不能同時使用 + + The retry provider requires the default TestHostManager implementation. + The retry provider requires the default TestHostManager implementation. + + Test host process exited before the retry service could connect to it. Exit code: {0} 測試主機處理序在重試服務連線到它之前已結束。結束代碼: {0} diff --git a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs index f95c9e6f5d..404fce2aaf 100644 --- a/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs +++ b/src/Platform/Microsoft.Testing.Extensions.Retry/RetryExtensions.cs @@ -42,7 +42,7 @@ CompositeExtensionFactory compositeExtensionFactory if (builder.TestHost is not TestHostManager testHostManager) { throw new InvalidOperationException( - "The retry provider requires the default TestHostManager implementation."); + ExtensionResources.RetryProviderRequiresDefaultTestHostManagerErrorMessage); } testHostManager From 771c8b62da37c6836c3ce894d86c057bf68b04b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Fri, 6 Mar 2026 17:09:41 +0100 Subject: [PATCH 13/13] Fix --- .../TestHostOrchestrator/OrchestratorBackCompat.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs index 0796c4e7b0..9e901be2ef 100644 --- a/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs +++ b/src/Platform/Microsoft.Testing.Platform/TestHostOrchestrator/OrchestratorBackCompat.cs @@ -14,4 +14,11 @@ internal interface ITestHostOrchestratorManager } // Kept for binary backward compatibility with extensions that cast to this concrete type. -internal sealed class TestHostOrchestratorManager : global::Microsoft.Testing.Platform.TestHostOrchestrator.TestHostOrchestratorManager; +internal sealed class TestHostOrchestratorManager : global::Microsoft.Testing.Platform.TestHostOrchestrator.TestHostOrchestratorManager +{ + // Old extensions call this method directly on the concrete type (not through an interface). + // The base class only has AddTestHostOrchestrator(Func<..., ITestHostExecutionOrchestrator>), + // so we need this overload to match the old signature with ITestHostOrchestrator. + public void AddTestHostOrchestrator(Func factory) + => base.AddTestHostOrchestrator(factory); +}