MathTest.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Crypt
  17. * @subpackage UnitTests
  18. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. require_once 'Zend/Crypt/Math.php';
  23. require_once 'Zend/Crypt/Exception.php';
  24. /**
  25. * @category Zend
  26. * @package Zend_Crypt
  27. * @subpackage UnitTests
  28. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  29. * @license http://framework.zend.com/license/new-bsd New BSD License
  30. * @group Zend_Crypt
  31. */
  32. class Zend_Crypt_MathTest extends PHPUnit_Framework_TestCase
  33. {
  34. public function testRand()
  35. {
  36. if (!extension_loaded('bcmath')) {
  37. $this->markTestSkipped('Extension bcmath not loaded');
  38. }
  39. try {
  40. $math = new Zend_Crypt_Math_BigInteger();
  41. } catch (Zend_Crypt_Math_BigInteger_Exception $e) {
  42. if (strpos($e->getMessage(), 'big integer precision math support not detected') !== false) {
  43. $this->markTestSkipped($e->getMessage());
  44. } else {
  45. throw $e;
  46. }
  47. }
  48. $math = new Zend_Crypt_Math();
  49. $higher = '155172898181473697471232257763715539915724801966915404479707795314057629378541917580651227423698188993727816152646631438561595825688188889951272158842675419950341258706556549803580104870537681476726513255747040765857479291291572334510643245094715007229621094194349783925984760375594985848253359305585439638443';
  50. $lower = '155172898181473697471232257763715539915724801966915404479707795314057629378541917580651227423698188993727816152646631438561595825688188889951272158842675419950341258706556549803580104870537681476726513255747040765857479291291572334510643245094715007229621094194349783925984760375594985848253359305585439638442';
  51. $result = $math->rand($lower, $higher);
  52. $this->assertTrue(bccomp($result, $higher) !== '1');
  53. $this->assertTrue(bccomp($result, $lower) !== '-1');
  54. }
  55. public function testRandBytes()
  56. {
  57. for ($length = 1; $length < 4096; $length++) {
  58. $rand = Zend_Crypt_Math::randBytes($length);
  59. $this->assertTrue(false !== $rand);
  60. $this->assertEquals($length, strlen($rand));
  61. }
  62. }
  63. public function testRandInteger()
  64. {
  65. for ($i = 0; $i < 1024; $i++) {
  66. $min = rand(1, PHP_INT_MAX/2);
  67. $max = $min + rand(1, PHP_INT_MAX/2 - 1);
  68. $rand = Zend_Crypt_Math::randInteger($min, $max);
  69. $this->assertGreaterThanOrEqual($min, $rand);
  70. $this->assertLessThanOrEqual($max, $rand);
  71. }
  72. }
  73. public static function provideRandInt()
  74. {
  75. return array(
  76. array(2, 1, 10000, 100, 0.9, 1.1, false),
  77. array(2, 1, 10000, 100, 0.8, 1.2, true)
  78. );
  79. }
  80. /**
  81. * A Monte Carlo test that generates $cycles numbers from 0 to $tot
  82. * and test if the numbers are above or below the line y=x with a
  83. * frequency range of [$min, $max]
  84. *
  85. * @dataProvider provideRandInt
  86. */
  87. public function testMontecarloRandInteger($num, $valid, $cycles, $tot, $min, $max, $strong)
  88. {
  89. try {
  90. $test = Zend_Crypt_Math::randBytes(1, $strong);
  91. } catch (Zend_Crypt_Exception $e) {
  92. $this->markTestSkipped($e->getMessage());
  93. }
  94. $i = 0;
  95. $count = 0;
  96. do {
  97. $up = 0;
  98. $down = 0;
  99. for ($i = 0; $i < $cycles; $i++) {
  100. $x = Zend_Crypt_Math::randInteger(0, $tot, $strong);
  101. $y = Zend_Crypt_Math::randInteger(0, $tot, $strong);
  102. if ($x > $y) {
  103. $up++;
  104. } elseif ($x < $y) {
  105. $down++;
  106. }
  107. }
  108. $this->assertGreaterThan(0, $up);
  109. $this->assertGreaterThan(0, $down);
  110. $ratio = $up / $down;
  111. if ($ratio > $min && $ratio < $max) {
  112. $count++;
  113. }
  114. $i++;
  115. } while ($i < $num && $count < $valid);
  116. if ($count < $valid) {
  117. $this->fail('The random number generator failed the Monte Carlo test');
  118. }
  119. }
  120. }