Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throwing results in test never completing #3971

Closed
Vijay-Braidable opened this issue Oct 26, 2024 · 7 comments
Closed

Throwing results in test never completing #3971

Vijay-Braidable opened this issue Oct 26, 2024 · 7 comments
Labels
External: Other This is caused by external issue, the external issue needs to be solved first. Resolution: By Design

Comments

@Vijay-Braidable
Copy link

Vijay-Braidable commented Oct 26, 2024

Describe the bug

When I throw a cyclical exception from a test (like is thrown when a resilience pipeline fails) the test from which it is thrown never exits.

Steps To Reproduce

  1. Run the test TestMethod1 in the attached project.
  2. See that the test runs forever (well I left it 5 mins)

Expected behavior

The test should finish as a failure.

Actual behavior

The test never exits.

Additional context

MSTest.XYZ Version: 3.6.1
Microsoft.NET.Test.Sdk Version: 17.11.0
Operating System: Windows 10 Pro
Visual Studio Version: 2022 (64-bit) - Preview (17.12.0 Preview 4.0)
.NET Version: net8.0

Toy test code for a repro if you don't want to download the zip:

    [TestMethod]
    public void TestMethod1()
    {
        // Arrange
        var exceptionA = new Exception("Exception A");
        var exceptionB = new Exception("Exception B", exceptionA);

        // Use reflection to set exceptionA's InnerException to exceptionB, creating a cycle
        FieldInfo innerExceptionField = typeof(Exception).GetField("_innerException", BindingFlags.Instance | BindingFlags.NonPublic);
        innerExceptionField.SetValue(exceptionA, exceptionB);

        // Act: Throw exceptionA, which now has a cyclic InnerException reference
        throw exceptionA;
    }

MSTest.Bug.Repro.zip

@thomhurst
Copy link
Contributor

Looking at this, I don't understand why you'd set the inner exception later on?

A has an inner B exception
Then B has an inner A exception

What's the use case?

From a purely (maybe basic) logical perspective they both can't have caused each other.

One must be the initial cause, which makes sense to be an inner exception if wrapped, but creating a cyclical exception doesn't make sense to me?

@Vijay-Braidable
Copy link
Author

Wrapped Exceptions: The pipeline might be wrapping an exception multiple times as it moves through different stages, leading to nested or cyclical exceptions. This can happen if each policy wraps the caught exception before rethrowing it, especially in complex configurations.

Inner Exception Referencing: Some policies might capture and throw a new exception with the original one as the InnerException. When this happens repeatedly, it creates a cyclical reference if an exception somewhere in the chain references one from an earlier stage, creating a loop of inner exceptions.

My view is that why it's happening doesn't matter, it can happen, and the test runner shouldn't run forever when it does.

@Vijay-Braidable
Copy link
Author

Vijay-Braidable commented Oct 27, 2024

I should add, this is what I believe is happening in my codebase, I can't be sure. I took a stab at the reasoning and made a repro, I don't personally throw nested exceptions. My guess was that some nested data object (thrown my the pipeline) in the exception was cyclical and that was causing the issue. It's why System.Text.Json has ReferenceHandler.Preserve, though as I say, it was a guess on my part that this was the reason.

@thomhurst
Copy link
Contributor

I think this is actually a runtime problem. The hang occurs at the throw call.

I've reproduced it in a console app with 0 dependencies -> dotnet/runtime#109262

@thomhurst
Copy link
Contributor

They've closed that issue as by design, so nothing we can do. We can't bypass the runtime rules.

@Evangelink
Copy link
Member

I would have been tempted to close as won't fix but as we are already doing some special casing, it seems that the hashset solution isn't going to add too much complexity.

@Evangelink Evangelink added this to the MSTest 3.7 / Platform 1.5 milestone Oct 30, 2024
@Evangelink Evangelink added Resolution: By Design External: Other This is caused by external issue, the external issue needs to be solved first. and removed Type: Feature In-PR labels Oct 30, 2024
@Evangelink Evangelink removed this from the MSTest 3.7 / Platform 1.5 milestone Oct 30, 2024
@Evangelink
Copy link
Member

Problem is actually when the exception is thrown so nothing linked to MSTest. Closing as by-design on runtime.

@Evangelink Evangelink closed this as not planned Won't fix, can't repro, duplicate, stale Oct 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
External: Other This is caused by external issue, the external issue needs to be solved first. Resolution: By Design
Projects
None yet
3 participants