Skip to content

Commit f900314

Browse files
authored
Merge pull request #10 from ingenerator/0.1/feat/mock-clock
Update StoppedMockClock to support newer phpunit and add unit tests.
2 parents 3aa5806 + ebf7ab6 commit f900314

File tree

3 files changed

+179
-3
lines changed

3 files changed

+179
-3
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
### Unreleased
22

3+
### v0.1.6 (2019-03-18)
4+
5+
* Update StoppedMockClock to support newer phpunit (use namespaced assert class) and add
6+
unit tests.
7+
38
### v0.1.6 (2018-09-06)
49

510
* Add AbstractArrayRepository

src/DateTime/Clock/StoppedMockClock.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace Ingenerator\PHPUtils\DateTime\Clock;
88

99
use Ingenerator\PHPUtils\DateTime\Clock\RealtimeClock;
10+
use PHPUnit\Framework\Assert;
1011

1112
class StoppedMockClock extends RealtimeClock
1213
{
@@ -25,7 +26,7 @@ class StoppedMockClock extends RealtimeClock
2526
*/
2627
protected function __construct(\DateTimeImmutable $start_time)
2728
{
28-
$this->current_microtime = $start_time->getTimestamp();
29+
$this->current_microtime = (float) $start_time->getTimestamp();
2930
}
3031

3132
/**
@@ -89,7 +90,7 @@ public function getMicrotime()
8990
public function tick(\DateInterval $period)
9091
{
9192
$now = $this->getDateTime()->add($period);
92-
$this->current_microtime = $now->getTimestamp();
93+
$this->current_microtime = (float) $now->getTimestamp();
9394
}
9495

9596
/**
@@ -108,7 +109,7 @@ public function usleep($microseconds)
108109

109110
public function assertSlept(array $expected, $msg = '')
110111
{
111-
\PHPUnit_Framework_Assert::assertSame($expected, $this->sleeps, $msg);
112+
Assert::assertSame($expected, $this->sleeps, $msg);
112113
}
113114

114115
}
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<?php
2+
3+
4+
namespace test\unit\Ingenerator\PHPUtils\unit\DateTime\Clock;
5+
6+
use Ingenerator\PHPUtils\DateTime\Clock\StoppedMockClock;
7+
use PHPUnit\Framework\TestCase;
8+
9+
class StoppedMockClockTest extends TestCase
10+
{
11+
12+
public function test_it_is_initialisable_now()
13+
{
14+
$clock = StoppedMockClock::atNow();
15+
$this->assertEquals(
16+
new \DateTimeImmutable,
17+
$clock->getDateTime(),
18+
'Starts at the right time',
19+
1
20+
);
21+
}
22+
23+
public function provider_at_fixed()
24+
{
25+
return [
26+
[
27+
'2019-03-04 10:02:03',
28+
new \DateTimeImmutable('2019-03-04 10:02:03'),
29+
1551693723.0
30+
],
31+
[
32+
new \DateTimeImmutable('2019-03-04 10:02:03'),
33+
new \DateTimeImmutable('2019-03-04 10:02:03'),
34+
1551693723.0
35+
],
36+
];
37+
}
38+
39+
40+
/**
41+
* @dataProvider provider_at_fixed
42+
*/
43+
public function test_it_is_initialisable_at_fixed_time_from_string_or_object($at_what, $expect_time, $expect_micro)
44+
{
45+
$clock = StoppedMockClock::at($at_what);
46+
$this->assertEquals($expect_time, $clock->getDateTime());
47+
$this->assertSame($expect_micro, $clock->getMicrotime());
48+
}
49+
50+
public function test_it_is_initialisable_at_fixed_microtime()
51+
{
52+
$clock = StoppedMockClock::atMicrotime(1551693723.1239);
53+
$this->assertSame(1551693723.1239, $clock->getMicrotime());
54+
$this->assertSame('2019-03-04 10:02:03', $clock->getDateTime()->format('Y-m-d H:i:s'));
55+
}
56+
57+
public function test_it_is_initialisable_at_a_date_interval_in_the_past()
58+
{
59+
$clock = StoppedMockClock::atTimeAgo('P3D');
60+
$ago = (new \DateTimeImmutable)->sub(new \DateInterval('P3D'));
61+
$this->assertEquals($ago, $clock->getDateTime(), 'Time is at correct interval', 1);
62+
}
63+
64+
public function test_it_holds_its_time_forever_in_real_life()
65+
{
66+
$clock = StoppedMockClock::atNow();
67+
$start_microtime = $clock->getMicrotime();
68+
$start_time = $clock->getDateTime();
69+
sleep(2);
70+
$this->assertEquals($start_time, $clock->getDateTime(), 'Stays at the same time');
71+
$this->assertSame($start_microtime, $clock->getMicrotime(), 'Stays at the same microtime');
72+
}
73+
74+
public function test_it_advances_time_after_each_tick()
75+
{
76+
$clock = StoppedMockClock::at('2019-01-05 10:03:02');
77+
$this->assertSame(1546682582.0, $clock->getMicrotime(), 'Correct starting microtime');
78+
79+
$clock->tick(new \DateInterval('P1D'));
80+
$this->assertEquals(new \DateTimeImmutable('2019-01-06 10:03:02'), $clock->getDateTime());
81+
$this->assertSame(1546768982.0, $clock->getMicrotime());
82+
}
83+
84+
public function test_it_advances_time_after_each_tick_microseconds()
85+
{
86+
$clock = StoppedMockClock::atMicrotime(1546682582.150);
87+
$this->assertEquals(new \DateTimeImmutable('2019-01-05 10:03:02'), $clock->getDateTime());
88+
89+
$clock->tickMicroseconds(150000);
90+
$this->assertSame(1546682582.300, round($clock->getMicrotime(), 3));
91+
$this->assertEquals(new \DateTimeImmutable('2019-01-05 10:03:02'), $clock->getDateTime(), 'DateTime not changed by sub-second tick');
92+
93+
94+
$clock->tickMicroseconds(750000);
95+
$this->assertSame(1546682583.050, round($clock->getMicrotime(), 3));
96+
$this->assertEquals(new \DateTimeImmutable('2019-01-05 10:03:03'), $clock->getDateTime(), 'DateTime changed after second boundary');
97+
}
98+
99+
public function test_its_usleep_is_immediate_but_advances_time()
100+
{
101+
$clock = StoppedMockClock::atMicrotime(1546682582.05);
102+
$start = microtime(TRUE);
103+
$clock->usleep(900000);
104+
$real_ms = 1000 * (microtime(TRUE) - $start);
105+
$this->assertLessThan(50, $real_ms, 'Should not actually sleep');
106+
$this->assertSame(1546682582.95, round($clock->getMicrotime(), 3), 'Should update time');
107+
}
108+
109+
public function provider_assert_slept_fails()
110+
{
111+
return [
112+
[
113+
function () {
114+
},
115+
[15],
116+
'Never slept at all'
117+
],
118+
[
119+
function (StoppedMockClock $clock) {
120+
$clock->usleep(150);
121+
},
122+
[15],
123+
'Wrong amount of sleep'
124+
],
125+
[
126+
function (StoppedMockClock $clock) {
127+
$clock->usleep(150);
128+
},
129+
[150, 30],
130+
'Incorrect number of sleeps'
131+
],
132+
[
133+
function (StoppedMockClock $clock) {
134+
$clock->usleep(150);
135+
$clock->usleep(10);
136+
},
137+
[10, 150],
138+
'Sleeps in wrong order'
139+
],
140+
];
141+
}
142+
143+
/**
144+
* @dataProvider provider_assert_slept_fails
145+
*/
146+
public function test_assert_slept_fails_if_not_slept_for_expected_intervals($callback, $expected, $msg)
147+
{
148+
$clock = StoppedMockClock::atNow();
149+
$callback($clock);
150+
$e = NULL;
151+
try {
152+
$clock->assertSlept($expected, $msg);
153+
} catch (\Exception $e) {
154+
}
155+
$this->assertInstanceOf(\Exception::class, $e, 'Should have thrown');
156+
// Do it like this to make it type-safe for old and new phpunit
157+
$this->assertContains('ExpectationFailedException', get_class($e), 'Should be assertion exception');
158+
}
159+
160+
public function test_assert_slept_passes_if_slept_for_expected_intervals()
161+
{
162+
$clock = StoppedMockClock::atNow();
163+
$clock->usleep(50000);
164+
$clock->usleep(20000);
165+
$clock->usleep(15000);
166+
$this->assertNull(
167+
$clock->assertSlept([50000, 20000, 15000])
168+
);
169+
}
170+
}

0 commit comments

Comments
 (0)