using System.Text.Json; namespace AyCode.Core.Benchmarks.Workloads.Scenarios; /// /// Round-trip correctness validator — serializes both sides to canonical System.Text.Json form /// and compares the resulting strings. Works for any object graph without a custom comparer (slower /// than property-by-property but universal). Used by every benchmark's VerifyRoundTrip() /// implementation as the deep-equality oracle before warmup begins. /// public static class RoundTripValidator { #if !AYCODE_NATIVEAOT private static readonly JsonSerializerOptions VerifyJsonOpts = new() { WriteIndented = false, DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles }; #endif /// /// Round-trip equality check via canonical System.Text.Json. Returns true if both sides serialize /// to identical JSON strings. /// /// /// AOT publish skip: System.Text.Json's reflection path uses runtime closed-generic instantiation /// (JsonPropertyInfo<TestStatus> et al.) that the trimmer drops, causing /// NotSupportedException: missing native code or metadata. The validation is JIT-only — the actual /// benchmark Serialize/Deserialize loops don't touch this path. Under AOT we return true so all /// VerifyRoundTrip() calls pass without running the cross-format validation. /// public static bool DeepEqualsViaJson(object? a, object? b) { #if AYCODE_NATIVEAOT // Skip cross-format validation under AOT — STJ reflection path is incompatible. The roundtrip // itself still runs (caller-side Serialize+Deserialize), just the JSON-canonical compare is bypassed. return true; #else if (a == null && b == null) return true; if (a == null || b == null) return false; var jsonA = JsonSerializer.Serialize(a, VerifyJsonOpts); var jsonB = JsonSerializer.Serialize(b, VerifyJsonOpts); return jsonA == jsonB; #endif } }