@@ -15,6 +15,7 @@ namespace Microsoft.Extensions.Internal;
1515
1616public class StackTraceHelperTest
1717{
18+ private static bool IsMono => Type . GetType ( "Mono.RuntimeStructs" ) != null ;
1819 [ Fact ]
1920 public void StackTraceHelper_IncludesLineNumbersForFiles ( )
2021 {
@@ -176,27 +177,33 @@ public void StackTraceHelper_ProducesReadableOutput()
176177
177178 // Act
178179 var stackFrames = StackTraceHelper . GetFrames ( exception , out _ ) ;
179- var methodNames = stackFrames . Select ( stackFrame => stackFrame . MethodDisplayInfo . ToString ( ) ) . ToList ( ) ;
180-
181- // Assert - Runtime-agnostic checks for essential stack trace components
182- // Instead of exact string matching, verify key components are present
183- Assert . Equal ( expectedCallStack . Count , methodNames . Count ) ;
184-
185- // Check each frame contains the essential method information
186- Assert . Contains ( "Iterator()+MoveNext()" , methodNames [ 0 ] ) ;
187- Assert . Contains ( "string.Join" , methodNames [ 1 ] ) ;
188- Assert . Contains ( "GenericClass<T>.GenericMethod<V>" , methodNames [ 2 ] ) ;
189- Assert . Contains ( "MethodAsync(int value)" , methodNames [ 3 ] ) ;
190-
191- // For async generic method, check for either resolved form or state machine form
192- var asyncGenericFrame = methodNames [ 4 ] ;
193- Assert . True (
194- asyncGenericFrame . Contains ( "MethodAsync<TValue>(TValue value)" ) || // CoreCLR resolved form
195- asyncGenericFrame . Contains ( "MethodAsync" ) && asyncGenericFrame . Contains ( "TValue" ) , // Mono state machine form
196- $ "Expected async generic method info in: { asyncGenericFrame } ") ;
197-
198- Assert . Contains ( "Method(string value)" , methodNames [ 5 ] ) ;
199- Assert . Contains ( "StackTraceHelper_ProducesReadableOutput()" , methodNames [ 6 ] ) ;
180+ var methodNames = stackFrames . Select ( stackFrame => stackFrame . MethodDisplayInfo . ToString ( ) ) . ToArray ( ) ;
181+
182+ // Assert
183+ Assert . Equal ( expectedCallStack . Count , methodNames . Length ) ;
184+
185+ if ( IsMono )
186+ {
187+ // On Mono, verify key components are present but allow for runtime-specific formatting
188+ Assert . Contains ( "Iterator()+MoveNext()" , methodNames [ 0 ] ) ;
189+ Assert . Contains ( "string.Join" , methodNames [ 1 ] ) ;
190+ Assert . Contains ( "GenericClass<T>.GenericMethod<V>" , methodNames [ 2 ] ) ;
191+ Assert . Contains ( "MethodAsync(int value)" , methodNames [ 3 ] ) ;
192+
193+ // For async generic method on Mono, check for either resolved form or state machine form
194+ var asyncGenericFrame = methodNames [ 4 ] ;
195+ Assert . True (
196+ asyncGenericFrame . Contains ( "MethodAsync<TValue>(TValue value)" ) || // Resolved form
197+ asyncGenericFrame . Contains ( "MethodAsync" ) && asyncGenericFrame . Contains ( "TValue" ) , // State machine form
198+ $ "Expected async generic method info in: { asyncGenericFrame } ") ;
199+
200+ Assert . Contains ( "Method(string value)" , methodNames [ 5 ] ) ;
201+ Assert . Contains ( "StackTraceHelper_ProducesReadableOutput()" , methodNames [ 6 ] ) ;
202+ }
203+ else
204+ {
205+ Assert . Equal ( expectedCallStack , methodNames ) ;
206+ }
200207 }
201208
202209 [ Fact ]
@@ -259,12 +266,20 @@ public void GetFrames_DoesNotFailForDynamicallyGeneratedAssemblies()
259266 // Assert
260267 var frame = frames [ 0 ] ;
261268 Assert . Null ( frame . FilePath ) ;
262- // Runtime-agnostic test: should contain "lambda_method" regardless of prefix
263- // CoreCLR: "lambda_method34(Closure )"
264- // Mono: "object.lambda_method34(Closure )"
265269 var methodDisplay = frame . MethodDisplayInfo . ToString ( ) ;
266- Assert . Contains ( "lambda_method" , methodDisplay ) ;
267- Assert . EndsWith ( "(Closure )" , methodDisplay ) ;
270+
271+ if ( IsMono )
272+ {
273+ // On Mono, lambda methods may include declaring type prefix (e.g., "object.lambda_method34")
274+ Assert . Contains ( "lambda_method" , methodDisplay ) ;
275+ Assert . EndsWith ( "(Closure )" , methodDisplay ) ;
276+ }
277+ else
278+ {
279+ // On CoreCLR, maintain strict check to prevent regressions
280+ Assert . StartsWith ( "lambda_method" , methodDisplay ) ;
281+ Assert . EndsWith ( "(Closure )" , methodDisplay ) ;
282+ }
268283 }
269284
270285 [ MethodImpl ( MethodImplOptions . NoOptimization | MethodImplOptions . NoInlining ) ]
0 commit comments