parent
684c47458b
commit
7dee6d0ac3
10 changed files with 229 additions and 5 deletions
@ -0,0 +1,15 @@ |
||||
<?php |
||||
|
||||
function randomDirectCalls(): array |
||||
{ |
||||
return [ |
||||
mt_rand(), |
||||
mt_rand(1, 10), |
||||
rand(), |
||||
rand(10, 1), |
||||
random_int(1, 10), |
||||
random_bytes(16), |
||||
mt_getrandmax(), |
||||
getrandmax(), |
||||
]; |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function invalidGetRandMaxArity(): int |
||||
{ |
||||
return mt_getrandmax(1); |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function invalidMtRandArity(): int |
||||
{ |
||||
return mt_rand(1); |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function invalidRandArity(): int |
||||
{ |
||||
return rand(1, 2, 3); |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function invalidRandomBytesArity(): string |
||||
{ |
||||
return random_bytes(1, 2); |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function invalidRandomIntArity(): int |
||||
{ |
||||
return random_int(1); |
||||
} |
||||
@ -0,0 +1,70 @@ |
||||
<?php |
||||
|
||||
use TypePhp\CompilerTest; |
||||
use TypePhp\Exception\TestError; |
||||
|
||||
final class RandomOptimizerTest extends BaseTest |
||||
{ |
||||
public function testRandomCallsUseDirectPhpxWrappersAndFoldFixedMaximum(): void |
||||
{ |
||||
$code = $this->compileFixture('random-direct-calls.php'); |
||||
|
||||
self::assertSame(2, substr_count($code, 'php::fn::mt_rand(')); |
||||
self::assertSame(2, substr_count($code, 'php::fn::rand(')); |
||||
self::assertSame(1, substr_count($code, 'php::fn::random_int(')); |
||||
self::assertSame(1, substr_count($code, 'php::fn::random_bytes(')); |
||||
self::assertSame(2, substr_count($code, '2147483647L')); |
||||
self::assertStringNotContainsString('mt_getrandmax', $code); |
||||
self::assertStringNotContainsString('getrandmax', $code); |
||||
self::assertStringNotContainsString('php::call(', $code); |
||||
} |
||||
|
||||
/** @dataProvider invalidArityProvider */ |
||||
public function testMtRandAndRandRejectUnsupportedArgumentCounts( |
||||
string $source, |
||||
string $message, |
||||
): void { |
||||
$this->expectException(TestError::class); |
||||
$this->expectExceptionMessage($message); |
||||
$this->compileFixture($source); |
||||
} |
||||
|
||||
public static function invalidArityProvider(): iterable |
||||
{ |
||||
yield 'mt_rand with one argument' => [ |
||||
'random-invalid-mt-rand-arity.php', |
||||
'mt_rand() expects exactly 0 or 2 arguments, 1 given', |
||||
]; |
||||
yield 'rand with three arguments' => [ |
||||
'random-invalid-rand-arity.php', |
||||
'rand() expects exactly 0 or 2 arguments, 3 given', |
||||
]; |
||||
yield 'random_int with one argument' => [ |
||||
'random-invalid-random-int-arity.php', |
||||
'random_int() expects at least 2 argument(s), 1 given', |
||||
]; |
||||
yield 'random_bytes with two arguments' => [ |
||||
'random-invalid-random-bytes-arity.php', |
||||
'random_bytes() expects at most 1 argument(s), 2 given', |
||||
]; |
||||
yield 'folded mt_getrandmax with an argument' => [ |
||||
'random-invalid-getrandmax-arity.php', |
||||
'mt_getrandmax() expects at most 0 argument(s), 1 given', |
||||
]; |
||||
} |
||||
|
||||
private function compileFixture(string $file): string |
||||
{ |
||||
global $translator; |
||||
|
||||
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH); |
||||
$translator = $compiler; |
||||
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/' . $file; |
||||
$compiler->addFiles([$source]); |
||||
$compiler->prepareFile($source); |
||||
$generated = $compiler->convertFile($source); |
||||
$code = file_get_contents($generated); |
||||
self::assertIsString($code); |
||||
return $code; |
||||
} |
||||
} |
||||
@ -0,0 +1,45 @@ |
||||
--TEST-- |
||||
random functions use direct wrappers and preserve PHP range semantics |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
$mt = mt_rand(); |
||||
var_dump($mt >= 0 && $mt <= mt_getrandmax()); |
||||
|
||||
$mtRange = mt_rand(10, 20); |
||||
var_dump($mtRange >= 10 && $mtRange <= 20); |
||||
|
||||
$randRange = rand(20, 10); |
||||
var_dump($randRange >= 10 && $randRange <= 20); |
||||
|
||||
$secure = random_int(5, 5); |
||||
var_dump($secure); |
||||
var_dump(strlen(random_bytes(8))); |
||||
var_dump(mt_getrandmax()); |
||||
var_dump(getrandmax()); |
||||
|
||||
try { |
||||
mt_rand(20, 10); |
||||
} catch (ValueError $error) { |
||||
echo $error->getMessage(), "\n"; |
||||
} |
||||
|
||||
try { |
||||
random_int(20, 10); |
||||
} catch (ValueError $error) { |
||||
echo $error->getMessage(), "\n"; |
||||
} |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
bool(true) |
||||
bool(true) |
||||
bool(true) |
||||
int(5) |
||||
int(8) |
||||
int(2147483647) |
||||
int(2147483647) |
||||
mt_rand(): Argument #2 ($max) must be greater than or equal to argument #1 ($min) |
||||
random_int(): Argument #1 ($min) must be less than or equal to argument #2 ($max) |
||||
Loading…
Reference in new issue