microsoft/coyote

IAsyncEnumerable with ToArrayAsync System.BadImageFormatException

andresgutierrez opened this issue · 2 comments

I ran into this problem when testing my library with Coyote. It looks rewriting ToArrayAsync leads to a System.BadImageFormatException. I nailed down the issue with the following code:

Code:

using Xunit;
using Xunit.Abstractions;
using System.Linq;

namespace Backend.Tests;

public class SomeClass
{

}

public class TestCoyote
{    
    private readonly ITestOutputHelper testOutputHelper;

    public TestCoyote(ITestOutputHelper testOutputHelper)
    {
        this.testOutputHelper = testOutputHelper;        
    }

    [Fact]
    public void TestMassInsert()
    {
        RunTest(testOutputHelper, TestMassInsertInternal);
    }
    
    public void RunTest(ITestOutputHelper testOutputHelper, Func<Task> func)
    {
        var config = Configuration.Create();
        config.WithTestingIterations(50);

        TestingEngine engine = TestingEngine.Create(config, func);
        engine.Run();

        var report = engine.TestReport;
        testOutputHelper.WriteLine("Coyote found {0} bug.", report.NumOfFoundBugs);
        Assert.True(report.NumOfFoundBugs == 0, $"Coyote found {report.NumOfFoundBugs} bug(s).");
    }

    private async IAsyncEnumerable<T> GetSequence<T>() where T : new()
    {
        for (int i = 0; i < 100; i++)
        {
            await Task.Yield();
            yield return new T();
        }
    }

    private async Task TestMassInsertInternal()
    {        
        var x = GetSequence<SomeClass>();
        await x.ToArrayAsync();
    }    
}

Produces the following error:

main@MacBook-Air ~/c/Backend.Tests (main) [1]> dotnet test --filter "FullyQualifiedName~Backend.Tests.TestCoyote"
  Determining projects to restore...
  All projects are up-to-date for restore.
  Backend.Generators -> /Users/main/backend-core/Backend.Generators/bin/Debug/netstandard2.0/Backend.Generators.dll
  Backend.Core -> /Users/main/backend-core/Backend.Core/bin/Debug/net7.0/Backend.Core.dll
  Backend.Tests -> /Users/main/backend-core/Backend.Tests/bin/Debug/net7.0/Backend.Tests.dll
  Microsoft (R) Coyote version 1.7.3.0 for .NET 7.0.1
  Copyright (C) Microsoft Corporation. All rights reserved.
  
  . Rewriting /Users/main/backend-core/Backend.Tests/bin/Debug/net7.0/Backend.Core.dll.
  ... Rewriting the 'Backend.Core.dll' assembly (Backend.Core, Version=0.9.1.0, Culture=neutral, PublicKeyToken=null)
  ..... Writing the modified 'Backend.Core.dll' assembly to /Users/main/backend-core/Backend.Tests/bin/Debug/net7.0/Backend.Core.dll
  ... Elapsed 0.5518598 sec.
  Microsoft (R) Coyote version 1.7.3.0 for .NET 7.0.1
  Copyright (C) Microsoft Corporation. All rights reserved.
  
  . Rewriting /Users/main/backend-core/Backend.Tests/bin/Debug/net7.0/Backend.Tests.dll.
  ... Rewriting the 'Backend.Tests.dll' assembly (Backend.Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null)
  ..... Writing the modified 'Backend.Tests.dll' assembly to /Users/main/backend-core/Backend.Tests/bin/Debug/net7.0/Backend.Tests.dll
  ... Elapsed 0.4201465 sec.
Test run for /Users/main/backend-core/Backend.Tests/bin/Debug/net7.0/Backend.Tests.dll (.NETCoreApp,Version=v7.0)
Microsoft (R) Test Execution Command Line Tool Version 17.4.0 (arm64)
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
..... Anonymized telemetry is enabled, see https://aka.ms/coyote-telemetry.
... Setting up the test:
..... Using the portfolio[fair,seed:591309164] exploration strategy.
... Running test iterations:
..... Iteration #1
..... Iteration #1 found bug #1
Unhandled exception. System.BadImageFormatException: An attempt was made to load a program with an incorrect format.
 (0x8007000B)
   at Backend.Tests.TestCoyote.TestMassInsertInternal()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at Backend.Tests.TestCoyote.TestMassInsertInternal()
   at Microsoft.Coyote.Runtime.CoyoteRuntime.<>c__DisplayClass60_0.<RunTestAsync>b__0()
   at Microsoft.Coyote.Runtime.CoyoteRuntime.<>c__DisplayClass63_0.<ScheduleOperation>b__0()
[xUnit.net 00:00:01.71]     Backend.Tests.TestCoyote.TestMassInsert [FAIL]
  Failed Backend.Tests.TestCoyote.TestMassInsert [1 s]
  Error Message:
   Coyote found 1 bug(s).
Expected: True
Actual:   False
  Stack Trace:
     at Backend.Tests.Utils.TestCoyote.RunTest(ITestOutputHelper testOutputHelper, Func`1 func) in /Users/main/backend-core/Backend.Tests/TestCoyote.cs:line 27
   at Backend.Tests.TestCoyote.TestMassInsert() in /Users/main/backend-core/Backend.Tests/TestCoyote.cs:line 34
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
  Standard Output Messages:
 Coyote found 1 bug.



Failed!  - Failed:     1, Passed:     0, Skipped:     0, Total:     1, Duration: < 1 ms - Backend.Tests.dll (net7.0)

Apologies for the delay in responding @andresgutierrez, took us a bit to get on this issue. But it is now fixed! Your code snippet was really helpful in identifying what was going on, thanks for that. It was a missing corner case in the rewriter for methods that return generic array types. The fix will be available on the next release once we publish it on NuGet.

Thanks 👍