Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5f8a479

Browse files
committedNov 2, 2023
Enhancement: Extract Time
1 parent a243c02 commit 5f8a479

File tree

7 files changed

+328
-3
lines changed

7 files changed

+328
-3
lines changed
 

‎CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ For a full diff see [`2.3.2...main`][2.3.2...main].
1313
- Extracted `Duration` ([#351]), by [@localheinz]
1414
- Merged `MaximumDuration` into `Duration` ([#352]), by [@localheinz]
1515
- Renamed `MaximumCount` to `Count` ([#353]), by [@localheinz]
16+
- Extracted `Time` ([#354]), by [@localheinz]
1617

1718
### Fixed
1819

@@ -178,5 +179,6 @@ For a full diff see [`7afa59c...1.0.0`][7afa59c...1.0.0].
178179
[#351]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/351
179180
[#352]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/352
180181
[#353]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/353
182+
[#354]: https://github.com/ergebnis/phpunit-slow-test-detector/pull/354
181183

182184
[@localheinz]: https://github.com/localheinz

‎psalm-baseline.xml

+14
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,21 @@
2424
<code>forMethod</code>
2525
<code>symbolAnnotations</code>
2626
</InternalMethod>
27+
<InvalidArgument>
28+
<code><![CDATA[$event->telemetryInfo()->time()]]></code>
29+
</InvalidArgument>
2730
<MixedArgument>
2831
<code>$maximumDuration</code>
2932
</MixedArgument>
3033
<MixedAssignment>
3134
<code>$maximumDuration</code>
3235
</MixedAssignment>
3336
</file>
37+
<file src="src/Subscriber/TestPreparedSubscriber.php">
38+
<InvalidArgument>
39+
<code><![CDATA[$event->telemetryInfo()->time()]]></code>
40+
</InvalidArgument>
41+
</file>
3442
<file src="test/Double/Collector/AppendingCollector.php">
3543
<UnusedClass>
3644
<code>AppendingCollector</code>
@@ -81,4 +89,10 @@
8189
<code>provideDurationAndFormattedDuration</code>
8290
</PossiblyUnusedMethod>
8391
</file>
92+
<file src="test/Unit/TimeTest.php">
93+
<PossiblyUnusedMethod>
94+
<code>provideStartEndAndDuration</code>
95+
<code>provideStartGreaterThanEnd</code>
96+
</PossiblyUnusedMethod>
97+
</file>
8498
</files>

‎src/Exception/InvalidStart.php

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2023 Andreas Möller
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE.md file that was distributed with this source code.
10+
*
11+
* @see https://github.com/ergebnis/phpunit-slow-test-detector
12+
*/
13+
14+
namespace Ergebnis\PHPUnit\SlowTestDetector\Exception;
15+
16+
/**
17+
* @internal
18+
*/
19+
final class InvalidStart extends \InvalidArgumentException
20+
{
21+
public static function notLessThanOrEqualToEnd(): self
22+
{
23+
return new self('Start should be less than or equal to end.');
24+
}
25+
}

‎src/Time.php

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2023 Andreas Möller
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE.md file that was distributed with this source code.
10+
*
11+
* @see https://github.com/ergebnis/phpunit-slow-test-detector
12+
*/
13+
14+
namespace Ergebnis\PHPUnit\SlowTestDetector;
15+
16+
final class Time
17+
{
18+
private function __construct(
19+
private readonly int $seconds,
20+
private readonly int $nanoseconds,
21+
) {
22+
}
23+
24+
/**
25+
* @throws Exception\InvalidNanoseconds
26+
* @throws Exception\InvalidSeconds
27+
*/
28+
public static function fromSecondsAndNanoseconds(
29+
int $seconds,
30+
int $nanoseconds,
31+
): self {
32+
if (0 > $seconds) {
33+
throw Exception\InvalidSeconds::notGreaterThanOrEqualToZero($seconds);
34+
}
35+
36+
if (0 > $nanoseconds) {
37+
throw Exception\InvalidNanoseconds::notGreaterThanOrEqualToZero($nanoseconds);
38+
}
39+
40+
if (999_999_999 < $nanoseconds) {
41+
throw Exception\InvalidNanoseconds::notLessThanOrEqualTo999999999($nanoseconds);
42+
}
43+
44+
return new self(
45+
$seconds,
46+
$nanoseconds,
47+
);
48+
}
49+
50+
public function seconds(): int
51+
{
52+
return $this->seconds;
53+
}
54+
55+
public function nanoseconds(): int
56+
{
57+
return $this->nanoseconds;
58+
}
59+
60+
/**
61+
* @throws Exception\InvalidStart
62+
*/
63+
public function duration(self $start): Duration
64+
{
65+
$seconds = $this->seconds - $start->seconds();
66+
$nanoseconds = $this->nanoseconds - $start->nanoseconds();
67+
68+
if (0 > $nanoseconds) {
69+
--$seconds;
70+
71+
$nanoseconds += 1_000_000_000;
72+
}
73+
74+
if (0 > $seconds) {
75+
throw Exception\InvalidStart::notLessThanOrEqualToEnd();
76+
}
77+
78+
return Duration::fromSecondsAndNanoseconds(
79+
$seconds,
80+
$nanoseconds,
81+
);
82+
}
83+
}

‎src/TimeKeeper.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
final class TimeKeeper
2222
{
2323
/**
24-
* @var array<string, Event\Telemetry\HRTime>
24+
* @var array<string, Time>
2525
*/
2626
private array $startedTimes = [];
2727

2828
public function start(
2929
Event\Code\Test $test,
30-
Event\Telemetry\HRTime $startedTime,
30+
Time $startedTime,
3131
): void {
3232
$key = $test->id();
3333

@@ -36,7 +36,7 @@ public function start(
3636

3737
public function stop(
3838
Event\Code\Test $test,
39-
Event\Telemetry\HRTime $stoppedTime,
39+
Time $stoppedTime,
4040
): Duration {
4141
$key = $test->id();
4242

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2023 Andreas Möller
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE.md file that was distributed with this source code.
10+
*
11+
* @see https://github.com/ergebnis/phpunit-slow-test-detector
12+
*/
13+
14+
namespace Ergebnis\PHPUnit\SlowTestDetector\Test\Unit\Exception;
15+
16+
use Ergebnis\PHPUnit\SlowTestDetector\Exception;
17+
use PHPUnit\Framework;
18+
19+
#[Framework\Attributes\CoversClass(Exception\InvalidStart::class)]
20+
final class InvalidStartTest extends Framework\TestCase
21+
{
22+
public function testNotLessThanOrEqualToEndReturnsException(): void
23+
{
24+
$exception = Exception\InvalidStart::notLessThanOrEqualToEnd();
25+
26+
self::assertSame('Start should be less than or equal to end.', $exception->getMessage());
27+
}
28+
}

‎test/Unit/TimeTest.php

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* Copyright (c) 2021-2023 Andreas Möller
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE.md file that was distributed with this source code.
10+
*
11+
* @see https://github.com/ergebnis/phpunit-slow-test-detector
12+
*/
13+
14+
namespace Ergebnis\PHPUnit\SlowTestDetector\Test\Unit;
15+
16+
use Ergebnis\PHPUnit\SlowTestDetector\Duration;
17+
use Ergebnis\PHPUnit\SlowTestDetector\Exception;
18+
use Ergebnis\PHPUnit\SlowTestDetector\Test;
19+
use Ergebnis\PHPUnit\SlowTestDetector\Time;
20+
use PHPUnit\Framework;
21+
22+
#[Framework\Attributes\CoversClass(Time::class)]
23+
#[Framework\Attributes\UsesClass(Duration::class)]
24+
final class TimeTest extends Framework\TestCase
25+
{
26+
use Test\Util\Helper;
27+
28+
public function testFromSecondsAndNanosecondsRejectsNegativeSeconds(): void
29+
{
30+
$this->expectException(Exception\InvalidSeconds::class);
31+
32+
Time::fromSecondsAndNanoseconds(
33+
-1,
34+
0,
35+
);
36+
}
37+
38+
public function testFromSecondsAndNanosecondsRejectsNegativeNanoseconds(): void
39+
{
40+
$this->expectException(Exception\InvalidNanoseconds::class);
41+
42+
Time::fromSecondsAndNanoseconds(
43+
0,
44+
-1,
45+
);
46+
}
47+
48+
public function testFromSecondsAndNanosecondsRejectsNanosecondsGreaterThan999999999(): void
49+
{
50+
$this->expectException(Exception\InvalidNanoseconds::class);
51+
52+
Time::fromSecondsAndNanoseconds(
53+
0,
54+
1000000000,
55+
);
56+
}
57+
58+
public function testFromSecondsAndNanosecondsReturnsTime(): void
59+
{
60+
$faker = self::faker();
61+
62+
$seconds = $faker->numberBetween(0, 999);
63+
$nanoseconds = $faker->numberBetween(0, 999_999_999);
64+
65+
$time = Time::fromSecondsAndNanoseconds(
66+
$seconds,
67+
$nanoseconds,
68+
);
69+
70+
self::assertSame($seconds, $time->seconds());
71+
self::assertSame($nanoseconds, $time->nanoseconds());
72+
}
73+
74+
#[Framework\Attributes\DataProvider('provideStartGreaterThanEnd')]
75+
public function testDurationRejectsStartGreaterThanEnd(
76+
int $startSeconds,
77+
int $startNanoseconds,
78+
int $endSeconds,
79+
int $endNanoseconds,
80+
): void {
81+
$start = Time::fromSecondsAndNanoseconds(
82+
$startSeconds,
83+
$startNanoseconds,
84+
);
85+
86+
$end = Time::fromSecondsAndNanoseconds(
87+
$endSeconds,
88+
$endNanoseconds,
89+
);
90+
91+
$this->expectException(Exception\InvalidStart::class);
92+
93+
$end->duration($start);
94+
}
95+
96+
/**
97+
* @return array<string, array{0: int, 1: int, 2: int, 3: int}>
98+
*/
99+
public static function provideStartGreaterThanEnd(): array
100+
{
101+
return [
102+
'seconds-greater' => [
103+
11,
104+
1,
105+
10,
106+
1,
107+
],
108+
'seconds-and-nanoseconds-greater' => [
109+
11,
110+
1,
111+
10,
112+
0,
113+
],
114+
'nanoseconds-greater' => [
115+
10,
116+
1,
117+
10,
118+
0,
119+
],
120+
];
121+
}
122+
123+
#[Framework\Attributes\DataProvider('provideStartEndAndDuration')]
124+
public function testDurationReturnsDifferenceBetweenEndAndStart(
125+
int $startSeconds,
126+
int $startNanoseconds,
127+
int $endSeconds,
128+
int $endNanoseconds,
129+
Duration $duration,
130+
): void {
131+
$start = Time::fromSecondsAndNanoseconds(
132+
$startSeconds,
133+
$startNanoseconds,
134+
);
135+
136+
$end = Time::fromSecondsAndNanoseconds(
137+
$endSeconds,
138+
$endNanoseconds,
139+
);
140+
141+
self::assertEquals($duration, $end->duration($start));
142+
}
143+
144+
/**
145+
* @return array<string, array{0: int, 1: int, 2: int, 3: int, 4: Duration}>
146+
*/
147+
public static function provideStartEndAndDuration(): array
148+
{
149+
return [
150+
'start-equal-to-end' => [
151+
10,
152+
50,
153+
10,
154+
50,
155+
Duration::fromSecondsAndNanoseconds(0, 0),
156+
],
157+
'start-smaller-than-end' => [
158+
10,
159+
50,
160+
12,
161+
70,
162+
Duration::fromSecondsAndNanoseconds(2, 20),
163+
],
164+
'start-nanoseconds-greater-than-end-nanoseconds' => [
165+
10,
166+
50,
167+
12,
168+
30,
169+
Duration::fromSecondsAndNanoseconds(1, 999999980),
170+
],
171+
];
172+
}
173+
}

0 commit comments

Comments
 (0)
Please sign in to comment.