Inital commit after splitting from main project
PHP Composer / build (push) Successful in 30s

This commit is contained in:
2026-07-26 17:56:01 +02:00
commit fa6fbd77b0
15 changed files with 618 additions and 0 deletions
+156
View File
@@ -0,0 +1,156 @@
<?php
declare(strict_types=1);
namespace Tez\Utils\Tests\Clock;
use PHPUnit\Framework\TestCase;
use Tez\Utils\Clock\ClockInterface;
use Tez\Utils\Clock\FrozenClock;
use Tez\Utils\Clock\Stopwatch;
use Tez\Utils\Clock\SystemClock;
final class ClockTest extends TestCase
{
// -------------------------------------------------------------------------
// SystemClock
// -------------------------------------------------------------------------
public function testSystemClockImplementsInterface(): void
{
self::assertInstanceOf(ClockInterface::class, new SystemClock());
}
public function testSystemClockReturnsDateTimeImmutable(): void
{
$clock = new SystemClock();
self::assertInstanceOf(\DateTimeImmutable::class, $clock->now());
}
public function testSystemClockReturnsCurrentTime(): void
{
$before = new \DateTimeImmutable();
$now = (new SystemClock())->now();
$after = new \DateTimeImmutable();
self::assertGreaterThanOrEqual($before->getTimestamp(), $now->getTimestamp());
self::assertLessThanOrEqual($after->getTimestamp(), $now->getTimestamp());
}
// -------------------------------------------------------------------------
// FrozenClock
// -------------------------------------------------------------------------
public function testFrozenClockImplementsInterface(): void
{
$clock = new FrozenClock(new \DateTimeImmutable('2026-01-01 12:00:00'));
self::assertInstanceOf(ClockInterface::class, $clock);
}
public function testFrozenClockAlwaysReturnsSameTime(): void
{
$fixed = new \DateTimeImmutable('2026-01-01 12:00:00');
$clock = new FrozenClock($fixed);
self::assertSame($fixed, $clock->now());
self::assertSame($fixed, $clock->now());
}
public function testFrozenClockSetAdvancesTime(): void
{
$clock = new FrozenClock(new \DateTimeImmutable('2026-01-01 12:00:00'));
$later = new \DateTimeImmutable('2026-06-15 08:30:00');
$clock->set($later);
self::assertSame($later, $clock->now());
}
public function testFrozenClockIsUsableInTypedContext(): void
{
$clock = new FrozenClock(new \DateTimeImmutable('2026-01-01 00:00:00'));
$timestamp = $this->readTimestamp($clock);
self::assertSame('2026-01-01 00:00:00', $timestamp);
}
private function readTimestamp(ClockInterface $clock): string
{
return $clock->now()->format('Y-m-d H:i:s');
}
// -------------------------------------------------------------------------
// Stopwatch
// -------------------------------------------------------------------------
public function testStopwatchStartReturnsInstance(): void
{
self::assertInstanceOf(Stopwatch::class, Stopwatch::start());
}
public function testStopwatchElapsedIsNonNegative(): void
{
$sw = Stopwatch::start();
self::assertGreaterThanOrEqual(0.0, $sw->elapsed());
}
public function testStopwatchElapsedMsIsNonNegative(): void
{
$sw = Stopwatch::start();
self::assertGreaterThanOrEqual(0.0, $sw->elapsedMs());
}
public function testStopwatchElapsedMsIsLargerThanElapsedSeconds(): void
{
$sw = Stopwatch::start();
// A non-trivial amount of time: elapsed in ms should be > in seconds
// for any time >= 1ms (both should be close to zero but ms > s for small values)
$elapsedSec = $sw->elapsed();
$elapsedMs = $sw->elapsedMs();
// For any positive time: ms value >= s value * 1 (since 1ms = 0.001s)
// This holds as long as elapsed < 1 second (which it will be in a test)
self::assertGreaterThanOrEqual($elapsedSec, $elapsedMs);
}
public function testStopwatchResetMakesElapsedNearZero(): void
{
$sw = Stopwatch::start();
// Let some time pass conceptually (we can't sleep), then reset
$sw->reset();
self::assertLessThan(0.01, $sw->elapsed()); // under 10ms
}
public function testStopwatchLapReturnsNonNegative(): void
{
$sw = Stopwatch::start();
self::assertGreaterThanOrEqual(0.0, $sw->lap());
}
public function testStopwatchSubsequentLapsAreIndependent(): void
{
$sw = Stopwatch::start();
$lap1 = $sw->lap();
$lap2 = $sw->lap();
// Both laps are non-negative and their sum should not exceed total elapsed
self::assertGreaterThanOrEqual(0.0, $lap1);
self::assertGreaterThanOrEqual(0.0, $lap2);
}
public function testStopwatchLapDoesNotResetTotalElapsed(): void
{
$sw = Stopwatch::start();
$sw->lap();
$total = $sw->elapsed();
self::assertGreaterThanOrEqual(0.0, $total);
}
}