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

Failed to resolve assembly while trying to run AltCover on some projects #156

Closed
zarzyckipawel opened this issue Jun 15, 2022 · 13 comments
Closed
Labels
enhancement Third party Problem lies in a consumed library which may or may not have a work-round

Comments

@zarzyckipawel
Copy link

When I tried to run tests with altcover on my codebase. AltCover failed with following error for 15 out of 132 test projects. I am using altcover 8.2.837. Any chance you can help me with that? I Cannot find anything common in those projects that make them differ from the rest yet.
The "AltCover.Prepare" task failed unexpectedly.
Mono.Cecil.ResolutionException: Failed to resolve System.Windows.Threading.DispatcherPriority
at Mono.Cecil.Mixin.CheckedResolve(TypeReference self)
at Mono.Cecil.MetadataBuilder.GetConstantType(TypeReference constant_type, Object constant)
at Mono.Cecil.MetadataBuilder.AddConstant(IConstantProvider owner, TypeReference type)
at Mono.Cecil.MetadataBuilder.AddParameter(UInt16 sequence, ParameterDefinition parameter, ParamTable table)
at Mono.Cecil.MetadataBuilder.AddParameters(MethodDefinition method)
at Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
at Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
at Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
at Mono.Cecil.MetadataBuilder.AddTypes()
at Mono.Cecil.MetadataBuilder.BuildTypes()
at Mono.Cecil.MetadataBuilder.BuildModule()
at Mono.Cecil.MetadataBuilder.BuildMetadata()
at Mono.Cecil.ModuleWriter.<>c.b__2_0(MetadataBuilder builder, MetadataReader )
at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func'3 read)
at Mono.Cecil.ModuleWriter.BuildMetadata(ModuleDefinition module, MetadataBuilder metadata)
at Mono.Cecil.ModuleWriter.Write(ModuleDefinition module, Disposable'1 stream, WriterParameters parameters)
at Mono.Cecil.ModuleWriter.WriteModule(ModuleDefinition module, Disposable'1 stream, WriterParameters parameters)
at Mono.Cecil.ModuleDefinition.Write(Stream stream, WriterParameters parameters)
at Mono.Cecil.AssemblyDefinition.Write(Stream stream, WriterParameters parameters)
at AltCover.Instrument.I.write@542-1(AssemblyDefinition a, String p, WriterParameters pk) in ///AltCover.Engine/Instrument.fs:line 546
at AltCover.Instrument.I.writeAssembly(AssemblyDefinition assembly, String path) in ///AltCover.Engine/Instrument.fs:line 553
at AltCover.Instrument.I.writeAssemblies(AssemblyDefinition definition, String file, IEnumerable'1 targets, FSharpFunc'2 sink) in ///AltCover.Engine/Instrument.fs:line 910
at AltCover.Instrument.I.visitAfterAssembly(InstrumentContext state, AssemblyEntry assembly) in ///AltCover.Engine/Instrument.fs:line 1172
at AltCover.Instrument.I.instrumentationVisitorWrapper(FSharpFunc'2 core, InstrumentContext state, Node node) in ///AltCover.Engine/Instrument.fs:line 1514
at [email protected](T node) in ///AltCover.Engine/Visitor.fs:line 1520
at Microsoft.FSharp.Primitives.Basics.List.mapToFreshConsTail[a,b](FSharpList'1 cons, FSharpFunc'2 f, FSharpList'1 x) in D:\a_work\1\s\src\fsharp\FSharp.Core\local.fs:line 237
at Microsoft.FSharp.Primitives.Basics.List.map[T,TResult](FSharpFunc'2 mapping, FSharpList'1 x) in D:\a_work\1\s\src\fsharp\FSharp.Core\local.fs:line 248
at Microsoft.FSharp.Collections.SeqModule.Fold[T,TState](FSharpFunc'2 folder, TState state, IEnumerable'1 source) in D:\a_work\1\s\src\fsharp\FSharp.Core\seq.fs:line 731
at AltCover.Visitor.visit(IEnumerable'1 visitors, IEnumerable'1 assemblies) in ///AltCover.Engine/Visitor.fs:line 1506
at [email protected](Unit unitVar0) in ///AltCover.Engine/Main.fs:line 705
at AltCover.CommandLine.I.doPathOperation[a](FSharpFunc'2 f, a defaultValue, Boolean store) in ///AltCover.Engine/CommandLine.fs:line 248
at [email protected](FSharpFunc'2 f, a defaultValue, Boolean store) in ///AltCover.Engine/CommandLine.fs:line 490
at AltCover.Main.I.doInstrumentation(String[] arguments) in ///AltCover.Engine/Main.fs:line 681
at AltCover.Main.I.main(String[] arguments) in ///AltCover.Engine/Main.fs:line 756
at [email protected](String[] arguments) in ///AltCover.Engine/Main.fs:line 762
at AltCover.Prepare.Execute() in /_//AltCover.Engine/Tasks.fs:line 191
at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
at Microsoft.Build.BackEnd.TaskBuilder.ExecuteInstantiatedTask(ITaskExecutionHost taskExecutionHost, TaskLoggingContext taskLoggingContext, TaskHost taskHost, ItemBucket bucket, TaskExecutionMode howToExecuteTask)

@SteveGilham
Copy link
Owner

Working through the Mono.Cecil code in the stack trace, it looks like this has to do with the way constant values are compiled in .Net -- they get inlined into the consuming assembly. The resolution failure is happening for an enum type, and is provoked when there is no associated assembly for the type. The particular enum is defined in an assembly that will be included in resolution searches, so clearly the association is being lost somewhere.

This looks like it's going to be an interesting problem to resolve. For the moment I'm still in the stage of experimenting to confirm/disprove some of my guesses on the subject.

@zarzyckipawel
Copy link
Author

zarzyckipawel commented Jun 17, 2022

Your comment made me look for strane enums in the source code of a problematic project. The only one I found was containing an enum defiend as public enum WindowShowStyle : uint but when I changed it to just public enum WindowShowStyle it didn't help with our problem here. Is there anything else that I can do to help you pinpoint the issue?

@SteveGilham
Copy link
Owner

The enum type involved is the one in the exception message, System.Windows.Threading.DispatcherPriority, defined in windowsbase.dll but used elsewhere. It seems from its description the sort of thing most likely used inside one of the GUI libraries that builds on top of that assembly.

If you can find a minimal repoduction case which you can share, that would be ideal; otherwise I'll keep working on building one myself.

@zarzyckipawel
Copy link
Author

zarzyckipawel commented Jun 17, 2022

I think I managed to get to a minimal reproduction case
Tests.zip

@SteveGilham
Copy link
Owner

Thank you for that.

Alas, the zip file doesn't contain the ..\ClassLibrary1\ClassLibrary1.csproj referenced from Test.csproj; instrumenting with dotnet test /p:AltCover=true completed successfully. I suspect that whatever was in the missing library project would be the cause of the issue.

@zarzyckipawel
Copy link
Author

zarzyckipawel commented Jun 17, 2022

Sorry about that. In this zip everything should be in the right place.
repos.zip

@SteveGilham
Copy link
Owner

That did the trick. And it's less complicated than the scenario I had been expecting to see. The ClassLibrary1 assembly does directly reference WindowsBase.dll; the difference from the usual cases is that this is a .Net Framework assembly referencing something in the GAC that doesn't get copied alongside the built binaries, as opposed to something in the nuget cache that doesn't.

So it should just be a matter of adding the GAC to the internal search path where appropriate.

As a work-round adding an explicit --dependency=C:\WINDOWS\Microsoft.NET\assembly\GAC_MSIL\WindowsBase\v4.0_4.0.0.0__31bf3856ad364e35\WindowsBase.dll should point the process in the correct direction; however trying it through dotnet test is showing a problem with the MSBuild integration that I also need to fix..

Oh, this is fun!

@SteveGilham
Copy link
Owner

SteveGilham commented Jun 18, 2022

I now have a workaround -- copy the indicated WindowsBase.dll assembly as above from the GAC to the build output directory before instrumenting.

This has also identified the following third-party issues I need to work around

  • For dotnet test (at least), arguments like /p:[AnyName]=[path to].dll (and the matching .exe) don't get interpreted as property definitions but as pure file paths
  • In the whole process up to the point of failure, Mono.Cecil does not try then fail to resolve the WindowsBase assembly, so simply extending the existing mechanism (implicit, or explicit via --dependency) that handles assembly resolution will not by itself be sufficient.

@zarzyckipawel
Copy link
Author

The workaround works fine indeed. Both for the minimal reproduction case as for our real projects. Thank you!

@SteveGilham SteveGilham added enhancement Third party Problem lies in a consumed library which may or may not have a work-round labels Jun 20, 2022
@SteveGilham
Copy link
Owner

Further investigations have shown that the problem comes from the presence of a stub WindowsBase.dll v4.0.0.0 in C:\Program Files\dotnet\shared\Microsoft.NETCore.App\[version]. A program running in .net core (e.g. altcover in dotnet test) will pick that one up directly from the internal Cecil file search if the workround is not applied. If you run the .Net Framework version of AltCover (as a command line tool, for example), then the issue should not arise.

I've submitted an issue against Cecil for this case -- jbevain/cecil#863

@SteveGilham
Copy link
Owner

While there's not a lot I can do without reimplementing a good piece of the Cecil code -- the GAC search is not even compiled in the netstandard2.0 binaries, so ruling out reflective magic, what I can do is make the --dependency added files be checked ahead of the platform dependent Cecil assembly resolution process. Here's a work-in-progress build for testing -

altcover.8.3.677-github-pre.nupkg.zip

Note -- if you are directly using the dotnet test integration (rather than --dependency on the command line or some other scripting approach) the files supplied via p:/AltCoverDependencyList=<files> are both separated and terminated with a | - the trailing | there to persuade the command interpreter that this is not a file

@zarzyckipawel
Copy link
Author

Thank you. For now I can live with a workaround you suggested.

@SteveGilham SteveGilham added the ready to close Believed addressed, waiting to hear to the contrary label Jun 27, 2022
@SteveGilham
Copy link
Owner

SteveGilham commented Jun 30, 2022

The extra functionality in the pre-release build is no_w_ in release v8.3.838.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Third party Problem lies in a consumed library which may or may not have a work-round
Projects
None yet
Development

No branches or pull requests

2 participants