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