diff --git a/NuGet.config b/NuGet.config index 0261f95fd9..d42940ea76 100644 --- a/NuGet.config +++ b/NuGet.config @@ -8,15 +8,16 @@ + + + + + + - - - - - diff --git a/TestPlatform.sln b/TestPlatform.sln index cd278af64a..26a8b21bb6 100644 --- a/TestPlatform.sln +++ b/TestPlatform.sln @@ -159,6 +159,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TestPlatform.Exte EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "coverlet.collector", "test\coverlet.collector\coverlet.collector.csproj", "{074F5BD6-DC05-460B-B78F-044D125FD787}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests", "test\Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests\Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests.csproj", "{DCD0C39E-C78C-4A44-B0BD-7325254A2E97}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -781,6 +783,18 @@ Global {074F5BD6-DC05-460B-B78F-044D125FD787}.Release|x64.Build.0 = Release|Any CPU {074F5BD6-DC05-460B-B78F-044D125FD787}.Release|x86.ActiveCfg = Release|Any CPU {074F5BD6-DC05-460B-B78F-044D125FD787}.Release|x86.Build.0 = Release|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Debug|x64.ActiveCfg = Debug|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Debug|x64.Build.0 = Debug|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Debug|x86.ActiveCfg = Debug|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Debug|x86.Build.0 = Debug|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Release|Any CPU.Build.0 = Release|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Release|x64.ActiveCfg = Release|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Release|x64.Build.0 = Release|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Release|x86.ActiveCfg = Release|Any CPU + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -849,6 +863,7 @@ Global {236A71E3-01DA-4679-9DFF-16A8E079ACFF} = {5E7F18A8-F843-4C8A-AB02-4C7D9205C6CF} {41248B96-6E15-4E5E-A78F-859897676814} = {020E15EA-731F-4667-95AF-226671E0C3AE} {074F5BD6-DC05-460B-B78F-044D125FD787} = {B27FAFDF-2DBA-4AB0-BA85-FD5F21D359D6} + {DCD0C39E-C78C-4A44-B0BD-7325254A2E97} = {B27FAFDF-2DBA-4AB0-BA85-FD5F21D359D6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0541B30C-FF51-4E28-B172-83F5F3934BCD} diff --git a/eng/Versions.props b/eng/Versions.props index 88e3350788..dfd644bdf1 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -75,5 +75,11 @@ 1.0.0-beta2-19554-01 1.0.0-beta.20567.6 1.0.0-beta.20055.1 + + + + 3.8.0-3.20427.2 diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 15150b7ada..bed8cb90d8 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -32,15 +32,15 @@ Param( [Parameter(Mandatory=$false)] [Alias("noloc")] - [Switch] $DisableLocalizedBuild = $false, + [Switch] $DisableLocalizedBuild, [Parameter(Mandatory=$false)] [Alias("ci")] - [Switch] $CIBuild = $false, + [Switch] $CIBuild, [Parameter(Mandatory=$false)] [Alias("pt")] - [Switch] $PublishTestArtifacts = $false, + [Switch] $PublishTestArtifacts, # Build specific projects [Parameter(Mandatory=$false)] @@ -119,7 +119,7 @@ $language = @("cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr # Capture error state in any step globally to modify return code $Script:ScriptFailed = $false -Import-Module "$($CurrentScriptDir.FullName)\verify-nupkgs.ps1" +Import-Module -Name "$($CurrentScriptDir.FullName)\verify-nupkgs.ps1" -Scope Local # Update the version in the dependencies props to be the TPB_version version, this is not ideal but because changing how this is resolved would # mean that we need to change the whole build process this is a solution with the least amount of impact, that does not require us to keep track of @@ -253,7 +253,6 @@ function Invoke-TestAssetsBuild Write-Log "Invoke-TestAssetsBuild: Start test assets build." $dotnetExe = Get-DotNetPath - Write-Log ".. .. Build: Source: $TPB_TestAssets_Solution" Write-Verbose "$dotnetExe build $TPB_TestAssets_Solution --configuration $TPB_Configuration -v:minimal -p:Version=$TPB_Version -p:CIBuild=$TPB_CIBuild" & $dotnetExe build $TPB_TestAssets_Solution --configuration $TPB_Configuration -v:minimal -p:CIBuild=$TPB_CIBuild -p:LocalizedBuild=$TPB_LocalizedBuild -bl:"$($env:TP_ROOT_DIR)\TestAssets.binlog" diff --git a/scripts/verify-nupkgs.ps1 b/scripts/verify-nupkgs.ps1 index 89ebfbc28b..55402d48a8 100644 --- a/scripts/verify-nupkgs.ps1 +++ b/scripts/verify-nupkgs.ps1 @@ -8,7 +8,6 @@ function Unzip [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath) } - function Verify-Nuget-Packages($packageDirectory) { Write-Log "Starting Verify-Nuget-Packages." @@ -59,4 +58,4 @@ function Verify-Nuget-Packages($packageDirectory) } Write-Log "Completed Verify-Nuget-Packages." -} +} \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Extensions/ReflectionExtensions.MethodBase.cs b/src/Microsoft.TestPlatform.CoreUtilities/Extensions/ReflectionExtensions.MethodBase.cs new file mode 100644 index 0000000000..5e20bad1bd --- /dev/null +++ b/src/Microsoft.TestPlatform.CoreUtilities/Extensions/ReflectionExtensions.MethodBase.cs @@ -0,0 +1,56 @@ +// 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.PlatformAbstractions.Extensions +{ + using System; + using System.Reflection; + + public static partial class ReflectionExtensions + { +#if NETSTANDARD1_0 || NETSTANDARD1_3 || WINDOWS_UWP + private static readonly Type methodBase = typeof(MethodBase); + + private const string MemberTypePropertyName = "MemberType"; + private const string ReflectedTypePropertyName = "ReflectedType"; + private const string MethodHandlePropertyName = "MethodHandle"; + + private static readonly PropertyInfo memberTypeProperty = methodBase.GetRuntimeProperty(MemberTypePropertyName); + private static readonly PropertyInfo reflectedTypeProperty = methodBase.GetRuntimeProperty(ReflectedTypePropertyName); + private static readonly PropertyInfo methodHandleProperty = methodBase.GetRuntimeProperty(MethodHandlePropertyName); +#endif + + public static bool IsMethod(this MethodBase method) + { +#if !NETSTANDARD1_0 && !NETSTANDARD1_3 && !WINDOWS_UWP + return method.MemberType == MemberTypes.Method; +#else + AssertSupport(memberTypeProperty, MemberTypePropertyName, methodBase.FullName); + + return (int)memberTypeProperty.GetValue(method) == 8; +#endif + } + + public static Type GetReflectedType(this MethodBase method) + { +#if !NETSTANDARD1_0 && !NETSTANDARD1_3 && !WINDOWS_UWP + return method.ReflectedType; +#else + AssertSupport(memberTypeProperty, ReflectedTypePropertyName, methodBase.FullName); + + return reflectedTypeProperty.GetValue(method) as Type; +#endif + } + + public static RuntimeMethodHandle GetMethodHandle(this MethodBase method) + { +#if !NETSTANDARD1_0 && !NETSTANDARD1_3 && !WINDOWS_UWP + return method.MethodHandle; +#else + AssertSupport(memberTypeProperty, MethodHandlePropertyName, methodBase.FullName); + + return (RuntimeMethodHandle)methodHandleProperty.GetValue(method); +#endif + } + } +} diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Extensions/ReflectionExtensions.Type.cs b/src/Microsoft.TestPlatform.CoreUtilities/Extensions/ReflectionExtensions.Type.cs new file mode 100644 index 0000000000..65670afd06 --- /dev/null +++ b/src/Microsoft.TestPlatform.CoreUtilities/Extensions/ReflectionExtensions.Type.cs @@ -0,0 +1,29 @@ +// 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.PlatformAbstractions.Extensions +{ + using System; + using System.Reflection; + + public static partial class ReflectionExtensions + { + public static bool IsGenericType(this Type type) + { +#if !NETSTANDARD1_0 && !NETSTANDARD1_3 && !WINDOWS_UWP + return type.IsGenericType; +#else + return type.GetTypeInfo().IsGenericType; +#endif + } + + public static MethodBase GetDeclaringMethod(this Type type) + { +#if !NETSTANDARD1_0 && !NETSTANDARD1_3 && !WINDOWS_UWP + return type.DeclaringMethod; +#else + return type.GetTypeInfo().DeclaringMethod; +#endif + } + } +} diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Extensions/ReflectionExtensions.cs b/src/Microsoft.TestPlatform.CoreUtilities/Extensions/ReflectionExtensions.cs new file mode 100644 index 0000000000..010567f0eb --- /dev/null +++ b/src/Microsoft.TestPlatform.CoreUtilities/Extensions/ReflectionExtensions.cs @@ -0,0 +1,21 @@ +// 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.PlatformAbstractions.Extensions +{ + using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Resources; + + using System; + + public static partial class ReflectionExtensions + { + private static void AssertSupport(T obj, string methodName, string className) + where T : class + { + if (obj == null) + { + throw new NotImplementedException(string.Format(Resources.MethodNotImplementedOnPlatform, className, methodName)); + } + } + } +} diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Utilities/StringBuilderExtensions.cs b/src/Microsoft.TestPlatform.CoreUtilities/Extensions/StringBuilderExtensions.cs similarity index 100% rename from src/Microsoft.TestPlatform.CoreUtilities/Utilities/StringBuilderExtensions.cs rename to src/Microsoft.TestPlatform.CoreUtilities/Extensions/StringBuilderExtensions.cs diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Utilities/StringExtensions.cs b/src/Microsoft.TestPlatform.CoreUtilities/Extensions/StringExtensions.cs similarity index 100% rename from src/Microsoft.TestPlatform.CoreUtilities/Utilities/StringExtensions.cs rename to src/Microsoft.TestPlatform.CoreUtilities/Extensions/StringExtensions.cs diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/Resources.Designer.cs b/src/Microsoft.TestPlatform.CoreUtilities/Resources/Resources.Designer.cs index 6a615e84d7..2f96768586 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/Resources.Designer.cs +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/Resources.Designer.cs @@ -206,5 +206,16 @@ internal static string NoDotnetExeFound return ResourceManager.GetString("NoDotnetExeFound", resourceCulture); } } + + /// + /// Looks up a localized string similar to '{0}.{1}' is not implemented on this platform!. + /// + internal static string MethodNotImplementedOnPlatform + { + get + { + return ResourceManager.GetString("MethodNotImplementedOnPlatform", resourceCulture); + } + } } } diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/Resources.resx b/src/Microsoft.TestPlatform.CoreUtilities/Resources/Resources.resx index ba520ac0b1..27a397f0d5 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/Resources.resx +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/Resources.resx @@ -165,4 +165,10 @@ Error getting process name. + + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.cs.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.cs.xlf index d3fcf4893f..47832fc031 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.cs.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.cs.xlf @@ -160,6 +160,13 @@ Hostitele {0} nešlo najít. Ujistěte se, jestli je {0} nainstalovaný na počítači a dostupný v cestě určené proměnnou prostředí PATH. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.de.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.de.xlf index e56739c937..7540c20d89 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.de.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.de.xlf @@ -160,6 +160,13 @@ Der Host "{0}" wurde nicht gefunden. Stellen Sie sicher, dass "{0}" auf dem Computer installiert und in der PATH-Umgebungsvariablen verfügbar ist. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.es.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.es.xlf index b428568d5f..f0b6d9d623 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.es.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.es.xlf @@ -160,6 +160,13 @@ No se pudo encontrar el host "{0}". Asegúrese de que "{0}" está instalado en el equipo y está disponible en la variable de entorno PATH. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.fr.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.fr.xlf index 776258dfeb..ca8c35a132 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.fr.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.fr.xlf @@ -160,6 +160,13 @@ L'hôte '{0}' est introuvable. Vérifiez que '{0}' est installé sur la machine et qu'il est disponible dans la variable d'environnement PATH. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.it.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.it.xlf index 2a67405108..406e82c52f 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.it.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.it.xlf @@ -160,6 +160,13 @@ L'host '{0}' non è stato trovato. Assicurarsi che '{0}' sia installato nel computer e che sia disponibile nella variabile di ambiente PATH. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ja.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ja.xlf index f7540bc847..bb418fbaac 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ja.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ja.xlf @@ -160,6 +160,13 @@ '{0}' ホストが見つかりませんでした。'{0}' がコンピューターにインストールされており、PATH 環境変数で使用できることを確認してください。 + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ko.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ko.xlf index 045f1456c0..7a0d780acc 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ko.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ko.xlf @@ -160,6 +160,13 @@ ‘{0}’ 호스트를 찾을 수 없습니다. ‘{0}’이(가) 컴퓨터에 설치되어 있고 PATH 환경 변수에서 사용할 수 있는지 확인하세요. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.pl.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.pl.xlf index 1a4f72c7c4..d6c0d233a4 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.pl.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.pl.xlf @@ -160,6 +160,13 @@ Nie można znaleźć hosta „{0}”. Upewnij się, że element „{0}” jest zainstalowany na maszynie i jest dostępny w zmiennej środowiskowej PATH. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.pt-BR.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.pt-BR.xlf index c1ca953991..01c4d89016 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.pt-BR.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.pt-BR.xlf @@ -160,6 +160,13 @@ Não foi possível encontrar o host '{0}'. Verifique se o '{0}' está instalado no computador e está disponível na variável de ambiente PATH. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ru.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ru.xlf index 439e58c02c..009f2c3f84 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ru.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.ru.xlf @@ -160,6 +160,13 @@ Не удалось найти хост "{0}". Убедитесь, что "{0}" установлен на компьютере и доступен в переменной среды PATH. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.tr.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.tr.xlf index e137c740bd..ac138ce520 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.tr.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.tr.xlf @@ -160,6 +160,13 @@ '{0}' konağı bulunamadı. '{0}' konağının makinede yüklü olduğundan ve PATH ortam değişkeninde bulunduğundan emin olun. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.xlf index 615147279b..f557a28547 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.xlf @@ -67,6 +67,13 @@ Could not find {0}. Make sure that the dotnet is installed on the machine. + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.zh-Hans.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.zh-Hans.xlf index 0c695e40d6..32b1ad3e48 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.zh-Hans.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.zh-Hans.xlf @@ -160,6 +160,13 @@ 找不到“{0}”主机。请确保计算机上已安装“{0}”且位于 PATH 环境变量中。 + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.zh-Hant.xlf b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.zh-Hant.xlf index ba717bee60..3cf3379924 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.zh-Hant.xlf +++ b/src/Microsoft.TestPlatform.CoreUtilities/Resources/xlf/Resources.zh-Hant.xlf @@ -160,6 +160,13 @@ 找不到 '{0}' 主機。請確認 '{0}' 已安裝在機器上,而且可在 PATH 環境變數中使用。 + + '{0}.{1}' is not implemented on this platform! + '{0}.{1}' is not implemented on this platform! + '{className}.{methodName}' is not implemented on this platform! + +Example: 'System.Reflection.MethodBase' is not implemented on this platform! + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs index cbcf4c962c..3ca84b4694 100644 --- a/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs +++ b/src/Microsoft.TestPlatform.Extensions.TrxLogger/Utility/Converter.cs @@ -70,8 +70,6 @@ public ITestElement ToTestElement( return testElement; } - - /// /// Converts the rockSteady result to unit test result /// diff --git a/src/Microsoft.TestPlatform.ObjectModel/Friends.cs b/src/Microsoft.TestPlatform.ObjectModel/Friends.cs index ea3b21f6f1..7e2123cd6d 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/Friends.cs +++ b/src/Microsoft.TestPlatform.ObjectModel/Friends.cs @@ -12,3 +12,4 @@ [assembly: InternalsVisibleTo("Microsoft.TestPlatform.ObjectModel.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("datacollector.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("Microsoft.TestPlatform.Extensions.EventLogCollector.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/ManagedNameUtilities/InvalidManagedNameException.cs b/src/Microsoft.TestPlatform.ObjectModel/ManagedNameUtilities/InvalidManagedNameException.cs new file mode 100644 index 0000000000..4a1e2a3a1f --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/ManagedNameUtilities/InvalidManagedNameException.cs @@ -0,0 +1,12 @@ +// 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.ObjectModel.ManagedNameUtilities +{ + using System; + + public class InvalidManagedNameException : Exception + { + public InvalidManagedNameException(string message) : base(message) { } + } +} \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/ManagedNameUtilities/ManagedNameHelper.Reflection.cs b/src/Microsoft.TestPlatform.ObjectModel/ManagedNameUtilities/ManagedNameHelper.Reflection.cs new file mode 100644 index 0000000000..b0d7727995 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/ManagedNameUtilities/ManagedNameHelper.Reflection.cs @@ -0,0 +1,277 @@ +// 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.ObjectModel.ManagedNameUtilities +{ + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Resources; + using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Extensions; + + using System; + using System.Globalization; + using System.Linq; + using System.Reflection; + using System.Text; + + public static partial class ManagedNameHelper + { + /// + /// Gets fully qualified type and method name from given MethodBase instance. + /// + /// + /// A MethodBase instance to get fully qualified type and method name. + /// + /// + /// When this method returns, contains the fully qualified type name of the . + /// This parameter is passed uninitialized; any value originally supplied in result will be overwritten. + /// + /// + /// When this method returns, contains the fully qualified method name of the . + /// This parameter is passed uninitialized; any value originally supplied in result will be overwritten. + /// + /// is null. + /// must describe a method. + /// + /// Required functionality on is missing on the current platform. + /// + public static void GetManagedName(MethodBase method, out string fullTypeName, out string fullMethodName) + { + if (method == null) + { + throw new ArgumentNullException(nameof(method)); + } + + if (!method.IsMethod()) + { + throw new NotSupportedException(nameof(method)); + } + + var semanticType = method.GetReflectedType(); + if (semanticType.IsGenericType()) + { + // The type might have some of its generic parameters specified, so make + // sure we are working with the open form of the generic type. + semanticType = semanticType.GetGenericTypeDefinition(); + + // The method might have some of its parameters specified by the original closed type + // declaration. Here we use the method handle (basically metadata token) to create + // a new method reference using the open form of the reflected type. The intent is + // to strip all generic type parameters. + var methodHandle = method.GetMethodHandle(); + method = MethodBase.GetMethodFromHandle(methodHandle, semanticType.TypeHandle); + } + + if (method.IsGenericMethod) + { + // If this method is generic, then convert to the generic method definition + // so that we get the open generic type definitions for parameters. + method = ((MethodInfo)method).GetGenericMethodDefinition(); + } + + var methodBuilder = new StringBuilder(); + var typeBuilder = new StringBuilder(); + + // Namespace and Type Name (with arity designation) + AppendTypeString(typeBuilder, semanticType, closedType: false); + + // Method Name with method arity + methodBuilder.Append(method.Name); + var arity = method.GetGenericArguments().Length; + if (arity > 0) + { + methodBuilder.Append('`'); + methodBuilder.Append(arity); + } + + // Type Parameters + var paramList = method.GetParameters(); + if (paramList.Any()) + { + methodBuilder.Append('('); + foreach (var p in paramList) + { + AppendTypeString(methodBuilder, p.ParameterType, closedType: true); + methodBuilder.Append(','); + } + // Replace the last ',' with ')' + methodBuilder[methodBuilder.Length - 1] = ')'; + } + + fullTypeName = typeBuilder.ToString(); + fullMethodName = methodBuilder.ToString(); + } + + /// + /// Gets the object with the specified + /// and in the instance. + /// + /// + /// An instance to search in. + /// + /// + /// The fully qualified name of the type. + /// + /// + /// The fully qualified name of the method. + /// + /// + /// A object that represents specified parameters, throws if null. + /// + /// + /// Values specified with and + /// does not correspond to a method in the instance, or malformed. + /// + public static MethodBase GetManagedName(Assembly assembly, string fullTypeName, string fullMethodName) + { + Type type; + +#if !NETSTANDARD1_0 && !NETSTANDARD1_3 && !WINDOWS_UWP + type = assembly.GetType(fullTypeName, throwOnError: false, ignoreCase: false); +#else + try + { + type = assembly.GetType(fullTypeName); + } + catch + { + type = null; + } +#endif + + if (type == null) + { + string message = String.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorTypeNotFound, fullTypeName); + throw new InvalidManagedNameException(message); + } + + MethodInfo method = null; + ManagedNameParser.ParseMethodName(fullMethodName, out var methodName, out var methodArity, out var parameterTypes); + if (!string.IsNullOrWhiteSpace(methodName)) + { + method = FindMethod(type, methodName, methodArity, parameterTypes); + } + + if (method == null) + { + string message = String.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorMethodNotFound, methodName, fullTypeName); + throw new InvalidManagedNameException(message); + } + + return method; + } + + private static MethodInfo FindMethod(Type type, string methodName, int methodArity, string[] parameterTypes) + { + bool filter(MemberInfo mbr, object param) + { + var method = mbr as MethodInfo; + if (method.Name != methodName || method.GetGenericArguments().Length != methodArity) + { + return false; + } + + var paramList = method.GetParameters(); + if (paramList.Length == 0 && parameterTypes == null) + { + return true; + } + else if (parameterTypes == null || paramList.Length != parameterTypes.Length) + { + return false; + } + + for (int i = 0; i < paramList.Length; i++) + { + if (TypeString(paramList[i].ParameterType, closedType: true) != parameterTypes[i]) + { + return false; + } + } + + return true; + } + +#if !NETSTANDARD1_0 && !NETSTANDARD1_3 && !WINDOWS_UWP + var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; + var methods = type.FindMembers(MemberTypes.Method, bindingFlags, filter, null); + return (MethodInfo)methods.SingleOrDefault(); +#else + return type.GetRuntimeMethods().Where(m => filter(m, null)).SingleOrDefault(); +#endif + } + + private static void AppendTypeString(StringBuilder b, Type type, bool closedType) + { + if (type.IsArray) + { + AppendTypeString(b, type.GetElementType(), closedType); + b.Append('['); + for (int i = 0; i < type.GetArrayRank() - 1; i++) + { + b.Append(','); + } + b.Append(']'); + } + else if (type.IsGenericParameter) + { + if (type.GetDeclaringMethod() != null) + { + b.Append('!'); + } + b.Append('!'); + b.Append(type.GenericParameterPosition); + } + else + { + b.Append(type.Namespace); + b.Append('.'); + + AppendNestedTypeName(b, type); + + if (closedType) + { + AppendGenericTypeParameters(b, type); + } + } + } + + private static void AppendNestedTypeName(StringBuilder b, Type type) + { + if (type.IsNested) + { + AppendNestedTypeName(b, type.DeclaringType); + b.Append('+'); + } + b.Append(type.Name); + } + + private static void AppendGenericTypeParameters(StringBuilder b, Type type) + { + Type[] genargs; + +#if !NETSTANDARD1_0 && !NETSTANDARD1_3 && !WINDOWS_UWP + genargs = type.GetGenericArguments(); +#else + genargs = type.GetTypeInfo().GenericTypeArguments; +#endif + + if (genargs.Any()) + { + b.Append('<'); + foreach (var argType in genargs) + { + AppendTypeString(b, argType, closedType: true); + b.Append(','); + } + // Replace the last ',' with '>' + b[b.Length - 1] = '>'; + } + } + + private static string TypeString(Type type, bool closedType) + { + var builder = new StringBuilder(); + AppendTypeString(builder, type, closedType); + return builder.ToString(); + } + } +} diff --git a/src/Microsoft.TestPlatform.ObjectModel/ManagedNameUtilities/ManagedNameParser.cs b/src/Microsoft.TestPlatform.ObjectModel/ManagedNameUtilities/ManagedNameParser.cs new file mode 100644 index 0000000000..f83eab158c --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/ManagedNameUtilities/ManagedNameParser.cs @@ -0,0 +1,188 @@ +// 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.ObjectModel.ManagedNameUtilities +{ + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Resources; + + using System.Collections.Generic; + using System.Diagnostics; + using System.Globalization; + using System.Linq; + + public class ManagedNameParser + { + internal static void ParseTypeName(string fullTypeName, out string namespaceName, out string typeName) + { + int pos = fullTypeName.LastIndexOf('.'); + if (pos == -1) + { + namespaceName = string.Empty; + typeName = fullTypeName; + } + else + { + namespaceName = fullTypeName.Substring(0, pos); + typeName = fullTypeName.Substring(pos + 1); + } + } + + internal static void ParseMethodName(string fullMethodName, out string methodName, out int arity, out string[] parameterTypes) + { + int pos = ParseMethodName(fullMethodName, 0, out methodName, out arity); + pos = ParseParameterTypeList(fullMethodName, pos, out parameterTypes); + if (pos != fullMethodName.Length) + { + string message = string.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorUnexpectedCharactersAtEnd, pos); + throw new InvalidManagedNameException(message); + } + } + + private static string Capture(string fullMethodName, int start, int end) + => fullMethodName.Substring(start, end - start); + + private static int ParseMethodName(string fullMethodName, int start, out string methodName, out int arity) + { + int i = start; + for (; i < fullMethodName.Length; i++) + { + switch (fullMethodName[i]) + { + case var w when char.IsWhiteSpace(w): + string message = string.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorWhitespaceNotValid, i); + throw new InvalidManagedNameException(message); + case '`': + methodName = Capture(fullMethodName, start, i); + return ParseArity(fullMethodName, i, out arity); + case '(': + methodName = Capture(fullMethodName, start, i); + arity = 0; + return i; + } + } + methodName = Capture(fullMethodName, start, i); + arity = 0; + return i; + } + + // parse arity in the form `nn where nn is an integer value. + private static int ParseArity(string fullMethodName, int start, out int arity) + { + arity = 0; + Debug.Assert(fullMethodName[start] == '`'); + + int i = start + 1; // skip initial '`' char + for (; i < fullMethodName.Length; i++) + { + if (fullMethodName[i] == '(') break; + } + if (!int.TryParse(Capture(fullMethodName, start + 1, i), out arity)) + { + string message = string.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorMethodArityMustBeNumeric); + throw new InvalidManagedNameException(message); + } + return i; + } + + private static int ParseParameterTypeList(string fullMethodName, int start, out string[] parameterTypes) + { + parameterTypes = null; + if (start == fullMethodName.Length) + { + return start; + } + Debug.Assert(fullMethodName[start] == '('); + + var types = new List(); + + int i = start + 1; // skip initial '(' char + for (; i < fullMethodName.Length; i++) + { + switch (fullMethodName[i]) + { + case ')': + if (types.Any()) + { + parameterTypes = types.ToArray(); + } + return i + 1; // consume right parens + case ',': + break; + default: + i = ParseParameterType(fullMethodName, i, out var parameterType); + types.Add(parameterType); + break; + } + } + + string message = string.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorIncompleteManagedName); + throw new InvalidManagedNameException(message); + } + + private static int ParseParameterType(string fullMethodName, int start, out string parameterType) + { + parameterType = string.Empty; + + int i = start; + for (; i < fullMethodName.Length; i++) + { + switch (fullMethodName[i]) + { + case '<': + i = ParseGenericBrackets(fullMethodName, i + 1); + break; + case '[': + i = ParseArrayBrackets(fullMethodName, i + 1); + break; + case ',': + case ')': + parameterType = Capture(fullMethodName, start, i); + return i - 1; + case var w when char.IsWhiteSpace(w): + string message = string.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorWhitespaceNotValid, i); + throw new InvalidManagedNameException(message); + } + } + return i; + } + + private static int ParseArrayBrackets(string fullMethodName, int start) + { + for (int i = start; i < fullMethodName.Length; i++) + { + switch (fullMethodName[i]) + { + case ']': + return i; + case var w when char.IsWhiteSpace(w): + string msg = string.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorWhitespaceNotValid, i); + throw new InvalidManagedNameException(msg); + } + } + + string message = string.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorIncompleteManagedName); + throw new InvalidManagedNameException(message); + } + + private static int ParseGenericBrackets(string fullMethodName, int start) + { + for (int i = start; i < fullMethodName.Length; i++) + { + switch (fullMethodName[i]) + { + case '<': + i = ParseGenericBrackets(fullMethodName, i + 1); + break; + case '>': + return i; + case var w when char.IsWhiteSpace(w): + string msg = string.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorWhitespaceNotValid, i); + throw new InvalidManagedNameException(msg); + } + } + + string message = string.Format(CultureInfo.CurrentCulture, ManagedNameMessages.ErrorIncompleteManagedName); + throw new InvalidManagedNameException(message); + } + } +} diff --git a/src/Microsoft.TestPlatform.ObjectModel/Microsoft.TestPlatform.ObjectModel.csproj b/src/Microsoft.TestPlatform.ObjectModel/Microsoft.TestPlatform.ObjectModel.csproj index 5428a9c273..e0bcb43aa0 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/Microsoft.TestPlatform.ObjectModel.csproj +++ b/src/Microsoft.TestPlatform.ObjectModel/Microsoft.TestPlatform.ObjectModel.csproj @@ -20,26 +20,11 @@ .NETPortable v4.5 $(DefineConstants);WINDOWS_UWP - - - .NETFramework - v4.5.1 - - - - - - - TextTemplatingFileGenerator - Resources\CommonResources.resx - - - - + @@ -48,7 +33,7 @@ - + @@ -67,10 +52,10 @@ - + - + @@ -81,7 +66,7 @@ - + @@ -89,13 +74,28 @@ - + + + + + + + + TextTemplatingFileGenerator + Resources\CommonResources.resx + + True True CommonResources.resx + + True + True + ManagedNameMessages.resx + True True @@ -108,6 +108,10 @@ Resources\CommonResources.tt CommonResources.Designer.cs + + ResXFileCodeGenerator + ManagedNameMessages.Designer.cs + ResXFileCodeGenerator Resources.Designer.cs diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/ManagedNameMessages.Designer.cs b/src/Microsoft.TestPlatform.ObjectModel/Resources/ManagedNameMessages.Designer.cs new file mode 100644 index 0000000000..266ad299d1 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/ManagedNameMessages.Designer.cs @@ -0,0 +1,118 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.Resources { + using System; + using System.Reflection; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class ManagedNameMessages { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ManagedNameMessages() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.VisualStudio.TestPlatform.ObjectModel.Resources.ManagedNameMessages", typeof(ManagedNameMessages).GetTypeInfo().Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to ManagedName is incomplete. + /// + internal static string ErrorIncompleteManagedName { + get { + return ResourceManager.GetString("ErrorIncompleteManagedName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Method arity must be numeric. + /// + internal static string ErrorMethodArityMustBeNumeric { + get { + return ResourceManager.GetString("ErrorMethodArityMustBeNumeric", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Method '{0}' not found on type '{1}'. + /// + internal static string ErrorMethodNotFound { + get { + return ResourceManager.GetString("ErrorMethodNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type '{0}' not found. + /// + internal static string ErrorTypeNotFound { + get { + return ResourceManager.GetString("ErrorTypeNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unexpected characters after the end of the ManagedName (pos: {0}). + /// + internal static string ErrorUnexpectedCharactersAtEnd { + get { + return ResourceManager.GetString("ErrorUnexpectedCharactersAtEnd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Whitespace is not valid in a ManagedName (pos: {0}). + /// + internal static string ErrorWhitespaceNotValid { + get { + return ResourceManager.GetString("ErrorWhitespaceNotValid", resourceCulture); + } + } + } +} diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/ManagedNameMessages.resx b/src/Microsoft.TestPlatform.ObjectModel/Resources/ManagedNameMessages.resx new file mode 100644 index 0000000000..1f24f6db76 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/ManagedNameMessages.resx @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ManagedName is incomplete + + + Method arity must be numeric + + + Method '{0}' not found on type '{1}' + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + {0} is the position of invalid whitespace + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/Resources.Designer.cs b/src/Microsoft.TestPlatform.ObjectModel/Resources/Resources.Designer.cs index 9750a2ace8..4f8bb8b497 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/Resources/Resources.Designer.cs +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/Resources.Designer.cs @@ -11,8 +11,8 @@ namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.Resources { using System; using System.Reflection; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -20,7 +20,7 @@ namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.Resources { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -32,7 +32,7 @@ internal class Resources { [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// @@ -277,6 +277,33 @@ internal static string Exception_RegisteredTestPropertyHasDifferentValueType { } } + /// + /// Looks up a localized string similar to Failed to Create msdia Session COM HResult '{0}'.. + /// + internal static string FailedToCreateDiaSession { + get { + return ResourceManager.GetString("FailedToCreateDiaSession", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to load msdia. + /// + internal static string FailedToLoadMsDia { + get { + return ResourceManager.GetString("FailedToLoadMsDia", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid URI in data collector settings '{0}'.. + /// + internal static string InvalidDataCollectorUriInSettings { + get { + return ResourceManager.GetString("InvalidDataCollectorUriInSettings", resourceCulture); + } + } + /// /// Looks up a localized string similar to The root node of the run settings must be named 'RunSettings'.. /// @@ -312,29 +339,16 @@ internal static string InvalidSettingsXmlElement { return ResourceManager.GetString("InvalidSettingsXmlElement", resourceCulture); } } - - /// - /// Looks up a localized string similar to Invalid URI in data collector settings '{0}'.. - /// - internal static string InvalidDataCollectorUriInSettings - { - get - { - return ResourceManager.GetString("InvalidDataCollectorUriInSettings", resourceCulture); - } - } - + /// /// Looks up a localized string similar to Invalid URI '{0}' in settings '{1}'.. /// - internal static string InvalidUriInSettings - { - get - { + internal static string InvalidUriInSettings { + get { return ResourceManager.GetString("InvalidUriInSettings", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid data collector settings. Expected attribute '{0}' is missing. A typical data collector setting would look like <DataCollector uri="dataCollector://Samples/SampleCollector/1.0" assemblyQualifiedName="Samples.SampleCollector.SampleDataCollector, SampleCollectors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1111111111111111" friendlyName="sampleCollector">.. /// @@ -343,18 +357,16 @@ internal static string MissingDataCollectorAttributes { return ResourceManager.GetString("MissingDataCollectorAttributes", resourceCulture); } } - + /// /// Looks up a localized string similar to Invalid settings '{0}'. Expected atleast one of the XmlAttribute among friendlyName, uri and assemblyQualifiedName.. /// - internal static string MissingLoggerAttributes - { - get - { + internal static string MissingLoggerAttributes { + get { return ResourceManager.GetString("MissingLoggerAttributes", resourceCulture); } } - + /// /// Looks up a localized string similar to Cannot specify TestCaseFilter for specific tests run. FilterCriteria is only for run with sources.. /// @@ -400,6 +412,15 @@ internal static string SolutionDirectoryNotExists { } } + /// + /// Looks up a localized string similar to Filter string '{0}' includes unrecognized escape sequence.. + /// + internal static string TestCaseFilterEscapeException { + get { + return ResourceManager.GetString("TestCaseFilterEscapeException", resourceCulture); + } + } + /// /// Looks up a localized string similar to Column Number. /// @@ -654,38 +675,5 @@ internal static string UnexpectedTypeOfProperty { return ResourceManager.GetString("UnexpectedTypeOfProperty", resourceCulture); } } - - /// - /// Looks up a localized string similar to The test property type '{0}' of property '{1}' is not supported. Use one of the supported property type (primitive types, uri, string, string[]) and try again. . - /// - internal static string FailedToLoadMsDia - { - get - { - return ResourceManager.GetString("FailedToLoadMsDia", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The test property type '{0}' of property '{1}' is not supported. Use one of the supported property type (primitive types, uri, string, string[]) and try again. . - /// - internal static string FailedToCreateDiaSession - { - get - { - return ResourceManager.GetString("FailedToCreateDiaSession", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Filter string '{0}' includes unrecognized escape sequence.. - /// - internal static string TestCaseFilterEscapeException - { - get - { - return ResourceManager.GetString("TestCaseFilterEscapeException", resourceCulture); - } - } } } diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.cs.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.cs.xlf new file mode 100644 index 0000000000..22dd7bfd1a --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.cs.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + PlněKvalifikovanýNázev je neúplný. + + + + Method arity must be numeric + Arita metody musí být číselná. + + + + Method '{0}' not found on type '{1}' + Metoda {0} nebyla nalezena u typu {1}. + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + Typ {0} nebyl nalezen. + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + Neočekávané znaky na konci položky PlněKvalifikovanýNázev (pos: {0}) + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + V položce PlněKvalifikovanýNázev není povolena mezera (pos: {0}). + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.de.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.de.xlf new file mode 100644 index 0000000000..173142e423 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.de.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + ManagedName ist unvollständig. + + + + Method arity must be numeric + Die Stelligkeit der Methode muss numerisch sein. + + + + Method '{0}' not found on type '{1}' + Die Methode "{0}" wurde für den Typ "{1}" nicht gefunden. + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + Der Typ "{0}" wurde nicht gefunden. + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + Nach dem Ende von ManagedName (Pos: {0}) wurden unerwartete Zeichen gefunden. + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + Leerzeichen sind in einem ManagedName (Pos: {0}) unzulässig. + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.es.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.es.xlf new file mode 100644 index 0000000000..61a0a28563 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.es.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + ManagedName está incompleto + + + + Method arity must be numeric + La aridad del método debe ser numérica + + + + Method '{0}' not found on type '{1}' + Método "{0}" no encontrado en el tipo "{1}" + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + Tipo "{0}" no encontrado + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + Caracteres inesperados después del final de ManagedName (pos: {0}) + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + El espacio en blanco no es válido en un elemento ManagedName (pos: {0}) + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.fr.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.fr.xlf new file mode 100644 index 0000000000..7f48d41414 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.fr.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + ManagedName est incomplet + + + + Method arity must be numeric + L'arité de la méthode doit être numérique + + + + Method '{0}' not found on type '{1}' + Méthode '{0}' introuvable sur le type '{1}' + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + Type '{0}' introuvable + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + Caractères inattendus après la fin du ManagedName (pos : {0}) + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + Les espaces blancs ne sont pas valides dans un ManagedName (pos : {0}) + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.it.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.it.xlf new file mode 100644 index 0000000000..cd33cbb7ea --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.it.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + L'elemento ManagedName è incompleto + + + + Method arity must be numeric + Il grado del metodo deve essere numerico + + + + Method '{0}' not found on type '{1}' + Il metodo '{0}' non è stato trovato nel tipo '{1}' + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + Il tipo '{0}' non è stato trovato + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + Caratteri imprevisti dopo la fine dell'elemento ManagedName (pos.: {0}) + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + Gli spazi vuoti non sono validi in un elemento ManagedName (pos.: {0}) + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.ja.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.ja.xlf new file mode 100644 index 0000000000..804c2891ba --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.ja.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + ManagedName が不完全です。 + + + + Method arity must be numeric + メソッドのアリティは、数値でなければなりません。 + + + + Method '{0}' not found on type '{1}' + メソッド '{0}' が型 '{1}' に見つかりませんでした。 + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + 型 '{0}' が見つかりません。 + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + ManagedName (pos: {0}) の末尾の後ろに予期しない文字があります + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + ManagedName (pos: {0}) では空白は無効です + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.ko.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.ko.xlf new file mode 100644 index 0000000000..f10f8d5bd8 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.ko.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + ManagedName이 불완전합니다. + + + + Method arity must be numeric + 메서드 인자 수는 숫자여야 합니다. + + + + Method '{0}' not found on type '{1}' + '{0}' 메서드를 '{1}' 형식에서 찾을 수 없습니다. + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + '{0}' 형식을 찾을 수 없습니다. + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + ManagedName의 끝 다음에 예기치 않은 문자가 있습니다(pos: {0}). + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + ManagedName에서 공백은 유효하지 않습니다(pos: {0}). + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.pl.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.pl.xlf new file mode 100644 index 0000000000..33f316fc55 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.pl.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + Wartość ManagedName jest niepełna + + + + Method arity must be numeric + Liczba argumentów metody musi być liczbą + + + + Method '{0}' not found on type '{1}' + Nie znaleziono metody „{0}” w typie „{1}” + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + Nie znaleziono typu „{0}” + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + Nieoczekiwane znaki za końcem wartości ManagedName (pozycja: {0}) + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + Biały znak jest niedozwolony w wartości ManagedName (pozycja: {0}) + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.pt-BR.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.pt-BR.xlf new file mode 100644 index 0000000000..0fa9a17b35 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.pt-BR.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + ManagedName está incompleto + + + + Method arity must be numeric + A aridade do método deve ser numérica + + + + Method '{0}' not found on type '{1}' + Método '{0}' não encontrado no tipo '{1}' + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + Tipo '{0}' não encontrado + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + Caracteres inesperados após o fnal de ManagedName (pos: {0}) + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + Espaço em branco não é válido em um ManagedName (pos: {0}) + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.ru.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.ru.xlf new file mode 100644 index 0000000000..542202b6a2 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.ru.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + ManagedName (Полное имя) содержит не все данные + + + + Method arity must be numeric + Арность метода должна быть числовым значением + + + + Method '{0}' not found on type '{1}' + Метод "{0}" не найден для типа "{1}" + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + Тип "{0}" не найден + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + Непредусмотренные символы после ManagedName (Полного имени), позиция: {0} + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + Пробел в ManagedName (Полном имени) недопустим, позиция: {0} + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.tr.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.tr.xlf new file mode 100644 index 0000000000..393b2edd77 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.tr.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + ManagedName eksik + + + + Method arity must be numeric + Method sayısı sayısal bir değer olmalıdır + + + + Method '{0}' not found on type '{1}' + '{1}' türünde '{0}' metodu bulunamadı + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + {0} türü bulunamadı. + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + ManagedName’den sonra beklenmeyen karakterler (konum: {0}) + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + ManagedName’de boşluk geçersizdir (konum: {0}) + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.xlf new file mode 100644 index 0000000000..6b76894923 --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.xlf @@ -0,0 +1,31 @@ + + + + + + ManagedName is incomplete + + + + Method arity must be numeric + + + + Method '{0}' not found on type '{1}' + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.zh-Hans.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.zh-Hans.xlf new file mode 100644 index 0000000000..2ed7fcaeab --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.zh-Hans.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + ManagedName 不完整 + + + + Method arity must be numeric + 方法参数数量必须是数值 + + + + Method '{0}' not found on type '{1}' + 类型“{1}”上找不到方法“{0}” + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + 找不到类型“{0}” + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + ManagedName (pos: {0}) 末尾后有不需要的字符 + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + ManagedName (pos: {0}) 中空白无效 + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.zh-Hant.xlf b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.zh-Hant.xlf new file mode 100644 index 0000000000..b3dcdd91cd --- /dev/null +++ b/src/Microsoft.TestPlatform.ObjectModel/Resources/xlf/ManagedNameMessages.zh-Hant.xlf @@ -0,0 +1,37 @@ + + + + + + ManagedName is incomplete + ManagedName 不完整 + + + + Method arity must be numeric + 方法 arity 必須為數值 + + + + Method '{0}' not found on type '{1}' + 在類型 '{1}' 上找不到方法 '{0}' + {0} is the method name, {1} is the full type name. + + + Type '{0}' not found + 找不到類型 '{0}' + {0} is the full type name. + + + Unexpected characters after the end of the ManagedName (pos: {0}) + ManagedName (pos: {0}) 的結尾出現未預期的字元 + {0} is the position of unexpected characters + + + Whitespace is not valid in a ManagedName (pos: {0}) + 空白字元在 ManagedName (pos: {0}) 中無效 + {0} is the position of invalid whitespace + + + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.ObjectModel/TestCase.cs b/src/Microsoft.TestPlatform.ObjectModel/TestCase.cs index a4493a5b31..7728529e6b 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/TestCase.cs +++ b/src/Microsoft.TestPlatform.ObjectModel/TestCase.cs @@ -10,6 +10,7 @@ namespace Microsoft.VisualStudio.TestPlatform.ObjectModel using System.Linq; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; + using System.Reflection; /// /// Stores information about a test case. @@ -21,13 +22,15 @@ public sealed class TestCase : TestObject /// LocalExtensionData which can be used by Adapter developers for local transfer of extended properties. /// Note that this data is available only for in-Proc execution, and may not be available for OutProc executors /// - private Object localExtensionData; + private object localExtensionData; private Guid defaultId = Guid.Empty; private Guid id; private string displayName; private string fullyQualifiedName; private string source; + private string managedMethod; + private string managedType; #region Constructor @@ -64,6 +67,63 @@ public TestCase(string fullyQualifiedName, Uri executorUri, string source) this.LineNumber = -1; } + /// + /// Initializes a new instance of the class. + /// + /// + /// Fully qualified name of the test case. + /// + /// + /// Managed method to extract the values of and . + /// + /// + /// The Uri of the executor to use for running this test. + /// + /// + /// Test container source from which the test is discovered. + /// + /// + /// If is specified, TestId will be calculated based on that instead of . + /// + public TestCase(string fullyQualifiedName, MethodBase method, Uri executorUri, string source) + : this(fullyQualifiedName, executorUri, source) + { + ValidateArg.NotNull(method, nameof(method)); + + ManagedNameUtilities.ManagedNameHelper.GetManagedName(method, out var managedType, out var managedMethod); + + ManagedType = managedType; + ManagedMethod = managedMethod; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// Fully qualified name of the test case. + /// + /// + /// Managed method to extract the values of and . + /// + /// + /// The Uri of the executor to use for running this test. + /// + /// + /// Test container source from which the test is discovered. + /// + /// + /// If and are specified, TestId will be calculated based on those instead of . + /// + public TestCase(string fullyQualifiedName, string managedType, string managedMethod, Uri executorUri, string source) + : this(fullyQualifiedName, executorUri, source) + { + ValidateArg.NotNullOrWhiteSpace(managedType, nameof(managedType)); + ValidateArg.NotNullOrWhiteSpace(managedMethod, nameof(managedMethod)); + + ManagedType = managedType; + ManagedMethod = managedMethod; + } + #endregion #region Properties @@ -92,6 +152,7 @@ public Guid Id { this.defaultId = this.GetTestId(); } + return this.defaultId; } @@ -104,23 +165,44 @@ public Guid Id } } + /// + /// Gets or sets the fully specified type name metadata format. + /// + /// + /// NamespaceA.NamespaceB.ClassName`1+InnerClass`2 + /// + [DataMember] + public string ManagedType { + get => managedType; + + // defaultId should be reset as it is based on ManagedType, ManagedMethod and Source. + set => SetVariableAndResetId(ref managedType, value); + } + + /// + /// Gets or sets the fully specified method name metadata format. + /// + /// + /// MethodName`2(ParamTypeA,ParamTypeB,�) + /// + [DataMember] + public string ManagedMethod { + get => managedMethod; + + // defaultId should be reset as it is based on ManagedType, ManagedMethod and Source. + set => SetVariableAndResetId(ref managedMethod, value); + } + /// /// Gets or sets the fully qualified name of the test case. /// [DataMember] public string FullyQualifiedName { - get - { - return this.fullyQualifiedName; - } - set - { - this.fullyQualifiedName = value; + get => fullyQualifiedName; - // defaultId should be reset as it is based on FullyQualifiedName and Source. - this.defaultId = Guid.Empty; - } + // defaultId should be reset as it is based on FullyQualifiedName and Source. + set => SetVariableAndResetId(ref fullyQualifiedName, value); } /// @@ -131,7 +213,17 @@ public string DisplayName { get { - return string.IsNullOrEmpty(this.displayName) ? this.FullyQualifiedName : this.displayName; + if(string.IsNullOrEmpty(this.displayName)) + { + if (this.HasManagedMethodAndType) + { + return $"{managedType}.{ManagedMethod}"; + } + + return this.FullyQualifiedName; + } + + return this.displayName; } set { @@ -196,10 +288,22 @@ public override IEnumerable Properties } } + /// + /// Returns true if both and are not null or whitespace. + /// + public bool HasManagedMethodAndType => !string.IsNullOrWhiteSpace(ManagedType) && !string.IsNullOrWhiteSpace(ManagedMethod); + /// public override string ToString() { - return this.FullyQualifiedName; + if (this.HasManagedMethodAndType) + { + return $"{ManagedType}.{ManagedMethod}"; + } + else + { + return this.FullyQualifiedName; + } } #endregion @@ -234,10 +338,29 @@ private Guid GetTestId() // do nothing } - string testcaseFullName = this.ExecutorUri + source + this.FullyQualifiedName; + // We still need to handle parameters in the case of a Theory or TestGroup of test cases that are only + // distinguished by parameters. + var testcaseFullName = this.ExecutorUri + source; + + // If ManagedType and ManagedMethod properties are filled than TestId should be based on those. + if (this.HasManagedMethodAndType) + { + testcaseFullName += $"{managedType}.{managedMethod}"; + } + else + { + testcaseFullName += this.FullyQualifiedName; + } + return EqtHash.GuidFromString(testcaseFullName); } + private void SetVariableAndResetId(ref T variable, T value) + { + variable = value; + this.defaultId = Guid.Empty; + } + #endregion #region Protected Methods @@ -260,6 +383,10 @@ protected override object ProtectedGetPropertyValue(TestProperty property, objec return this.ExecutorUri; case "TestCase.FullyQualifiedName": return this.FullyQualifiedName; + case "TestCase.ManagedType": + return this.ManagedType; + case "TestCase.ManagedMethod": + return this.ManagedMethod; case "TestCase.Id": return this.Id; case "TestCase.LineNumber": @@ -282,19 +409,40 @@ protected override void ProtectedSetPropertyValue(TestProperty property, object switch (property.Id) { case "TestCase.CodeFilePath": - this.CodeFilePath = (string)value; return; + this.CodeFilePath = value as string; + return; + case "TestCase.DisplayName": - this.DisplayName = (string)value; return; + this.DisplayName = value as string; + return; + case "TestCase.ExecutorUri": - this.ExecutorUri = value as Uri ?? new Uri((string)value); return; + this.ExecutorUri = value as Uri ?? new Uri(value as string); + return; + case "TestCase.FullyQualifiedName": - this.FullyQualifiedName = (string)value; return; + this.FullyQualifiedName = value as string; + return; + + case "TestCase.ManagedType": + this.ManagedType = value as string; + return; + + case "TestCase.ManagedMethod": + this.ManagedMethod = value as string; + return; + case "TestCase.Id": - this.Id = value is Guid ? (Guid)value : Guid.Parse((string)value); return; + this.Id = value is Guid ? (Guid)value : Guid.Parse(value as string); + return; + case "TestCase.LineNumber": - this.LineNumber = (int)value; return; + this.LineNumber = (int)value; + return; + case "TestCase.Source": - this.Source = (string)value; return; + this.Source = value as string; + return; } // It is a custom test case property. Should be set in the TestObject store. @@ -317,6 +465,8 @@ public static class TestCaseProperties /// private const string IdLabel = "Id"; private const string FullyQualifiedNameLabel = "FullyQualifiedName"; + private const string ManagedTypeLabel = "ManagedType"; + private const string ManagedMethodLabel = "ManagedMethod"; private const string NameLabel = "Name"; private const string ExecutorUriLabel = "Executor Uri"; private const string SourceLabel = "Source"; @@ -331,6 +481,12 @@ public static class TestCaseProperties [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly TestProperty FullyQualifiedName = TestProperty.Register("TestCase.FullyQualifiedName", FullyQualifiedNameLabel, string.Empty, string.Empty, typeof(string), ValidateName, TestPropertyAttributes.Hidden, typeof(TestCase)); + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly TestProperty ManagedType = TestProperty.Register("TestCase.ManagedType", ManagedTypeLabel, string.Empty, string.Empty, typeof(string), ValidateName, TestPropertyAttributes.Hidden, typeof(TestCase)); + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly TestProperty ManagedMethod = TestProperty.Register("TestCase.ManagedMethod", ManagedMethodLabel, string.Empty, string.Empty, typeof(string), ValidateName, TestPropertyAttributes.Hidden, typeof(TestCase)); + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly TestProperty DisplayName = TestProperty.Register("TestCase.DisplayName", NameLabel, string.Empty, string.Empty, typeof(string), ValidateDisplay, TestPropertyAttributes.None, typeof(TestCase)); @@ -352,6 +508,8 @@ public static class TestCaseProperties DisplayName, ExecutorUri, FullyQualifiedName, + ManagedType, + ManagedMethod, Id, LineNumber, Source diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj b/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj index 7aa8192472..a21f24c86a 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/Microsoft.TestPlatform.PlatformAbstractions.csproj @@ -2,15 +2,19 @@ ..\..\ + false Microsoft.TestPlatform.PlatformAbstractions - net45;net451;netcoreapp2.1;netstandard1.3;netstandard2.0 + Microsoft.TestPlatform.PlatformAbstractions + net45;net451;netcoreapp1.0;netcoreapp2.1;netstandard1.3;netstandard2.0 $(TargetFrameworks);uap10.0;netstandard1.0 netstandard1.0;netstandard1.3;netstandard2.0;netcoreapp2.1 true - NU1605 + + + NU1605 @@ -23,8 +27,8 @@ v4.5 $(DefineConstants);WINDOWS_UWP - - + + @@ -47,9 +51,5 @@ - - Microsoft.TestPlatform.PlatformAbstractions - - diff --git a/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard/Tracing/PlatformEqtTrace.cs b/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard/Tracing/PlatformEqtTrace.cs index d055815d86..8333c5c1ff 100644 --- a/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard/Tracing/PlatformEqtTrace.cs +++ b/src/Microsoft.TestPlatform.PlatformAbstractions/netstandard/Tracing/PlatformEqtTrace.cs @@ -6,6 +6,7 @@ namespace Microsoft.VisualStudio.TestPlatform.ObjectModel { using System; + using System.Diagnostics; /// /// Wrapper class for tracing. @@ -22,48 +23,53 @@ namespace Microsoft.VisualStudio.TestPlatform.ObjectModel /// public class PlatformEqtTrace : IPlatformEqtTrace { + private PlatformTraceLevel traceLevel = PlatformTraceLevel.Off; + public static string ErrorOnInitialization { get; set; } - public bool DoNotInitialize - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } + public bool DoNotInitialize { get; set; } - public void WriteLine(PlatformTraceLevel level, string message) + public void WriteLine(PlatformTraceLevel traceLevel, string message) { - throw new NotImplementedException(); + if (!this.ShouldTrace(traceLevel)) + { + return; + } + + var level = Enum.GetName(typeof(PlatformTraceLevel), traceLevel); + Debug.WriteLine($"[{level}] {message}"); } public bool InitializeVerboseTrace(string customLogFile) { - throw new NotImplementedException(); + return false; } public bool InitializeTrace(string customLogFile, PlatformTraceLevel traceLevel) { - throw new NotImplementedException(); + this.traceLevel = traceLevel; + + return false; } public bool ShouldTrace(PlatformTraceLevel traceLevel) { - throw new NotImplementedException(); - } + if (this.DoNotInitialize) + { + return false; + } - public string GetLogFile() - { - throw new NotImplementedException(); + return (int)this.traceLevel >= (int)traceLevel; } + public string GetLogFile() => string.Empty; + public void SetTraceLevel(PlatformTraceLevel value) { - throw new NotImplementedException(); + this.traceLevel = value; } - public PlatformTraceLevel GetTraceLevel() - { - throw new NotImplementedException(); - } + public PlatformTraceLevel GetTraceLevel() => this.traceLevel; } } diff --git a/src/package/nuspec/TestPlatform.TestHost.nuspec b/src/package/nuspec/TestPlatform.TestHost.nuspec index 9615cd4f8f..a3896fc778 100644 --- a/src/package/nuspec/TestPlatform.TestHost.nuspec +++ b/src/package/nuspec/TestPlatform.TestHost.nuspec @@ -19,6 +19,13 @@ + + + + + + + @@ -55,7 +62,6 @@ - diff --git a/src/testhost.x86/TestHostTraceListener.cs b/src/testhost.x86/TestHostTraceListener.cs index 214b9db411..423dc1a947 100644 --- a/src/testhost.x86/TestHostTraceListener.cs +++ b/src/testhost.x86/TestHostTraceListener.cs @@ -43,8 +43,11 @@ public static void Setup() // Debug.Assert fails. This method is internal, but the class is on purpose keeping the // callback settable so tests can set the callback var field = typeof(Debug).GetField("s_ShowDialog", BindingFlags.Static | BindingFlags.NonPublic); - var value = field.GetValue(null); - field.SetValue(null, (Action)ShowDialog); + if (field != null) + { + var value = field.GetValue(null); + field.SetValue(null, (Action)ShowDialog); + } } catch (Exception ex) { diff --git a/src/testhost.x86/testhost.x86.csproj b/src/testhost.x86/testhost.x86.csproj index 670383d5ba..1527b52d70 100644 --- a/src/testhost.x86/testhost.x86.csproj +++ b/src/testhost.x86/testhost.x86.csproj @@ -14,6 +14,8 @@ true Exe app.manifest + + win7-x86 false diff --git a/test/Microsoft.TestPlatform.AcceptanceTests/Microsoft.TestPlatform.AcceptanceTests.csproj b/test/Microsoft.TestPlatform.AcceptanceTests/Microsoft.TestPlatform.AcceptanceTests.csproj index d0e8054689..3afe883253 100644 --- a/test/Microsoft.TestPlatform.AcceptanceTests/Microsoft.TestPlatform.AcceptanceTests.csproj +++ b/test/Microsoft.TestPlatform.AcceptanceTests/Microsoft.TestPlatform.AcceptanceTests.csproj @@ -12,19 +12,22 @@ Microsoft.TestPlatform.AcceptanceTests - - - - $(ChutzpahAdapterVersion) - - - 2.0.0 - - - 2.0.0 - + + + + + + + + + + + + + + @@ -32,12 +35,5 @@ - - - - - - - diff --git a/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/TestResultSerializationTests.cs b/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/TestResultSerializationTests.cs index f84c978312..7f16a8a11b 100644 --- a/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/TestResultSerializationTests.cs +++ b/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/Serialization/TestResultSerializationTests.cs @@ -238,7 +238,7 @@ public void TestResultObjectShouldSerializeAttachmentsV2(int version) result.StartTime = default(DateTimeOffset); result.EndTime = default(DateTimeOffset); result.Attachments.Add(new AttachmentSet(new Uri("http://dummyUri"), "sampleAttachment")); - var expectedJson = "{\"TestCase\":{\"Id\":\"28e7a7ed-8fb9-05b7-5e90-4a8c52f32b5b\",\"FullyQualifiedName\":\"sampleTestClass.sampleTestCase\",\"DisplayName\":\"sampleTestClass.sampleTestCase\",\"ExecutorUri\":\"executor://sampleTestExecutor\",\"Source\":\"sampleTest.dll\",\"CodeFilePath\":null,\"LineNumber\":-1,\"Properties\":[]},\"Attachments\":[{\"Uri\":\"http://dummyUri\",\"DisplayName\":\"sampleAttachment\",\"Attachments\":[]}],\"Outcome\":0,\"ErrorMessage\":null,\"ErrorStackTrace\":null,\"DisplayName\":null,\"Messages\":[],\"ComputerName\":null,\"Duration\":\"00:00:00\",\"StartTime\":\"0001-01-01T00:00:00+00:00\",\"EndTime\":\"0001-01-01T00:00:00+00:00\",\"Properties\":[]}"; + var expectedJson = "{\"TestCase\":{\"Id\":\"28e7a7ed-8fb9-05b7-5e90-4a8c52f32b5b\",\"ManagedType\":null,\"ManagedMethod\":null,\"FullyQualifiedName\":\"sampleTestClass.sampleTestCase\",\"DisplayName\":\"sampleTestClass.sampleTestCase\",\"ExecutorUri\":\"executor://sampleTestExecutor\",\"Source\":\"sampleTest.dll\",\"CodeFilePath\":null,\"LineNumber\":-1,\"Properties\":[]},\"Attachments\":[{\"Uri\":\"http://dummyUri\",\"DisplayName\":\"sampleAttachment\",\"Attachments\":[]}],\"Outcome\":0,\"ErrorMessage\":null,\"ErrorStackTrace\":null,\"DisplayName\":null,\"Messages\":[],\"ComputerName\":null,\"Duration\":\"00:00:00\",\"StartTime\":\"0001-01-01T00:00:00+00:00\",\"EndTime\":\"0001-01-01T00:00:00+00:00\",\"Properties\":[]}"; var json = Serialize(result, version); diff --git a/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/FindMethodExtensions.cs b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/FindMethodExtensions.cs new file mode 100644 index 0000000000..dee213e414 --- /dev/null +++ b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/FindMethodExtensions.cs @@ -0,0 +1,101 @@ +// 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.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests +{ + using Microsoft.CodeAnalysis; + + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Reflection; + + internal static class FindMethodExtensions + { + private const BindingFlags PrivateBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + + internal static MethodInfo FindMethod(this Type type, string signature) + => type.FindMembers(MemberTypes.Method, PrivateBindingFlags, + (mbr, sig) => mbr.ToString() == (string)sig, signature).FirstOrDefault() as MethodInfo; + + internal static IMethodSymbol FindMethod( + this INamedTypeSymbol type, + string methodName, + int methodGenericArity = -1, + params ITypeSymbol[] methodParameterTypes) + { + var candidates = GetCandidateMethods(type, methodName); + if (candidates.Any() && !candidates.Skip(1).Any()) + { + return candidates.Single(); + } + + if (methodGenericArity != -1) + { + candidates = candidates.Where(m => m.Arity == methodGenericArity); + if (candidates.Any() && !candidates.Skip(1).Any()) + { + return candidates.Single(); + } + } + + if (methodParameterTypes != null && methodParameterTypes.Length >= 0) + { + candidates = candidates.Where(m => m.Parameters.Length == methodParameterTypes.Length); + if (candidates.Any() && !candidates.Skip(1).Any()) + { + return candidates.Single(); + } + + candidates = candidates.Where(m => m.Parameters.Select(p => p.Type).SequenceEqual(methodParameterTypes)); + } + + Debug.Assert(candidates.Any() && !candidates.Skip(1).Any()); + return candidates.SingleOrDefault(); + } + + internal static IMethodSymbol FindMethod( + this INamedTypeSymbol type, + string methodName, + int methodGenericArity, + int methodParameterCount, + Func selector) + { + var candidates = GetCandidateMethods(type, methodName); + if (candidates.Any() && !candidates.Skip(1).Any()) + { + return candidates.Single(); + } + + candidates = candidates.Where(m => m.Arity == methodGenericArity); + if (candidates.Any() && !candidates.Skip(1).Any()) + { + return candidates.Single(); + } + + candidates = candidates.Where(m => m.Parameters.Length == methodParameterCount); + if (candidates.Any() && !candidates.Skip(1).Any()) + { + return candidates.Single(); + } + + candidates = candidates.Where(selector); + + Debug.Assert(candidates.Any() && !candidates.Skip(1).Any()); + return candidates.SingleOrDefault(); + } + + private static IEnumerable GetCandidateMethods(INamedTypeSymbol type, string methodName) + { + var candidates = type.GetMembers(methodName).OfType(); + + if (type.BaseType != null && type.BaseType.SpecialType != SpecialType.System_Object) + { + candidates = candidates.Union(GetCandidateMethods(type.BaseType, methodName)); + } + + return candidates; + } + } +} diff --git a/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/ManagedNameParserTests.cs b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/ManagedNameParserTests.cs new file mode 100644 index 0000000000..b56b54774c --- /dev/null +++ b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/ManagedNameParserTests.cs @@ -0,0 +1,75 @@ +// 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.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests +{ + using Microsoft.VisualStudio.TestPlatform.ObjectModel.ManagedNameUtilities; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class ManagedNameParserTests + { + [TestMethod] + public void ParseTypeName() + { + (string, string) Parse(string fullTypeName) + { + ManagedNameParser.ParseTypeName(fullTypeName, out var namespaceName, out var typeName); + return (namespaceName, typeName); + }; + + Assert.AreEqual(("NS", "Class"), Parse("NS.Class")); + Assert.AreEqual(("NS.NS", "Class"), Parse("NS.NS.Class")); + Assert.AreEqual(("NS.NS", "Class`2"), Parse("NS.NS.Class`2")); + Assert.AreEqual(("NS.NS", "ClassA`2+ClassInner"), Parse("NS.NS.ClassA`2+ClassInner")); + Assert.AreEqual(("NS.NS", "ClassA`2+ClassInner`1"), Parse("NS.NS.ClassA`2+ClassInner`1")); + Assert.AreEqual(("", "ClassA`2+ClassInner`1"), Parse("ClassA`2+ClassInner`1")); + } + + [TestMethod] + public void ParseMethodName() + { + (string, int, string[]) Parse(string methodName) + { + ManagedNameParser.ParseMethodName(methodName, out var method, out var arity, out var parameterTypes); + return (method, arity, parameterTypes); + } + + void AssertParse(string expectedMethod, int expectedArity, string[] expectedParams, string expression) + { + var (method, arity, parameters) = Parse(expression); + Assert.AreEqual(expectedMethod, method); + Assert.AreEqual(expectedArity, arity); + CollectionAssert.AreEqual(expectedParams, parameters, "parameter comparison"); + } + + Assert.AreEqual(("Method", 0, null), Parse("Method")); + Assert.AreEqual(("Method", 0, null), Parse("Method()")); + Assert.AreEqual(("Method", 2, null), Parse("Method`2()")); + AssertParse("Method", 0, new string[] { "System.Int32" }, "Method(System.Int32)"); + AssertParse("Method", 0, new string[] { "TypeA", "List" }, "Method(TypeA,List)"); + AssertParse("Method", 1, new string[] { "B", "List" }, "Method`1(B,List)"); + AssertParse("Method", 0, new string[] { "B[]" }, "Method(B[])"); + AssertParse("Method", 0, new string[] { "A[,]", "B[,,][]" }, "Method(A[,],B[,,][])"); + } + + [TestMethod] + public void ParseInvalidMethodName() + { + (string, int, string[]) Parse(string methodName) + { + ManagedNameParser.ParseMethodName(methodName, out var method, out var arity, out var parameterTypes); + return (method, arity, parameterTypes); + } + + Assert.ThrowsException(() => Parse(" Method"), "Whitespace is not valid in a ManagedName (pos: 0)"); + Assert.ThrowsException(() => Parse("Method( List)"), "Whitespace is not valid in a ManagedName (pos: 7)"); + + Assert.ThrowsException(() => Parse("Method(List)xa"), "Unexpected characters after the end of the ManagedName (pos: 7)"); + + Assert.ThrowsException(() => Parse("Method("), "ManagedName is incomplete"); + Assert.ThrowsException(() => Parse("Method`4a"), "Method arity must be numeric"); + } + + } +} diff --git a/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/ManagedNameRoundTripTests.cs b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/ManagedNameRoundTripTests.cs new file mode 100644 index 0000000000..bc69a9dcc1 --- /dev/null +++ b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/ManagedNameRoundTripTests.cs @@ -0,0 +1,938 @@ +// 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.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests +{ + using Microsoft.CodeAnalysis; + using Microsoft.CodeAnalysis.CSharp; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.ManagedNameUtilities; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + using System.IO; + using System.Linq; + using System.Reflection; + + [TestClass] + [DeploymentItem("TestClasses.cs")] + public partial class ManagedNameRoundTripTests + { + private const BindingFlags PrivateBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + private Compilation _compilation; + + [TestInitialize] + public void Initialize() + => _compilation = CSharpCompilation.Create( + "Test.dll", + new[] { CSharpSyntaxTree.ParseText(File.ReadAllText("TestClasses.cs")) }, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }); + + [TestMethod] + public void Simple1() + { + var outer = _compilation.GetTypeByMetadataName("TestClasses.Outer"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer).GetMethod("Method0"), + containingTypeSymbol: outer, + methodSymbol: outer.FindMethod("Method0"), + fullTypeName: "TestClasses.Outer", + fullMethodName: "Method0"); + } + + [TestMethod] + public void Simple2() + { + var outer = _compilation.GetTypeByMetadataName("TestClasses.Outer"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer).GetMethod("Method1"), + containingTypeSymbol: outer, + methodSymbol: outer.FindMethod("Method1"), + fullTypeName: "TestClasses.Outer", + fullMethodName: "Method1(System.Int32)"); + } + + [TestMethod] + public void Simple3() + { + var outer = _compilation.GetTypeByMetadataName("TestClasses.Outer"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer).GetMethod("Method2"), + containingTypeSymbol: outer, + methodSymbol: outer.FindMethod("Method2"), + fullTypeName: "TestClasses.Outer", + fullMethodName: "Method2(System.Collections.Generic.List`1)"); + } + + [TestMethod] + public void Simple4() + { + var outer = _compilation.GetTypeByMetadataName("TestClasses.Outer"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer).GetMethod("Method3"), + containingTypeSymbol: outer, + methodSymbol: outer.FindMethod("Method3"), + fullTypeName: "TestClasses.Outer", + fullMethodName: "Method3(System.String,System.Int32)"); + } + + [TestMethod] + public void Nested1() + { + var outerInner = _compilation.GetTypeByMetadataName("TestClasses.Outer+Inner"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer.Inner).GetMethod("Method0"), + containingTypeSymbol: outerInner, + methodSymbol: outerInner.FindMethod("Method0"), + fullTypeName: "TestClasses.Outer+Inner", + fullMethodName: "Method0"); + } + + [TestMethod] + public void Nested2() + { + var outerInner = _compilation.GetTypeByMetadataName("TestClasses.Outer+Inner"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer.Inner).GetMethod("Method1"), + containingTypeSymbol: outerInner, + methodSymbol: outerInner.FindMethod("Method1"), + fullTypeName: "TestClasses.Outer+Inner", + fullMethodName: "Method1(System.Int32)"); + } + + [TestMethod] + public void OpenGeneric1() + { + var outerT = _compilation.GetTypeByMetadataName("TestClasses.Outer`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer<>).GetMethod("Method0"), + containingTypeSymbol: outerT, + methodSymbol: outerT.FindMethod("Method0"), + fullTypeName: "TestClasses.Outer`1", + fullMethodName: "Method0"); + } + + [TestMethod] + public void OpenGeneric2() + { + var outerT = _compilation.GetTypeByMetadataName("TestClasses.Outer`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer<>).GetMethod("Method1"), + containingTypeSymbol: outerT, + methodSymbol: outerT.FindMethod("Method1"), + fullTypeName: "TestClasses.Outer`1", + fullMethodName: "Method1(!0)"); + } + + [TestMethod] + public void OpenGeneric3() + { + var outerT = _compilation.GetTypeByMetadataName("TestClasses.Outer`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer<>).GetMethod("Method2"), + containingTypeSymbol: outerT, + methodSymbol: outerT.FindMethod("Method2"), + fullTypeName: "TestClasses.Outer`1", + fullMethodName: "Method2`1(!!0[])"); + } + + [TestMethod] + public void OpenGeneric4() + { + var outerT = _compilation.GetTypeByMetadataName("TestClasses.Outer`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer<>).GetMethod("Method3"), + containingTypeSymbol: outerT, + methodSymbol: outerT.FindMethod("Method3"), + fullTypeName: "TestClasses.Outer`1", + fullMethodName: "Method3`1(!0,!!0)"); + } + + [TestMethod] + public void OpenGenericNested1() + { + var outerTInnterV = _compilation.GetTypeByMetadataName("TestClasses.Outer`1+Inner`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer<>.Inner<>).GetMethod("Method0"), + containingTypeSymbol: outerTInnterV, + methodSymbol: outerTInnterV.FindMethod("Method0"), + fullTypeName: "TestClasses.Outer`1+Inner`1", + fullMethodName: "Method0"); + } + + [TestMethod] + public void OpenGenericNested2() + { + var outerTInnterV = _compilation.GetTypeByMetadataName("TestClasses.Outer`1+Inner`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer<>.Inner<>).GetMethod("Method1"), + containingTypeSymbol: outerTInnterV, + methodSymbol: outerTInnterV.FindMethod("Method1"), + fullTypeName: "TestClasses.Outer`1+Inner`1", + fullMethodName: "Method1(!0)"); + } + + [TestMethod] + public void OpenGenericNested3() + { + var outerTInnterV = _compilation.GetTypeByMetadataName("TestClasses.Outer`1+Inner`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer<>.Inner<>).GetMethod("Method2"), + containingTypeSymbol: outerTInnterV, + methodSymbol: outerTInnterV.FindMethod("Method2"), + fullTypeName: "TestClasses.Outer`1+Inner`1", + fullMethodName: "Method2(!1)"); + } + + [TestMethod] + public void OpenGenericNested4() + { + var outerTInnterV = _compilation.GetTypeByMetadataName("TestClasses.Outer`1+Inner`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer<>.Inner<>).GetMethod("Method3"), + containingTypeSymbol: outerTInnterV, + methodSymbol: outerTInnterV.FindMethod("Method3"), + fullTypeName: "TestClasses.Outer`1+Inner`1", + fullMethodName: "Method3`1(!0,!!0,!1)"); + } + + [TestMethod] + public void OpenGenericNested5() + { + var outerTInnterV = _compilation.GetTypeByMetadataName("TestClasses.Outer`1+Inner`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer<>.Inner<>).GetMethod("Method4"), + containingTypeSymbol: outerTInnterV, + methodSymbol: outerTInnterV.FindMethod("Method4"), + fullTypeName: "TestClasses.Outer`1+Inner`1", + fullMethodName: "Method4`2(!!1,!!0)"); + } + + [TestMethod] + public void OpenGenericNested6() + { + var outerTInnerVMoreInnerI = _compilation.GetTypeByMetadataName("TestClasses.Outer`1+Inner`1+MoreInner`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer<>.Inner<>.MoreInner<>).GetMethod("Method0"), + containingTypeSymbol: outerTInnerVMoreInnerI, + methodSymbol: outerTInnerVMoreInnerI.FindMethod("Method0"), + fullTypeName: "TestClasses.Outer`1+Inner`1+MoreInner`1", + fullMethodName: "Method0`1(!0,!1,!2,!!0)"); + } + + [TestMethod] + public void ClosedGeneric1() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var outerTInt = _compilation.GetTypeByMetadataName("TestClasses.Outer`1").Construct(@int); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer).GetMethod("Method0"), + containingTypeSymbol: outerTInt, + methodSymbol: outerTInt.FindMethod("Method0"), + fullTypeName: "TestClasses.Outer`1", + fullMethodName: "Method0"); + } + + [TestMethod] + public void ClosedGeneric2() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var outerTInt = _compilation.GetTypeByMetadataName("TestClasses.Outer`1").Construct(@int); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer).GetMethod("Method1"), + containingTypeSymbol: outerTInt, + methodSymbol: outerTInt.FindMethod("Method1"), + fullTypeName: "TestClasses.Outer`1", + fullMethodName: "Method1(!0)"); + } + + [TestMethod] + public void ClosedGeneric3() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var outerTInt = _compilation.GetTypeByMetadataName("TestClasses.Outer`1").Construct(@int); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer).GetMethod("Method2"), + containingTypeSymbol: outerTInt, + methodSymbol: outerTInt.FindMethod("Method2"), + fullTypeName: "TestClasses.Outer`1", + fullMethodName: "Method2`1(!!0[])"); + } + + [TestMethod] + public void ClosedGeneric4() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var outerTInt = _compilation.GetTypeByMetadataName("TestClasses.Outer`1").Construct(@int); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer).GetMethod("Method3"), + containingTypeSymbol: outerTInt, + methodSymbol: outerTInt.FindMethod("Method3"), + fullTypeName: "TestClasses.Outer`1", + fullMethodName: "Method3`1(!0,!!0)"); + } + + [TestMethod] + public void ClosedGenericNested1() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var @string = _compilation.GetSpecialType(SpecialType.System_String); + var outerTInt = _compilation.GetTypeByMetadataName("TestClasses.Outer`1").Construct(@int); + var outerTIntInnerVString = outerTInt.GetTypeMembers().Single().Construct(@string); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer.Inner).GetMethod("Method0"), + containingTypeSymbol: outerTIntInnerVString, + methodSymbol: outerTIntInnerVString.FindMethod("Method0"), + fullTypeName: "TestClasses.Outer`1+Inner`1", + fullMethodName: "Method0"); + } + + [TestMethod] + public void ClosedGenericNested2() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var @string = _compilation.GetSpecialType(SpecialType.System_String); + var outerTInt = _compilation.GetTypeByMetadataName("TestClasses.Outer`1").Construct(@int); + var outerTIntInnerVString = outerTInt.GetTypeMembers().Single().Construct(@string); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer.Inner).GetMethod("Method1"), + containingTypeSymbol: outerTIntInnerVString, + methodSymbol: outerTIntInnerVString.FindMethod("Method1"), + fullTypeName: "TestClasses.Outer`1+Inner`1", + fullMethodName: "Method1(!0)"); + } + + [TestMethod] + public void ClosedGenericNested3() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var @string = _compilation.GetSpecialType(SpecialType.System_String); + var outerTInt = _compilation.GetTypeByMetadataName("TestClasses.Outer`1").Construct(@int); + var outerTIntInnerVString = outerTInt.GetTypeMembers().Single().Construct(@string); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer.Inner).GetMethod("Method2"), + containingTypeSymbol: outerTIntInnerVString, + methodSymbol: outerTIntInnerVString.FindMethod("Method2"), + fullTypeName: "TestClasses.Outer`1+Inner`1", + fullMethodName: "Method2(!1)"); + } + + [TestMethod] + public void ClosedGenericNested4() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var @string = _compilation.GetSpecialType(SpecialType.System_String); + var outerTInt = _compilation.GetTypeByMetadataName("TestClasses.Outer`1").Construct(@int); + var outerTIntInnerVString = outerTInt.GetTypeMembers().Single().Construct(@string); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer.Inner).GetMethod("Method3"), + containingTypeSymbol: outerTIntInnerVString, + methodSymbol: outerTIntInnerVString.FindMethod("Method3"), + fullTypeName: "TestClasses.Outer`1+Inner`1", + fullMethodName: "Method3`1(!0,!!0,!1)"); + } + + [TestMethod] + public void ClosedGenericNested5() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var @string = _compilation.GetSpecialType(SpecialType.System_String); + var outerTInt = _compilation.GetTypeByMetadataName("TestClasses.Outer`1").Construct(@int); + var outerTIntInnerVString = outerTInt.GetTypeMembers().Single().Construct(@string); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer.Inner).GetMethod("Method4"), + containingTypeSymbol: outerTIntInnerVString, + methodSymbol: outerTIntInnerVString.FindMethod("Method4"), + fullTypeName: "TestClasses.Outer`1+Inner`1", + fullMethodName: "Method4`2(!!1,!!0)"); + } + + [TestMethod] + public void ClosedGenericMethod1() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var @string = _compilation.GetSpecialType(SpecialType.System_String); + var outerTInt = _compilation.GetTypeByMetadataName("TestClasses.Outer`1").Construct(@int); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer).GetMethod("Method3").MakeGenericMethod(typeof(string)), + containingTypeSymbol: outerTInt, + methodSymbol: outerTInt.FindMethod("Method3").Construct(@string), + fullTypeName: "TestClasses.Outer`1", + fullMethodName: "Method3`1(!0,!!0)"); + } + + [TestMethod] + public void ClosedGenericMethod2() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var outerInner = _compilation.GetTypeByMetadataName("TestClasses.Outer+Inner"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer.Inner).GetMethod("Method2").MakeGenericMethod(typeof(int)), + containingTypeSymbol: outerInner, + methodSymbol: outerInner.FindMethod("Method2").Construct(@int), + fullTypeName: "TestClasses.Outer+Inner", + fullMethodName: "Method2`1(System.Int32)"); + } + + [TestMethod] + public void ClosedGenericMethod3() + { + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var @float = _compilation.GetSpecialType(SpecialType.System_Single); + var @string = _compilation.GetSpecialType(SpecialType.System_String); + var outerInner = _compilation.GetTypeByMetadataName("TestClasses.Outer+Inner"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Outer.Inner).GetMethod("Method3").MakeGenericMethod(typeof(float), typeof(string)), + containingTypeSymbol: outerInner, + methodSymbol: outerInner.FindMethod("Method3").Construct(@float, @string), + fullTypeName: "TestClasses.Outer+Inner", + fullMethodName: "Method3`2(System.Int32)"); + } + + [TestMethod] + public void ExplicitInterfaceImplementation1() + { + var impl = _compilation.GetTypeByMetadataName("TestClasses.Impl"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Impl).GetMethod("TestClasses.IImplementation.ImplMethod0", PrivateBindingFlags), + containingTypeSymbol: impl, + methodSymbol: impl.FindMethod("TestClasses.IImplementation.ImplMethod0"), + fullTypeName: "TestClasses.Impl", + fullMethodName: "TestClasses.IImplementation.ImplMethod0"); + } + + [TestMethod] + public void ExplicitInterfaceImplementation2() + { + var impl = _compilation.GetTypeByMetadataName("TestClasses.Impl"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Impl).GetMethod("TestClasses.IImplementation.ImplMethod1", PrivateBindingFlags), + containingTypeSymbol: impl, + methodSymbol: impl.FindMethod("TestClasses.IImplementation.ImplMethod1"), + fullTypeName: "TestClasses.Impl", + fullMethodName: "TestClasses.IImplementation.ImplMethod1(System.Int32)"); + } + + [TestMethod] + public void GenericExplicitInterfaceImplementation1() + { + var implT = _compilation.GetTypeByMetadataName("TestClasses.Impl`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Impl<>).GetMethod("TestClasses.IImplementation.ImplMethod0", PrivateBindingFlags), + containingTypeSymbol: implT, + methodSymbol: implT.FindMethod("TestClasses.IImplementation.ImplMethod0"), + fullTypeName: "TestClasses.Impl`1", + fullMethodName: "TestClasses.IImplementation.ImplMethod0"); + } + + [TestMethod] + public void GenericExplicitInterfaceImplementation2() + { + var implT = _compilation.GetTypeByMetadataName("TestClasses.Impl`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Impl<>).GetMethod("TestClasses.IImplementation.ImplMethod1", PrivateBindingFlags), + containingTypeSymbol: implT, + methodSymbol: implT.FindMethod("TestClasses.IImplementation.ImplMethod1"), + fullTypeName: "TestClasses.Impl`1", + fullMethodName: "TestClasses.IImplementation.ImplMethod1(!0)"); + } + + [TestMethod] + public void GenericExplicitInterfaceImplementation3() + { + var implT = _compilation.GetTypeByMetadataName("TestClasses.Impl`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Impl<>).GetMethod("TestClasses.IImplementation.ImplMethod2", PrivateBindingFlags), + containingTypeSymbol: implT, + methodSymbol: implT.FindMethod("TestClasses.IImplementation.ImplMethod2"), + fullTypeName: "TestClasses.Impl`1", + fullMethodName: "TestClasses.IImplementation.ImplMethod2`1(!0,!!0,System.String)"); + } + + [TestMethod] + public void Inheritance1() + { + var outerPrime = _compilation.GetTypeByMetadataName("TestClasses.OuterPrime"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.OuterPrime).GetMethod("Method3"), + containingTypeSymbol: outerPrime, + methodSymbol: outerPrime.FindMethod("Method3"), + fullTypeName: "TestClasses.OuterPrime", + fullMethodName: "Method3(System.String,System.Int32)"); + } + + [TestMethod] + public void Inheritance2() + { + var outerPrimeZ = _compilation.GetTypeByMetadataName("TestClasses.OuterPrime`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.OuterPrime<>).GetMethod("Method3"), + containingTypeSymbol: outerPrimeZ, + methodSymbol: outerPrimeZ.FindMethod("Method3"), + fullTypeName: "TestClasses.OuterPrime`1", + fullMethodName: "Method3`1(!0,!!0)"); + } + + [TestMethod] + public void Inheritance3() + { + var outerPrimeYZ = _compilation.GetTypeByMetadataName("TestClasses.OuterPrime`2"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.OuterPrime<,>).GetMethod("Method3"), + containingTypeSymbol: outerPrimeYZ, + methodSymbol: outerPrimeYZ.FindMethod("Method3"), + fullTypeName: "TestClasses.OuterPrime`2", + fullMethodName: "Method3`1(!1,!!0)"); + } + + [TestMethod] + public void Inheritance4() + { + var outerString = _compilation.GetTypeByMetadataName("TestClasses.OuterString"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.OuterString).GetMethod("Method3"), + containingTypeSymbol: outerString, + methodSymbol: outerString.FindMethod("Method3"), + fullTypeName: "TestClasses.OuterString", + fullMethodName: "Method3`1(System.String,!!0)"); + } + + [TestMethod] + public void Overloads1() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0()"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 0), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0"); + } + + [TestMethod] + public void Overloads2() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0(Int32)"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 0, @int), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0(System.Int32)"); + } + + [TestMethod] + public void Overloads3() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0(Int32, TestClasses.Overloads)"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 0, @int, overloads), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0(System.Int32,TestClasses.Overloads)"); + } + + [TestMethod] + public void Overloads4() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var intptr = _compilation.CreatePointerTypeSymbol(@int); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0(Int32*)"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 0, intptr), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0(System.Int32*)"); + } + + [TestMethod] + public void Overloads5() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + var dynamic = _compilation.DynamicType; + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0(System.Object)"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 0, dynamic), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0(System.Object)"); + } + + [TestMethod] + public void Overloads6() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U](U)"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 1, 1, m => m.Parameters.Single().Type == m.TypeParameters.Single()), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`1(!!0)"); + } + + [TestMethod] + public void Overloads7() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U]()"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 1), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`1"); + } + + [TestMethod] + public void Overloads8() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U,T]()"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 2), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`2"); + } + + [TestMethod] + public void Overloads9() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U](U[])"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 1, 1, + m => m.Parameters.Single().Type is IArrayTypeSymbol arrayType && + arrayType.Rank == 1 && + arrayType.ElementType == m.TypeParameters.Single()), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`1(!!0[])"); + } + + [TestMethod] + public void Overloads10() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U](U[][])"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 1, 1, + m => m.Parameters.Single().Type is IArrayTypeSymbol arrayType && + arrayType.Rank == 1 && + arrayType.ElementType is IArrayTypeSymbol innerArrayType && + innerArrayType.Rank == 1 && + innerArrayType.ElementType == m.TypeParameters.Single()), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`1(!!0[][])"); + } + + [TestMethod] + public void Overloads11() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U](U[,])"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 1, 1, + m => m.Parameters.Single().Type is IArrayTypeSymbol arrayType && + arrayType.Rank == 2 && + arrayType.ElementType == m.TypeParameters.Single()), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`1(!!0[,])"); + } + + [TestMethod] + public void Overloads12() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U](U[,,])"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 1, 1, + m => m.Parameters.Single().Type is IArrayTypeSymbol arrayType && + arrayType.Rank == 3 && + arrayType.ElementType == m.TypeParameters.Single()), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`1(!!0[,,])"); + } + + [TestMethod] + public void Overloads13() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + var @int = _compilation.GetSpecialType(SpecialType.System_Int32); + var listInt = _compilation.GetTypeByMetadataName("System.Collections.Generic.List`1").Construct(@int); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U](System.Collections.Generic.List`1[System.Int32])"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 1, listInt), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`1(System.Collections.Generic.List`1)"); + } + + [TestMethod] + public void Overloads14() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + var list = _compilation.GetTypeByMetadataName("System.Collections.Generic.List`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U](System.Collections.Generic.List`1[U])"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 1, 1, + m => + m.Parameters.Single().Type is INamedTypeSymbol p && + p.OriginalDefinition == list && + p.TypeArguments.Single() == m.TypeParameters.Single()), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`1(System.Collections.Generic.List`1)"); + } + + [TestMethod] + public void Overloads15() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + var tuple2 = _compilation.GetTypeByMetadataName("System.Tuple`2"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U,V](System.Tuple`2[U,V], System.Tuple`2[V,U])"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 2, 2, + m => + m.Parameters.First() is INamedTypeSymbol p1 && + p1.OriginalDefinition == tuple2 && + p1.TypeArguments.SequenceEqual(m.TypeParameters) && + m.Parameters.Last() is INamedTypeSymbol p2 && + p2.OriginalDefinition == tuple2 && + p2.TypeArguments.SequenceEqual(m.TypeParameters.Reverse())), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`2(System.Tuple`2,System.Tuple`2)"); + } + + [TestMethod] + public void Overloads16() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + var tuple1 = _compilation.GetTypeByMetadataName("System.Tuple`1"); + var tuple2 = _compilation.GetTypeByMetadataName("System.Tuple`2"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0(System.Tuple`1[System.Tuple`2[System.String[,],System.Int32]])"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 0, 1, + m => + m.Parameters.Single().Type is INamedTypeSymbol p && + p.OriginalDefinition == tuple1 && + p.TypeArguments.Single() is INamedTypeSymbol t && + t.OriginalDefinition == tuple2), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0(System.Tuple`1>)"); + } + + [TestMethod] + public void Overloads17() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + var tuple1 = _compilation.GetTypeByMetadataName("System.Tuple`1"); + var tuple2 = _compilation.GetTypeByMetadataName("System.Tuple`2"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0(System.Tuple`2[System.Tuple`1[System.String],System.Tuple`1[System.Int32]])"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 0, 1, + m => + m.Parameters.Single().Type is INamedTypeSymbol p && + p.OriginalDefinition == tuple2 && + p.TypeArguments.All(t => t.OriginalDefinition == tuple1)), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0(System.Tuple`2,System.Tuple`1>)"); + } + + [TestMethod] + public void Overloads18() + { + var overloads = _compilation.GetTypeByMetadataName("TestClasses.Overloads"); + var tuple1 = _compilation.GetTypeByMetadataName("System.Tuple`1"); + + VerifyRoundTrip( + methodInfo: typeof(TestClasses.Overloads).FindMethod("Void Overload0[U](System.Tuple`1[System.Tuple`1[TestClasses.Outer`1+Inner`1[U,U]]])"), + containingTypeSymbol: overloads, + methodSymbol: overloads.FindMethod("Overload0", 1, 1, + m => + m.Parameters.Single().Type is INamedTypeSymbol p && + p.OriginalDefinition == tuple1 && + p.TypeArguments.Single() is INamedTypeSymbol t && + t.OriginalDefinition == tuple1), + fullTypeName: "TestClasses.Overloads", + fullMethodName: "Overload0`1(System.Tuple`1>>)"); + } + + #region Helpers + private void VerifyRoundTrip( + MethodInfo methodInfo, + INamedTypeSymbol containingTypeSymbol, + IMethodSymbol methodSymbol, + string fullTypeName, + string fullMethodName) + { + VerifyRoundTripFromMethodInfo(methodInfo, fullTypeName, fullMethodName); + VerifyRoundTripFromName(fullTypeName, fullMethodName, methodInfo); + // VerifyRoundTripFromMethodSymbol(containingTypeSymbol, methodSymbol, fullTypeName, fullMethodName); + // VerifyRoundTripFromName(fullTypeName, fullMethodName, containingTypeSymbol, methodSymbol); + } + + private void VerifyRoundTripFromMethodInfo( + MethodInfo methodInfo, + string expectedFullTypeName, + string expectedFullMethodName) + { + // Generate the fqn for the Reflection MethodInfo + ManagedNameHelper.GetManagedName(methodInfo, out var fullTypeName, out var fullMethodName); + + Assert.AreEqual(expectedFullTypeName, fullTypeName); + Assert.AreEqual(expectedFullMethodName, fullMethodName); + + // Lookup the Reflection MethodInfo using fullTypeName and fullMethodName + var roundTrippedMethodInfo = ManagedNameHelper.GetManagedName( + Assembly.GetExecutingAssembly(), + fullTypeName, + fullMethodName); + + Assert.AreEqual(methodInfo.MetadataToken, roundTrippedMethodInfo.MetadataToken); + } + + private void VerifyRoundTripFromName( + string fullTypeName, + string fullMethodName, + MethodInfo expectedMethodInfo) + { + // Lookup the Reflection MethodInfo using fullTypeName and fullMethodName + var methodInfo = ManagedNameHelper.GetManagedName( + Assembly.GetExecutingAssembly(), + fullTypeName, + fullMethodName); + + Assert.AreEqual(expectedMethodInfo.MetadataToken, methodInfo.MetadataToken); + + // Generate the fqn for the Reflection MethodInfo + ManagedNameHelper.GetManagedName( + methodInfo, + out var roundTrippedFullTypeName, + out var roundTrippedFullMethodName); + + Assert.AreEqual(fullTypeName, roundTrippedFullTypeName); + Assert.AreEqual(fullMethodName, roundTrippedFullMethodName); + } + + // private void VerifyRoundTripFromMethodSymbol( + // INamedTypeSymbol containingTypeSymbol, + // IMethodSymbol methodSymbol, + // string expectedFullTypeName, + // string expectedFullMethodName) + // { + // // Generate the fqn for the Roslyn IMethodSymbol + // FullyQualifiedNameHelper.GetFullyQualifiedName( + // containingTypeSymbol, + // methodSymbol, + // out var fullTypeName, + // out var fullMethodName); + + // Assert.AreEqual(expectedFullTypeName, fullTypeName); + // Assert.AreEqual(expectedFullMethodName, fullMethodName); + + // // Lookup the Roslyn ITypeSymbol and IMethodSymbol using fullTypeName and fullMethodName + // var roundTrippedContainingTypeSymbol = _compilation.GetTypeByMetadataName(fullTypeName); + + // Assert.AreEqual(containingTypeSymbol.OriginalDefinition, roundTrippedContainingTypeSymbol.OriginalDefinition); + + // var roundTrippedMethodSymbol = FullyQualifiedNameHelper.GetMethodFromFullyQualifiedName( + // _compilation, + // fullTypeName, + // fullMethodName); + + // Assert.AreEqual(methodSymbol.OriginalDefinition, roundTrippedMethodSymbol.OriginalDefinition); + // } + + // private void VerifyRoundTripFromName( + // string fullTypeName, + // string fullMethodName, + // INamedTypeSymbol expectedContainingTypeSymbol, + // IMethodSymbol expectedMethodSymbol) + // { + // // Lookup the Roslyn ITypeSymbol and IMethodSymbol using fullTypeName and fullMethodName + // var containingTypeSymbol = _compilation.GetTypeByMetadataName(fullTypeName); + // + // Assert.AreEqual(expectedContainingTypeSymbol.OriginalDefinition, containingTypeSymbol.OriginalDefinition); + // + // var methodSymbol = FullyQualifiedNameHelper.GetMethodFromFullyQualifiedName( + // _compilation, + // fullTypeName, + // fullMethodName); + // + // Assert.AreEqual(expectedMethodSymbol.OriginalDefinition, methodSymbol.OriginalDefinition); + // + // // Generate the fqn for the Roslyn IMethodSymbol + // FullyQualifiedNameHelper.GetFullyQualifiedName( + // containingTypeSymbol, + // methodSymbol, + // out var roundTrippedFullTypeName, + // out var roundTrippedFullMethodName); + // + // Assert.AreEqual(fullTypeName, roundTrippedFullTypeName); + // Assert.AreEqual(fullMethodName, roundTrippedFullMethodName); + // } + #endregion + } +} diff --git a/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests.csproj b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests.csproj new file mode 100644 index 0000000000..87797a50dc --- /dev/null +++ b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests.csproj @@ -0,0 +1,30 @@ + + + + ..\..\ + true + + + + netcoreapp2.1 + Exe + Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests + true + 3.8.0-3.20427.2 + $(NoWarn);RS1024 + + + + + + + + + + + PreserveNewest + + + + + diff --git a/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/Program.cs b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/Program.cs new file mode 100644 index 0000000000..fbe5689406 --- /dev/null +++ b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/Program.cs @@ -0,0 +1,12 @@ +// 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.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests +{ + public static class Program + { + public static void Main(string[] args) + { + } + } +} \ No newline at end of file diff --git a/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/TestClasses.cs b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/TestClasses.cs new file mode 100644 index 0000000000..f40b044ec0 --- /dev/null +++ b/test/Microsoft.TestPlatform.ObjectModel.ManagedNameUtilities.UnitTests/TestClasses.cs @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace TestClasses +{ + using System; + using System.Collections.Generic; + + internal class Outer + { + public void Method0() { } + public void Method1(int i) { } + public void Method2(List ls) { } + public void Method3(string p, int l) { } + internal class Inner + { + public void Method0() { } + public void Method1(int i) { } + public void Method2(int i) { } + public void Method3(int i) { } + } + } + + internal class OuterPrime : Outer { } + + internal class Outer + { + public void Method0() { } + public void Method1(T t) { } + public void Method2(U[] u) { } + public void Method3(T t, U u) { } + + internal class Inner + { + public void Method0() { } + public void Method1(T t) { } + public void Method2(V v) { } + public void Method3(T t, U u, V v) { } + public void Method4(X x, U u) { } + public void Method5(List x, U u) { } + + internal class MoreInner + { + public void Method0(T t, V v, I i, U u) { } + } + } + } + + internal class OuterPrime : Outer { } + + internal class OuterPrime : Outer { } + + internal class OuterString : Outer { } + + internal interface IImplementation + { + void ImplMethod0(); + void ImplMethod1(int i); + } + + internal class Impl : IImplementation + { + void IImplementation.ImplMethod0() { } + void IImplementation.ImplMethod1(int i) { } + } + + internal interface IImplementation + { + void ImplMethod0(); + void ImplMethod1(T t); + void ImplMethod2(T t, U u, string s); + } + + internal class Impl : IImplementation + { + void IImplementation.ImplMethod0() { } + void IImplementation.ImplMethod1(T t) { } + void IImplementation.ImplMethod2(T t, U u, string s) { } + } + + internal class Overloads + { + public void Overload0() { } + public void Overload0(int i) { } + public void Overload0(int i, Overloads c) { } + public unsafe void Overload0(int* p) { } + public void Overload0(dynamic d) { } + public void Overload0(U u) { } + public void Overload0() { } + public void Overload0() { } + public void Overload0(U[] u) { } + public void Overload0(U[][] u) { } + public void Overload0(U[,] u) { } + public void Overload0(U[,,] u) { } + public void Overload0(List l) { } + public void Overload0(List l) { } + public void Overload0(Tuple t0, Tuple t1) { } + public void Overload0(Tuple> t0) { } + public void Overload0(Tuple, Tuple> t) { } + public void Overload0(Tuple.Inner>> t) { } + } +}