SteveGilham / altcover

Cross-platform coverage gathering and processing tool set for dotnet/.Net Framework and Mono
MIT License
494 stars 17 forks source link

altcover fails with Fody injected code #178

Closed EMarshal closed 1 year ago

EMarshal commented 1 year ago

I've got a project where I'm trying to consolidate opencover/coverlet tests that uses PropertyChanged.Fody to inject code during compilation.

This breaks altcover. As one would expect, disabling Fody during build allows altcover to run, but then any tests that rely on the injected code will fail.

Are there any available workarounds to this?

I've created a solution reproducing the issue here: https://github.com/EMarshal/altcover_fody

SteveGilham commented 1 year ago

Having repro'd

The "AltCover.Prepare" task failed unexpectedly.
System.InvalidOperationException: 'Object reference not set to an instance of an object.' while visiting 'Method
  { Method = System.Void PropertyChanged.Fody_library.Class1::set_FodyModifiedProperty(System.Boolean)
    VisibleMethod = System.Void PropertyChanged.Fody_library.Class1::set_FodyModifiedProperty(System.Boolean)
    Inspection = Instrument
    Track =None
    DefaultVisitCount = None }'
 ---> System.NullReferenceException: Object reference not set to an instance of an object.
   at Mono.Cecil.Cil.MethodDebugInformation.GetSequencePoint(Instruction instruction)
   at AltCover.Visitor.I.firstOfSequencePoint(MethodDebugInformation dbg, Instruction i) in /_//AltCover.Engine/Visitor.fs:line 1258
   at AltCover.Visitor.I.generated@1371(MethodDebugInformation dbg, Instruction i) in /_//AltCover.Engine/Visitor.fs:line 1372
   at AltCover.Visitor.I.extractBranchPoints@1386-12.Invoke(Instruction i) in /_//AltCover.Engine/Visitor.fs:line 1388
   at Microsoft.FSharp.Collections.Internal.IEnumerator.next@248[T](FSharpFunc`2 f, IEnumerator`1 e, FSharpRef`1 started, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 252
   at Microsoft.FSharp.Collections.Internal.IEnumerator.filter@238.System.Collections.IEnumerator.MoveNext() in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 254
   at Microsoft.FSharp.Collections.Internal.IEnumerator.map@99.DoMoveNext(b& curr) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 101
   at Microsoft.FSharp.Collections.Internal.IEnumerator.MapEnumerator`1.System.Collections.IEnumerator.MoveNext() in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 84
   at Microsoft.FSharp.Collections.Internal.IEnumerator.next@248[T](FSharpFunc`2 f, IEnumerator`1 e, FSharpRef`1 started, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 252
   at Microsoft.FSharp.Collections.Internal.IEnumerator.filter@238.System.Collections.IEnumerator.MoveNext() in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 254
   at Microsoft.FSharp.Collections.Internal.IEnumerator.map@99.DoMoveNext(b& curr) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 101
   at Microsoft.FSharp.Collections.Internal.IEnumerator.MapEnumerator`1.System.Collections.IEnumerator.MoveNext() in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 84
   at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeOuter@322[T,TResult](ConcatEnumerator`2 x, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seqcore.fs:line 323
   at Microsoft.FSharp.Collections.Internal.IEnumerator.mapi@116.DoMoveNext(b& curr) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line120
   at Microsoft.FSharp.Collections.Internal.IEnumerator.MapEnumerator`1.System.Collections.IEnumerator.MoveNext() in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 84
   at Microsoft.FSharp.Collections.Internal.IEnumerator.choose@211.System.Collections.IEnumerator.MoveNext() in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 222
   at AltCover.Visitor.I.extractBranchPoints(MethodDebugInformation dbg, IEnumerable rawInstructions, Boolean interesting, Exemption vc) in /_//AltCover.Engine/Visitor.fs:line 1383
   at AltCover.Visitor.I.visitMethod(MethodEntry m) in /_//AltCover.Engine/Visitor.fs:line 1547
   at AltCover.Visitor.I.wrap[a](FSharpFunc`2 op, Node node) in /_//AltCover.Engine/Visitor.fs:line 1562
   --- End of inner exception stack trace ---
   at AltCover.Visitor.I.wrap[a](FSharpFunc`2 op, Node node) in /_//AltCover.Engine/Visitor.fs:line 1582
   at AltCover.Visitor.I.sequenceBuilder(Node node) in /_//AltCover.Engine/Visitor.fs:line 1598
   at AltCover.Visitor.I.deeper@1591-4.Invoke(Node node)
   at Microsoft.FSharp.Collections.Internal.IEnumerator.map@99.DoMoveNext(b& curr) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 102
   at Microsoft.FSharp.Collections.Internal.IEnumerator.MapEnumerator`1.System.Collections.IEnumerator.MoveNext() in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 84
   at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeOuter@322[T,TResult](ConcatEnumerator`2 x, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seqcore.fs:line 323
   at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeInner@315[T,TResult](ConcatEnumerator`2 x, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seqcore.fs:line 317
   at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeInner@315[T,TResult](ConcatEnumerator`2 x, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seqcore.fs:line 317
   at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeInner@315[T,TResult](ConcatEnumerator`2 x, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seqcore.fs:line 317
   at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeInner@315[T,TResult](ConcatEnumerator`2 x, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seqcore.fs:line 317
   at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeInner@315[T,TResult](ConcatEnumerator`2 x, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seqcore.fs:line 317
   at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeInner@315[T,TResult](ConcatEnumerator`2 x, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seqcore.fs:line 317
   at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeInner@315[T,TResult](ConcatEnumerator`2 x, Unit unitVar0) in D:\a\_work\1\s\src\FSharp.Core\seqcore.fs:line 317
   at Microsoft.FSharp.Collections.SeqModule.Fold[T,TState](FSharpFunc`2 folder, TState state, IEnumerable`1 source) in D:\a\_work\1\s\src\FSharp.Core\seq.fs:line 885
   at AltCover.Visitor.visit(IEnumerable`1 visitors, IEnumerable`1 assemblies) in /_//AltCover.Engine/Visitor.fs:line 1614
   at AltCover.Main.I.result@730.Invoke(Unit unitVar0) in /_//AltCover.Engine/Main.fs:line 752
   at AltCover.PathOperation.DoPathOperation[TAny](FSharpFunc`2 operation, FSharpFunc`2 handle) in /_//AltCover.Engine/Output.fs:line 21
   at AltCover.CommandLine.I.doPathOperation[a](FSharpFunc`2 f, a defaultValue, Boolean store) in /_//AltCover.Engine/CommandLine.fs:line 193
   at AltCover.CommandLine.doPathOperation@431-1.Invoke(FSharpFunc`2 f, a defaultValue, Boolean store)
   at AltCover.Main.I.doInstrumentation(String[] arguments) in /_//AltCover.Engine/Main.fs:line 728
   at AltCover.Main.I.main(String[] arguments) in /_//AltCover.Engine/Main.fs:line 803
   at AltCover.Main.effectiveMain@809.Invoke(String[] arguments)
   at AltCover.Prepare.Execute() in /_//AltCover.Engine/Tasks.fs:line 195
   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)

it's as I suspected it might be - the injected code lacks some of the expected debug information, and this is being hit while looking at whether branch instructions are significant (leave a user-defined code segment) or not. For the time being switching off branch coverage checking via /p:AltCoverLineCover=true allows the provided test program to run.

SteveGilham commented 1 year ago

The Fody generated code violated the assumption that the first instruction of a method would be a sequence point; the resolution is the simple matter of adding that the first instruction of a method (with previous == null) is implicitly the start of a sequence point, whatever. When I've finished running tests, it'll be time to put out a release with this and other recent updates in.

SteveGilham commented 1 year ago

Should be fixed in release 8.6.40.

EMarshal commented 1 year ago

Looks great, thanks!