diff --git a/src/Verify.Tests/ScrubStackTrace.cs b/src/Verify.Tests/ScrubStackTrace.cs index e617f096e..f2c459432 100644 --- a/src/Verify.Tests/ScrubStackTrace.cs +++ b/src/Verify.Tests/ScrubStackTrace.cs @@ -31,6 +31,34 @@ at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& complete return Verify(scrubbed); } + // NativeAOT renders unresolved frames with no parameter list + [Fact] + public Task NoParens() + { + var scrubbed = ScrubStackTrace.Scrub( + """ + System.Exception: Boom + at MyApp!+0x1a2b3c + at MyApp.Program.Main(String[] args) in /src/Program.cs:line 12 + at MyApp!+0x4d5e6f + """); + return Verify(scrubbed); + } + + [Fact] + public Task NoParens_RemoveParams() + { + var scrubbed = ScrubStackTrace.Scrub( + """ + System.Exception: Boom + at MyApp!+0x1a2b3c + at MyApp.Program.Main(String[] args) in /src/Program.cs:line 12 + at MyApp!+0x4d5e6f + """, + removeParams: true); + return Verify(scrubbed); + } + [Fact] public Task WhiteSpace() { diff --git a/src/Verify.Tests/ScrubStackTraceTests.NoParens.verified.txt b/src/Verify.Tests/ScrubStackTraceTests.NoParens.verified.txt new file mode 100644 index 000000000..30811a456 --- /dev/null +++ b/src/Verify.Tests/ScrubStackTraceTests.NoParens.verified.txt @@ -0,0 +1,4 @@ +System.Exception: Boom +at MyApp!+0x1a2b3c +at MyApp.Program.Main(String[] args) +at MyApp!+0x4d5e6f \ No newline at end of file diff --git a/src/Verify.Tests/ScrubStackTraceTests.NoParens_RemoveParams.verified.txt b/src/Verify.Tests/ScrubStackTraceTests.NoParens_RemoveParams.verified.txt new file mode 100644 index 000000000..718d0b668 --- /dev/null +++ b/src/Verify.Tests/ScrubStackTraceTests.NoParens_RemoveParams.verified.txt @@ -0,0 +1,4 @@ +System.Exception: Boom +at MyApp!+0x1a2b3c +at MyApp.Program.Main(...) +at MyApp!+0x4d5e6f \ No newline at end of file diff --git a/src/Verify/Serialization/Scrubbers/ScrubStackTrace.cs b/src/Verify/Serialization/Scrubbers/ScrubStackTrace.cs index 06b15711d..f1377f845 100644 --- a/src/Verify/Serialization/Scrubbers/ScrubStackTrace.cs +++ b/src/Verify/Serialization/Scrubbers/ScrubStackTrace.cs @@ -36,6 +36,16 @@ public static string Scrub(string stackTrace, bool removeParams = false) var indexOfLeft = span.IndexOf('('); var indexOfRight = span.IndexOf(')'); + + // Not every frame has a parameter list. NativeAOT renders unresolved frames + // as `at MyApp!+0x1a2b3c`, which has nothing to trim. + if (indexOfLeft == -1 || + indexOfRight == -1) + { + builder.AppendLineN(span); + continue; + } + if (removeParams) { var next = indexOfLeft + 1; diff --git a/src/todo.md b/src/todo.md index 03784f69b..736248a0f 100644 --- a/src/todo.md +++ b/src/todo.md @@ -61,7 +61,7 @@ All six resolved 2026-08-16 (five fixed here; the inline item resolved as by-des ## Minor / edge cases -- [ ] **Stack-trace scrubber destroys paren-less `at` frames** (NativeAOT: `at MyApp!+0x1a2b3c`). +- [x] **Stack-trace scrubber destroys paren-less `at` frames** (NativeAOT: `at MyApp!+0x1a2b3c`). `Verify/Serialization/Scrubbers/ScrubStackTrace.cs:36-58` — `IndexOf('(')`/`')'` return −1, slice keeps zero chars → frame becomes an empty line, or the literal `...)` with `removeParams: true`. - [ ] **MSTest source generator ignores `record` test classes.**