Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,168 @@
<?php
/*
* The RandomLib library for securely generating random numbers and strings in PHP
*
* @author Anthony Ferrara <ircmaxell@ircmaxell.com>
* @copyright 2011 The Authors
* @license http://www.opensource.org/licenses/mit-license.html MIT License
* @version Build @@version@@
*/
use RandomLib\Generator;
use RandomLibTest\Mocks\Random\Mixer;
use RandomLibTest\Mocks\Random\Source;
class Vectors_Random_GeneratorTest extends PHPUnit_Framework_TestCase
{
public static function provideGenerateInt()
{
return array(
// First, lets test each offset based range
array(0, 7),
array(0, 15),
array(0, 31),
array(0, 63),
array(0, 127),
array(0, 255),
array(0, 511),
array(0, 1023),
// Let's try a range not starting at 0
array(8, 15),
// Let's try a range with a negative number
array(-18, -11),
// Let's try a non-power-of-2 range
array(10, 100),
// Finally, let's try two large numbers
array(100000, 100007),
array(100000000, 100002047),
// Now, let's force a few loops by setting a valid offset
array(0, 5, 2),
array(0, 9, 5),
array(0, 27, 4),
);
}
public static function provideGenerators()
{
$factory = new \RandomLib\Factory();
$generator = $factory->getLowStrengthGenerator();
$sources = $generator->getSources();
$ret = array();
$ret[] = array(new Generator($sources, new \RandomLib\Mixer\Hash()), 10000, 'hash');
return $ret;
}
/**
* This test asserts that the algorithm that generates the integers does not
* actually introduce any bias into the generated numbers. If this test
* passes, the generated integers from the generator will be as unbiased as
* the sources that provide the data.
*
* @dataProvider provideGenerateInt
*/
public function testGenerateInt($min, $max, $offset = 0)
{
$generator = $this->getGenerator($max - $min + $offset);
for ($i = $max; $i >= $min; $i--) {
$this->assertEquals($i, $generator->generateInt($min, $max));
}
}
/**
* This generator generates two bytes at a time, and uses each 8 bit segment of
* the generated byte as a coordinate on a grid (so 01011010 would be the
* coordinate (0101, 1010) or (5, 10). These are used as inputs to a MonteCarlo
* algorithm for the integral of y=x over a 15x15 grid. The expected answer is
* 1/2 * 15 * 15 (or 1/2 * base * height, since the result is a triangle).
* Therefore, if we get an answer close to that, we know the generator is good.
*
* Now, since the area under the line should be equal to the area above the line.
* Therefore, the ratio of the two areas should be equal. This way, we can avoid
* computing total to figure out the areas.
*
* I have set the bounds on the test to be 80% and 120%. Meaning that I will
* consider the test valid and unbiased if the number of random elements that
* fall under (inside) of the line and the number that fall outside of the line
* are at most 20% apart.
*
* Since testing randomness is not reliable or repeatable, I will only fail the
* test in two different scenarios. The first is if after the iterations the
* outside or the inside is 0. The chances of that happening are so low that
* if it happens, it's relatively safe to assume that something bad happened. The
* second scenario happens when the ratio is outside of the 20% tolerance. If
* that happens, I will re-run the entire test. If that test is outside of the 20%
* tolerance, then the test will fail
*
*
* @dataProvider provideGenerators
*/
public function testGenerate(\RandomLib\Generator $generator, $times)
{
$ratio = $this->doTestGenerate($generator, $times);
if ($ratio < 0.8 || $ratio > 1.2) {
$ratio2 = $this->doTestGenerate($generator, $times);
if ($ratio2 > 1.2 || $ratio2 < 0.8) {
$this->fail(
sprintf(
'The test failed multiple runs with final ratios %f and %f',
$ratio,
$ratio2
)
);
}
}
}
protected function doTestGenerate(\RandomLib\Generator $generator, $times)
{
$inside = 0;
$outside = 0;
$on = 0;
for ($i = 0; $i < $times; $i++) {
$byte = $generator->generate(2);
$byte = unpack('n', $byte);
$byte = array_shift($byte);
$xCoord = ($byte >> 8);
$yCoord = ($byte & 0xFF);
if ($xCoord < $yCoord) {
$outside++;
} elseif ($xCoord == $yCoord) {
$on++;
} else {
$inside++;
}
}
$this->assertGreaterThan(0, $outside, 'Outside Is 0');
$this->assertGreaterThan(0, $inside, 'Inside Is 0');
$ratio = $inside / $outside;
return $ratio;
}
public function getGenerator($random)
{
$source1 = new Source(array(
'generate' => function ($size) use (&$random) {
$ret = pack('N', $random);
$random--;
return substr($ret, -1 * $size);
},
));
$sources = array($source1);
$mixer = new Mixer(array(
'mix'=> function (array $sources) {
if (empty($sources)) {
return '';
}
return array_pop($sources);
},
));
return new Generator($sources, $mixer);
}
}