From f6a8f02a349fca4a8b96a374b131dcec18a254b2 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Sun, 12 Jan 2025 08:14:47 +0100 Subject: [PATCH] Fix DynamicData.GetData regression preventing it to work without adapter --- .../PlatformServiceProvider.cs | 13 +-- .../Resources/Resource.Designer.cs | 9 -- .../Resources/Resource.resx | 3 - .../Resources/xlf/Resource.cs.xlf | 5 - .../Resources/xlf/Resource.de.xlf | 5 - .../Resources/xlf/Resource.es.xlf | 5 - .../Resources/xlf/Resource.fr.xlf | 5 - .../Resources/xlf/Resource.it.xlf | 5 - .../Resources/xlf/Resource.ja.xlf | 5 - .../Resources/xlf/Resource.ko.xlf | 5 - .../Resources/xlf/Resource.pl.xlf | 5 - .../Resources/xlf/Resource.pt-BR.xlf | 5 - .../Resources/xlf/Resource.ru.xlf | 5 - .../Resources/xlf/Resource.tr.xlf | 5 - .../Resources/xlf/Resource.zh-Hans.xlf | 5 - .../Resources/xlf/Resource.zh-Hant.xlf | 5 - .../SourceGeneratedDynamicDataOperations.cs | 6 -- .../DataSource/DynamicDataAttribute.cs | 2 +- .../DataSource}/DynamicDataOperations.cs | 25 ++--- .../DataSource/DynamicDataProvider.cs | 16 --- .../DataSource/IDynamicDataOperations.cs | 11 --- .../Resources/FrameworkMessages.Designer.cs | 9 ++ .../Resources/FrameworkMessages.resx | 5 +- .../Resources/xlf/FrameworkMessages.cs.xlf | 5 + .../Resources/xlf/FrameworkMessages.de.xlf | 5 + .../Resources/xlf/FrameworkMessages.es.xlf | 5 + .../Resources/xlf/FrameworkMessages.fr.xlf | 5 + .../Resources/xlf/FrameworkMessages.it.xlf | 5 + .../Resources/xlf/FrameworkMessages.ja.xlf | 5 + .../Resources/xlf/FrameworkMessages.ko.xlf | 5 + .../Resources/xlf/FrameworkMessages.pl.xlf | 5 + .../Resources/xlf/FrameworkMessages.pt-BR.xlf | 5 + .../Resources/xlf/FrameworkMessages.ru.xlf | 5 + .../Resources/xlf/FrameworkMessages.tr.xlf | 5 + .../xlf/FrameworkMessages.zh-Hans.xlf | 5 + .../xlf/FrameworkMessages.zh-Hant.xlf | 5 + .../FrameworkOnlyTests.cs | 97 +++++++++++++++++++ .../DynamicDataAttributeTests.cs | 2 +- .../TestablePlatformServiceProvider.cs | 3 - 39 files changed, 193 insertions(+), 138 deletions(-) delete mode 100644 src/Adapter/MSTest.TestAdapter/SourceGeneratedDynamicDataOperations.cs rename src/{Adapter/MSTest.TestAdapter => TestFramework/TestFramework/Attributes/DataSource}/DynamicDataOperations.cs (89%) delete mode 100644 src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataProvider.cs delete mode 100644 src/TestFramework/TestFramework/Attributes/DataSource/IDynamicDataOperations.cs create mode 100644 test/IntegrationTests/MSTest.Acceptance.IntegrationTests/FrameworkOnlyTests.cs diff --git a/src/Adapter/MSTest.TestAdapter/PlatformServiceProvider.cs b/src/Adapter/MSTest.TestAdapter/PlatformServiceProvider.cs index 1ad6cc37b1..da2c4da789 100644 --- a/src/Adapter/MSTest.TestAdapter/PlatformServiceProvider.cs +++ b/src/Adapter/MSTest.TestAdapter/PlatformServiceProvider.cs @@ -23,16 +23,9 @@ internal sealed class PlatformServiceProvider : IPlatformServiceProvider /// /// Initializes a new instance of the class - a singleton. /// - private PlatformServiceProvider() => -#if !WINDOWS_UWP - // Set the provider that is used by DynamicDataAttribute when generating data, to allow substituting functionality - // in TestFramework without having to put all the stuff in that library. - UTF.DynamicDataProvider.Instance = SourceGeneratorToggle.UseSourceGenerator - ? new SourceGeneratedDynamicDataOperations() - : new DynamicDataOperations(); -#else - UTF.DynamicDataProvider.Instance = new DynamicDataOperations(); -#endif + private PlatformServiceProvider() + { + } /// /// Gets an instance to the platform service validator for test sources. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/Resource.Designer.cs b/src/Adapter/MSTest.TestAdapter/Resources/Resource.Designer.cs index d459e481e5..c36dc6047b 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/Resource.Designer.cs +++ b/src/Adapter/MSTest.TestAdapter/Resources/Resource.Designer.cs @@ -242,15 +242,6 @@ internal static string DuplicateConfigurationError { } } - /// - /// Looks up a localized string similar to The dynamic data source '{0}' in type '{1}' should exist and be a property or a method.. - /// - internal static string DynamicDataSourceShouldExistAndBeValid { - get { - return ResourceManager.GetString("DynamicDataSourceShouldExistAndBeValid", resourceCulture); - } - } - /// /// Looks up a localized string similar to {0}: {1}. /// diff --git a/src/Adapter/MSTest.TestAdapter/Resources/Resource.resx b/src/Adapter/MSTest.TestAdapter/Resources/Resource.resx index fba272ebdf..5114079ad8 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/Resource.resx +++ b/src/Adapter/MSTest.TestAdapter/Resources/Resource.resx @@ -414,7 +414,4 @@ but received {4} argument(s), with types '{5}'. Found two conflicting types for generic parameter '{0}'. The conflicting types are '{1}' and '{2}'. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - \ No newline at end of file diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.cs.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.cs.xlf index 0e1defb645..b617109aa8 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.cs.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.cs.xlf @@ -61,11 +61,6 @@ byl však přijat tento počet argumentů: {4} s typy {5}. Byly zjištěny soubory .runsettings i .testconfig.json. Vyberte prosím jenom jeden z těchto souborů konfigurace testu. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - Dynamický zdroj dat '{0}' v typu '{1}' by měl existovat a být vlastností nebo metodou. - - Test '{0}' timed out after {1}ms Časový limit '{0}' testu vypršel po {1}ms. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.de.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.de.xlf index 4f563a2f9d..63d2badfb1 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.de.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.de.xlf @@ -61,11 +61,6 @@ aber empfing {4} Argument(e) mit den Typen „{5}“. Es wurden sowohl die Dateien „.runsettings“ als auch „.testconfig.json“ erkannt. Wählen Sie nur eine dieser Testkonfigurationsdateien aus. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - Die dynamische Datenquelle '{0}' im Typ '{1}' muss vorhanden sein und eine Eigenschaft oder Methode sein. - - Test '{0}' timed out after {1}ms Timeout bei test '{0}' nach {1}ms. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.es.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.es.xlf index a7665e8fe1..e154ea5b8f 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.es.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.es.xlf @@ -61,11 +61,6 @@ pero recibió {4} argumento(s), con los tipos "{5}". Se han detectado los archivos ".runsettings" y ".testconfig.json". Seleccione solo uno de estos archivos de configuración de prueba. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - El origen de datos dinámico '{0}' en el tipo '{1}' debe existir y ser una propiedad o un método. - - Test '{0}' timed out after {1}ms Se agotó el tiempo de espera de la '{0}' de pruebas después de {1}ms diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.fr.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.fr.xlf index 908df3801d..297db55777 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.fr.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.fr.xlf @@ -61,11 +61,6 @@ mais a reçu {4} argument(s), avec les types « {5} ». Les fichiers « .runsettings » et « .testconfig.json » ont été détectés. Veuillez sélectionner un seul de ces fichiers de configuration de test. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - La source de données dynamique '{0}' dans le type '{1}' doit exister et être une propriété ou une méthode. - - Test '{0}' timed out after {1}ms Délai de '{0}' de test dépassé après {1}ms diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.it.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.it.xlf index 4bbe3658f6..6400699fe3 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.it.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.it.xlf @@ -61,11 +61,6 @@ ma ha ricevuto {4} argomenti, con tipi "{5}". Sono stati rilevati sia i file '.runsettings' sia '.testconfig.json'. Selezionare solo uno di questi file di configurazione di test. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - L'origine dati dinamica '{0}' nel tipo '{1}' deve esistere ed essere una proprietà o un metodo. - - Test '{0}' timed out after {1}ms Timeout del '{0}' di test dopo {1}ms diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ja.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ja.xlf index f33a668f43..0653992bae 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ja.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ja.xlf @@ -62,11 +62,6 @@ but received {4} argument(s), with types '{5}'. '.runsettings' ファイルと '.testconfig.json' ファイルの両方が検出されました。これらのテスト構成ファイルのいずれか 1 つだけを選択してください。 - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - 型 '{1}' の動的データ ソース '{0}' は、プロパティまたはメソッドである必要があります。 - - Test '{0}' timed out after {1}ms テスト '{0}' が {1}ミリ秒後にタイムアウトしました diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ko.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ko.xlf index 83f037d230..8ba4f31f0d 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ko.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ko.xlf @@ -61,11 +61,6 @@ but received {4} argument(s), with types '{5}'. '.runsettings' 및 '.testconfig.json' 파일이 모두 검색되었습니다. 이러한 테스트 구성 파일 중 하나만 선택하세요. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - '{1}' 형식의 동적 데이터 원본 '{0}' 존재하며 속성 또는 메서드여야 합니다. - - Test '{0}' timed out after {1}ms 테스트 '{0}' {1}밀리초 후에 시간 초과되었습니다. diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pl.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pl.xlf index 4889dce291..64cabef2cc 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pl.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pl.xlf @@ -61,11 +61,6 @@ ale liczba odebranych argumentów to {4} z typami „{5}”. Wykryto zarówno pliki „.runsettings”, jak i „.testconfig.json”. Wybierz tylko jeden z tych plików konfiguracji testu. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - Dynamiczne źródło danych '{0}' w typie '{1}' powinno istnieć i być właściwością lub metodą. - - Test '{0}' timed out after {1}ms Upłynął limit czasu '{0}' testu po {1}ms diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pt-BR.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pt-BR.xlf index 25daeea3dc..ba1846f2b2 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pt-BR.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.pt-BR.xlf @@ -61,11 +61,6 @@ mas {4} argumentos recebidos, com tipos '{5}'. Ambos os arquivos '.runsettings' e '.testconfig.json' foram detectados. Selecione apenas um desses arquivos de configuração de teste. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - A fonte de dados dinâmica '{0}' no tipo '{1}' deve existir e ser uma propriedade ou um método. - - Test '{0}' timed out after {1}ms Tempo '{0}' tempo limite do teste após {1}ms diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ru.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ru.xlf index ce2e4f5ef3..e0288f0d0f 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ru.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.ru.xlf @@ -61,11 +61,6 @@ but received {4} argument(s), with types '{5}'. Обнаружены файлы ".runsettings" и ".testconfig.json". Выберите только один из этих файлов тестовой конфигурации. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - Динамический источник '{0}' в типе '{1}' должен существовать и быть свойством или методом. - - Test '{0}' timed out after {1}ms Время ожидания '{0}' истекло через {1}мс diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.tr.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.tr.xlf index 255dbab729..4b00fbda3a 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.tr.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.tr.xlf @@ -61,11 +61,6 @@ ancak, '{5}' türüyle {4} argüman aldı. Hem '.runsettings' hem de '.testconfig.json' dosyaları algılandı. Lütfen bu test yapılandırma dosyalarından yalnızca birini seçin. - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - Dinamik veri kaynağı '{0}' türdeki '{1}' bir özellik veya yöntem olmalıdır. - - Test '{0}' timed out after {1}ms Test '{0}' ms sonra zaman aşımına {1}oldu diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hans.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hans.xlf index c8617c0588..6a3fcfd0a4 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hans.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hans.xlf @@ -61,11 +61,6 @@ but received {4} argument(s), with types '{5}'. 检测到 ".runsettings" 和 ".testconfig.json" 文件。请仅选择其中一个测试配置文件。 - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - 类型 '{1}' 中的动态数据源 '{0}' 应存在,并且应为属性或方法。 - - Test '{0}' timed out after {1}ms 测试 '{0}' 在 {1}毫秒后超时 diff --git a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hant.xlf b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hant.xlf index 6943b4e708..c18f1e45a9 100644 --- a/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hant.xlf +++ b/src/Adapter/MSTest.TestAdapter/Resources/xlf/Resource.zh-Hant.xlf @@ -61,11 +61,6 @@ but received {4} argument(s), with types '{5}'. 偵測到 '.runsettings' 和 '.testconfig.json' 檔案。請只選取其中一個測試設定檔。 - - The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. - 類型 '{1}' 中的動態數據源 '{0}' 應該存在,而且必須是屬性或方法。 - - Test '{0}' timed out after {1}ms 測試 '{0}' 在 {1}毫秒後逾時 diff --git a/src/Adapter/MSTest.TestAdapter/SourceGeneratedDynamicDataOperations.cs b/src/Adapter/MSTest.TestAdapter/SourceGeneratedDynamicDataOperations.cs deleted file mode 100644 index 9ea21161d0..0000000000 --- a/src/Adapter/MSTest.TestAdapter/SourceGeneratedDynamicDataOperations.cs +++ /dev/null @@ -1,6 +0,0 @@ -// 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.VisualStudio.TestPlatform.MSTest.TestAdapter; - -internal sealed class SourceGeneratedDynamicDataOperations : DynamicDataOperations; diff --git a/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataAttribute.cs b/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataAttribute.cs index 370ab10af2..be069e817d 100644 --- a/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataAttribute.cs +++ b/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataAttribute.cs @@ -121,7 +121,7 @@ public DynamicDataAttribute(string dynamicDataSourceName, Type dynamicDataDeclar /// public IEnumerable GetData(MethodInfo methodInfo) - => DynamicDataProvider.Instance.GetData(_dynamicDataDeclaringType, _dynamicDataSourceType, _dynamicDataSourceName, methodInfo); + => DynamicDataOperations.GetData(_dynamicDataDeclaringType, _dynamicDataSourceType, _dynamicDataSourceName, methodInfo); /// public string? GetDisplayName(MethodInfo methodInfo, object?[]? data) diff --git a/src/Adapter/MSTest.TestAdapter/DynamicDataOperations.cs b/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataOperations.cs similarity index 89% rename from src/Adapter/MSTest.TestAdapter/DynamicDataOperations.cs rename to src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataOperations.cs index 954b9b435e..0fed3d7239 100644 --- a/src/Adapter/MSTest.TestAdapter/DynamicDataOperations.cs +++ b/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataOperations.cs @@ -1,13 +1,13 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// 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.VisualStudio.TestTools.UnitTesting; +namespace Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter; - -internal class DynamicDataOperations : IDynamicDataOperations +internal static class DynamicDataOperations { - public IEnumerable GetData(Type? _dynamicDataDeclaringType, DynamicDataSourceType _dynamicDataSourceType, string _dynamicDataSourceName, MethodInfo methodInfo) + private const BindingFlags DeclaredOnlyLookup = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; + + public static IEnumerable GetData(Type? _dynamicDataDeclaringType, DynamicDataSourceType _dynamicDataSourceType, string _dynamicDataSourceName, MethodInfo methodInfo) { // Check if the declaring type of test data is passed in. If not, default to test method's class type. _dynamicDataDeclaringType ??= methodInfo.DeclaringType; @@ -29,7 +29,7 @@ public IEnumerable GetData(Type? _dynamicDataDeclaringType, DynamicDat } else { - throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Resource.DynamicDataSourceShouldExistAndBeValid, _dynamicDataSourceName, _dynamicDataDeclaringType.FullName)); + throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, FrameworkMessages.DynamicDataSourceShouldExistAndBeValid, _dynamicDataSourceName, _dynamicDataDeclaringType.FullName)); } #pragma warning restore IDE0045 // Convert to conditional expression @@ -105,15 +105,14 @@ public IEnumerable GetData(Type? _dynamicDataDeclaringType, DynamicDat return property.GetValue(null, null); } - /// - public string? GetDisplayName(string? DynamicDataDisplayName, Type? DynamicDataDisplayNameDeclaringType, MethodInfo methodInfo, object?[]? data) + public static string? GetDisplayName(string? DynamicDataDisplayName, Type? DynamicDataDisplayNameDeclaringType, MethodInfo methodInfo, object?[]? data) { if (DynamicDataDisplayName != null) { Type? dynamicDisplayNameDeclaringType = DynamicDataDisplayNameDeclaringType ?? methodInfo.DeclaringType; DebugEx.Assert(dynamicDisplayNameDeclaringType is not null, "Declaring type of test data cannot be null."); - MethodInfo method = PlatformServiceProvider.Instance.ReflectionOperations.GetDeclaredMethod(dynamicDisplayNameDeclaringType, DynamicDataDisplayName) + MethodInfo method = dynamicDisplayNameDeclaringType.GetMethod(DynamicDataDisplayName, DeclaredOnlyLookup) ?? throw new ArgumentNullException($"{DynamicDataSourceType.Method} {DynamicDataDisplayName}"); ParameterInfo[] parameters = method.GetParameters(); return parameters.Length != 2 || @@ -235,6 +234,7 @@ private static bool IsTupleOrValueTuple(Type type, out int tupleSize) return true; } +#if !NET462 // TODO: Add dependency on System.ValueTuple for net462? if (genericTypeDefinition == typeof(ValueTuple<>) || genericTypeDefinition == typeof(ValueTuple<,>) || genericTypeDefinition == typeof(ValueTuple<,,>) || @@ -247,6 +247,7 @@ private static bool IsTupleOrValueTuple(Type type, out int tupleSize) tupleSize = type.GetGenericArguments().Length; return true; } +#endif return false; } @@ -258,7 +259,7 @@ private static bool IsTupleOrValueTuple(Type type, out int tupleSize) Type? currentType = type; while (currentType is not null) { - PropertyInfo? property = PlatformServiceProvider.Instance.ReflectionOperations.GetDeclaredProperty(currentType, propertyName); + PropertyInfo? property = currentType.GetProperty(propertyName, DeclaredOnlyLookup); if (property is not null) { return property; @@ -276,7 +277,7 @@ private static bool IsTupleOrValueTuple(Type type, out int tupleSize) Type? currentType = type; while (currentType is not null) { - MethodInfo? method = PlatformServiceProvider.Instance.ReflectionOperations.GetDeclaredMethod(currentType, methodName); + MethodInfo? method = currentType.GetMethod(methodName, DeclaredOnlyLookup); if (method is not null) { return method; diff --git a/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataProvider.cs b/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataProvider.cs deleted file mode 100644 index 6b04212aa6..0000000000 --- a/src/TestFramework/TestFramework/Attributes/DataSource/DynamicDataProvider.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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.VisualStudio.TestTools.UnitTesting; - -internal static class DynamicDataProvider -{ - [field: MaybeNull] - public static IDynamicDataOperations Instance - { - get => field - ?? throw new InvalidOperationException($"Dynamic data provider is not set, it should be set by MSTest adapter. " + - $"If you are seeing this error, you are using Test Framework without Test Adapter, and your adapter should set {nameof(DynamicDataProvider)}.{nameof(Instance)}. In MSTestAdapter, this happens when PlatformServiceProvider.Instance is called."); - internal set; - } -} diff --git a/src/TestFramework/TestFramework/Attributes/DataSource/IDynamicDataOperations.cs b/src/TestFramework/TestFramework/Attributes/DataSource/IDynamicDataOperations.cs deleted file mode 100644 index e865440d94..0000000000 --- a/src/TestFramework/TestFramework/Attributes/DataSource/IDynamicDataOperations.cs +++ /dev/null @@ -1,11 +0,0 @@ -// 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.VisualStudio.TestTools.UnitTesting; - -internal interface IDynamicDataOperations -{ - IEnumerable GetData(Type? dynamicDataDeclaringType, DynamicDataSourceType dynamicDataSourceType, string dynamicDataSourceName, MethodInfo methodInfo); - - string? GetDisplayName(string? displayName, Type? dynamicDataDisplayNameDeclaringType, MethodInfo methodInfo, object?[]? data); -} diff --git a/src/TestFramework/TestFramework/Resources/FrameworkMessages.Designer.cs b/src/TestFramework/TestFramework/Resources/FrameworkMessages.Designer.cs index 9fd4712ea7..df3ee2d2b0 100644 --- a/src/TestFramework/TestFramework/Resources/FrameworkMessages.Designer.cs +++ b/src/TestFramework/TestFramework/Resources/FrameworkMessages.Designer.cs @@ -321,6 +321,15 @@ internal static string DynamicDataInvalidPropertyLayout { } } + /// + /// Looks up a localized string similar to The dynamic data source '{0}' in type '{1}' should exist and be a property or a method.. + /// + internal static string DynamicDataSourceShouldExistAndBeValid { + get { + return ResourceManager.GetString("DynamicDataSourceShouldExistAndBeValid", resourceCulture); + } + } + /// /// Looks up a localized string similar to Value returned by property or method {0} shouldn't be null.. /// diff --git a/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx b/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx index dd36b5c2f8..77056ad096 100644 --- a/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx +++ b/src/TestFramework/TestFramework/Resources/FrameworkMessages.resx @@ -287,4 +287,7 @@ Actual: {2} Dynamic data property '{0}' should be static and have a getter. - + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + \ No newline at end of file diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf index efcae52e82..0de5837b52 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.cs.xlf @@ -92,6 +92,11 @@ Vlastnost dynamických dat {0} by měla být statická a měla by mít metodu getter. + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} Počet elementů v kolekcích nesouhlasí. Očekáváno:<{1}>. Aktuálně:<{2}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf index 57407eec58..6859acd7ff 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.de.xlf @@ -92,6 +92,11 @@ Die dynamische Dateneigenschaft "{0}" muss statisch sein und über einen Getter verfügen. + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} Die Anzahl der Elemente in den Sammlungen stimmt nicht überein. Erwartet: <{1}>. Tatsächlich: <{2}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf index 8a290bc795..c91aa3614e 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.es.xlf @@ -92,6 +92,11 @@ La propiedad de datos dinámicos '{0}' debe ser estática y tener un captador. + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} El número de elementos de las colecciones no coincide. Se esperaba:<{1}>, pero es:<{2}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf index 18dbed07b6..c2de59379f 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.fr.xlf @@ -92,6 +92,11 @@ La propriété de données dynamiques « {0} » doit être statique et avoir un getter. + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} Le nombre d'éléments dans les collections ne correspond pas. Attendu : <{1}>, Réel : <{2}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf index 1006368d73..29f222d24c 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.it.xlf @@ -92,6 +92,11 @@ La proprietà '{0}' di Dynamic Data deve essere statica e avere un getter. + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} Il numero di elementi nelle raccolte non corrisponde. Previsto:<{1}>. Effettivo:<{2}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf index b58f7b2049..71fc16e5d1 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ja.xlf @@ -92,6 +92,11 @@ 動的データ プロパティ '{0}' は静的であり、ゲッターを持つ必要があります。 + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} コレクション内の要素数が一致しません。<{1}> が必要ですが <{2}> が指定されています。{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf index fe070e4435..174c7e0be7 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ko.xlf @@ -92,6 +92,11 @@ 동적 데이터 속성 '{0}'은(는) 정적이고 getter가 있어야 합니다. + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} 컬렉션의 요소 수가 일치하지 않습니다. 예상 값: <{1}>. 실제 값: <{2}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf index e4b1caef63..8edbd520a3 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pl.xlf @@ -92,6 +92,11 @@ Właściwość danych dynamicznych „{0}” powinna być statyczna i mieć metodę pobierającą. + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} Nie zgadza się liczba elementów w kolekcji. Oczekiwana:<{1}>. Rzeczywista:<{2}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf index 9adbd43bab..38d1801195 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.pt-BR.xlf @@ -92,6 +92,11 @@ A propriedade de dados dinâmicos "{0}" deve ser estática e ter um getter. + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} O número de elementos nas coleções não coincidem. Esperado:<{1}>. Real:<{2}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf index 5c4480127b..8ea5f13c12 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.ru.xlf @@ -92,6 +92,11 @@ Свойство динамических данных "{0}" должно быть статическим и иметь метод получения. + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} Число элементов в наборе не соответствует ожидаемому. Ожидается: <{1}>. Фактически: <{2}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf index b6bd361bb9..c81c9e1889 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.tr.xlf @@ -92,6 +92,11 @@ '{0}' dinamik veri özelliği statik olmalı ve bir alıcı içermelidir. + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} Koleksiyonlar içindeki öğe sayıları eşleşmiyor. Beklenen:<{1}>. Gerçek:<{2}>.{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf index 3743d96cd0..131e0640a4 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hans.xlf @@ -92,6 +92,11 @@ 动态数据属性“{0}”应为静态且具有 getter。 + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} 集合中元素的数量不匹配。应为: <{1}>,实际为: <{2}>。{0} diff --git a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf index 8ab05baa18..d454beb4f6 100644 --- a/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf +++ b/src/TestFramework/TestFramework/Resources/xlf/FrameworkMessages.zh-Hant.xlf @@ -92,6 +92,11 @@ 動態資料屬性 '{0}' 應為靜態且具有 getter。 + + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + The dynamic data source '{0}' in type '{1}' should exist and be a property or a method. + + The number of elements in the collections do not match. Expected:<{1}>. Actual:<{2}>.{0} 集合中的項目數目不符。預期: <{1}>。實際: <{2}>。{0} diff --git a/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/FrameworkOnlyTests.cs b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/FrameworkOnlyTests.cs new file mode 100644 index 0000000000..097353fecc --- /dev/null +++ b/test/IntegrationTests/MSTest.Acceptance.IntegrationTests/FrameworkOnlyTests.cs @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.Testing.Platform.Acceptance.IntegrationTests; +using Microsoft.Testing.Platform.Acceptance.IntegrationTests.Helpers; +using Microsoft.Testing.Platform.Helpers; + +namespace MSTest.Acceptance.IntegrationTests; + +[TestClass] +public class FrameworkOnlyTests : AcceptanceTestBase +{ + private const string AssetName = nameof(FrameworkOnlyTests); + + [TestMethod] + public async Task DynamicDataAttributeGetDataShouldWorkWithoutAdapter() + { + // This is an important scenario to not regress. + // Users shouldn't need to reference adapter, nor do anything + // special, to be able to call DynamicData.GetData. + var testHost = TestHost.LocateFrom(AssetFixture.TargetAssetPath, AssetName, TargetFrameworks.NetCurrent); + TestHostResult testHostResult = await testHost.ExecuteAsync(); + testHostResult.AssertOutputContains(""" + 1,2 + 3,4 + """); + + testHostResult.AssertExitCodeIs(ExitCodes.Success); + } + + public sealed class TestAssetFixture() : TestAssetFixtureBase(AcceptanceFixture.NuGetGlobalPackagesFolder) + { + private const string Sources = """ +#file FrameworkOnlyTests.csproj + + + $TargetFrameworks$ + Exe + + + + + + + +#file Program.cs + +using System; +using System.Reflection; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +var methodInfo = typeof(UnitTest1).GetMethod("TestMethod1"); +if (methodInfo.GetCustomAttribute() is not { } dynamicData) +{ + Console.WriteLine("Error: Cannot find DynamicDataAttribute"); + return; +} + +var data = dynamicData.GetData(methodInfo); +foreach (var row in data) +{ + Console.WriteLine(string.Join(',', row)); +} + +#file TestClass1.cs +using System.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +[TestClass] +public class UnitTest1 +{ + [TestMethod] + [DynamicData(nameof(Data))] + public void TestMethod1() + { + } + + public static IEnumerable Data { get; } + = new[] + { + new object[] { 1, 2 }, + new object[] { 3, 4 } + }; +} +"""; + + public string TargetAssetPath => GetAssetPath(AssetName); + + public override IEnumerable<(string ID, string Name, string Code)> GetAssetsToGenerate() + { + yield return (AssetName, AssetName, + Sources + .PatchTargetFrameworks(TargetFrameworks.NetCurrent) + .PatchCodeWithReplace("$MSTestVersion$", MSTestVersion)); + } + } +} diff --git a/test/UnitTests/MSTestAdapter.UnitTests/DynamicDataAttributeTests.cs b/test/UnitTests/MSTestAdapter.UnitTests/DynamicDataAttributeTests.cs index 5993212f62..3aebaf4a6d 100644 --- a/test/UnitTests/MSTestAdapter.UnitTests/DynamicDataAttributeTests.cs +++ b/test/UnitTests/MSTestAdapter.UnitTests/DynamicDataAttributeTests.cs @@ -29,7 +29,7 @@ public void GetDataShouldThrowExceptionIfInvalidPropertyNameIsSpecifiedOrPropert { _dynamicDataAttribute = new DynamicDataAttribute("ABC"); InvalidOperationException ex = VerifyThrows(() => _dynamicDataAttribute.GetData(_testMethodInfo)); - Verify(ex.Message == string.Format(CultureInfo.InvariantCulture, Resource.DynamicDataSourceShouldExistAndBeValid, "ABC", _testMethodInfo.DeclaringType.FullName)); + Verify(ex.Message == string.Format(CultureInfo.InvariantCulture, FrameworkMessages.DynamicDataSourceShouldExistAndBeValid, "ABC", _testMethodInfo.DeclaringType.FullName)); } public void GetDataShouldReadDataFromProperty() diff --git a/test/UnitTests/MSTestAdapter.UnitTests/TestableImplementations/TestablePlatformServiceProvider.cs b/test/UnitTests/MSTestAdapter.UnitTests/TestableImplementations/TestablePlatformServiceProvider.cs index 5f9bec282d..d747410ba1 100644 --- a/test/UnitTests/MSTestAdapter.UnitTests/TestableImplementations/TestablePlatformServiceProvider.cs +++ b/test/UnitTests/MSTestAdapter.UnitTests/TestableImplementations/TestablePlatformServiceProvider.cs @@ -27,9 +27,6 @@ public TestablePlatformServiceProvider() MockTraceListener = new Mock(); MockTraceListenerManager = new Mock(); MockThreadOperations = new Mock(); - UTF.DynamicDataProvider.Instance = SourceGeneratorToggle.UseSourceGenerator - ? new SourceGeneratedDynamicDataOperations() - : new DynamicDataOperations(); } #region Mock Implementations