Files
php-uuid/tests/Generator/DefaultTimeGeneratorTest.php
T
Ben Ramsey 0d7b8c2b7a Update coding style to include PSR-12, among other options
This also includes heavy use of slevomat/coding-standard to apply
various checks to the code, based on maintainer (me) preference.
2020-01-18 12:13:55 -06:00

221 lines
7.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Ramsey\Uuid\Test\Generator;
use AspectMock\Test as AspectMock;
use Mockery;
use PHPUnit\Framework\MockObject\MockObject;
use Ramsey\Uuid\BinaryUtils;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Generator\DefaultTimeGenerator;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Provider\TimeProviderInterface;
use Ramsey\Uuid\Test\TestCase;
class DefaultTimeGeneratorTest extends TestCase
{
/**
* @var TimeProviderInterface & MockObject
*/
private $timeProvider;
/**
* @var NodeProviderInterface & MockObject
*/
private $nodeProvider;
/**
* @var TimeConverterInterface & MockObject
*/
private $timeConverter;
/**
* @var string
*/
private $nodeId = '122f80ca9e06';
/**
* @var int[]
*/
private $currentTime;
/**
* @var string[]
*/
private $calculatedTime;
/**
* @var int
*/
private $clockSeq = 4066;
protected function setUp(): void
{
parent::setUp();
$this->timeProvider = $this->getMockBuilder(TimeProviderInterface::class)->getMock();
$this->nodeProvider = $this->getMockBuilder(NodeProviderInterface::class)->getMock();
$this->timeConverter = $this->getMockBuilder(TimeConverterInterface::class)->getMock();
$this->currentTime = ['sec' => 1458733431, 'usec' => 877449];
$this->calculatedTime = ['low' => '83cb98e0', 'mid' => '98e0', 'hi' => '03cb'];
}
protected function tearDown(): void
{
parent::tearDown();
unset($this->timeProvider, $this->nodeProvider, $this->timeConverter);
Mockery::close();
AspectMock::clean();
}
public function testGenerateUsesNodeProviderWhenNodeIsNull(): void
{
$this->nodeProvider->expects($this->once())
->method('getNode')
->willReturn('122f80ca9e06');
$this->timeProvider->method('currentTime')
->willReturn($this->currentTime);
$this->timeConverter->expects($this->once())
->method('calculateTime')
->with($this->currentTime['sec'], $this->currentTime['usec'])
->willReturn($this->calculatedTime);
$defaultTimeGenerator = new DefaultTimeGenerator(
$this->nodeProvider,
$this->timeConverter,
$this->timeProvider
);
$defaultTimeGenerator->generate(null, $this->clockSeq);
}
public function testGenerateUsesTimeProvidersCurrentTime(): void
{
$this->timeProvider->expects($this->once())
->method('currentTime')
->willReturn($this->currentTime);
$this->timeConverter->expects($this->once())
->method('calculateTime')
->with($this->currentTime['sec'], $this->currentTime['usec'])
->willReturn($this->calculatedTime);
$defaultTimeGenerator = new DefaultTimeGenerator(
$this->nodeProvider,
$this->timeConverter,
$this->timeProvider
);
$defaultTimeGenerator->generate($this->nodeId, $this->clockSeq);
}
public function testGenerateCalculatesTimeWithConverter(): void
{
$this->timeProvider->method('currentTime')
->willReturn($this->currentTime);
$this->timeConverter->expects($this->once())
->method('calculateTime')
->with($this->currentTime['sec'], $this->currentTime['usec'])
->willReturn($this->calculatedTime);
$defaultTimeGenerator = new DefaultTimeGenerator(
$this->nodeProvider,
$this->timeConverter,
$this->timeProvider
);
$defaultTimeGenerator->generate($this->nodeId, $this->clockSeq);
}
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testGenerateAppliesVersionAndVariant(): void
{
$expectedBytes = hex2bin('83cb98e098e003cb8fe2122f80ca9e06');
$this->timeProvider->method('currentTime')
->willReturn($this->currentTime);
$this->timeConverter->method('calculateTime')
->with($this->currentTime['sec'], $this->currentTime['usec'])
->willReturn($this->calculatedTime);
$binaryUtils = Mockery::mock('alias:' . BinaryUtils::class);
$binaryUtils->shouldReceive('applyVersion')
->with($this->calculatedTime['hi'], 1)
->andReturn(971);
$clockSeqShifted = 15;
$binaryUtils->shouldReceive('applyVariant')
->with($clockSeqShifted)
->andReturn(143);
$defaultTimeGenerator = new DefaultTimeGenerator(
$this->nodeProvider,
$this->timeConverter,
$this->timeProvider
);
$this->assertSame($expectedBytes, $defaultTimeGenerator->generate($this->nodeId, $this->clockSeq));
}
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testGenerateReturnsBinaryStringInUuidFormat(): void
{
$this->timeProvider->method('currentTime')->willReturn($this->currentTime);
$this->timeConverter->method('calculateTime')->willReturn($this->calculatedTime);
$binaryUtils = Mockery::mock('alias:' . BinaryUtils::class);
$binaryUtils->shouldReceive('applyVersion')->andReturn(971);
$binaryUtils->shouldReceive('applyVariant')->andReturn(143);
$defaultTimeGenerator = new DefaultTimeGenerator(
$this->nodeProvider,
$this->timeConverter,
$this->timeProvider
);
$result = $defaultTimeGenerator->generate($this->nodeId, $this->clockSeq);
// Given we use values:
// $low = '83cb98e0';
// $mid = '98e0';
// $timeHi = 971;
// $clockSeqHi = 143;
// $clockSeq = 4066;
// $node = '122f80ca9e06';
//
// $values = [
// $low,
// $mid,
// sprintf('%04x', $timeHi),
// sprintf('%02x', $clockSeqHi),
// sprintf('%02x', $clockSeq & 0xff),
// $node
// ];
//
// then:
// $hex = vsprintf('%08s%04s%04s%02s%02s%012s', $values);
$hex = '83cb98e098e003cb8fe2122f80ca9e06';
$binary = hex2bin($hex);
$this->assertEquals($binary, $result);
}
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testGenerateUsesRandomSequenceWhenClockSeqNull(): void
{
$randomInt = AspectMock::func('Ramsey\Uuid\Generator', 'random_int', 9622);
$this->timeProvider->method('currentTime')
->willReturn($this->currentTime);
$this->timeConverter->expects($this->once())
->method('calculateTime')
->with($this->currentTime['sec'], $this->currentTime['usec'])
->willReturn($this->calculatedTime);
$defaultTimeGenerator = new DefaultTimeGenerator(
$this->nodeProvider,
$this->timeConverter,
$this->timeProvider
);
$defaultTimeGenerator->generate($this->nodeId);
$randomInt->verifyInvokedOnce([0, 0x3fff]);
}
}