microsoft / vstest

Visual Studio Test Platform is the runner and engine that powers test explorer and vstest.console.
MIT License
898 stars 323 forks source link

`Microsoft.TestPlatform.CoreUtilities` doesn't have a `System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute` #4638

Closed RyuChigon closed 4 months ago

RyuChigon commented 1 year ago

Description

Hello, I have used Microsoft.NET.Test.Sdk for testing my service (.NET 6.0).

In my service, reflection is used for finding specific custom attributes. It is okay until Microsoft.NET.Test.Sdk 17.3.3 version.

However, when using Microsoft.NET.Test.Sdk v17.4.0, I faced a problem about getting custom attributes by using MethodInfo.GetCustomAttributes(Type, bool).

The reason is


assembly_ThrowFormatExceptionForInvalidCondition_17_4_0

This is the IL of Void ThrowFormatExceptionForInvalidCondition(string). It refers to System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute of Microsoft.TestPlatform.CoreUtilities.

I think Microsoft.VisualStudio.TestPlatform.Common.dll has wrong reference about System.Diagnostics.CodeAnalysis.

Could you solve this problem? Thank you :)


IL of Microsoft.TestPlatform.CoreUtilities v17.3.3

assembly_CoreUtilities_17_3_3

It includes DoesNotReturnAttribute


IL of Microsoft.TestPlatform.CoreUtilities v17.4.0

assembly_CoreUtilities_17_4_0

not include DoesNotReturnAttribute


Sample Code

using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var targetAssemblies = AppDomain.CurrentDomain.GetAssemblies();
            var targetTypes = targetAssemblies.SelectMany(assembly => assembly.GetTypes());

            var targetMethodBindingFlag
                = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly;

            var targetMethods = targetTypes.SelectMany(type => type.GetMethods(targetMethodBindingFlag));

            foreach (var method in targetMethods)
            {
                var attributes = method.GetCustomAttributes(); // TypeLoadException !!
            }
        }
    }
}

Dependencies


Diagnostic logs

  Message: 
Test method TestProject1.UnitTest1.TestMethod1 threw exception: 
System.TypeLoadException: Could not load type 'System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute' from assembly 'Microsoft.TestPlatform.CoreUtilities, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

  Stack Trace: 
ModuleHandle.ResolveType(QCallModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
ModuleHandle.ResolveTypeHandle(Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
CustomAttribute.FilterCustomAttributeRecord(MetadataToken caCtorToken, MetadataImport& scope, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1& derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctorWithParameters, Boolean& isVarArg)
CustomAttribute.AddCustomAttributes(ListBuilder`1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes)
CustomAttribute.GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, Boolean inherit)
RuntimeMethodInfo.GetCustomAttributes(Type attributeType, Boolean inherit)
Attribute.GetCustomAttributes(MemberInfo element, Boolean inherit)
CustomAttributeExtensions.GetCustomAttributes(MemberInfo element)
UnitTest1.TestMethod1() line 21

Environment

nohwnd commented 1 year ago

I think the reason for this is the same as #4624. The compiler attributes are emitted into the file as a polyfill and in packaging there are 2 versions of the dll put in the same folder. Those dlls are compatible on runtime, but they use different polyfills pointing at different types.

nohwnd commented 4 months ago

Duplicate of https://github.com/microsoft/vstest/issues/4624