Randomness¶
Eris allow multiple sources of randomness, with the requirements that they must accept a seed for reproducibility. Therefore, sequence Pseudo Random Number Generators (PRNG) are used instead of Cryptographically Secure PRNG, which would provide no additional value in generating test cases but make impossible to run the same test twice.
The supported random number generators are:
- the
rand
PHP function: this is the default, and simpler, choice. - the
mt_rand
PHP function: this is a faster PRNG. - the PHP code implementation
purePhpMtRand()
is equivalent tomt_rand
.
Being implemented inside a PHP object, purePhpMtRand()
allows to isolate its state while the first two implementations modify the global state of the PHP process. Use purePhpMtRand()
when your code calls rand()
or mt_rand()
and you don’t want it to interact with the testing framework.
Configuration¶
<?php
use Eris\Generator;
use Eris\Random;
use Eris\TestTrait;
class RandConfigurationTest extends PHPUnit_Framework_TestCase
{
use TestTrait;
public function testUsingTheDefaultRandFunction()
{
$this
->withRand('rand')
->forAll(
Generator\int()
)
->withMaxSize(1000 * 1000* 1000)
->then($this->isInteger());
}
/**
* @eris-method rand
*/
public function testUsingTheDefaultRandFunctionFromAnnotation()
{
$this
->forAll(
Generator\int()
)
->withMaxSize(1000 * 1000* 1000)
->then($this->isInteger());
}
public function testUsingTheDefaultMtRandFunction()
{
$this
->withRand('mt_rand')
->forAll(
Generator\int()
)
->then($this->isInteger());
}
/**
* @eris-method mt_rand
*/
public function testUsingTheDefaultMtRandFunctionFromAnnotation()
{
$this
->forAll(
Generator\int()
)
->then($this->isInteger());
}
public function testUsingThePurePhpMtRandFunction()
{
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('MersenneTwister class does not support HHVM');
}
$this
->withRand(Random\purePhpMtRand())
->forAll(
Generator\int()
)
->then($this->isInteger());
}
private function isInteger()
{
return function ($number) {
$this->assertInternalType('integer', $number);
};
}
}
testUsingTheDefaultRandFunction
specifies the rand
variant, but is equivalent to not calling withRand()
at all. srand
is the corresponding seed function.
testUsingTheDefaultMtRandFunction
configured mt_rand
and mt_srand
as its seed function.
testUsingThePurePhpMtRandFunction
configures purePhpMtRand()
.
Maximum sizes¶
The size that can be set and actually reached with withMaxSize()
is limited by the chosen PRNG.
- For
rand
the maximum values is the result ofgetrandmax()
, which is platform dependent but usually 2^31-1. - For
mt_rand
the maximum value is the result ofmt_getrandmax()
, which is also platform dependent but usually 2^31-1. - For
purePhpMtRand()
, being implemented in PHP code, the maximum value is 2^32-1.
The limitation on size depends not only on the processor architecture but also on the parameters of the algorithm. Both mt_rand
and purePhpMtRand()` implement MT19937, which generates 32-bit integers that can be scaled on any smaller interval.
However, according to the PHP source code, mt_rand
implementations uses a lower limit for backward compatibility with rand
. purePhpMtRand()
has no need for backward compatibility and chooses to allow numbers up to 2^32-1, which is the maximum unsigned number representable with 32 bit.
Seeding¶
The PRNGS are seeded using the microtime()
of the system, or with the ERIS_SEED
environment variable for test reproducibility.
Comparison¶
Variant | Portability | Speed | Global state |
---|---|---|---|
rand |
PHP core | Slow | Yes |
mt_rand |
PHP core | Fast | Yes |
purePhpMtRand() |
Eris source code | Medium | No |