Build/Test Issues

RDI fails to run tests involving ImmutableArray

Started by NeilMacMullen on 2,643 views

First of all congrats on the release of 5.0 - _really_ impressed with the promise of RDI :-)

Unfortunately in our codebase we seem to be encountering problems related to the use of ImmutableArrays

Errors fall into three categories (quite possibly with the same root cause...)

System.InvalidOperationException: This operation cannot be performed on a default instance of ImmutableArray<T>. Consider initializing the array, or checking the ImmutableArray<T>.IsDefault property.
at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.MemoryMappedLog.LogObjectValue(Object value, Int32 componentMappingId, UInt32 rdiDataPointId)
at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.RdiEventListener.NCrunchLogWithReturnObject(Object value, Int32 componentMappingId, UInt32 rdiDataPointId)
at our code .....
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)



System.AggregateException: One or more errors occurred. (The given key 'ourObject'+<MergeFiles>d__9' was not present in the dictionary.)
---> System.Collections.Generic.KeyNotFoundException: The given key 'ourObject+<MergeFiles>d__9' was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.RdiStateMachineTracker.EnterInnerScopeWithinStateMachine(Object stateMachineInstance, UInt32 newScopeFrameIndex, UInt32 relativeScopeTransientId)
at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.MemoryMappedLog.LogStateMachineInnerScopeEntry(Object stateMachineInstance, Int32 componentMappingId, UInt32 innerScopeTransientId, UInt32 outerScopeTransientId, UInt32 parentScopeFrameIndex)
at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.RdiEventListener.NCrunchLogStateMachineInnerScopeEntry(Object stateMachineInstance, Int32 componentMappingId, UInt32 innerScopeTransientId, UInt32 outerScopeTransientId, UInt32 parentScopeFrameIndex)
at ... our code
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)



NCrunch was unable to retrieve a meaningful result from this test due to an unexpected error - was the execution process terminated?




All these tests passed before migrating to 5.0 (we're currently using 5.1.0.2)

If RDI is disable in Ncrunch configuration then the tests also run to completion and pass.

Happy to collect/provide more detailed info.

Neil
I think, I have the same Issue.

While reading XML Documents with System.XML.Linq.XDocument I get the following excepiton:

System.Collections.Generic.KeyNotFoundException: 'The given key 'BmeCat.Import.BmeImporter+<CheckClassificationSystem>d__42' was not present in the dictionary.'

Disabled RDI fixes the Issue.

Edited

Thanks nextPIM. I wonder if my assumption that these are all the same root cause is incorrect. We use a lot of immutable arrays in our code and the set of failing tests seemed to be related to those but possible the second failure mode (which matches yours) is caused by something else.
We're getting the same middle exception (not being present in the Dictionary) but ours is around an "await foreach" rather than an ImmutableArray

System.AggregateException: One or more errors occurred. (The given key 'Ledgerscope.Utilities.Helpers.EnumerableHelper+<AsCollectionAsync>d__21`1[Ledgerscope.Core.Models.Pocos.FullJournal]' was not present in the dictionary.)
 ---> System.Collections.Generic.KeyNotFoundException: The given key 'Ledgerscope.Utilities.Helpers.EnumerableHelper+<AsCollectionAsync>d__21`1[Ledgerscope.Core.Models.Pocos.FullJournal]' was not present in the dictionary.
   at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.RdiStateMachineTracker.EnterInnerScopeWithinStateMachine(Object stateMachineInstance, UInt32 newScopeFrameIndex, UInt32 relativeScopeTransientId)
   at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.RdiEventListener.NCrunchLogStateMachineInnerScopeEntry(Object stateMachineInstance, Int32 componentMappingId, UInt32 innerScopeTransientId, UInt32 outerScopeTransientId, UInt32 parentScopeFrameIndex)
   at Ledgerscope.Utilities.Helpers.EnumerableHelper.AsCollectionAsync[T](IAsyncEnumerable`1 values) in Q:\Source\Repos\Core\LedgerscopeSolution\Ledgerscope.Utilities\Helpers\EnumerableHelper.cs:line 272


I've submitted a bug report through the extension
First of all, RDI is super cool. Thanks for all the hard work you put in to making this.

I'm getting the same exception when setting up an ImmutableArray<> in a unit test. The exception is being thrown because RDI (I assume) is trying to access the ImmutableArray<> property when code looks like it's using it even though it's not. When I disable RDI, all of my tests run successfully.

I use NSubstitute to setup some substitute objects. In the code below line 1 creates the substitute, and then line 2 sets up what the response will be when something in the test tries to use the `MyImmutableArray` property. I assume RDI is trying to access the `MyImmutableArray` property even though the code doesn't do that at runtime.



var mySub = NSubstitute.Substitute.For<IMyInterface>();
_ = mySub.MyImmutableArray.ReturnsForAnyArgs(x => new[]{"aaa"}.ToImmutableArray());


The stack trace shows the same exception as others mentioned above:

System.InvalidOperationException: This operation cannot be performed on a default instance of ImmutableArray<T>. Consider initializing the array, or checking the ImmutableArray<T>.IsDefault property.
at System.Collections.Immutable.ImmutableArray`1.System.Collections.ICollection.get_Count()
at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.MemoryMappedLog.LogObjectValue(Object value, Int32 componentMappingId, UInt32 rdiDataPointId)
at nCrunch.TestRuntime.DotNetCore.RuntimeDataInspection.RdiEventListener.NCrunchLogWithReturnObject(Object value, Int32 componentMappingId, UInt32 rdiDataPointId)
at PurpleSpikeProductions.UnitTests.GamesManagement.DockerControl.DockerGameControllerTests..ctor() in C:\GitHub\Purple-Spike\arcade-machine-device-services\src\ArcadeMachineServices\UnitTests\GamesManagement\DockerControl\DockerGameControllerTests.cs:line 54
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
Hi, thanks everyone for sharing these issues.

The ImmutableArray one looks fairly easy to solve. We're missing an exception trap on the call to .Count. I should be able to provide a fix for this one shortly.

The async related issues are ... harder. Async makes everything hard in RDI. To track these down, I'll need some sample code that can reproduce them. I hope that this may be as simple as just making a copy of the method and stubbing out anything it depends on, but if you're running a custom async context or task scheduler, this may also be involved. If you can isolate it, please send through a sample project to me through the contact form and I'll see what I can do about getting it fixed.

Neil's issue with the process disappearing would be my least favourite issue here. When NCrunch gives this error, it means that the execution process was torn down without warning. Sometimes there is useful error information in the event viewer. If you're able to get me a stack trace, this would be a huge help. If there's nothing to go from, I think the best plan here would be for me to fix the two above problems and we can try it out with the new build.

Note also that if RDI gives you problems over a specific region of code, you can deactivate it selectively using inline comments. This might give you a way to work around issues without needing to shut it off entirely.

Ok, I've prepared a fix for the ImmutableArray issue. This build also includes a fix to handle the async issue a bit better, but I'm not sure if this issue is properly solved yet .. as I can't reproduce it. Most likely the fix will stop the async issue from blowing up the test, but I'm not sure if the async frame will open correctly in the RDI overlay. It would be great if you could test this for me.

NCrunch_Console_5.2.0.1.msi
NCrunch_Console_5.2.0.1.zip
NCrunch_GridNodeServer_5.2.0.1.msi
NCrunch_GridNodeServer_5.2.0.1.zip
NCrunch_LicenseServer_5.2.0.1.zip
NCrunch_Rider_5.2.0.1.7z
NCrunch_Rider_5.2.0.1.zip
NCrunch_VS2010_5.2.0.1.msi
NCrunch_VS2010_5.2.0.1.zip
NCrunch_VS2012_5.2.0.1.msi
NCrunch_VS2012_5.2.0.1.zip
NCrunch_VS2013_5.2.0.1.msi
NCrunch_VS2013_5.2.0.1.zip
NCrunch_VS2015_5.2.0.1.msi
NCrunch_VS2015_5.2.0.1.msi.7z
NCrunch_VS2015_5.2.0.1.zip
NCrunch_VS2017_5.2.0.1.msi
NCrunch_VS2017_5.2.0.1.msi.7z
NCrunch_VS2017_5.2.0.1.zip
NCrunch_VS2019_5.2.0.1.msi
NCrunch_VS2019_5.2.0.1.msi.7z
NCrunch_VS2019_5.2.0.1.zip
NCrunch_VS2022_5.2.0.1.msi
NCrunch_VS2022_5.2.0.1.msi.7z
NCrunch_VS2022_5.2.0.1.zip
Wanted to chime in that this new build did fix my issue with NSubsitute substitutes using ImmutableArray<>. Thanks for the quick fix!
Thanks! This has made a very significant improvement. Test failures down to 7 from 75. All ImmutableArray and "unable to obtain meaninful result" errors are now gone.

The only ones left are the "key ... was not present in the dictionary". These tests (in our codebase) are heavily async. We'll spend some time this week to try and find a minimal repro case.
Ok, here's my next attempt at a workaround for the async exception:

NCrunch_Console_5.2.0.2.msi
NCrunch_Console_5.2.0.2.zip
NCrunch_GridNodeServer_5.2.0.2.msi
NCrunch_GridNodeServer_5.2.0.2.zip
NCrunch_LicenseServer_5.2.0.2.zip
NCrunch_Rider_5.2.0.2.7z
NCrunch_Rider_5.2.0.2.zip
NCrunch_VS2010_5.2.0.2.msi
NCrunch_VS2010_5.2.0.2.zip
NCrunch_VS2012_5.2.0.2.msi
NCrunch_VS2012_5.2.0.2.zip
NCrunch_VS2013_5.2.0.2.msi
NCrunch_VS2013_5.2.0.2.zip
NCrunch_VS2015_5.2.0.2.msi
NCrunch_VS2015_5.2.0.2.msi.7z
NCrunch_VS2015_5.2.0.2.zip
NCrunch_VS2017_5.2.0.2.msi
NCrunch_VS2017_5.2.0.2.msi.7z
NCrunch_VS2017_5.2.0.2.zip
NCrunch_VS2019_5.2.0.2.msi
NCrunch_VS2019_5.2.0.2.msi.7z
NCrunch_VS2019_5.2.0.2.zip
NCrunch_VS2022_5.2.0.2.msi
NCrunch_VS2022_5.2.0.2.msi.7z
NCrunch_VS2022_5.2.0.2.zip

What seems to be happening here is that we have a loop inside an sync structure that seems to get called by the platform outside of the expected async execution scope. I don't know how this happens. The fix above basically just doesn't try to log this particular action under RDI. I have no idea what impact this will have if you try to open the frame in RDI - it might be OK, or you might get a strange result .. but it's my hope that at least the tests covering the code will run to completion. Please do let me know if you manage to isolate this in some code you can share with me.
Wow - fast work! Pleased to say I'm now seeing the reassuring green N circle indicating all tests are passing :-) Haven't yet played with RDI in much detail but will try it out next week and report any issues found.

Post a reply

Log in to reply.