Hi

On 9/26/22 09:28, Andreas Heigl wrote:
Isn't it already covered natively by https://wiki.php.net/rfc/rng_extension?
IMO Yes and No.

The rng_extension describes the Random\Engine interface. This interface
has only the `generate` method which returns a string. The length of
this string can not be specified.

Indeed, because the engines represent some externally specified algorithm that operates on a well-specified "output size".

In general the idea of the whole package was to "Create a single
Randomizer class which provides various randomization methods (like get
int/bytes, shuffle string/arrays). This class will take an Engine
interface in the constructor which can be swapped based on users needs.

ext/random provides Random\Randomizer as a high-level interface to an engine's randomness. It will call the underlying engine as needed to obtain enough random bits to perform the requested operation, without introducing any biases.

Some essential RNG engines will be prepackaged for convenience but an
Interface will also be provided so that algorithms can be easily added."

The main task here is to ease adding randomizers in the core later.

The task is only to a certain extend to allow interoperability (due to
everyone using those methods) but sadly not to ease testing as the
methods of the provided Randomizer class are not based on an interface.

So to be able to test this with fixed values you will have to depend on
the Random\Randomizer-class and inject your own fixed Random\Engine
implementation. There is no way to replace the Random\Randomizer with
something else.

The engine is intended to be the pluggable part, not the Randomizer. I'd say if you pass along an instance of Random\Randomizer, then you are doing it wrong. Your service should create a Randomizer based on the provided engine by itself if it wants to use the Randomizer's high level interface.

The same is true if the Randomizer's API does not provide what you need. If you use a library providing additional high level functionality, then that library should take an engine. If it uses the Randomizer internally as a building block, then that should be considered an implementation detail.

For testing purposes you can provide a engine that is seeded with a fixed seed (new Xoshiro256StarStar(hash('sha256', 'My PHPUnit Seed', true)) would work) - or you can provide your own userland engine that provides whatever values you need. You just need to be careful that the userland engine is not too biased, because otherwise the Randomizer might be unable to generate an unbiased result and throw (BrokenRandomEngineError).

So if that is enough of interoperability, then I'm fine with that and
there is no need for any further investigation.

I'd say that "testing randomness" in general pretty hard and the same is true when mocking the randomness. You can't really verify that your logic exhibits the properties it should have. For example you can't test that Randomizer::getInt() really is unbiased: https://dilbert.com/strip/2001-10-25.

The tests in PHP itself only verify that getInt() does not return numbers outside of the request change for a sufficiently large number of attempts: https://github.com/php/php-src/blob/master/ext/random/tests/03_randomizer/methods/getInt.phpt

For some superficial tests based on hardcoded results, the pluggable Engine should be sufficient.

Best regards
Tim Düsterhus

--
You received this message because you are subscribed to the Google Groups "PHP 
Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/php-fig/c34c3918-e44b-9cac-89e6-793927dca73d%40bastelstu.be.

Reply via email to