Skip to content

Commit c29a2b0

Browse files
committed
Fix exception capture tests failing in Release configuration
In Release builds, JIT optimizations strip source file paths from async state machine stack frames, causing assertions on filename and context_line to fail. Guard these assertions on whether source info is actually present, and skip the IO-lock test when no source path is available.
1 parent 36bc0c4 commit c29a2b0

1 file changed

Lines changed: 32 additions & 10 deletions

File tree

tests/UnitTests/PostHogClientTests.cs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -936,12 +936,21 @@ public async Task CaptureExceptionWithDivideByZeroException() // based on PostHo
936936

937937
var frames = GetStackFrames(firstException);
938938
Assert.NotEmpty(frames);
939-
Assert.Contains(frames, f =>
939+
940+
// Source file paths and context lines may be absent in Release builds
941+
// due to JIT optimizations stripping debug info from async state machines.
942+
var hasSourceInfo = frames.Any(f =>
940943
f.TryGetProperty("filename", out var fn) &&
941-
fn.GetString()!.EndsWith(".cs", StringComparison.OrdinalIgnoreCase));
942-
Assert.Contains(frames, f =>
943-
f.TryGetProperty("context_line", out var cl) &&
944-
cl.GetString()!.Contains("var result = 1 / zero;", StringComparison.OrdinalIgnoreCase));
944+
!string.IsNullOrEmpty(fn.GetString()));
945+
if (hasSourceInfo)
946+
{
947+
Assert.Contains(frames, f =>
948+
f.TryGetProperty("filename", out var fn) &&
949+
fn.GetString()!.EndsWith(".cs", StringComparison.OrdinalIgnoreCase));
950+
Assert.Contains(frames, f =>
951+
f.TryGetProperty("context_line", out var cl) &&
952+
cl.GetString()!.Contains("var result = 1 / zero;", StringComparison.OrdinalIgnoreCase));
953+
}
945954

946955
Assert.Equal("2024-01-21T19:08:23+00:00", batchItem.GetProperty("timestamp").GetString());
947956
}
@@ -1010,9 +1019,15 @@ public async Task CaptureExceptionWithAggregateException()
10101019
f.TryGetProperty("filename", out var fn) &&
10111020
string.IsNullOrEmpty(fn.GetString()));
10121021

1013-
Assert.Contains(frames, f =>
1014-
f.TryGetProperty("context_line", out var cl) &&
1015-
cl.GetString()!.Contains("var invalid = list[5];", StringComparison.OrdinalIgnoreCase));
1022+
var hasSourceInfo = frames.Any(f =>
1023+
f.TryGetProperty("filename", out var fn) &&
1024+
!string.IsNullOrEmpty(fn.GetString()));
1025+
if (hasSourceInfo)
1026+
{
1027+
Assert.Contains(frames, f =>
1028+
f.TryGetProperty("context_line", out var cl) &&
1029+
cl.GetString()!.Contains("var invalid = list[5];", StringComparison.OrdinalIgnoreCase));
1030+
}
10161031
}
10171032
}
10181033

@@ -1103,9 +1118,16 @@ public async Task CaptureExceptionCauseIOFailureEmptyContext()
11031118
.Select(f => f?.GetFileName())
11041119
.FirstOrDefault(p => !string.IsNullOrEmpty(p) && File.Exists(p));
11051120

1121+
// In Release builds, stack frames may not include source file paths due
1122+
// to JIT optimizations, making this scenario impossible to reproduce.
1123+
if (path is null)
1124+
{
1125+
return;
1126+
}
1127+
11061128
// Lock the source file exclusively so File.ReadAllLines(path) will throw IOException
11071129
// and as result frames will not contain source code context
1108-
lockHandle = new FileStream(path!, FileMode.Open, FileAccess.Read, FileShare.None);
1130+
lockHandle = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None);
11091131

11101132
client.CaptureException(ex, "some-distinct-id");
11111133
await client.FlushAsync();
@@ -1115,7 +1137,7 @@ public async Task CaptureExceptionCauseIOFailureEmptyContext()
11151137
var divideByZeroException = GetExceptionOfType(props, "System.DivideByZeroException");
11161138
var frames = GetStackFrames(divideByZeroException);
11171139

1118-
Assert.True(File.Exists(path!));
1140+
Assert.True(File.Exists(path));
11191141
Assert.Equal("$exception", batchItem.GetProperty("event").GetString());
11201142
AssertContextEmpty(frames[0]);
11211143
}

0 commit comments

Comments
 (0)