xunit / visualstudio.xunit

VSTest runner for xUnit.net (for Visual Studio Test Explorer and dotnet test)
https://xunit.net/
Other
144 stars 81 forks source link

Explicit static interface implementation results in "Test host process crashed" #376

Closed frankbuckley closed 1 year ago

frankbuckley commented 1 year ago

Given the following:

using System.Numerics;
using Xunit;

public interface IValue<TSelf, T> : IEquatable<TSelf>, IModulusOperators<TSelf, TSelf, int>
    where T : struct, IEquatable<T>, IModulusOperators<T, T, int>
    where TSelf : IValue<TSelf, T>
{
    T Value { get; }

    static int IModulusOperators<TSelf, TSelf, int>.operator %(TSelf left, TSelf right) => left.Value % right.Value;
}

public readonly record struct Int32Value(int Value) : IValue<Int32Value, int>;

public class Test
{
    [Fact]
    public void ValuesEqual() => Assert.Equal(new Int32Value(), new Int32Value());
}

Running dotnet test results in an error:

PS C:\dev\frankbuckley\XUnitDiscovery\XUnitDiscovery> dotnet test
  Determining projects to restore...
  All projects are up-to-date for restore.
  XUnitDiscovery -> C:\dev\frankbuckley\XUnitDiscovery\XUnitDiscovery\bin\Debug\net7.0\XUnitDiscovery.dll
Test run for C:\dev\frankbuckley\XUnitDiscovery\XUnitDiscovery\bin\Debug\net7.0\XUnitDiscovery.dll (.NETCoreApp,Version=v7.0)
Microsoft (R) Test Execution Command Line Tool Version 17.6.0 (x64)
Copyright (c) Microsoft Corporation.  All rights reserved.

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
The active test run was aborted. Reason: Test host process crashed

Test Run Aborted with error System.Exception: One or more errors occurred.
 ---> System.Exception: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..
 ---> System.Exception: An existing connection was forcibly closed by the remote host.
   at System.Net.Sockets.NetworkStream.Read(Span`1 buffer)
   --- End of inner exception stack trace ---
   at System.Net.Sockets.NetworkStream.Read(Span`1 buffer)
   at System.Net.Sockets.NetworkStream.ReadByte()
   at System.IO.BinaryReader.Read7BitEncodedInt()
   at System.IO.BinaryReader.ReadString()
   at Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.LengthPrefixCommunicationChannel.NotifyDataAvailable()
   at Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.TcpClientExtensions.MessageLoopAsync(TcpClient client, ICommunicationChannel channel, Action`1 errorHandler, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---.
bradwilson commented 1 year ago

This appears to be a bug in .NET, not a bug in xUnit.net.

I noticed the reason the process was crashing was a stack overflow, and it was happening in a very strange place in .NET itself (we were calling Assembly.GetTypes()).

So in an attempt to see if I could isolate the issue away from xUnit.net, I put your code into a standalone console application:

using System;
using System.Numerics;

var value1 = new Int32Value();
var value2 = new Int32Value();

Console.WriteLine($"Value1 == Value2 is {value1 == value2}");

public interface IValue<TSelf, T> : IEquatable<TSelf>, IModulusOperators<TSelf, TSelf, int>
    where T : struct, IEquatable<T>, IModulusOperators<T, T, int>
    where TSelf : IValue<TSelf, T>
{
    T Value { get; }

    static int IModulusOperators<TSelf, TSelf, int>.operator %(TSelf left, TSelf right) => left.Value % right.Value;
}

public readonly record struct Int32Value(int Value) : IValue<Int32Value, int>;

Calling dotnet run on this program causes a simple Fatal error. message and a process crash. I assume that the .NET startup code is experiencing an issue similar or identical to the stack overflow that we got, but in a layer much earlier (there was no way for me to try/catch around it here).

I don't have any .NET 8 betas installed, so I don't know if the problem is persistent into .NET 8, but I would open a new issue against .NET itself and see if they can track it down and maybe fix it for .NET 8's release later this year.

bradwilson commented 1 year ago

Here is the repro project I was using: vs376-repro.zip

frankbuckley commented 1 year ago

Thanks - sorry - I should have ruled that out before assuming Xunit had an issue. I will file an issue with .NET runtime.

bradwilson commented 1 year ago

No worries! It was an easy and interesting deduction. 😄