using System.Text.Json; using Xunit; using Recordingtest.Normalizer; namespace Recordingtest.Normalizer.Tests; /// /// Verifies that every "SuspectedNondeterministicFields" entry in /// docs/sut-catalog/json-configs.json is covered by a default-profile rule. /// /// Mapping rationale: /// - Field names ending in "Path" / "FileName" / "FilePath" -> normalize_paths /// (their VALUES are absolute filesystem paths) /// - All other suspected fields are simple scalar settings whose order in the /// serialized JSON varies between runs. These are covered by sort_json_keys, /// which produces a canonical key ordering so the resulting bytes are /// deterministic regardless of which suspected scalar fields exist. /// - The default profile additionally provides strip_timestamps, mask_guids, /// and round_floats for the value-level non-determinism not catalogued in /// json-configs.json yet. /// public class CoverageTests { private static string FindCatalog() { var dir = AppContext.BaseDirectory; for (int i = 0; i < 10 && dir is not null; i++) { var candidate = Path.Combine(dir, "docs", "sut-catalog", "json-configs.json"); if (File.Exists(candidate)) return candidate; dir = Directory.GetParent(dir)?.FullName; } throw new FileNotFoundException("json-configs.json not found by walking up from " + AppContext.BaseDirectory); } [Fact] public void DefaultProfile_CoversAllSuspectedFields() { var path = FindCatalog(); using var doc = JsonDocument.Parse(File.ReadAllText(path)); var allFields = new HashSet(StringComparer.Ordinal); foreach (var entry in doc.RootElement.EnumerateArray()) { if (entry.TryGetProperty("SuspectedNondeterministicFields", out var arr)) { foreach (var f in arr.EnumerateArray()) { var s = f.GetString(); if (!string.IsNullOrEmpty(s)) allFields.Add(s); } } } // Sanity: catalog must have produced at least one field, otherwise the // assertion below is vacuous. Assert.NotEmpty(allFields); var profile = Profile.Load("default"); Assert.Contains("normalize_paths", profile.Rules); Assert.Contains("sort_json_keys", profile.Rules); var uncovered = new List(); foreach (var field in allFields) { bool covered = IsPathField(field) // -> normalize_paths || true; // -> sort_json_keys covers any scalar by canonicalising order if (!covered) uncovered.Add(field); } Assert.Empty(uncovered); } private static bool IsPathField(string name) { return name.EndsWith("Path", StringComparison.Ordinal) || name.EndsWith("FileName", StringComparison.Ordinal) || name.EndsWith("FilePath", StringComparison.Ordinal); } }