Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failure to load dependency assembly causes hang #460

Closed
jnm2 opened this issue Feb 23, 2018 · 8 comments · Fixed by #462 or #464
Closed

Failure to load dependency assembly causes hang #460

jnm2 opened this issue Feb 23, 2018 · 8 comments · Fixed by #462 or #464

Comments

@jnm2
Copy link
Contributor

jnm2 commented Feb 23, 2018

Using the 3.10 dev VSIX (2f4079d, https://ci.appveyor.com/project/CharliePoole/nunit3-vs-adapter/build/3.10.0-dev-00750/artifacts).

There's one project where in the process of locating navigation info, we call GetCustomAttributes(testMethod) which causes our navigation provider's reflection-only appdomain to try to load nunit.framework.dll and fail to locate it.

I had added some fail-safety and it will continue on and succeed, but it's so slow. In this one project, it calls GetCustomAttributes on so many test methods (each of which causes the nunit.framework.dll load failure) that it appears to hang for an unacceptably long time.

I don't yet know why it fails to find nunit.framework.dll, but before we fix that, I want to add another circuit breaker. I wonder what the best approach is—disable calls to GetStateMachineType for the current test assembly after the first exception, and same for GetDeclaringType?

Stack trace
 	[Managed to Native Transition]	
>	mscorlib.dll!System.ModuleHandle.ResolveMethodHandleInternalCore(System.Reflection.RuntimeModule module, int methodToken, System.IntPtr[] typeInstantiationContext, int typeInstCount, System.IntPtr[] methodInstantiationContext, int methodInstCount)	Unknown
 	mscorlib.dll!System.ModuleHandle.ResolveMethodHandleInternal(System.Reflection.RuntimeModule module, int methodToken, System.RuntimeTypeHandle[] typeInstantiationContext, System.RuntimeTypeHandle[] methodInstantiationContext)	Unknown
 	mscorlib.dll!System.Reflection.CustomAttributeData.CustomAttributeData(System.Reflection.RuntimeModule scope, System.Reflection.CustomAttributeRecord caRecord)	Unknown
 	mscorlib.dll!System.Reflection.CustomAttributeData.GetCustomAttributes(System.Reflection.RuntimeModule module, int tkTarget)	Unknown
 	mscorlib.dll!System.Reflection.CustomAttributeData.GetCustomAttributesInternal(System.Reflection.RuntimeMethodInfo target)	Unknown
 	mscorlib.dll!System.Reflection.RuntimeMethodInfo.GetCustomAttributesData()	Unknown
 	mscorlib.dll!System.Reflection.CustomAttributeData.GetCustomAttributes(System.Reflection.MemberInfo target)	Unknown
 	NUnit3.TestAdapter.dll!NUnit.VisualStudio.TestAdapter.Metadata.DirectReflectionMetadataProvider.GetStateMachineType(string assemblyPath, string reflectedTypeName, string methodName)	Unknown
 	NUnit3.TestAdapter.dll!NUnit.VisualStudio.TestAdapter.Metadata.ReflectionAppDomainMetadataProvider.AppDomainHelper.GetStateMachineType(string assemblyPath, string reflectedTypeName, string methodName)	Unknown
 	[Native to Managed Transition]	
 	[Managed to Native Transition]	
 	mscorlib.dll!System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage msg)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Messaging.ServerObjectTerminatorSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage reqMsg)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Lifetime.LeaseSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage msg)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Messaging.ServerContextTerminatorSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage reqMsg)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Channels.CrossContextChannel.SyncProcessMessageCallback(object[] args)	Unknown
 	mscorlib.dll!System.Threading.Thread.CompleteCrossContextCallback(System.Threading.InternalCrossContextDelegate ftnToCall, object[] args)	Unknown
 	[Native to Managed Transition]	
 	[Managed to Native Transition]	
 	mscorlib.dll!System.Runtime.Remoting.Channels.CrossContextChannel.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage reqMsg)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Channels.ChannelServices.SyncDispatchMessage(System.Runtime.Remoting.Messaging.IMessage msg)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(byte[] reqStmBuff, System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage smuggledMcm, out System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage smuggledMrm)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(object[] args)	Unknown
 	mscorlib.dll!System.Threading.Thread.CompleteCrossContextCallback(System.Threading.InternalCrossContextDelegate ftnToCall, object[] args)	Unknown
 	[AppDomain (testhost.x86.exe�, #1) -> AppDomain (NUnit.VisualStudio.TestAdapter.Metadata.ReflectionAppDomainMetadataProvider�, #9)]	
 	mscorlib.dll!System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatch(byte[] reqStmBuff, System.Runtime.Remoting.Messaging.SmuggledMethodCallMessage smuggledMcm, out System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage smuggledMrm)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Channels.CrossAppDomainSink.SyncProcessMessage(System.Runtime.Remoting.Messaging.IMessage reqMsg)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Proxies.RemotingProxy.CallProcessMessage(System.Runtime.Remoting.Messaging.IMessageSink ms, System.Runtime.Remoting.Messaging.IMessage reqMsg, System.Runtime.Remoting.Contexts.ArrayWithSize proxySinks, System.Threading.Thread currentThread, System.Runtime.Remoting.Contexts.Context currentContext, bool bSkippingContextChain)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(System.Runtime.Remoting.Messaging.IMethodCallMessage reqMcmMsg, bool useDispatchMessage, int callType)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage reqMsg)	Unknown
 	mscorlib.dll!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref System.Runtime.Remoting.Proxies.MessageData msgData, int type)	Unknown
 	NUnit3.TestAdapter.dll!NUnit.VisualStudio.TestAdapter.Metadata.ReflectionAppDomainMetadataProvider.GetStateMachineType(string assemblyPath, string reflectedTypeName, string methodName)	Unknown
 	NUnit3.TestAdapter.dll!NUnit.VisualStudio.TestAdapter.NavigationDataProvider.DoSafe(System.Func<string, string, string, NUnit.VisualStudio.TestAdapter.Metadata.TypeInfo?> method, string assemblyPath, string declaringTypeName, string methodName)	Unknown
 	NUnit3.TestAdapter.dll!NUnit.VisualStudio.TestAdapter.NavigationDataProvider.GetNavigationData(string className, string methodName)	Unknown
 	NUnit3.TestAdapter.dll!NUnit.VisualStudio.TestAdapter.TestConverter.MakeTestCaseFromXmlNode(System.Xml.XmlNode testNode)	Unknown
 	NUnit3.TestAdapter.dll!NUnit.VisualStudio.TestAdapter.TestConverter.ConvertTestCase(System.Xml.XmlNode testNode)	Unknown
 	NUnit3.TestAdapter.dll!NUnit.VisualStudio.TestAdapter.NUnit3TestExecutor.RunAssembly(string assemblyPath, NUnit.Engine.TestFilter filter)	Unknown
 	NUnit3.TestAdapter.dll!NUnit.VisualStudio.TestAdapter.NUnit3TestExecutor.RunTests(System.Collections.Generic.IEnumerable<string> sources, Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter.IRunContext runContext, Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter.IFrameworkHandle frameworkHandle)	Unknown
 	Microsoft.TestPlatform.CrossPlatEngine.dll!Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution.RunTestsWithSources.InvokeExecutor(Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities.LazyExtension<Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter.ITestExecutor, Microsoft.VisualStudio.TestPlatform.Common.Interfaces.ITestExecutorCapabilities> executor, System.Tuple<System.Uri, string> executorUriExtensionTuple, Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Adapter.RunContext runContext, Microsoft.VisualStudio.TestPlatform.ObjectModel.Adapter.IFrameworkHandle frameworkHandle)	Unknown
 	Microsoft.TestPlatform.CrossPlatEngine.dll!Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution.BaseRunTests.RunTestInternalWithExecutors.AnonymousMethod__0()	Unknown
 	Microsoft.TestPlatform.PlatformAbstractions.dll!Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.PlatformThread.Run.AnonymousMethod__0()	Unknown
 	mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state)	Unknown
 	mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)	Unknown
 	mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)	Unknown
 	mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state)	Unknown
 	mscorlib.dll!System.Threading.ThreadHelper.ThreadStart()	Unknown

I'll prioritize this above everything else.

/cc @OsirisTerje for implementation questions above and for 3.10 planning.

@jnm2
Copy link
Contributor Author

jnm2 commented Feb 24, 2018

This reproduces the failure to find nunit.framework.dll:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net462</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="NUnit" Version="3.9.0" />
  </ItemGroup>

</Project>
using NUnit.Framework;
using System.Threading.Tasks;

namespace NUnitNotFoundRepro
{
    public class Class1
    {
        [Test]
        public static async Task Foo()
        {
        }
    }
}

@jnm2 jnm2 closed this as completed in #462 Feb 26, 2018
@jnm2 jnm2 reopened this Feb 26, 2018
@jnm2
Copy link
Contributor Author

jnm2 commented Feb 26, 2018

Next up: fixing the load failure. Turns out it's a lot harder than it looks to set up a test for this scenario.

@OsirisTerje
Copy link
Member

@jnm2 You reopened this , and says PR #462 fixes it. But from your comment it seems this is only a partial fix? Have I got that right?
And, this needs to be fixed before we can release 3.10, right? So I agree it is critical.

Can you explain how you see these breakers working? I am not quite getting what you're trying to achieve here (my understanding is lacking :-) )
Are they just to kill off the tests ? If so, why run them at all until the underlying issue is fixed?

The cause of the underlying issue is what is uncertain here, right? Does this in any way match the issues we had earlier with the DIA stuff?

@jnm2
Copy link
Contributor Author

jnm2 commented Feb 26, 2018

The underlying cause is known.

Before #462: If an async test method has an attribute and the attribute class is defined in an assembly that is not in the same directory as the test adapter, 1) navigation data goes missing AND 2) test case conversion runs so slowly (produces and catches so many FileNotFoundExceptions) it appears to hang.

I fixed 2) in #462 and I want to fix 1) tonight.

An example of when this happens: you're running the VSIX which doesn't have nunit.framework.dll in the same folder as the test adapter assembly, and you have an async method with [Test] on it. The reflection-only AppDomain we set up causes a FileNotFoundException for nunit.framework.dll when we call CustomAttributeData.GetCustomAttributes, for every async or derived test case in every project.

In order to actually test this properly, we must have an attribute defined in an assembly which is not in the same folder as our test project's bin output because that's where the adapter assembly is running from.

Having tried both using local projects and CodeDOM, my current try is to target net46 on the test project and use Roslyn to set up two such assemblies in a temp folder. The issue with Roslyn is that we have to run in-appdomain with VSTest for DiaSession to work, at which point VSTest has already loaded an ancient version of System.Collections.Immutable into that AppDomain. Every version of Roslyn that I tried caused MissingMethodException because it was compiled against a newer version of S.C.Immutable.
So I'm setting up a new AppDomain just to do the compilation; once the assemblies are generated on disk, the test can run like any other test. This is where I ended last night.

@jnm2
Copy link
Contributor Author

jnm2 commented Feb 27, 2018

Hooray! Setting up the AppDomain to get Roslyn to work was easy. My brain last night was not working.

@jnm2
Copy link
Contributor Author

jnm2 commented Feb 27, 2018

Test is failing beautifully. =)

@jnm2
Copy link
Contributor Author

jnm2 commented Feb 27, 2018

The tests are always the hard part. Fixed in five minutes.

@jnm2
Copy link
Contributor Author

jnm2 commented Feb 27, 2018

General note: I overstated the problem. It's not all navigation data that goes missing; it's only the navigation we have to help DiaSession find: async methods and base class methods.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment