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