namespace HSchool.People.Tests; /// /// One line per class and person, sorted, so a generator change shows up as the first /// mismatched line instead of "the snapshots differ". /// internal static class RosterFingerprint { public static string Format(Roster roster, int seed, string country, string native) { var lines = new List { $"# seed={seed} country={country} native={native} people={roster.People.Count} classes={roster.Classes.Count}", }; foreach (var schoolClass in roster.Classes.OrderBy(row => row.Id, StringComparer.Ordinal)) { var pupils = string.Join(',', schoolClass.PupilIds.Order(StringComparer.Ordinal)); lines.Add( $"class {schoolClass.Id} year={schoolClass.Year} letter={schoolClass.Letter} room={schoolClass.RoomId} capacity={schoolClass.Capacity} pupils={pupils}"); } foreach (var person in roster.People.OrderBy(row => row.Id, StringComparer.Ordinal)) { lines.Add(PersonLine(person)); } return string.Join('\n', lines) + '\n'; } public static void AssertEqual(string expected, string actual) { var left = expected.Replace("\r\n", "\n", StringComparison.Ordinal).Split('\n'); var right = actual.Replace("\r\n", "\n", StringComparison.Ordinal).Split('\n'); var count = Math.Min(left.Length, right.Length); for (var i = 0; i < count; i++) { if (!string.Equals(left[i], right[i], StringComparison.Ordinal)) { Assert.Fail($"first mismatch at line {i + 1}\nexpected: {left[i]}\nactual: {right[i]}"); } } if (left.Length != right.Length) { Assert.Fail($"line count {left.Length} vs {right.Length}"); } } private static string PersonLine(Person person) { var roles = string.Join(',', Roles(person)); var traits = string.Join(',', person.Traits.Order(StringComparer.Ordinal)); var skills = string.Join( ',', person.Skills.OrderBy(pair => pair.Key, StringComparer.Ordinal).Select(pair => $"{pair.Key}={pair.Value}")); return $"person {person.Id} {person.Name.Full} female={person.Female} roles={roles} class={person.ClassId ?? "-"} born={person.BirthDate:yyyy-MM-dd} traits={traits} skills={skills}"; } private static IEnumerable Roles(Person person) { if (person.IsStudent) { yield return "student"; } if (person.IsStaff) { yield return "staff"; } if (person.IsParent) { yield return "parent"; } } }