From 9574f08d4902b18e9db2deb01b2b0e74526fa401 Mon Sep 17 00:00:00 2001 From: Youssef1313 <youssefvictor00@gmail.com> Date: Fri, 17 Jan 2025 14:21:14 +0100 Subject: [PATCH] Simplify reflection --- .../Discovery/AssemblyEnumerator.cs | 2 +- .../Discovery/TestMethodValidator.cs | 2 +- .../Discovery/TypeValidator.cs | 2 +- .../Execution/TestClassInfo.cs | 10 +-- .../Execution/TestMethodInfo.cs | 8 +- .../Execution/TestMethodRunner.cs | 4 +- .../MSTest.TestAdapter/Execution/TypeCache.cs | 14 ++-- .../Helpers/AttributeComparer.cs | 14 ---- .../Helpers/ReflectHelper.cs | 82 ++++--------------- .../Discovery/TestMethodValidatorTests.cs | 4 +- .../Discovery/TypeValidatorTests.cs | 4 +- .../Execution/TypeCacheTests.cs | 30 +++---- .../Helpers/ReflectHelperTests.cs | 10 +-- 13 files changed, 59 insertions(+), 127 deletions(-) delete mode 100644 src/Adapter/MSTest.TestAdapter/Helpers/AttributeComparer.cs diff --git a/src/Adapter/MSTest.TestAdapter/Discovery/AssemblyEnumerator.cs b/src/Adapter/MSTest.TestAdapter/Discovery/AssemblyEnumerator.cs index 74654b6bca..69c5d1e277 100644 --- a/src/Adapter/MSTest.TestAdapter/Discovery/AssemblyEnumerator.cs +++ b/src/Adapter/MSTest.TestAdapter/Discovery/AssemblyEnumerator.cs @@ -359,7 +359,7 @@ private static bool TryUnfoldITestDataSources(UnitTestElement test, TestMethodIn // We don't have a special method to filter attributes that are not derived from Attribute, so we take all // attributes and filter them. We don't have to care if there is one, because this method is only entered when // there is at least one (we determine this in TypeEnumerator.GetTestFromMethod. - IEnumerable<ITestDataSource> testDataSources = ReflectHelper.Instance.GetDerivedAttributes<Attribute>(testMethodInfo.MethodInfo, inherit: false).OfType<ITestDataSource>(); + IEnumerable<ITestDataSource> testDataSources = ReflectHelper.Instance.GetAttributes<Attribute>(testMethodInfo.MethodInfo, inherit: false).OfType<ITestDataSource>(); // We need to use a temporary list to avoid adding tests to the main list if we fail to expand any data source. List<UnitTestElement> tempListOfTests = new(); diff --git a/src/Adapter/MSTest.TestAdapter/Discovery/TestMethodValidator.cs b/src/Adapter/MSTest.TestAdapter/Discovery/TestMethodValidator.cs index 2669c119ad..043a3e7d60 100644 --- a/src/Adapter/MSTest.TestAdapter/Discovery/TestMethodValidator.cs +++ b/src/Adapter/MSTest.TestAdapter/Discovery/TestMethodValidator.cs @@ -53,7 +53,7 @@ internal virtual bool IsValidTestMethod(MethodInfo testMethodInfo, Type type, IC // but the difference is quite small, and we don't expect a huge amount of non-test methods in the assembly. // // Also skip all methods coming from object, because they cannot be tests. - if (testMethodInfo.DeclaringType == typeof(object) || !_reflectHelper.IsDerivedAttributeDefined<TestMethodAttribute>(testMethodInfo, inherit: false)) + if (testMethodInfo.DeclaringType == typeof(object) || !_reflectHelper.IsAttributeDefined<TestMethodAttribute>(testMethodInfo, inherit: false)) { return false; } diff --git a/src/Adapter/MSTest.TestAdapter/Discovery/TypeValidator.cs b/src/Adapter/MSTest.TestAdapter/Discovery/TypeValidator.cs index 9e8e1c98d6..b82623ca7c 100644 --- a/src/Adapter/MSTest.TestAdapter/Discovery/TypeValidator.cs +++ b/src/Adapter/MSTest.TestAdapter/Discovery/TypeValidator.cs @@ -52,7 +52,7 @@ internal virtual bool IsValidTestClass(Type type, List<string> warnings) // gives us a better performance. // It would be possible to use non-caching reflection here if we knew that we are only doing discovery that won't be followed by run, // but the difference is quite small, and we don't expect a huge amount of non-test classes in the assembly. - if (!type.IsClass || !_reflectHelper.IsDerivedAttributeDefined<TestClassAttribute>(type, inherit: false)) + if (!type.IsClass || !_reflectHelper.IsAttributeDefined<TestClassAttribute>(type, inherit: false)) { return false; } diff --git a/src/Adapter/MSTest.TestAdapter/Execution/TestClassInfo.cs b/src/Adapter/MSTest.TestAdapter/Execution/TestClassInfo.cs index 2139e2340b..4d5261ecd3 100644 --- a/src/Adapter/MSTest.TestAdapter/Execution/TestClassInfo.cs +++ b/src/Adapter/MSTest.TestAdapter/Execution/TestClassInfo.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Extensions; @@ -411,7 +411,7 @@ internal UnitTestResult GetResultOrRunClassInitialize(ITestContext testContext, DebugEx.Assert(!IsClassInitializeExecuted, "If class initialize was executed, we should have been in the previous if were we have a result available."); - bool isSTATestClass = AttributeComparer.IsDerived<STATestClassAttribute>(ClassAttribute); + bool isSTATestClass = ClassAttribute is STATestClassAttribute; bool isWindowsOS = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); if (isSTATestClass && isWindowsOS @@ -631,7 +631,7 @@ internal void ExecuteClassCleanup(TestContext testContext) if (classCleanupMethod is not null) { if (ClassAttribute.IgnoreMessage is null && - !ReflectHelper.Instance.IsNonDerivedAttributeDefined<IgnoreAttribute>(classCleanupMethod.DeclaringType!, false)) + !ReflectHelper.Instance.IsAttributeDefined<IgnoreAttribute>(classCleanupMethod.DeclaringType!, false)) { ClassCleanupException = InvokeCleanupMethod(classCleanupMethod, remainingCleanupCount: BaseClassCleanupMethods.Count, testContext); } @@ -643,7 +643,7 @@ internal void ExecuteClassCleanup(TestContext testContext) { classCleanupMethod = BaseClassCleanupMethods[i]; if (ClassAttribute.IgnoreMessage is null && - !ReflectHelper.Instance.IsNonDerivedAttributeDefined<IgnoreAttribute>(classCleanupMethod.DeclaringType!, false)) + !ReflectHelper.Instance.IsAttributeDefined<IgnoreAttribute>(classCleanupMethod.DeclaringType!, false)) { ClassCleanupException = InvokeCleanupMethod(classCleanupMethod, remainingCleanupCount: BaseClassCleanupMethods.Count - 1 - i, testContext); if (ClassCleanupException is not null) @@ -711,7 +711,7 @@ internal void RunClassCleanup(ITestContext testContext, ClassCleanupManager clas return; } - bool isSTATestClass = AttributeComparer.IsDerived<STATestClassAttribute>(ClassAttribute); + bool isSTATestClass = ClassAttribute is STATestClassAttribute; bool isWindowsOS = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); if (isSTATestClass && isWindowsOS diff --git a/src/Adapter/MSTest.TestAdapter/Execution/TestMethodInfo.cs b/src/Adapter/MSTest.TestAdapter/Execution/TestMethodInfo.cs index 4085813c23..6551b6c106 100644 --- a/src/Adapter/MSTest.TestAdapter/Execution/TestMethodInfo.cs +++ b/src/Adapter/MSTest.TestAdapter/Execution/TestMethodInfo.cs @@ -95,11 +95,11 @@ internal TestMethodInfo( internal RetryBaseAttribute? RetryAttribute { get; } - public Attribute[]? GetAllAttributes(bool inherit) => ReflectHelper.Instance.GetDerivedAttributes<Attribute>(TestMethod, inherit).ToArray(); + public Attribute[]? GetAllAttributes(bool inherit) => ReflectHelper.Instance.GetAttributes<Attribute>(TestMethod, inherit).ToArray(); public TAttributeType[] GetAttributes<TAttributeType>(bool inherit) where TAttributeType : Attribute - => ReflectHelper.Instance.GetDerivedAttributes<TAttributeType>(TestMethod, inherit).ToArray(); + => ReflectHelper.Instance.GetAttributes<TAttributeType>(TestMethod, inherit).ToArray(); /// <summary> /// Execute test method. Capture failures, handle async and return result. @@ -231,7 +231,7 @@ public virtual TestResult Invoke(object?[]? arguments) try { - expectedExceptions = ReflectHelper.Instance.GetDerivedAttributes<ExpectedExceptionBaseAttribute>(TestMethod, inherit: true); + expectedExceptions = ReflectHelper.Instance.GetAttributes<ExpectedExceptionBaseAttribute>(TestMethod, inherit: true); } catch (Exception ex) { @@ -267,7 +267,7 @@ public virtual TestResult Invoke(object?[]? arguments) /// </returns> private RetryBaseAttribute? GetRetryAttribute() { - IEnumerable<RetryBaseAttribute> attributes = ReflectHelper.Instance.GetDerivedAttributes<RetryBaseAttribute>(TestMethod, inherit: true); + IEnumerable<RetryBaseAttribute> attributes = ReflectHelper.Instance.GetAttributes<RetryBaseAttribute>(TestMethod, inherit: true); using IEnumerator<RetryBaseAttribute> enumerator = attributes.GetEnumerator(); if (!enumerator.MoveNext()) { diff --git a/src/Adapter/MSTest.TestAdapter/Execution/TestMethodRunner.cs b/src/Adapter/MSTest.TestAdapter/Execution/TestMethodRunner.cs index 249301cd2d..1c4ddb68f3 100644 --- a/src/Adapter/MSTest.TestAdapter/Execution/TestMethodRunner.cs +++ b/src/Adapter/MSTest.TestAdapter/Execution/TestMethodRunner.cs @@ -64,8 +64,8 @@ public TestMethodRunner(TestMethodInfo testMethodInfo, TestMethod testMethod, IT /// <returns>The test results.</returns> internal List<TestResult> Execute(string initializationLogs, string initializationErrorLogs, string initializationTrace, string initializationTestContextMessages) { - bool isSTATestClass = AttributeComparer.IsDerived<STATestClassAttribute>(_testMethodInfo.Parent.ClassAttribute); - bool isSTATestMethod = AttributeComparer.IsDerived<STATestMethodAttribute>(_testMethodInfo.TestMethodOptions.Executor); + bool isSTATestClass = _testMethodInfo.Parent.ClassAttribute is STATestClassAttribute; + bool isSTATestMethod = _testMethodInfo.TestMethodOptions.Executor is STATestMethodAttribute; bool isSTARequested = isSTATestClass || isSTATestMethod; bool isWindowsOS = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); if (isSTARequested && isWindowsOS && Thread.CurrentThread.GetApartmentState() != ApartmentState.STA) diff --git a/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs b/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs index 2b13c8384d..8323241a16 100644 --- a/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs +++ b/src/Adapter/MSTest.TestAdapter/Execution/TypeCache.cs @@ -397,7 +397,7 @@ private TestAssemblyInfo GetAssemblyInfo(Type type) try { // Only examine classes which are TestClass or derives from TestClass attribute - if (!_reflectionHelper.IsDerivedAttributeDefined<TestClassAttribute>(t, inherit: false)) + if (!_reflectionHelper.IsAttributeDefined<TestClassAttribute>(t, inherit: false)) { continue; } @@ -448,7 +448,7 @@ private bool IsAssemblyOrClassInitializeMethod<TInitializeAttribute>(MethodInfo // { // return false; // } - if (!_reflectionHelper.IsNonDerivedAttributeDefined<TInitializeAttribute>(methodInfo, false)) + if (!_reflectionHelper.IsAttributeDefined<TInitializeAttribute>(methodInfo, false)) { return false; } @@ -476,7 +476,7 @@ private bool IsAssemblyOrClassCleanupMethod<TCleanupAttribute>(MethodInfo method // { // return false; // } - if (!_reflectionHelper.IsNonDerivedAttributeDefined<TCleanupAttribute>(methodInfo, false)) + if (!_reflectionHelper.IsAttributeDefined<TCleanupAttribute>(methodInfo, false)) { return false; } @@ -607,8 +607,8 @@ private void UpdateInfoIfTestInitializeOrCleanupMethod( bool isBase, Dictionary<string, string?> instanceMethods) { - bool hasTestInitialize = _reflectionHelper.IsNonDerivedAttributeDefined<TestInitializeAttribute>(methodInfo, inherit: false); - bool hasTestCleanup = _reflectionHelper.IsNonDerivedAttributeDefined<TestCleanupAttribute>(methodInfo, inherit: false); + bool hasTestInitialize = _reflectionHelper.IsAttributeDefined<TestInitializeAttribute>(methodInfo, inherit: false); + bool hasTestCleanup = _reflectionHelper.IsAttributeDefined<TestCleanupAttribute>(methodInfo, inherit: false); if (!hasTestCleanup && !hasTestInitialize) { @@ -833,12 +833,12 @@ private void SetCustomProperties(TestMethodInfo testMethodInfo, ITestContext tes DebugEx.Assert(testMethodInfo != null, "testMethodInfo is Null"); DebugEx.Assert(testMethodInfo.TestMethod != null, "testMethodInfo.TestMethod is Null"); - IEnumerable<TestPropertyAttribute> attributes = _reflectionHelper.GetDerivedAttributes<TestPropertyAttribute>(testMethodInfo.TestMethod, inherit: true); + IEnumerable<TestPropertyAttribute> attributes = _reflectionHelper.GetAttributes<TestPropertyAttribute>(testMethodInfo.TestMethod, inherit: true); DebugEx.Assert(attributes != null, "attributes is null"); if (testMethodInfo.TestMethod.DeclaringType is { } testClass) { - attributes = attributes.Concat(_reflectionHelper.GetDerivedAttributes<TestPropertyAttribute>(testClass, inherit: true)); + attributes = attributes.Concat(_reflectionHelper.GetAttributes<TestPropertyAttribute>(testClass, inherit: true)); } foreach (TestPropertyAttribute attribute in attributes) diff --git a/src/Adapter/MSTest.TestAdapter/Helpers/AttributeComparer.cs b/src/Adapter/MSTest.TestAdapter/Helpers/AttributeComparer.cs deleted file mode 100644 index c82f46d996..0000000000 --- a/src/Adapter/MSTest.TestAdapter/Helpers/AttributeComparer.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Helpers; - -internal static class AttributeComparer -{ - public static bool IsNonDerived<TAttribute>(Attribute attribute) => - // We are explicitly checking the given type *exactly*. We don't want to consider inheritance. - // So, this should NOT be refactored to 'attribute is TAttribute'. - attribute.GetType() == typeof(TAttribute); - - public static bool IsDerived<TAttribute>(Attribute attribute) => attribute is TAttribute; -} diff --git a/src/Adapter/MSTest.TestAdapter/Helpers/ReflectHelper.cs b/src/Adapter/MSTest.TestAdapter/Helpers/ReflectHelper.cs index 7dcd86d56d..9800bd70ce 100644 --- a/src/Adapter/MSTest.TestAdapter/Helpers/ReflectHelper.cs +++ b/src/Adapter/MSTest.TestAdapter/Helpers/ReflectHelper.cs @@ -28,35 +28,6 @@ internal class ReflectHelper : MarshalByRefObject public static ReflectHelper Instance => InstanceValue.Value; - /// <summary> - /// Checks to see if a member or type is decorated with the given attribute. The type is checked exactly. If attribute is derived (inherits from) a class, e.g. [MyTestClass] from [TestClass] it won't match if you look for [TestClass]. The inherit parameter does not impact this checking. - /// </summary> - /// <remarks> - /// Note that because derived attribute types are not considered, <typeparamref name="TAttribute"/> should be sealed. - /// </remarks> - /// <typeparam name="TAttribute">Attribute to search for by fully qualified name.</typeparam> - /// <param name="memberInfo">Member/Type to test.</param> - /// <param name="inherit">Inspect inheritance chain of the member or class. E.g. if parent class has this attribute defined.</param> - /// <returns>True if the attribute of the specified type is defined on this member or a class.</returns> - public virtual bool IsNonDerivedAttributeDefined<TAttribute>(MemberInfo memberInfo, bool inherit) - where TAttribute : Attribute - { - Guard.NotNull(memberInfo); - - // Get attributes defined on the member from the cache. - Attribute[] attributes = GetCustomAttributesCached(memberInfo, inherit); - - foreach (Attribute attribute in attributes) - { - if (AttributeComparer.IsNonDerived<TAttribute>(attribute)) - { - return true; - } - } - - return false; - } - /// <summary> /// Checks to see if a member or type is decorated with the given attribute, or an attribute that derives from it. e.g. [MyTestClass] from [TestClass] will match if you look for [TestClass]. The inherit parameter does not impact this checking. /// </summary> @@ -64,7 +35,7 @@ public virtual bool IsNonDerivedAttributeDefined<TAttribute>(MemberInfo memberIn /// <param name="memberInfo">Member to inspect for attributes.</param> /// <param name="inherit">Inspect inheritance chain of the member or class. E.g. if parent class has this attribute defined.</param> /// <returns>True if the attribute of the specified type is defined on this member or a class.</returns> - public virtual /* for testing */ bool IsDerivedAttributeDefined<TAttribute>(MemberInfo memberInfo, bool inherit) + public virtual /* for testing */ bool IsAttributeDefined<TAttribute>(MemberInfo memberInfo, bool inherit) where TAttribute : Attribute { Guard.NotNull(memberInfo); @@ -77,7 +48,7 @@ public virtual bool IsNonDerivedAttributeDefined<TAttribute>(MemberInfo memberIn { DebugEx.Assert(attribute != null, $"{nameof(ReflectHelper)}.{nameof(GetCustomAttributesCached)}: internal error: wrong value in the attributes dictionary."); - if (AttributeComparer.IsDerived<TAttribute>(attribute)) + if (attribute is TAttribute) { return true; } @@ -98,31 +69,6 @@ public virtual bool IsNonDerivedAttributeDefined<TAttribute>(MemberInfo memberIn #endif public override object InitializeLifetimeService() => null!; - /// <summary> - /// Gets first attribute that matches the type (but is not derived from it). Use this together with attribute that is both sealed and does not allow multiple. - /// In such case there cannot be more attributes, and this will avoid the cost of - /// checking for more than one attribute. - /// </summary> - /// <typeparam name="TAttribute">Type of the attribute to find.</typeparam> - /// <param name="attributeProvider">The type, assembly or method.</param> - /// <param name="inherit">If we should inspect parents of this type.</param> - /// <returns>The attribute that is found or null.</returns> - public TAttribute? GetFirstNonDerivedAttributeOrDefault<TAttribute>(ICustomAttributeProvider attributeProvider, bool inherit) - where TAttribute : Attribute - { - Attribute[] cachedAttributes = GetCustomAttributesCached(attributeProvider, inherit); - - foreach (Attribute cachedAttribute in cachedAttributes) - { - if (AttributeComparer.IsNonDerived<TAttribute>(cachedAttribute)) - { - return (TAttribute)cachedAttribute; - } - } - - return null; - } - /// <summary> /// Gets first attribute that matches the type or is derived from it. /// Use this together with attribute that does not allow multiple. In such case there cannot be more attributes, and this will avoid the cost of @@ -140,9 +86,9 @@ public virtual bool IsNonDerivedAttributeDefined<TAttribute>(MemberInfo memberIn foreach (Attribute cachedAttribute in cachedAttributes) { - if (AttributeComparer.IsDerived<TAttribute>(cachedAttribute)) + if (cachedAttribute is TAttribute cachedAttributeAsTAttribute) { - return (TAttribute)cachedAttribute; + return cachedAttributeAsTAttribute; } } @@ -179,9 +125,9 @@ internal virtual bool IsMethodDeclaredInSameAssemblyAsType(MethodInfo method, Ty /// <returns>Categories defined.</returns> internal virtual /* for tests, we are mocking this */ string[] GetTestCategories(MemberInfo categoryAttributeProvider, Type owningType) { - IEnumerable<TestCategoryBaseAttribute> methodCategories = GetDerivedAttributes<TestCategoryBaseAttribute>(categoryAttributeProvider, inherit: true); - IEnumerable<TestCategoryBaseAttribute> typeCategories = GetDerivedAttributes<TestCategoryBaseAttribute>(owningType, inherit: true); - IEnumerable<TestCategoryBaseAttribute> assemblyCategories = GetDerivedAttributes<TestCategoryBaseAttribute>(owningType.Assembly, inherit: true); + IEnumerable<TestCategoryBaseAttribute> methodCategories = GetAttributes<TestCategoryBaseAttribute>(categoryAttributeProvider, inherit: true); + IEnumerable<TestCategoryBaseAttribute> typeCategories = GetAttributes<TestCategoryBaseAttribute>(owningType, inherit: true); + IEnumerable<TestCategoryBaseAttribute> assemblyCategories = GetAttributes<TestCategoryBaseAttribute>(owningType.Assembly, inherit: true); return methodCategories.Concat(typeCategories).Concat(assemblyCategories).SelectMany(c => c.TestCategories).ToArray(); } @@ -240,8 +186,8 @@ internal static TestIdGenerationStrategy GetTestIdGenerationStrategy(Assembly as /// <param name="owningType">The type that owns <paramref name="testMethod"/>.</param> /// <returns>True if test method should not run in parallel.</returns> internal bool IsDoNotParallelizeSet(MemberInfo testMethod, Type owningType) - => IsDerivedAttributeDefined<DoNotParallelizeAttribute>(testMethod, inherit: true) - || IsDerivedAttributeDefined<DoNotParallelizeAttribute>(owningType, inherit: true); + => IsAttributeDefined<DoNotParallelizeAttribute>(testMethod, inherit: true) + || IsAttributeDefined<DoNotParallelizeAttribute>(owningType, inherit: true); /// <summary> /// Get the parallelization behavior for a test assembly. @@ -327,11 +273,11 @@ internal static bool IsDoNotParallelizeSet(Assembly assembly) /// <returns>List of traits.</returns> internal virtual IEnumerable<Trait> GetTestPropertiesAsTraits(MemberInfo testPropertyProvider) { - IEnumerable<TestPropertyAttribute> testPropertyAttributes = GetDerivedAttributes<TestPropertyAttribute>(testPropertyProvider, inherit: true); + IEnumerable<TestPropertyAttribute> testPropertyAttributes = GetAttributes<TestPropertyAttribute>(testPropertyProvider, inherit: true); if (testPropertyProvider.DeclaringType is { } testClass) { - testPropertyAttributes = testPropertyAttributes.Concat(GetDerivedAttributes<TestPropertyAttribute>(testClass, inherit: true)); + testPropertyAttributes = testPropertyAttributes.Concat(GetAttributes<TestPropertyAttribute>(testClass, inherit: true)); } foreach (TestPropertyAttribute testProperty in testPropertyAttributes) @@ -348,7 +294,7 @@ internal virtual IEnumerable<Trait> GetTestPropertiesAsTraits(MemberInfo testPro /// <param name="attributeProvider">The member to inspect.</param> /// <param name="inherit">Look at inheritance chain.</param> /// <returns>An instance of the attribute.</returns> - internal virtual /* for tests, for moq */ IEnumerable<TAttributeType> GetDerivedAttributes<TAttributeType>(ICustomAttributeProvider attributeProvider, bool inherit) + internal virtual /* for tests, for moq */ IEnumerable<TAttributeType> GetAttributes<TAttributeType>(ICustomAttributeProvider attributeProvider, bool inherit) where TAttributeType : Attribute { Attribute[] attributes = GetCustomAttributesCached(attributeProvider, inherit); @@ -358,9 +304,9 @@ internal virtual IEnumerable<Trait> GetTestPropertiesAsTraits(MemberInfo testPro { DebugEx.Assert(attribute != null, "ReflectHelper.DefinesAttributeDerivedFrom: internal error: wrong value in the attributes dictionary."); - if (AttributeComparer.IsDerived<TAttributeType>(attribute)) + if (attribute is TAttributeType attributeAsAttributeType) { - yield return (TAttributeType)attribute; + yield return attributeAsAttributeType; } } } diff --git a/test/UnitTests/MSTestAdapter.UnitTests/Discovery/TestMethodValidatorTests.cs b/test/UnitTests/MSTestAdapter.UnitTests/Discovery/TestMethodValidatorTests.cs index ef2d8b35b7..c12268190f 100644 --- a/test/UnitTests/MSTestAdapter.UnitTests/Discovery/TestMethodValidatorTests.cs +++ b/test/UnitTests/MSTestAdapter.UnitTests/Discovery/TestMethodValidatorTests.cs @@ -34,7 +34,7 @@ public TestMethodValidatorTests() public void IsValidTestMethodShouldReturnFalseForMethodsWithoutATestMethodAttributeOrItsDerivedAttributes() { _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<UTF.TestMethodAttribute>(It.IsAny<MemberInfo>(), false)).Returns(false); + rh => rh.IsAttributeDefined<UTF.TestMethodAttribute>(It.IsAny<MemberInfo>(), false)).Returns(false); Verify(!_testMethodValidator.IsValidTestMethod(_mockMethodInfo.Object, _type, _warnings)); } @@ -183,7 +183,7 @@ public void WhenDiscoveryOfInternalsIsEnabledIsValidTestMethodShouldReturnFalseF #endregion private void SetupTestMethod() => _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<UTF.TestMethodAttribute>(It.IsAny<MemberInfo>(), false)).Returns(true); + rh => rh.IsAttributeDefined<UTF.TestMethodAttribute>(It.IsAny<MemberInfo>(), false)).Returns(true); } #region Dummy types diff --git a/test/UnitTests/MSTestAdapter.UnitTests/Discovery/TypeValidatorTests.cs b/test/UnitTests/MSTestAdapter.UnitTests/Discovery/TypeValidatorTests.cs index 68687c1bd7..d1ce91ead0 100644 --- a/test/UnitTests/MSTestAdapter.UnitTests/Discovery/TypeValidatorTests.cs +++ b/test/UnitTests/MSTestAdapter.UnitTests/Discovery/TypeValidatorTests.cs @@ -49,7 +49,7 @@ public void IsValidTestClassShouldReturnTrueForClassesMarkedByAnAttributeDerived { _mockReflectHelper.Setup(rh => rh.IsNonDerivedAttributeDefined<UTF.TestClassAttribute>(It.IsAny<TypeInfo>(), false)).Returns(false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<UTF.TestClassAttribute>(It.IsAny<TypeInfo>(), false)).Returns(true); + rh => rh.IsAttributeDefined<UTF.TestClassAttribute>(It.IsAny<TypeInfo>(), false)).Returns(true); Verify(_typeValidator.IsValidTestClass(typeof(TypeValidatorTests), _warnings)); } @@ -393,7 +393,7 @@ private static Type[] GetAllTestTypes() #region private methods - private void SetupTestClass() => _mockReflectHelper.Setup(rh => rh.IsDerivedAttributeDefined<UTF.TestClassAttribute>(It.IsAny<TypeInfo>(), false)).Returns(true); + private void SetupTestClass() => _mockReflectHelper.Setup(rh => rh.IsAttributeDefined<UTF.TestClassAttribute>(It.IsAny<TypeInfo>(), false)).Returns(true); #endregion } diff --git a/test/UnitTests/MSTestAdapter.UnitTests/Execution/TypeCacheTests.cs b/test/UnitTests/MSTestAdapter.UnitTests/Execution/TypeCacheTests.cs index 2398bd2457..65fc5893da 100644 --- a/test/UnitTests/MSTestAdapter.UnitTests/Execution/TypeCacheTests.cs +++ b/test/UnitTests/MSTestAdapter.UnitTests/Execution/TypeCacheTests.cs @@ -233,7 +233,7 @@ public void GetTestMethodInfoShouldCacheAssemblyInitializeAttribute() var testMethod = new TestMethod("TestInit", type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<AssemblyInitializeAttribute>(type.GetMethod("AssemblyInit"), false)).Returns(true); @@ -253,7 +253,7 @@ public void GetTestMethodInfoShouldCacheAssemblyCleanupAttribute() var testMethod = new TestMethod("TestCleanup", type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<AssemblyCleanupAttribute>(type.GetMethod("AssemblyCleanup"), false)).Returns(true); @@ -273,7 +273,7 @@ public void GetTestMethodInfoShouldCacheAssemblyInitAndCleanupAttribute() var testMethod = new TestMethod("TestInitOrCleanup", type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<AssemblyInitializeAttribute>(type.GetMethod("AssemblyInit"), false)).Returns(true); @@ -296,7 +296,7 @@ public void GetTestMethodInfoShouldThrowIfAssemblyInitHasIncorrectSignature() var testMethod = new TestMethod("M", type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<AssemblyInitializeAttribute>(type.GetMethod("AssemblyInit"), false)).Returns(true); @@ -326,7 +326,7 @@ public void GetTestMethodInfoShouldThrowIfAssemblyCleanupHasIncorrectSignature() var testMethod = new TestMethod("M", type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<AssemblyCleanupAttribute>(type.GetMethod("AssemblyCleanup"), false)).Returns(true); @@ -357,7 +357,7 @@ public void GetTestMethodInfoShouldCacheAssemblyInfoInstanceAndReuseTheCache() var testMethod = new TestMethod(methodInfo.Name, type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _typeCache.GetTestMethodInfo( testMethod, @@ -369,7 +369,7 @@ public void GetTestMethodInfoShouldCacheAssemblyInfoInstanceAndReuseTheCache() new TestContextImplementation(testMethod, new ThreadSafeStringWriter(null, "test"), new Dictionary<string, object>()), false); - _mockReflectHelper.Verify(rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false), Times.Once); + _mockReflectHelper.Verify(rh => rh.IsAttributeDefined<TestClassAttribute>(type, false), Times.Once); Verify(_typeCache.AssemblyInfoCache.Count == 1); } @@ -425,7 +425,7 @@ public void GetTestMethodInfoShouldCacheBaseClassInitializeAttributes() var testMethod = new TestMethod("TestMethod", type.FullName, "A", false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<ClassInitializeAttribute>(baseType.GetMethod("AssemblyInit"), false)).Returns(true); @@ -474,7 +474,7 @@ public void GetTestMethodInfoShouldCacheBaseClassCleanupAttributes() var testMethod = new TestMethod("TestMethod", type.FullName, "A", false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<ClassCleanupAttribute>(baseType.GetMethod("AssemblyCleanup"), false)).Returns(true); _mockReflectHelper.Setup( @@ -523,7 +523,7 @@ public void GetTestMethodInfoShouldCacheBaseClassInitAndCleanupAttributes() MethodInfo baseCleanupMethod = baseType.GetMethod("ClassCleanup"); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<ClassInitializeAttribute>(baseInitializeMethod, false)).Returns(true); @@ -623,7 +623,7 @@ public void GetTestMethodInfoShouldThrowIfClassInitHasIncorrectSignature() var testMethod = new TestMethod("M", type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<ClassInitializeAttribute>(type.GetMethod("AssemblyInit"), false)).Returns(true); @@ -653,7 +653,7 @@ public void GetTestMethodInfoShouldThrowIfClassCleanupHasIncorrectSignature() var testMethod = new TestMethod("M", type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<ClassCleanupAttribute>(type.GetMethod("AssemblyCleanup"), false)).Returns(true); @@ -723,7 +723,7 @@ public void GetTestMethodInfoShouldThrowIfTestInitOrCleanupHasIncorrectSignature var testMethod = new TestMethod("M", type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<TestInitializeAttribute>(type.GetMethod("TestInit"), false)).Returns(true); @@ -1277,7 +1277,7 @@ public void AssemblyInfoListWithExecutableCleanupMethodsShouldReturnEmptyListWhe var testMethod = new TestMethod(methodInfo.Name, type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<AssemblyCleanupAttribute>(type.GetMethod("AssemblyCleanup"), false)).Returns(false); @@ -1299,7 +1299,7 @@ public void AssemblyInfoListWithExecutableCleanupMethodsShouldReturnAssemblyInfo var testMethod = new TestMethod(methodInfo.Name, type.FullName, "A", isAsync: false); _mockReflectHelper.Setup( - rh => rh.IsDerivedAttributeDefined<TestClassAttribute>(type, false)).Returns(true); + rh => rh.IsAttributeDefined<TestClassAttribute>(type, false)).Returns(true); _mockReflectHelper.Setup( rh => rh.IsNonDerivedAttributeDefined<AssemblyCleanupAttribute>(type.GetMethod("AssemblyCleanup"), false)).Returns(true); diff --git a/test/UnitTests/MSTestAdapter.UnitTests/Helpers/ReflectHelperTests.cs b/test/UnitTests/MSTestAdapter.UnitTests/Helpers/ReflectHelperTests.cs index 54a001d1e8..5ea8ae6689 100644 --- a/test/UnitTests/MSTestAdapter.UnitTests/Helpers/ReflectHelperTests.cs +++ b/test/UnitTests/MSTestAdapter.UnitTests/Helpers/ReflectHelperTests.cs @@ -201,7 +201,7 @@ public void HasAttributeDerivedFromShouldReturnTrueIfSpecifiedAttributeIsDefined Setup(ro => ro.GetCustomAttributes(mockMemberInfo.Object, true)). Returns(attributes); - Verify(rh.IsDerivedAttributeDefined<TestMethodAttribute>(mockMemberInfo.Object, true)); + Verify(rh.IsAttributeDefined<TestMethodAttribute>(mockMemberInfo.Object, true)); } public void HasAttributeDerivedFromShouldReturnFalseIfSpecifiedAttributeIsNotDefinedOnAMember() @@ -231,10 +231,10 @@ public void HasAttributeDerivedFromShouldReturnFromCache() Setup(ro => ro.GetCustomAttributes(memberInfo, true)). Returns(attributes); - Verify(rh.IsDerivedAttributeDefined<TestMethodAttribute>(memberInfo, true)); + Verify(rh.IsAttributeDefined<TestMethodAttribute>(memberInfo, true)); // Validate that reflection APIs are not called again. - Verify(rh.IsDerivedAttributeDefined<TestMethodAttribute>(memberInfo, true)); + Verify(rh.IsAttributeDefined<TestMethodAttribute>(memberInfo, true)); _testablePlatformServiceProvider.MockReflectionOperations.Verify(ro => ro.GetCustomAttributes(memberInfo, true), Times.Once); // Also validate that reflection APIs for an individual type is not called since the cache gives us what we need already. @@ -275,8 +275,8 @@ public void GettingAttributesShouldNotReturnInheritedAttributesWhenAskingForNonI Setup(ro => ro.GetCustomAttributes(It.IsAny<Type>(), /* inherit */ false)). Returns([new TestClassAttribute()]); - TestClassAttribute[] inheritedAttributes = rh.GetDerivedAttributes<TestClassAttribute>(typeof(object), inherit: true).ToArray(); - TestClassAttribute[] nonInheritedAttributes = rh.GetDerivedAttributes<TestClassAttribute>(typeof(object), inherit: false).ToArray(); + TestClassAttribute[] inheritedAttributes = rh.GetAttributes<TestClassAttribute>(typeof(object), inherit: true).ToArray(); + TestClassAttribute[] nonInheritedAttributes = rh.GetAttributes<TestClassAttribute>(typeof(object), inherit: false).ToArray(); Verify(inheritedAttributes.Length == 2); Verify(nonInheritedAttributes.Length == 1);