-
-
Notifications
You must be signed in to change notification settings - Fork 266
/
clock.test.ts
99 lines (79 loc) 路 3.78 KB
/
clock.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import {describe, it, expect, beforeEach, afterEach, vi} from "vitest";
import {config} from "@lodestar/config/default";
import {SLOTS_PER_EPOCH} from "@lodestar/params";
import {BeaconConfig} from "@lodestar/config";
import {Clock, getCurrentSlotAround} from "../../../src/util/clock.js";
import {testLogger} from "../../utils/logger.js";
describe("util / Clock", function () {
const logger = testLogger();
let controller: AbortController;
beforeEach(() => {
controller = new AbortController();
vi.useFakeTimers({now: Date.now()});
});
afterEach(() => {
controller.abort();
vi.useRealTimers();
});
it("Should call on slot", async () => {
const genesisTime = Math.floor(Date.now() / 1000) - config.SECONDS_PER_SLOT / 2;
const clock = new Clock(config, logger, {genesisTime});
const onSlot = vi.fn().mockResolvedValue(undefined);
clock.runEverySlot(onSlot);
clock.start(controller.signal);
// Must run once immediately
expect(onSlot).toHaveBeenCalledOnce();
expect(onSlot).toHaveBeenNthCalledWith(1, 0, expect.any(AbortSignal));
await vi.advanceTimersByTimeAsync(config.SECONDS_PER_SLOT * 1000);
expect(onSlot).toHaveBeenCalledTimes(2);
expect(onSlot).toHaveBeenNthCalledWith(2, 1, expect.any(AbortSignal));
await vi.advanceTimersByTimeAsync(config.SECONDS_PER_SLOT * 1000);
expect(onSlot).toHaveBeenCalledTimes(3);
expect(onSlot).toHaveBeenNthCalledWith(3, 2, expect.any(AbortSignal));
});
it("Should stop calling on slot after stop()", async () => {
const genesisTime = Math.floor(Date.now() / 1000) - config.SECONDS_PER_SLOT / 2;
const clock = new Clock(config, logger, {genesisTime});
const onSlot = vi.fn().mockResolvedValue(undefined);
clock.runEverySlot(onSlot);
clock.start(controller.signal);
await vi.advanceTimersByTimeAsync(config.SECONDS_PER_SLOT * 1000);
expect(onSlot).toBeCalledTimes(2);
expect(onSlot).toHaveBeenNthCalledWith(2, 1, expect.any(AbortSignal));
// Stop clock
controller.abort();
await vi.advanceTimersByTimeAsync(config.SECONDS_PER_SLOT * 1000);
expect(onSlot).toBeCalledTimes(2);
});
it("Should call on epoch", async () => {
// Start halfway through an epoch, so advancing a slot does not cross to the next epoch
const genesisTime = Math.floor(Date.now() / 1000) - (SLOTS_PER_EPOCH * config.SECONDS_PER_SLOT) / 2;
const clock = new Clock(config, logger, {genesisTime});
const onEpoch = vi.fn().mockResolvedValue(undefined);
clock.runEveryEpoch(onEpoch);
clock.start(controller.signal);
// Must run once immediately
expect(onEpoch).toHaveBeenCalledOnce();
expect(onEpoch).toHaveBeenCalledWith(0, expect.any(AbortSignal));
await vi.advanceTimersByTimeAsync(config.SECONDS_PER_SLOT * 1000);
expect(onEpoch).toHaveBeenCalledOnce();
await vi.advanceTimersByTimeAsync(SLOTS_PER_EPOCH * config.SECONDS_PER_SLOT * 1000);
expect(onEpoch).toHaveBeenCalledTimes(2);
expect(onEpoch).toHaveBeenNthCalledWith(2, 1, expect.any(AbortSignal));
});
describe("getCurrentSlot", function () {
// eslint-disable-next-line @typescript-eslint/naming-convention
const testConfig = {SECONDS_PER_SLOT: 12} as BeaconConfig;
const genesisTime = Math.floor(new Date("2021-01-01").getTime() / 1000);
const testCase: {name: string; delta: number}[] = [
{name: "should return next slot after 11.5s", delta: 11.5},
{name: "should return next slot after 12s", delta: 12},
{name: "should return next slot after 12.5s", delta: 12.5},
];
it.each(testCase)("$name", async function ({delta}) {
const currentSlot = getCurrentSlotAround(testConfig, genesisTime);
vi.advanceTimersByTime(delta * 1000);
expect(getCurrentSlotAround(testConfig, genesisTime)).toBe(currentSlot + 1);
});
});
});