expects()->generate(16)->andReturns( "\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00", ); $unixTimeGenerator = new UnixTimeGenerator($randomGenerator); $bytes = $unixTimeGenerator->generate(null, null, $dateTime); $this->assertSame($expectedBytes, $bytes); } /** * @runInSeparateProcess since values are stored statically on the class * @preserveGlobalState disabled */ public function testGenerateProducesMonotonicResults(): void { $randomGenerator = new RandomBytesGenerator(); $unixTimeGenerator = new UnixTimeGenerator($randomGenerator); $previous = ''; for ($i = 0; $i < self::ITERATIONS; $i++) { $bytes = $unixTimeGenerator->generate(); $this->assertTrue( $bytes > $previous, 'Failed on iteration ' . $i . ' when evaluating ' . bin2hex($bytes) . ' > ' . bin2hex($previous), ); $previous = $bytes; } } /** * @runInSeparateProcess since values are stored statically on the class * @preserveGlobalState disabled */ public function testGenerateProducesMonotonicResultsWithSameDate(): void { $dateTime = new DateTimeImmutable('now'); $randomGenerator = new RandomBytesGenerator(); $unixTimeGenerator = new UnixTimeGenerator($randomGenerator); $previous = ''; for ($i = 0; $i < self::ITERATIONS; $i++) { $bytes = $unixTimeGenerator->generate(null, null, $dateTime); $this->assertTrue( $bytes > $previous, 'Failed on iteration ' . $i . ' when evaluating ' . bin2hex($bytes) . ' > ' . bin2hex($previous), ); $previous = $bytes; } } /** * @runInSeparateProcess since values are stored statically on the class * @preserveGlobalState disabled */ public function testGenerateProducesMonotonicResultsFor32BitPath(): void { $randomGenerator = new RandomBytesGenerator(); $unixTimeGenerator = new UnixTimeGenerator($randomGenerator, 4); $previous = ''; for ($i = 0; $i < self::ITERATIONS; $i++) { $bytes = $unixTimeGenerator->generate(); $this->assertTrue( $bytes > $previous, 'Failed on iteration ' . $i . ' when evaluating ' . bin2hex($bytes) . ' > ' . bin2hex($previous), ); $previous = $bytes; } } /** * @runInSeparateProcess since values are stored statically on the class * @preserveGlobalState disabled */ public function testGenerateProducesMonotonicResultsWithSameDateFor32BitPath(): void { $dateTime = new DateTimeImmutable('now'); $randomGenerator = new RandomBytesGenerator(); $unixTimeGenerator = new UnixTimeGenerator($randomGenerator, 4); $previous = ''; for ($i = 0; $i < self::ITERATIONS; $i++) { $bytes = $unixTimeGenerator->generate(null, null, $dateTime); $this->assertTrue( $bytes > $previous, 'Failed on iteration ' . $i . ' when evaluating ' . bin2hex($bytes) . ' > ' . bin2hex($previous), ); $previous = $bytes; } } /** * @runInSeparateProcess since values are stored statically on the class * @preserveGlobalState disabled */ public function testGenerateProducesMonotonicResultsStartingWithAllBitsSet(): void { /** @var RandomGeneratorInterface&MockInterface $randomGenerator */ $randomGenerator = Mockery::mock(RandomGeneratorInterface::class); $randomGenerator->expects()->generate(16)->andReturns( "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", ); $randomGenerator->allows()->generate(10)->andReturns( "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", ); $unixTimeGenerator = new UnixTimeGenerator($randomGenerator); $previous = ''; for ($i = 0; $i < self::ITERATIONS; $i++) { $bytes = $unixTimeGenerator->generate(); $this->assertTrue( $bytes > $previous, 'Failed on iteration ' . $i . ' when evaluating ' . bin2hex($bytes) . ' > ' . bin2hex($previous), ); $previous = $bytes; } } /** * @runInSeparateProcess since values are stored statically on the class * @preserveGlobalState disabled */ public function testGenerateProducesMonotonicResultsStartingWithAllBitsSetWithSameDate(): void { $this->markTestSkipped('Bytes generator is failing to properly increment under these conditions'); /* @phpstan-ignore-next-line */ $dateTime = new DateTimeImmutable('now'); /** @var RandomGeneratorInterface&MockInterface $randomGenerator */ $randomGenerator = Mockery::mock(RandomGeneratorInterface::class); $randomGenerator->expects()->generate(16)->andReturns( "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", ); $randomGenerator->allows()->generate(10)->andReturns( "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", ); $unixTimeGenerator = new UnixTimeGenerator($randomGenerator); $previous = ''; for ($i = 0; $i < self::ITERATIONS; $i++) { $bytes = $unixTimeGenerator->generate(null, null, $dateTime); $this->assertTrue( $bytes > $previous, 'Failed on iteration ' . $i . ' when evaluating ' . bin2hex($bytes) . ' > ' . bin2hex($previous), ); $previous = $bytes; } } /** * @runInSeparateProcess since values are stored statically on the class * @preserveGlobalState disabled */ public function testGenerateProducesMonotonicResultsStartingWithAllBitsSetFor32BitPath(): void { /** @var RandomGeneratorInterface&MockInterface $randomGenerator */ $randomGenerator = Mockery::mock(RandomGeneratorInterface::class); $randomGenerator->expects()->generate(16)->andReturns( "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", ); $randomGenerator->allows()->generate(10)->andReturns( "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", ); $unixTimeGenerator = new UnixTimeGenerator($randomGenerator, 4); $previous = ''; for ($i = 0; $i < self::ITERATIONS; $i++) { $bytes = $unixTimeGenerator->generate(); $this->assertTrue( $bytes > $previous, 'Failed on iteration ' . $i . ' when evaluating ' . bin2hex($bytes) . ' > ' . bin2hex($previous), ); $previous = $bytes; } } /** * @runInSeparateProcess since values are stored statically on the class * @preserveGlobalState disabled */ public function testGenerateProducesMonotonicResultsStartingWithAllBitsSetWithSameDateFor32BitPath(): void { $this->markTestSkipped('Bytes generator is failing to properly increment under these conditions'); /* @phpstan-ignore-next-line */ $dateTime = new DateTimeImmutable('now'); /** @var RandomGeneratorInterface&MockInterface $randomGenerator */ $randomGenerator = Mockery::mock(RandomGeneratorInterface::class); $randomGenerator->expects()->generate(16)->andReturns( "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", ); $randomGenerator->allows()->generate(10)->andReturns( "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", ); $unixTimeGenerator = new UnixTimeGenerator($randomGenerator, 4); $previous = ''; for ($i = 0; $i < self::ITERATIONS; $i++) { $bytes = $unixTimeGenerator->generate(null, null, $dateTime); $this->assertTrue( $bytes > $previous, 'Failed on iteration ' . $i . ' when evaluating ' . bin2hex($bytes) . ' > ' . bin2hex($previous), ); $previous = $bytes; } } }