perf(worker): exact-format timestamp parse and compiled status-field accessors on the event path
This commit is contained in:
@@ -238,6 +238,97 @@ public sealed class MxAccessEventMapperTests
|
||||
Assert.False(MxAccessEventMapper.TryParseSourceTimestamp(text, out _));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the exact-format fast path PERF-20 added in front of the
|
||||
/// general parse chain returns exactly what that chain returned. The
|
||||
/// cases cover the captured MXAccess shape (which the fast path is meant
|
||||
/// to catch on a US-shaped host), its zero-padded and second-precision
|
||||
/// siblings, and strings the derived formats cannot match — an ISO
|
||||
/// round-trip form, a long-date form, and a day-first European form —
|
||||
/// which must fall through to the unchanged two-stage chain. The
|
||||
/// expectation is computed with the pre-PERF-20 chain in this test, so it
|
||||
/// holds on any host culture: the fast path is a shortcut, never a
|
||||
/// different answer.
|
||||
/// </summary>
|
||||
/// <param name="text">Timestamp string to parse.</param>
|
||||
[Theory]
|
||||
[InlineData("3/26/2026 1:38:22.907 PM")]
|
||||
[InlineData("3/26/2026 1:38:22 PM")]
|
||||
[InlineData("03/26/2026 01:38:22 PM")]
|
||||
[InlineData("12/31/2026 11:59:59.999 PM")]
|
||||
[InlineData("2026-03-26T13:38:22.9070000")]
|
||||
[InlineData("Thursday, March 26, 2026 1:38:22 PM")]
|
||||
[InlineData("26.03.2026 13:38:22")]
|
||||
[InlineData("not a timestamp")]
|
||||
public void TryParseSourceTimestamp_MatchesPreFastPathChain(string text)
|
||||
{
|
||||
bool expectedParsed = TryParseWithGeneralChainOnly(text, out DateTime expectedUtc);
|
||||
|
||||
bool parsed = MxAccessEventMapper.TryParseSourceTimestamp(text, out DateTime utc);
|
||||
|
||||
Assert.Equal(expectedParsed, parsed);
|
||||
Assert.Equal(expectedUtc, utc);
|
||||
if (parsed)
|
||||
{
|
||||
Assert.Equal(DateTimeKind.Utc, utc.Kind);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies a timestamp written in the host culture's own patterns —
|
||||
/// including the millisecond fraction MXAccess appends, which no culture
|
||||
/// publishes in its long-time pattern — parses as local wall-clock time
|
||||
/// and comes back as UTC. This is the string shape the derived exact
|
||||
/// formats are built for, so it exercises the fast path on the worker's
|
||||
/// own host regardless of which culture that host runs.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TryParseSourceTimestamp_WithCultureShapedMillisecondTimestamp_ReturnsLocalWallClockAsUtc()
|
||||
{
|
||||
CultureInfo culture = CultureInfo.CurrentCulture;
|
||||
string longTime = culture.DateTimeFormat.LongTimePattern;
|
||||
int secondsIndex = longTime.IndexOf("ss", StringComparison.Ordinal);
|
||||
|
||||
// Every Windows culture publishes seconds in its long-time pattern; the
|
||||
// guard keeps the test honest rather than green-by-accident if one does not.
|
||||
Assert.True(secondsIndex >= 0, $"Long-time pattern '{longTime}' has no seconds specifier.");
|
||||
|
||||
DateTime localWall = new(2026, 3, 26, 13, 38, 22, 907, DateTimeKind.Unspecified);
|
||||
string text = localWall.ToString(
|
||||
culture.DateTimeFormat.ShortDatePattern + " " + longTime.Insert(secondsIndex + 2, ".fff"),
|
||||
culture);
|
||||
|
||||
Assert.True(MxAccessEventMapper.TryParseSourceTimestamp(text, out DateTime utc));
|
||||
Assert.Equal(DateTimeKind.Utc, utc.Kind);
|
||||
Assert.Equal(DateTime.SpecifyKind(localWall, DateTimeKind.Local).ToUniversalTime(), utc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The parse chain exactly as it stood before PERF-20 added the
|
||||
/// exact-format stage, used as the parity oracle above.
|
||||
/// </summary>
|
||||
/// <param name="text">Timestamp string to parse.</param>
|
||||
/// <param name="utc">The parsed UTC timestamp on success.</param>
|
||||
/// <returns><see langword="true"/> when the string parsed successfully.</returns>
|
||||
private static bool TryParseWithGeneralChainOnly(string? text, out DateTime utc)
|
||||
{
|
||||
utc = default;
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const DateTimeStyles styles = DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal;
|
||||
if (DateTime.TryParse(text, CultureInfo.CurrentCulture, styles, out DateTime parsed)
|
||||
|| DateTime.TryParse(text, CultureInfo.InvariantCulture, styles, out parsed))
|
||||
{
|
||||
utc = DateTime.SpecifyKind(parsed, DateTimeKind.Utc);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private sealed class FakeStatus
|
||||
{
|
||||
public int success;
|
||||
|
||||
Reference in New Issue
Block a user