lib/quic/src/sim/clock.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 /// A nanosecond counter a test owns and moves forward itself. A test holds a manual clock and
4 /// passes its reading wherever a connection or a link asks for the current time. The clock starts
5 /// at zero. A test alone moves the clock, so the test decides the exact instant of every step.
6 pub const Clock = struct {
7 now_ns: u64 = 0,
8
9 /// Moves the clock forward by a given number of nanoseconds so a test puts a chosen span of
10 /// time between steps. At the largest representable instant the clock stops there, so the
11 /// reading never goes backward.
12 pub fn advance(self: *Clock, delta_ns: u64) void {
13 const previous = self.now_ns;
14 self.now_ns = std.math.add(u64, self.now_ns, delta_ns) catch
15 std.math.maxInt(u64);
16 std.debug.assert(self.now_ns >= previous);
17 if (self.now_ns != std.math.maxInt(u64)) {
18 std.debug.assert(self.now_ns - previous == delta_ns);
19 }
20 }
21 };
22
23 test "manual clock advances by the requested nanoseconds" {
24 var clock = Clock{};
25 clock.advance(41);
26 try std.testing.expectEqual(@as(u64, 41), clock.now_ns);
27 }
28
29 test "manual clock never moves backward at integer capacity" {
30 var clock = Clock{ .now_ns = std.math.maxInt(u64) - 1 };
31 clock.advance(2);
32 try std.testing.expectEqual(std.math.maxInt(u64), clock.now_ns);
33 clock.advance(1);
34 try std.testing.expectEqual(std.math.maxInt(u64), clock.now_ns);
35 }