-
Notifications
You must be signed in to change notification settings - Fork 152
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
nunit-console ignores deps.json file #1311
Comments
Yes, and you can use System.Runtime.Loader.AssemblyDependencyResolver for that to parse dependencies: System.Runtime.Loader.AssemblyDependencyResolver resolver = new AssemblyDependencyResolver("testAssemby.dll"); |
@svg2003 Actually the 3.16 engine does use the This is a difficult and almost completely undocumented area of .NET. If you know something about it you may want to consider making a contribution to solve this problem. |
Interesting. When I got source code, build it and replace my official version with new net6.0 agent - it seems starts load them smoothly. And I noticed - it (new version) doesn't have Microsoft.Extensions.DependencyModel.dll file in net6.0 folder at all. |
Seems Microsoft.Extensions.DependencyModel (or some logic, based on it) broke everything. Test works fine in 3.15.2 (where I don't see Microsoft.Extensions.DependencyModel.dll in agents\net6.0 folder), and fails in 3.16.0, 3.16.1 and 3.16.2 |
Of course, some tests don't pass in 3.15.2, and pass in 3.16.2. In particular, assemblies from dependent packages, which are not copied by .NET cannot be opened. Hopefully, someone still on the @nunit/engine-team is reading this. :-) |
I recall, I fixed some magic errors about "Cannot load XXX or their dependencies", changing framework in runtimeconfig.json for agent. Yes, it's not too good to change official config manually, and I'd rather to pass them (deps.json and runtimeconfig.json) as some command line parameters, but it is, what it is. "runtimeOptions": { PS. Let's keep original error, so google could index it and help other people to resolve the similar error 12:05:16.046 281>EXEC : 18) error : TestXXX.TestProcessMessageWithSpecialChars [] |
In fact, at one point, I had that as an additional framework (along with asp.net core) but that led to #1274. :-( |
People usually know what target they are going to test (including target and runtime), so, might be, if they could have option to pass runtimeconfig.json for agent as command line option, it would help. |
That's possible, although ideally I'd rather see the console just know how to load things the way Microsoft does. Hopefully, somebody will pick up this project soon and improve this area one way or another. |
After more tests, I've decided to keep 3.16.2. Indeed some assemblies are not loaded in 3.15.2, some in 3.16.2. |
@svg2003 Is the case where a reference assembly is present in the output directory the only regression you have seen? I have a suspicion as to where that error may be found in the code. |
If I remember correct, for latest 3.16.2, I have 2 issues (actually there are more, but they are different). Sorry, after all edits, message became pretty big. Hopefully, it will help Let's look on them with System.Threading.AccessControl package structure. I'm not sure about terminology, so would reference on files and folders structure from appropriate nuget package. 1. My test assembly (targeted to net6) use class from System.Threading.AccessControl explicitly in test code
Then, I have System.Threading.AccessControl.dll file from system.threading.accesscontrol.6.0.0\lib\net6.0\ package folder next to my test.dll test assembly and nunit-console would load this file. 1: Loaded assembly: G:\Net6.Test\Rhino.Mocks.Standard.dll Errors, Failures and Warnings
When I manually delete a file, test passed with below dependencies: 1: Loaded assembly: G:\Net6.Test\Rhino.Mocks.Standard.dll Here is a deps.json and if I will manually copy (or what 3.15.2 version does, load it from runtime folder), test also would pass
2. My test assembly (targeted to net6) does not use class from System.Threading.AccessControl explicitly in test code. But it's used in tested class, targeted to net472, might be through the some dependencies chain like AssemblyA.Foo -> AssemblyB.Goo
1: Loaded assembly: G:\Net6.Test\Rhino.Mocks.Standard.dll Errors, Failures and Warnings
With manually deleted file - test is passed: 1: Loaded assembly: G:\Net6.Test\Rhino.Mocks.Standard.dll From MSVS test run (trough the Reshaper): 1: Loaded assembly: G:\Net6.Test\Rhino.Mocks.Standard.dll |
@svg2003 Thanks for all that! I'll experiment with it and post if I come up with anything. |
Hi @CharliePoole , Did you have a chance to look on it? And seems for System.Configurationion.ConfigurationManager it's even worse - we have 2 loaded assemblies and class, that is using configuration.GetSection() call (a lot of legacy code could do it) throw an exception about wrong inheritance. System.Configuration.ConfigurationErrorsException : An error occurred creating the configuration section handler: Type 'XxxSection' does not inherit from 'System.Configuration.IConfigurationSectionHandler'. In domain: System.Configuration.ConfigurationManager, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51 at C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\6.0.13\System.Configuration.ConfigurationManager.dll |
Sorry @svg2003, I am impacted by this issue too (in TestCentric GUI) so I'd like to see a solution but I haven't had the time to dig any deeper as this week is very busy for me. |
That's fine, don't worry. I hope I could have a time to take a look tomorrow or on Friday. |
I quick looked through the code and added some debug prints, and seems here are the issues. 1. Assembly can be loaded twice:
If assembly in domain, code will execute base.Load() that may produce undefined behavior. Sometimes it will return you null assembly, sometimes, loaded from another place. I'd suggest you either delete it completely or change condition to ' == null ' 2. OnResolving callback would be never called, if assembly is next to the test assembly. Seems callback will be called only if you return null in Load(), so this condition would be executed first You will return wrong assembly (not from deps.json file). That's why I see my original issue with System.ThreadingAccessControl.dll So, probably need to call resolver explicitly here 3. Resolving logic works incorrect I frankly have no idea how resolver class is working, but (when I deleted assembly manually), it's NOT resolved from deps.json. So, to summarize, I'd do something like this: internal sealed class TestAssemblyLoadContext : AssemblyLoadContext
|
I used above code in our project and it solved both mentioned cases and seems does not bring any new issues. I'd appreciate, if you would ask someone from nunit team (or could do it yourselves), to create PR and deploy new version with fix. |
@svg2003 Did you actually get rid of the deps.json issue with the PR? When working with the adapter now, it doesn't stop that. (Note: I haven't read all of the text above in detail.....) |
Could you please elaborate, what are you talking about? I don't use adapter and don't know what is it and how it affects anything. Just for test dll, it fixed the issue for cases with managed assemblies. Native DLLs still cannot be loaded properly at some cases, but I frankly, didn't check why. |
@svg2003 I assumed the error you saw when raising this issue is the same one I see when I add 3.16.2 to the adapter code, not being able to find the Microsoft.Extensions.DependencyModel package. But I see now you have a different error message. |
Closed as it fixed here |
Could you please somehow provide a way to load dependencies for netcore test assemblies from .deps.json file, instead of loading dependencies from files next to the test dll?
I'm using latest 3.16.2 nunit console and have below test.
In output - (in g:\Net6.Test folder) mytest.dll and System.Threading.AccessControl.dll.
When I start it from nunit-console, test throws an error due to wrong dependencies.
System.ArgumentNullException : Value cannot be null. (Parameter 'identity')
at System.Security.AccessControl.AuthorizationRule..ctor(IdentityReference identity, Int32 accessMask, Boolean isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
at System.Security.AccessControl.AccessRule..ctor(IdentityReference identity, Int32 accessMask, Boolean isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)
at System.Security.AccessControl.EventWaitHandleAccessRule..ctor(IdentityReference identity, EventWaitHandleRights eventRights, AccessControlType type)
at Amat.CgaFE.Bridge.TemporaryNet6Tests.Test.NUnitTestFixture1.TestDeps() in G:\TemporaryNet6Tests.Test\NUnitTestFixture1.cs:line 71
Run Settings
DisposeRunners: True
InternalTraceLevel: Verbose
ImageRuntimeVersion: 4.0.30319
ImageTargetFrameworkName: .NETCoreApp,Version=v6.0
ImageRequiresX86: False
ImageRequiresDefaultAppDomainAssemblyResolver: False
TargetRuntimeFramework: netcore-6.0
NumberOfTestWorkers: 32
So, I started to print assemblies location into console and here is the difference:
From MSVS (I'm using Resharper.TestRunner there):
IdentityAssembly: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.11\System.Security.Principal.Windows.dll, v4.0.30319
EventWaitHandleAccessRule: G:\Net6.Test\runtimes\win\lib\net6.0\System.Threading.AccessControl.dll, v4.0.30319
This is correct - System.Threading.AccessControl.dll is loaded from deps.json file for test assembly.
From nunit-console: - System.Threading.AccessControl.dll assembly loaded from wrong path, next to the mytest.dll.
IdentityAssembly: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.11\System.Security.Principal.Windows.dll, v4.0.30319
EventWaitHandleAccessRule: G:\Net6.Test\System.Threading.AccessControl.dll, v4.0.30319
Errors, Failures and Warnings
System.ArgumentNullException : Value cannot be null. (Parameter 'identity')
at System.Security.AccessControl.AuthorizationRule..ctor(IdentityReference identity, Int32 accessMask, Boolean isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags)
at System.Security.AccessControl.AccessRule..ctor(IdentityReference identity, Int32 accessMask, Boolean isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)
at System.Security.AccessControl.EventWaitHandleAccessRule..ctor(IdentityReference identity, EventWaitHandleRights eventRights, AccessControlType type)
at Amat.CgaFE.Bridge.TemporaryNet6Tests.Test.NUnitTestFixture1.TestDeps() ...
From nunit-console, but I manually deleted System.Threading.AccessControl.dll file from a folder - now test passed, but assembly is loaded NOT from real dependencies again:
IdentityAssembly: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\6.0.11\System.Security.Principal.Windows.dll, v4.0.30319
EventWaitHandleAccessRule: C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\6.0.11\System.Threading.AccessControl.dll, v4.0.30319
Test Run Summary
Overall result: Warning
Test Count: 8, Passed: 6, Failed: 0, Warnings: 0, Inconclusive: 0, Skipped: 2
The text was updated successfully, but these errors were encountered: