Compare commits

...

24 Commits

Author SHA1 Message Date
Anton Smirnov 1c36416a2b Build coverage for tags 2023-09-07 16:01:52 +03:00
Anton Smirnov a96b7769db Changelog for 1.0.2 2023-09-07 16:00:12 +03:00
Anton Smirnov 9f177d14d1 Group by major version 2023-09-07 15:58:20 +03:00
Anton Smirnov 6337d693f7 Require arokettu/unsigned at least v1.2.1 2023-09-05 17:10:55 +03:00
Anton Smirnov 4ddedb80bf Test gmp only on versions where it properly builds 2023-09-05 02:13:41 +03:00
Anton Smirnov 8e0c74b85f Fix test error on 7.1 2023-09-05 02:08:27 +03:00
Anton Smirnov c8f2d081fe Build matrix 2023-09-04 23:31:25 +03:00
Anton Smirnov f536dfea76 Update configs from templates 2023-08-18 22:46:33 +03:00
Anton Smirnov 379fe45154 Pin PHPUnit to 9.5 2023-02-23 23:08:22 +02:00
Anton Smirnov b0382f15c4 Stable code standard 2023-02-18 09:45:10 +02:00
Anton Smirnov 87b2372582 License link should lead to the repo 2023-02-18 09:41:11 +02:00
Anton Smirnov eafd1ef4e6 Make license detectable by github 2023-02-18 09:39:18 +02:00
Anton Smirnov 1ffe409988 Run release image 2022-12-09 18:20:12 +02:00
Anton Smirnov 1b1be45ea1 Update docs to reflect PHP 8.2 final release 2022-12-08 21:35:45 +02:00
Anton Smirnov 0e5326edae Changelog for 1.0.1 2022-11-12 01:32:27 +02:00
Anton Smirnov 0e7cf39973 Changelog for compatibility fix 2022-11-12 01:23:14 +02:00
Anton Smirnov 6758b6e517 Fall back to badscaling only directly in getInt 2022-11-12 01:23:14 +02:00
Anton Smirnov 32119d9ef3 Prepare a test case for 9839 compatibility 2022-11-12 01:23:14 +02:00
Anton Smirnov 6f480a73cf Move development to GitHub 2022-11-10 23:21:43 +02:00
Anton Smirnov 273dcaae8c Changelog for #6 2022-11-10 23:17:44 +02:00
Anton Smirnov 08e9aa6dd3 Ignore class name in the exception message 2022-11-10 23:12:40 +02:00
Nicolas Grekas f604b83754 Rely on symfony/polyfill-php82 ^1.27 2022-11-10 22:57:45 +02:00
Anton Smirnov 54307e9fea Missing final 2022-11-03 20:40:47 +02:00
Anton Smirnov 45c39e14d5 Fix more insanity in the docs 2022-10-26 19:00:27 +03:00
27 changed files with 278 additions and 253 deletions

7
.gitattributes vendored
View File

@ -1,8 +1,13 @@
# template
/docs/*.py export-ignore
/docs/*.txt export-ignore
/docs/_* export-ignore
/tests export-ignore
/debug export-ignore
/.git* export-ignore
/*.yml export-ignore
/*.yaml export-ignore
/*.xml export-ignore
/*.xml.dist export-ignore
# project
/debug export-ignore

View File

@ -26,10 +26,6 @@ cache:
- composer config -g cache-dir "$(pwd)/.composer-cache"
script:
- composer update
# native + unsigned
- vendor/bin/phpunit
- docker-php-ext-install gmp
# native + gmp
- vendor/bin/phpunit
# coverage
@ -40,6 +36,7 @@ coverage:
stage: report
only:
- master
- tags
image: php:8.1
script:
- composer update
@ -48,43 +45,46 @@ coverage:
- bash <(curl -s https://codecov.io/bash)
# test in every version
test-7.1:
test:
extends: .test
stage: test
image: php:7.1
image: ${ARCH}/php:${PHP_VERSION}
parallel:
matrix:
- PHP_VERSION:
- '7.1'
- '7.2'
- '7.3'
- '7.4'
- '8.0'
- '8.1'
ARCH:
- amd64
- i386
test-7.2:
test-gmp:
extends: .test
stage: test
image: php:7.2
test-7.3:
extends: .test
stage: test
image: php:7.3
test-7.4:
extends: .test
stage: test
image: php:7.4
test-8.0:
extends: .test
stage: test
image: php:8.0
test-8.1:
extends: .test
stage: test
image: php:8.1
image: ${ARCH}/php:${PHP_VERSION}
parallel:
matrix:
- PHP_VERSION:
- '7.4'
- '8.0'
- '8.1'
ARCH:
- amd64
- i386
script:
- docker-php-ext-install gmp
- composer update
- vendor/bin/phpunit
# control that our tests are valid
test-8.2-control:
extends: .test
stage: test
image: php:8.2-rc
image: php:8.2
script:
# fake the version for some dependencies
- composer config platform.php '8.1.0'
- composer update
- vendor/bin/phpunit

13
.readthedocs.yaml Normal file
View File

@ -0,0 +1,13 @@
version: 2
build:
os: 'ubuntu-22.04'
tools:
python: '3.11'
sphinx:
configuration: 'docs/conf.py'
python:
install:
- requirements: 'docs/requirements.txt'

View File

@ -1,6 +1,29 @@
# Changelog
## 1.0.0
[gh@TimWolla]: https://github.com/TimWolla
[gh@nicolas-grekas]: https://github.com/nicolas-grekas
## 1.x
### 1.0.2
*Sep 7, 2023*
* Bump arokettu/unsigned to 1.2.1, previous versions may cause invalid results in Mersenne Twister on 32-bit systems.
### 1.0.1
*Nov 12, 2022*
* Rely on symfony/polyfill-php82 for interface implementations and Random\Engine\Secure ([#6][gh#6]),
thanks to [Nicolas Grekas][gh@nicolas-grekas]
* Added compatibility with PHP regression fix: [PHP#9839] ([#5][gh#5])
[gh#6]: https://github.com/arokettu/php-random-polyfill/pull/6
[PHP#9839]: https://github.com/php/php-src/pull/9839
[gh#5]: https://github.com/arokettu/php-random-polyfill/pull/5
### 1.0.0
*Oct 26, 2022*
@ -9,13 +32,13 @@ RC2 is re-released as stable.
* No user facing changes since RC2
## 1.0.0-rc2
### 1.0.0-rc2
*Oct 1, 2022*
* Speed up 32 bit calculations in 64 bit envs
## 1.0.0-rc1
### 1.0.0-rc1
*Sep 14, 2022*
@ -24,13 +47,15 @@ RC2 is re-released as stable.
* Generated data is truncated to 64 bits in `Randomizer::getBytes()`
* Fixed integer overflow in the upstream math lib
## 1.0.0-beta1
### 1.0.0-beta1
*Sep 2, 2022*
* Fix incompatibility with PHP 8.2.0 RC1
## 0.5.0
## 0.x
### 0.5.0
*Sep 1, 2022*
@ -40,7 +65,7 @@ Hopefully the last alpha
* Full coverage
* GMP is now an optional dependency (but highly recommended)
## 0.4.0
### 0.4.0
*Aug 19, 2022*
@ -49,7 +74,7 @@ Hopefully the last alpha
* Various compatibility fixes
* Exceptions compatibility (mostly)
## 0.3.0
### 0.3.0
*Aug 5, 2022*
@ -58,7 +83,7 @@ Hopefully the last alpha
* `Xoshiro256StarStar`
* Split `nextInt()` and `getInt($min, $max)` like in beta 2
## 0.2.1
### 0.2.1
*Jul 31, 2022*
@ -67,13 +92,12 @@ Hopefully the last alpha
* ``arrayPickKeys()`` throws a warning because full compatibility is not achievable.
Thanks to [Tim Düsterhus][gh@TimWolla] for [the explanation][gh#1]
* No warning if the engine is ``CryptoSafeEngine``
* Fixed incorrect range function selection [[#1][gh#1]], thanks to [Tim Düsterhus][gh@TimWolla]
* Fixed incorrect range function selection ([#1][gh#1]), thanks to [Tim Düsterhus][gh@TimWolla]
* Fixed byte selection in range64
[gh#1]: https://github.com/arokettu/php-random-polyfill/issues/1
[gh@TimWolla]: https://github.com/TimWolla
## 0.2.0
### 0.2.0
*Jul 27, 2022*
@ -92,13 +116,13 @@ This will be fixed in 0.3.0 after PHP 8.2.0 beta 2 is released with some critica
* Serialization and unserialization are now compatible with PHP 8.2
if performed in PHP 7.4+
## 0.1.1
### 0.1.1
*Jul 23, 2022*
* Fixed Mt not generating enough data sometimes
## 0.1.0
### 0.1.0
*Jul 23, 2022*

View File

@ -1,7 +1,5 @@
# BSD 3-Clause "New" or "Revised" License
_This is a license for the product as a whole, see `COPYING.adoc` for additional licenses._
Copyright © 2022 Anton Smirnov
Redistribution and use in source and binary forms, with or without

View File

@ -1,16 +1,11 @@
# Random Extension Polyfill for PHP
[![PHP](https://img.shields.io/packagist/php-v/arokettu/random-polyfill/dev-master.svg?style=flat-square)](https://packagist.org/packages/arokettu/random-polyfill)
[![Packagist](https://img.shields.io/packagist/l/arokettu/random-polyfill.svg?style=flat-square)](https://opensource.org/licenses/BSD-3-Clause)
[![Packagist](https://img.shields.io/packagist/l/arokettu/random-polyfill.svg?style=flat-square)][COPYING]
[![Gitlab pipeline status](https://img.shields.io/gitlab/pipeline/sandfox/php-random-polyfill/master.svg?style=flat-square)](https://gitlab.com/sandfox/php-random-polyfill/-/pipelines)
[![Codecov](https://img.shields.io/codecov/c/gl/sandfox/php-random-polyfill?style=flat-square)](https://codecov.io/gl/sandfox/php-random-polyfill/)
This is a polyfill for the new `ext-random` extension that will be released with PHP 8.2.
RFC:
* https://wiki.php.net/rfc/rng_extension
* https://wiki.php.net/rfc/random_extension_improvement
This is a polyfill for the new `ext-random` extension that was released with PHP 8.2.
## Requirements
@ -29,18 +24,24 @@ The library aims to be compatible with `ext-random` as released in PHP 8.2.0 and
## Documentation
### Random Extension
Read the official PHP doc: https://www.php.net/manual/en/book.random.php
### The Polyfill
Read full documentation here: <https://sandfox.dev/php/random-polyfill.html>
Also on Read the Docs: <https://php-random-polyfill.readthedocs.io/>
## Support
Please file issues on our main repo at GitLab: <https://gitlab.com/sandfox/php-random-polyfill/-/issues>
Please file issues on our main repo at GitHub: <https://github.com/arokettu/php-random-polyfill/issues>
## License
The library is available as open source under the terms of the [3-Clause BSD License].
See [COPYING.adoc][COPYING] for additional licenses.
[3-Clause BSD License]: https://opensource.org/licenses/BSD-3-Clause
[3-Clause BSD License]: LICENSE.md
[COPYING]: COPYING.adoc

View File

@ -6,8 +6,8 @@
"license": "BSD-3-Clause",
"homepage": "https://sandfox.dev/php/random-polyfill.html",
"support": {
"issues": "https://gitlab.com/sandfox/php-random-polyfill/-/issues",
"source": "https://gitlab.com/sandfox/php-random-polyfill",
"issues": "https://github.com/arokettu/php-random-polyfill/issues",
"source": "https://github.com/arokettu/php-random-polyfill",
"docs": "https://php-random-polyfill.readthedocs.io/",
"chat": "https://gitter.im/arokettu/community"
},
@ -37,14 +37,15 @@
},
"require": {
"php": "^7.1 | ^8.0",
"arokettu/unsigned": "^1.0.1",
"arokettu/unsigned": "^1.2.1",
"symfony/polyfill-php80": "^1.22",
"symfony/polyfill-php81": "^1.22"
"symfony/polyfill-php81": "^1.22",
"symfony/polyfill-php82": "^1.27"
},
"require-dev": {
"phpunit/phpunit": "^7.5 | ^8.5 | ^9.5",
"phpunit/phpunit": "^7.5 | ^8.5 | 9.5.*",
"psy/psysh": "*",
"sandfox.dev/code-standard": "^10@dev",
"sandfox.dev/code-standard": "^1",
"squizlabs/php_codesniffer": "*",
"vimeo/psalm": "^4.24"
},

3
docs/_templates/rtd-version.html vendored Normal file
View File

@ -0,0 +1,3 @@
{%- if current_version -%}
<div class="sidebar-brand">{{ current_version }}</div>
{%- endif -%}

View File

@ -1,22 +0,0 @@
<a class="sidebar-brand{% if logo %} centered{% endif %}" href="{{ pathto(master_doc) }}">
{% block brand_content %}
{%- if logo_url %}
<div class="sidebar-logo-container">
<img class="sidebar-logo" src="{{ logo_url }}" alt="Logo"/>
</div>
{%- endif %}
{%- if theme_light_logo and theme_dark_logo %}
<div class="sidebar-logo-container">
<img class="sidebar-logo only-light" src="{{ pathto('_static/' + theme_light_logo, 1) }}" alt="Light Logo"/>
<img class="sidebar-logo only-dark" src="{{ pathto('_static/' + theme_dark_logo, 1) }}" alt="Dark Logo"/>
</div>
{%- endif %}
{% if not theme_sidebar_hide_name %}
<span class="sidebar-brand-text">{{ docstitle if docstitle else project }}</span>
{%- endif %}
{% endblock brand_content %}
</a>
{%- if current_version -%}
<div class="sidebar-brand">{{ current_version }}</div>
{%- endif -%}

View File

@ -4,9 +4,28 @@ Compatibility Notes
PHP
===
.. note::
Random Extension doc on the PHP website:
https://www.php.net/manual/en/book.random.php
The library aims to be compatible with ``ext-random`` as released in PHP 8.2.0 and subsequent patch releases.
The library will not be a full replacement for ``ext-random`` and total compatibility does not seem to be achievable.
Available classes:
* This polyfill:
* `Random\\Randomizer <https://www.php.net/manual/en/class.random-randomizer.php>`__
* `Random\\Engine\\Mt19937 <https://www.php.net/manual/en/class.random-engine-mt19937.php>`__
* `Random\\Engine\\PcgOneseq128XslRr64 <https://www.php.net/manual/en/class.random-engine-pcgoneseq128xslrr64.php>`__
* `Random\\Engine\\Xoshiro256StarStar <https://www.php.net/manual/en/class.random-engine-xoshiro256starstar.php>`__
* From `symfony/polyfill-php82 <https://packagist.org/packages/symfony/polyfill-php82>`__:
* `Random\\Engine <https://www.php.net/manual/en/class.random-engine.php>`__
* `Random\\Engine\\CryptoSafeEngine <https://www.php.net/manual/en/class.random-cryptosafeengine.php>`__
* `Random\\Engine\\Secure <https://www.php.net/manual/en/class.random-engine-secure.php>`__
Version 1.99.0
==============

View File

@ -1,6 +1,10 @@
from datetime import datetime
project = 'Random Extension Polyfill'
# import specific project config
import os, sys
sys.path.append(os.curdir)
from conf_project import *
author = 'Anton Smirnov'
copyright = '{} {}'.format(datetime.now().year, author)
language = 'en'
@ -8,3 +12,17 @@ language = 'en'
html_title = project
html_theme = 'furo'
templates_path = ["_templates"]
html_sidebars = {
"**": [
"sidebar/brand.html",
"rtd-version.html",
"sidebar/search.html",
"sidebar/scroll-start.html",
"sidebar/navigation.html",
"sidebar/ethical-ads.html",
"sidebar/scroll-end.html",
"sidebar/variant-selector.html",
]
}
exclude_patterns = ['venv/*']

1
docs/conf_project.py Normal file
View File

@ -0,0 +1 @@
project = 'Random Extension Polyfill'

View File

@ -3,12 +3,7 @@ Random Extension Polyfill
|Packagist| |GitLab| |GitHub| |Bitbucket| |Gitea|
This is a polyfill for the new ``ext-random`` extension that will be released with PHP 8.2.
RFC:
* https://wiki.php.net/rfc/rng_extension
* https://wiki.php.net/rfc/random_extension_improvement
This is a polyfill for the new ``ext-random`` extension that was released with PHP 8.2.
Requirements
============
@ -23,6 +18,11 @@ Installation
composer require 'arokettu/random-polyfill'
Random Extension Documentation
==============================
On the PHP website: https://www.php.net/manual/en/book.random.php
Documentation
=============

View File

@ -12,9 +12,9 @@ https://github.com/arokettu/random-polyfill-perf
* Secure engine is mostly unaffected by the choice of backend (except for nextInt() case)
* PHP 7:
* With GMP installed, all engines is approximately 400 times slower than native
* With GMP installed, all engines are approximately 400 times slower than native
* Mersenne Twister is consistently 400 times slower than native, whether you use GMP or not
* PCG is 100 times slower than GMP and xoshiro256** is 50 times slower than GMP
* PCG is 100 times slower without GMP and xoshiro256** is 50 times slower without GMP
* PHP 8:
* 100-150 times slower than native

View File

@ -1 +1,2 @@
sphinx>=7
furo

View File

@ -18,7 +18,7 @@ namespace Arokettu\Random;
*/
// phpcs:disable SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint
// phpcs:disable SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint
class MathNative extends Math
final class MathNative extends Math
{
/** @var int */
private $mask;

View File

@ -1,9 +0,0 @@
<?php
declare(strict_types=1);
namespace Random;
class BrokenRandomEngineError extends RandomError
{
}

View File

@ -1,18 +0,0 @@
<?php
/**
* @copyright Copyright © 2022 Anton Smirnov
* @license BSD-3-Clause https://spdx.org/licenses/BSD-3-Clause.html
*
* Includes adaptation of C code from the PHP Interpreter
* @license PHP-3.01 https://spdx.org/licenses/PHP-3.01.html
* @see https://github.com/php/php-src/blob/master/ext/random/php_random.h
*/
declare(strict_types=1);
namespace Random;
interface CryptoSafeEngine extends Engine
{
}

View File

@ -1,19 +0,0 @@
<?php
/**
* @copyright Copyright © 2022 Anton Smirnov
* @license BSD-3-Clause https://spdx.org/licenses/BSD-3-Clause.html
*
* Includes adaptation of C code from the PHP Interpreter
* @license PHP-3.01 https://spdx.org/licenses/PHP-3.01.html
* @see https://github.com/php/php-src/blob/master/ext/random/php_random.h
*/
declare(strict_types=1);
namespace Random;
interface Engine
{
public function generate(): string;
}

View File

@ -1,70 +0,0 @@
<?php
/**
* @copyright Copyright © 2022 Anton Smirnov
* @license BSD-3-Clause https://spdx.org/licenses/BSD-3-Clause.html
*
* Includes adaptation of C code from the PHP Interpreter
* @license PHP-3.01 https://spdx.org/licenses/PHP-3.01.html
* @see https://github.com/php/php-src/blob/master/ext/random/engine_secure.c
*/
declare(strict_types=1);
namespace Random\Engine;
use Arokettu\Random\NoDynamicProperties;
use Error;
use Exception;
use Random\CryptoSafeEngine;
use Random\RandomException;
final class Secure implements CryptoSafeEngine
{
use NoDynamicProperties;
/**
* @throws RandomException
*/
public function generate(): string
{
try {
return \random_bytes(\PHP_INT_SIZE);
// @codeCoverageIgnoreStart
// catch unreproducible
} catch (\Exception $e) {
// random_bytes throws Exception in <= 8.1 but RandomException in >= 8.2
throw new RandomException($e->getMessage(), (int)$e->getCode(), $e->getPrevious());
// @codeCoverageIgnoreEnd
}
}
/**
* @throws RandomException
*/
private function range(int $min, int $max): ?int
{
try {
return \random_int($min, $max);
// @codeCoverageIgnoreStart
// catch unreproducible
} catch (\Exception $e) {
// random_bytes throws Exception in <= 8.1 but RandomException in >= 8.2
throw new RandomException($e->getMessage(), (int)$e->getCode(), $e->getPrevious());
// @codeCoverageIgnoreEnd
}
}
/**
* @throws Exception
*/
public function __sleep(): array
{
throw new Exception("Serialization of 'Random\Engine\Secure' is not allowed");
}
public function __clone()
{
throw new Error('Trying to clone an uncloneable object of class Random\Engine\Secure');
}
}

View File

@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace Random;
use Arokettu\Random\NoDynamicProperties;
use Error;
class RandomError extends Error
{
use NoDynamicProperties;
}

View File

@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace Random;
use Arokettu\Random\NoDynamicProperties;
use Exception;
class RandomException extends Exception
{
use NoDynamicProperties;
}

View File

@ -113,17 +113,6 @@ final class Randomizer implements Serializable
);
}
// engine has range func
if (
$this->engine instanceof Secure
) {
/** @psalm-suppress PossiblyInvalidFunctionCall */
return Closure::bind(function (int $min, int $max): ?int {
/** @psalm-suppress UndefinedMethod */
return $this->range($min, $max);
}, $this->engine, $this->engine)($min, $max);
}
// handle MT_RAND_PHP
/** @psalm-suppress PossiblyInvalidFunctionCall */
if (
@ -136,6 +125,26 @@ final class Randomizer implements Serializable
return $this->rangeBadscaling($min, $max);
}
return $this->doGetInt($min, $max);
}
private function doGetInt(int $min, int $max): int
{
// special handler for Secure
if (
$this->engine instanceof Secure
) {
try {
return \random_int($min, $max);
// @codeCoverageIgnoreStart
// catch unreproducible
} catch (\Exception $e) {
// random_bytes throws Exception in <= 8.1 but RandomException in >= 8.2
throw new RandomException($e->getMessage(), (int)$e->getCode(), $e->getPrevious());
// @codeCoverageIgnoreEnd
}
}
$umax = self::$math64->subInt(self::$math64->fromInt($max), $min);
if (self::$math64->compare($umax, self::$UINT32_MAX_64) > 0) {
@ -300,7 +309,7 @@ final class Randomizer implements Serializable
$nLeft = \count($hash);
while (--$nLeft) {
$rndIdx = $this->getInt(0, $nLeft);
$rndIdx = $this->doGetInt(0, $nLeft);
$tmp = $hash[$nLeft];
$hash[$nLeft] = $hash[$rndIdx];
$hash[$rndIdx] = $tmp;
@ -318,7 +327,7 @@ final class Randomizer implements Serializable
$nLeft = \strlen($bytes);
while (--$nLeft) {
$rndIdx = $this->getInt(0, $nLeft);
$rndIdx = $this->doGetInt(0, $nLeft);
$tmp = $bytes[$nLeft];
$bytes[$nLeft] = $bytes[$rndIdx];
$bytes[$rndIdx] = $tmp;
@ -342,7 +351,7 @@ final class Randomizer implements Serializable
$keys = \array_keys($array);
if ($num === 1) {
return [$keys[$this->getInt(0, $numAvail - 1)]];
return [$keys[$this->doGetInt(0, $numAvail - 1)]];
}
if ($num <= 0 || $num > $numAvail) {
@ -357,7 +366,7 @@ final class Randomizer implements Serializable
$i = $num;
while ($i) {
$idx = $this->getInt(0, $numAvail - 1);
$idx = $this->doGetInt(0, $numAvail - 1);
if (\array_key_exists($idx, $retval) === false) {
$retval[$idx] = $keys[$idx];

View File

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace Arokettu\Random\Tests;
trait AssertRegexCompat
{
public static function assertRegex(string $pattern, string $string, string $message = ''): void
{
if (\method_exists(static::class, 'assertMatchesRegularExpression')) {
self::assertMatchesRegularExpression($pattern, $string, $message);
return;
}
if (\method_exists(static::class, 'assertRegExp')) {
self::assertRegExp($pattern, $string, $message);
return;
}
throw new \LogicException('Class should have either assertMatchesRegularExpression or assertRegExp');
}
}

View File

@ -16,6 +16,8 @@ use Throwable;
class DynamicPropertiesTest extends TestCase
{
use AssertRegexCompat;
public function testRandomizer(): void
{
try {
@ -63,8 +65,8 @@ class DynamicPropertiesTest extends TestCase
$engine = new Secure();
$engine->test = 123;
} catch (Throwable $e) {
self::assertEquals(
'Cannot create dynamic property Random\Engine\Secure::$test',
self::assertRegex(
'/^Cannot create dynamic property (?<classname>.*)::\\$test$/',
$e->getMessage()
);
self::assertEquals(Error::class, \get_class($e));

View File

@ -168,6 +168,11 @@ class EngineMt19937Test extends TestCase
public function testVerySpecialRange32Branch(): void
{
// @see https://www.php.net/manual/en/migration72.incompatible.php#migration72.incompatible.rand-mt_rand-output
if (\PHP_VERSION_ID < 70200) {
$this->markTestSkipped('PHP 7.1 has glitchy mt_rand');
}
\mt_srand(123456);
$r = new Randomizer(new Mt19937(123456));

View File

@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
namespace Arokettu\Random\Tests;
use PHPUnit\Framework\TestCase;
use Random\Engine\Mt19937;
use Random\Randomizer;
/**
* @see https://github.com/php/php-src/pull/9839
* @see https://github.com/arokettu/php-random-polyfill/issues/4#issuecomment-1293353629
*/
class PhpSrcGH9839Test extends TestCase
{
// just so we don't break the regular algo
public function testShuffleBytes(): void
{
$digits = '0123456789';
$expected = '0827613495';
$r = new Randomizer(new Mt19937(1, \MT_RAND_MT19937));
$s = $r->shuffleBytes($digits);
self::assertEquals($expected, $s);
}
public function testShuffleBytesCompat(): void
{
$digits = '0123456789';
$expected = '8926013475'; // not 8132476905
$r = new Randomizer(new Mt19937(1, \MT_RAND_PHP));
$s = $r->shuffleBytes($digits);
self::assertEquals($expected, $s);
}
// just so we don't break the regular algo
public function testShuffleArray(): void
{
$digits = \str_split('0123456789');
$expected = \str_split('0827613495');
$r = new Randomizer(new Mt19937(1, \MT_RAND_MT19937));
$s = $r->shuffleArray($digits);
self::assertEquals($expected, $s);
}
public function testShuffleArrayCompat(): void
{
$digits = \str_split('0123456789');
$expected = \str_split('8926013475'); // not 8132476905
$r = new Randomizer(new Mt19937(1, \MT_RAND_PHP));
$s = $r->shuffleArray($digits);
self::assertEquals($expected, $s);
}
}