Build/Test Issues

System.NotImplementedException: GenericInst

Started by _shvo_ on 2,584 views

When building xunit test project with .net core 2.0 in Visual Studio 2019 (16.0.1) and NCrunch (3.25.0.3) I get the following error:

[12:46:22.6417-LocalBuildTask-25] ERROR (Build): XXX.UnitTest:  (0): System.NotImplementedException: GenericInst
   at _Mono.Cecil.SignatureReader.ReadPrimitiveValue(ElementType type)
   at _Mono.Cecil.SignatureReader.ReadCustomAttributeElementValue(TypeReference type)
   at _Mono.Cecil.SignatureReader.ReadCustomAttributeElement(TypeReference type)
   at _Mono.Cecil.SignatureReader.ReadCustomAttributeElement(TypeReference type)
   at _Mono.Cecil.SignatureReader.ReadCustomAttributeFixedArrayArgument(ArrayType type)
   at _Mono.Cecil.SignatureReader.ReadCustomAttributeFixedArgument(TypeReference type)
   at _Mono.Cecil.SignatureReader.ReadCustomAttributeConstructorArguments(CustomAttribute attribute, Collection`1 parameters)
   at _Mono.Cecil.MetadataReader.ReadCustomAttributeSignature(CustomAttribute attribute)
   at _Mono.Cecil.CustomAttribute.<Resolve>b__32_0(CustomAttribute attribute, MetadataReader reader)
   at _Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
   at _Mono.Cecil.CustomAttribute.Resolve()
   at _Mono.Cecil.CustomAttribute.get_Fields()
   at nCrunch.Compiler.CecilReflection.ILHashGenerator.HashCustomAttribute(FNV64& hash, CustomAttribute customAttribute)
   at nCrunch.Compiler.CecilReflection.ILHashGenerator.(FNV64& , MethodDefinition )
   at nCrunch.Compiler.CecilReflection.ILHashGenerator.HashMethod(MethodDefinition cecilMethod, Int32 stackSize)
   at nCrunch.Compiler.CecilReflection.CecilMethod.get_Hash()
   at nCrunch.TestExecution.Frameworks.DefaultClassMethodDescriptionLocator.(ReflectedType , ReflectedMethod , SequencePoint , Boolean , FNV64 )
   at nCrunch.TestExecution.Frameworks.DefaultClassMethodDescriptionLocator.ExtractClassMemberDataFromType(ReflectedType type, Boolean hashAllMethods)
   at nCrunch.Compiler.StaticManipulation.BuiltAssembly.(ReflectedAssembly , IDictionary`2 , TestFrameworkDescription[] , Boolean )
   at nCrunch.Compiler.StaticManipulation.BuiltAssembly.ExtractClassMethodData(TestFrameworkDescription[] applicableTestFrameworks, IDictionary`2 codeFileIDsByFilePath, Boolean hashMethods)
   at nCrunch.Compiler.RemoteBuildRunner..()
   at nCrunch.Common.PerformanceTracking.PerfTracker.TrackActivity(String name, Action activity)
   at nCrunch.Compiler.RemoteBuildRunner.(ComponentBuildParameters , FilePath , BuildOutput , DirectoryPath[] , FilePath[] )
   at nCrunch.Compiler.RemoteBuildRunner..()
   at nCrunch.Common.PerformanceTracking.PerfTracker.TrackActivity(String name, Action activity)
   at nCrunch.Compiler.RemoteBuildRunner.(ComponentBuildParameters )


I tried to manipulate with options for the projects (https://www.ncrunch.net/documentation/troubleshooting_compatibility-mode) but no luck.
Thanks for sharing this issue.

It looks like you have an IL sequence in this assembly that is structured in a way NCrunch can't handle. So you've found a hole in our CIL handling.

Looking at the stack, it seems you have a method making use of an attribute with an array argument containing a generic instance. You might be able to narrow this down to the declaration by selectively commenting out code. If you're able to find the signature and share it with me, I may be able to implement a fix.

Changing your impact detection mode to 'WatchText' may allow you to work around this problem.
Thank you for your feedback. I localized the problem:

using System;
using System.ComponentModel.DataAnnotations;
using FluentAssertions;
using Xunit;

namespace AdHoc.Tests
{
    public class Tests
    {
        [Theory, InlineData(typeof(GenericType<string>), 10)]
        public void GenericInAttributeGeneric(Type type, int value)
        {
            type.Should().Be<GenericType<string>>();
            value.Should().Be(10);
        }

        [Theory, InlineData(Abs<string>.FlagsType.One | Abs<string>.FlagsType.Three)]
        public void Flags(Abs<string>.FlagsType type)
        {
            type.Should().Be(Abs<string>.FlagsType.One | Abs<string>.FlagsType.Three);
        }

        [Theory, InlineData(Abs<string>.FlagsType.One | Abs<string>.FlagsType.Three, EnumType.E1)]
        public void EnumAndFlags(Abs<string>.FlagsType flags, EnumType @enum)
        {
            flags.Should().Be(Abs<string>.FlagsType.One | Abs<string>.FlagsType.Three);
            @enum.Should().Be(EnumType.E1);
        }
    }

    public class GenericType<T>
    {
        public T Value { get; set; }
    }


    public abstract class Abs<T>
        where T : class
    {
        [Flags]
        public enum FlagsType
        {
            One = 1 << 0,
            Two = 1 << 1,
            Three = 1 << 2,
            Four = 1 << 3
        }

        protected void Load<T>(T value)
        {
        }
    }

    public enum EnumType
    {
        [Display(Description = "First")]
        E1,
        [Display(Description = "Second")]
        E2
    }
}


Failed with test: EnumAndFlags. The root of the evil Enum inside generic class, as you said.
Don`t understand why someone need this type of construction but anyway...

P.S.: Change Impact detection mode to Watch Text not working for me.

Edited

Nice work in narrowing this down. As you've correctly established, the problem here is the attribute reference to the enum in the generic class. I've had a go at implementing a fix for this, but the problem is a huge bombshell that seems to break everything. The current version of NCrunch performs its handling in this space using an aging library that was never built to consider this particular CIL sequence, and updating the library to work in this case doesn't seem to be feasible.

The good news is that we're already much of the way through replacing this library with our own implementation. I've taken note of this particular structure to ensure we're able to handle it with the new system. The bad news is that we're still at least a couple of months away from having a stable build that use the new CIL system. So I can't provide you with an immediate fix for this problem.

Can I perhaps convince you to move the enum out of the generic class or avoid using inlinedata for this particular use case?
Remco wrote:Can I perhaps convince you to move the enum out of the generic class or avoid using inlinedata for this particular use case?

Sure, I fixed in this way.
Maybe the improvement for current version of NCrunch will be more concrete error in logs or just point to file in solution with this problem.

Post a reply

Log in to reply.