namespace AcDream.Core.Net.Tests.Transport; /// /// Deterministic monotonic time source for transport tests. Exposes the same /// (timestamp, frequency) shape as System.Diagnostics.Stopwatch /// (GetTimestamp() + Frequency) so slice N1 can inject it /// behind the production TransportClock without adapting call sites. /// Time only moves when a test calls . /// /// /// Deliberately dependency-free (System only) and NOT tied to the machine's /// Stopwatch.Frequency: a fixed 100 ns tick makes every gate /// computation reproducible across platforms. /// /// internal sealed class VirtualClock { /// /// Fixed tick rate: 100 ns ticks (10,000,000 per second), equal to /// so /// arithmetic maps 1:1 onto clock ticks. /// public const long TicksPerSecond = TimeSpan.TicksPerSecond; private long _timestamp; public VirtualClock(long startTimestamp = 0) => _timestamp = startTimestamp; /// Stopwatch.Frequency equivalent. public long Frequency => TicksPerSecond; /// Stopwatch.GetTimestamp() equivalent. public long GetTimestamp() => _timestamp; /// /// Seconds since the clock's epoch as a double — the shape of the /// retail/ACE PortalYearTicks-style wall values written into TimeSync /// payloads and the packet header's 16-bit Time field. /// public double Seconds => (double)_timestamp / TicksPerSecond; /// Move time forward. The clock is monotonic — negative deltas throw. public void Advance(TimeSpan delta) { if (delta < TimeSpan.Zero) { throw new ArgumentOutOfRangeException( nameof(delta), "the clock is monotonic — it cannot go backwards"); } _timestamp += delta.Ticks; } }