diff --git a/Tests/Serialization/ComplexObject/Model.cs b/Tests/Serialization/ComplexObject/Model.cs index c3f084f..99d0228 100644 --- a/Tests/Serialization/ComplexObject/Model.cs +++ b/Tests/Serialization/ComplexObject/Model.cs @@ -96,9 +96,9 @@ public class Variant : IRecord if (Bytes != null) if (!other.Bytes.SequenceEqual(Bytes)) return false; - if (other.DtAsLong != DtAsLong) + if (other.DtAsLong != DtAsLong) return false; - if (other.Dt != Dt) + if (other.Dt != Dt) return false; return true; @@ -366,8 +366,16 @@ public class Payment : IRecord if (Method != other.Method) return false; if (Amount != other.Amount) return false; if (Reference != other.Reference) return false; - //if (Timestamp != other.Timestamp) return false; - //if (TimestampAsLong != other.TimestampAsLong) return false; + + if (Timestamp == DateTime.MinValue || other.Timestamp == DateTime.MinValue) + { + if (TimestampAsLong != other.TimestampAsLong) + return false; + } + else + if (!ModelRunner.DatesEqual(Timestamp, other.Timestamp)) + return false; + if (Fee != other.Fee) return false; //if (CurrencyOverride != other.CurrencyOverride) return false; @@ -475,6 +483,7 @@ public class DocumentHeader : IRecord [FlatBufferItem(8), Ignore, IgnoreMember] public Variant[] MetaValues { get; set; } + public override bool Equals(object? obj) { var other = obj as DocumentHeader; @@ -485,8 +494,10 @@ public class DocumentHeader : IRecord if (Version != other.Version) return false; //if (CreatedAtAsLong != other.CreatedAtAsLong) return false; //if (UpdatedAtAsLong != other.UpdatedAtAsLong) return false; - if (CreatedAt != other.CreatedAt) return false; - if (UpdatedAt != other.UpdatedAt) return false; + if (!ModelRunner.DatesEqual(CreatedAt, other.CreatedAt)) + return false; + if (UpdatedAt != other.UpdatedAt) + return false; if (Currency != other.Currency) return false; if (Notes != other.Notes) return false; @@ -552,33 +563,33 @@ public class BusinessDocument : IRecord public override bool Equals(object? obj) { var other = obj as BusinessDocument; - if (other == null) + if (other == null) return false; - if (!Header.Equals(other.Header)) + if (!Header.Equals(other.Header)) return false; - if (!Seller.Equals(other.Seller)) + if (!Seller.Equals(other.Seller)) return false; - if (!Buyer.Equals(other.Buyer)) + if (!Buyer.Equals(other.Buyer)) return false; if (Items != null) for (var i = 0; i < Items.Length; i++) - if (!Items[i].Equals(other.Items[i])) + if (!Items[i].Equals(other.Items[i])) return false; if (Payments != null) for (var i = 0; i < Payments.Length; i++) - if (!Payments[i].Equals(other.Payments[i])) + if (!Payments[i].Equals(other.Payments[i])) return false; if (Attachments != null) for (var i = 0; i < Attachments.Length; i++) - if (!Attachments[i].Equals(other.Attachments[i])) + if (!Attachments[i].Equals(other.Attachments[i])) return false; - if (!RiskScores.SequenceEqual(other.RiskScores)) + if (!RiskScores.SequenceEqual(other.RiskScores)) return false; return true; diff --git a/Tests/Serialization/ComplexObject/ModelGenerator.cs b/Tests/Serialization/ComplexObject/ModelGenerator.cs index 5cb47cd..ff5040c 100644 --- a/Tests/Serialization/ComplexObject/ModelGenerator.cs +++ b/Tests/Serialization/ComplexObject/ModelGenerator.cs @@ -32,7 +32,7 @@ public static class ModelGenerator var seller = MakeParty(rng, opt.IncludeV2Fields, isSeller: true, opt.IncludeUnicode); var buyer = MakeParty(rng, opt.IncludeV2Fields, isSeller: false, opt.IncludeUnicode); - var createdAt = DateTime.UtcNow.AddMinutes(-rng.Next(0, 60 * 24)); + var createdAt = ModelRunner.FixedDateTime.AddMinutes(-rng.Next(0, 60 * 24)); var doc = new BusinessDocument { Header = new DocumentHeader @@ -101,7 +101,7 @@ public static class ModelGenerator var rng = new Random(seed); var v2 = DeepClone(v1); - v2.Header.UpdatedAt = DateTime.UtcNow; + v2.Header.UpdatedAt = ModelRunner.FixedDateTime; var toChange = Math.Max(1, (int)Math.Round(v2.Items.Length * changeRatio)); // change random lines @@ -112,7 +112,7 @@ public static class ModelGenerator li.Qty = RoundQty(li.Qty + (double)(rng.NextDouble() * 2.0 - 1.0)); // ±1 li.UnitPrice = RoundMoney(li.UnitPrice * (double)(0.95 + rng.NextDouble() * 0.1)); // ±5% if (li.Ext == null) li.Ext = new Dictionary(); - li.Ext["lastEdit"] = VDate(DateTime.UtcNow); + li.Ext["lastEdit"] = VDate(ModelRunner.FixedDateTime); li.ExtKeys = li.Ext.Keys.ToArray(); li.ExtValues = li.Ext.Values.ToArray(); } @@ -226,7 +226,7 @@ public static class ModelGenerator Method = (PaymentMethod)rng.Next(0, 5), Amount = RoundMoney(amount), Reference = "REF-" + rng.Next(100_000, 999_999), - Timestamp = DateTime.UtcNow.AddMinutes(-rng.Next(0, 60 * 24)), + Timestamp = ModelRunner.FixedDateTime.AddMinutes(-rng.Next(0, 60 * 24)), Fee = includeV2 && rng.Next(0, 2) == 0 ? RoundMoney((double)rng.NextDouble() * 2.0) : null, //CurrencyOverride = includeV2 && rng.Next(0, 2) == 0 ? Currency.IQD : Currency.USD }; diff --git a/Tests/Serialization/ComplexObject/ModelRunner.cs b/Tests/Serialization/ComplexObject/ModelRunner.cs index 9d15e36..91c39fa 100644 --- a/Tests/Serialization/ComplexObject/ModelRunner.cs +++ b/Tests/Serialization/ComplexObject/ModelRunner.cs @@ -304,6 +304,14 @@ public sealed class ModelRunner private static volatile byte[]? _sinkBytes; private static volatile BusinessDocument? _sinkDoc; + // DateTime is fixed to guarantee consistent serialization across runs (otherwise, DateTime.UtcNow will vary) + public static DateTime FixedDateTime = DateTime.Parse("2026-06-08T13:56:00+03:00"); + //public static DateTime FixedDateTime = new DateTime(2026, 6, 8, 13, 56, 0, DateTimeKind.); + + + + + public void Run() { const int Rounds = 100; @@ -417,7 +425,7 @@ public sealed class ModelRunner Console.WriteLine(); - File.AppendAllLines("complex_model_results.csv", st.ToString().Split(Environment.NewLine)); + File.WriteAllLines($"complex_model_results_{wName.ToLower()}.csv", st.ToString().Split(Environment.NewLine)); } } @@ -490,4 +498,20 @@ public sealed class ModelRunner return result; } + + + public static bool DatesEqual(DateTime dt1, DateTime dt2) + { + // Quick fix to handle DateTimeKind differences (local vs UTC) in roundtrip equality checks + if (dt1 == dt2) + return true; + if (dt1.ToUniversalTime() == dt2.ToUniversalTime()) + return true; + if (dt1.ToUniversalTime() == dt2) + return true; + if (dt2.ToUniversalTime() == dt1) + return true; + + return false; + } }