Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions src/Shared/test/Shared.Tests/StackTraceHelperTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,27 @@ public void StackTraceHelper_ProducesReadableOutput()

// Act
var stackFrames = StackTraceHelper.GetFrames(exception, out _);
var methodNames = stackFrames.Select(stackFrame => stackFrame.MethodDisplayInfo.ToString()).ToArray();

// Assert
Assert.Equal(expectedCallStack, methodNames);
var methodNames = stackFrames.Select(stackFrame => stackFrame.MethodDisplayInfo.ToString()).ToList();

// Assert - Runtime-agnostic checks for essential stack trace components
// Instead of exact string matching, verify key components are present
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you are still verifying that key components are present, it does mean that we are a bit less strict in CoreCLR which could be a potential for regressions. Would it make sense to instead of relaxing some of these matches, to instead first do a Runtime check to see if running under CoreCLR or Mono, and then if CoreCLR we keep the stricter checks but for Mono we just validate key components? This way you are not losing any regression coverage, but you are making the tests pass on more runtimes.

Copy link
Contributor Author

@medhatiwari medhatiwari Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joperezr Good point! I've updated it with runtime-specific assertions as you suggested

Assert.Equal(expectedCallStack.Count, methodNames.Count);

// Check each frame contains the essential method information
Assert.Contains("Iterator()+MoveNext()", methodNames[0]);
Assert.Contains("string.Join", methodNames[1]);
Assert.Contains("GenericClass<T>.GenericMethod<V>", methodNames[2]);
Assert.Contains("MethodAsync(int value)", methodNames[3]);

// For async generic method, check for either resolved form or state machine form
var asyncGenericFrame = methodNames[4];
Assert.True(
asyncGenericFrame.Contains("MethodAsync<TValue>(TValue value)") || // CoreCLR resolved form
asyncGenericFrame.Contains("MethodAsync") && asyncGenericFrame.Contains("TValue"), // Mono state machine form
$"Expected async generic method info in: {asyncGenericFrame}");

Assert.Contains("Method(string value)", methodNames[5]);
Assert.Contains("StackTraceHelper_ProducesReadableOutput()", methodNames[6]);
}

[Fact]
Expand Down Expand Up @@ -242,9 +259,12 @@ public void GetFrames_DoesNotFailForDynamicallyGeneratedAssemblies()
// Assert
var frame = frames[0];
Assert.Null(frame.FilePath);
// lambda_method{RandomNumber}(Closure )
Assert.StartsWith("lambda_method", frame.MethodDisplayInfo.ToString());
Assert.EndsWith("(Closure )", frame.MethodDisplayInfo.ToString());
// Runtime-agnostic test: should contain "lambda_method" regardless of prefix
// CoreCLR: "lambda_method34(Closure )"
// Mono: "object.lambda_method34(Closure )"
var methodDisplay = frame.MethodDisplayInfo.ToString();
Assert.Contains("lambda_method", methodDisplay);
Assert.EndsWith("(Closure )", methodDisplay);
}

[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
Expand Down
Loading