Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
53 / 53
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2
3declare(strict_types=1);
4
5pest()->group('integration');
6
7use Phexium\Plugin\Clock\Adapter\FrozenClock;
8use Phexium\Plugin\Clock\Adapter\MonotonicClock;
9use Phexium\Plugin\Clock\Adapter\OffsetClock;
10use Phexium\Plugin\Clock\Port\ClockInterface;
11
12describe('Time retrieval', function (): void {
13    it('returns inner clock time on first call', function (): void {
14        $inner = new FrozenClock('2024-01-15 10:30:00');
15        $clock = new MonotonicClock($inner);
16
17        $result = $clock->now();
18
19        expect($result)->toEqual(new DateTimeImmutable('2024-01-15 10:30:00'));
20    });
21
22    it('returns inner clock time when time advances', function (): void {
23        $inner = new OffsetClock(new FrozenClock('2024-01-15 10:30:00'));
24        $clock = new MonotonicClock($inner);
25
26        $clock->now();
27
28        $inner->advanceSeconds(1);
29        $result = $clock->now();
30
31        expect($result)->toEqual(new DateTimeImmutable('2024-01-15 10:30:01'));
32    });
33});
34
35describe('Monotonicity', function (): void {
36    it('increments by microsecond when time is equal', function (): void {
37        $inner = new FrozenClock('2024-01-15 10:30:00.000000');
38        $clock = new MonotonicClock($inner);
39
40        $first = $clock->now();
41        $second = $clock->now();
42
43        expect($second)->toBeGreaterThan($first);
44        expect($second)->toEqual(new DateTimeImmutable('2024-01-15 10:30:00.000000')->modify('+1 microsecond'));
45    });
46
47    it('increments by microsecond when time goes backward', function (): void {
48        $sequence = [
49            new DateTimeImmutable('2024-01-15 10:30:00'),
50            new DateTimeImmutable('2024-01-15 10:29:59'),
51        ];
52        $index = 0;
53        $inner = new class($sequence, $index) implements ClockInterface {
54            public function __construct(
55                private readonly array $sequence,
56                private int $index,
57            ) {}
58
59            #[Override]
60            public function now(): DateTimeImmutable
61            {
62                return $this->sequence[$this->index++];
63            }
64        };
65
66        $clock = new MonotonicClock($inner);
67
68        $first = $clock->now();
69        $second = $clock->now();
70
71        expect($second)->toBeGreaterThan($first);
72        expect($second)->toEqual(new DateTimeImmutable('2024-01-15 10:30:00')->modify('+1 microsecond'));
73    });
74
75    it('guarantees strictly increasing time over multiple calls', function (): void {
76        $inner = new FrozenClock('2024-01-15 10:30:00.000000');
77        $clock = new MonotonicClock($inner);
78
79        $times = [];
80
81        for ($i = 0; $i < 5; ++$i) {
82            $times[] = $clock->now();
83        }
84        $counter = count($times);
85
86        for ($i = 1; $i < $counter; ++$i) {
87            expect($times[$i])->toBeGreaterThan($times[$i - 1]);
88        }
89    });
90});