Hey Tim. On 26.09.22 17:52, Tim Düsterhus wrote:
HiOn 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.
As far as I understood the RFC Random\Randomizer isn't an interface but a final class. So there is no way to use that to either inject a random providing randomizer or a known values providing randomizer (yes! I know very well that known values aren'T random any more).
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.
The interface I was proposing here was intended for those high-level libraries. Whether they use the Random-extension or paragonie/random or the random_* functions is up to them and should not be part of the proposal.
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).
This is not what the proposed interface is about. The idea is to have at least two possible implementations of a high-level interface:
* One for testing that provides a predictable set of values and * One for production that provides an unpredictable set of values.The proposal should *not* make assumptions about the quality of the unpredictability and how the unpredictability is achieved and how unpredictable the unpredictability is. That is what the implementing libraries are there for. They do a great job at providnig a facade to that complexity.
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.So if that is enough of interoperability, then I'm fine with that and there is no need for any further investigation.
The idea is explicitly *not* to test the randomness with the proposed interface. That is the task of the library that implements said interface.
The here proposed interface should make it possible for the developer to test their code with *known* values, to make sure that certain values will cause a defined action.
In the production environment these *known* values will then be replaced with the random values but the randomness does not need to be tested as that was tested in the used library.
This allows decoupled code and better separation of concerns. In my opinion it targets a different use-case than the random-extension.For me the random extension is a great way to provide the underlying randomness within a random-library, but for the higher-level unit-testing a decoupling from the actual implementation via a separate interface is necessary.
Cheers Andreas -- ,,, (o o) +---------------------------------------------------------ooO-(_)-Ooo-+ | Andreas Heigl | | mailto:andr...@heigl.org N 50°22'59.5" E 08°23'58" | | https://andreas.heigl.org | +---------------------------------------------------------------------+ | https://hei.gl/appointmentwithandreas | +---------------------------------------------------------------------+ -- 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 php-fig+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/a9acc36a-1882-7ff7-da76-2d23d02ae68f%40heigl.org.
OpenPGP_0xA8D5437ECE724FE5.asc
Description: OpenPGP public key
OpenPGP_signature
Description: OpenPGP digital signature