Hi

On 9/26/22 18:53, Andreas Heigl wrote:
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).

Yes, that is correct.

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.

I don't see much value in that, see below.

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:


Such an interface would be incredibly limiting, because there's all kinds of things that you could randomly generate:

- Uniformly distributed integers within a given range
- Integers that follow a binomial distribution
- Strings with arbitrary bytes
- Strings with bytes taken from some input string ("Replacement sampling")
- Strings containing a UUIDv4
- A UUID object containg a UUIDv4
- Uniformly distributed floats in [0, 1)
- booleans ("Bernoulli distribution")
- DateTimeImmutables

And there are many more examples in https://github.com/FakerPHP/Faker.

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 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.

I would expect that the "randomness" would usually be generated in the outer layers (e.g. the controller) and the randomly generated value (e.g. a randomly generated UUID object) would then be passed to the functions that do whatever they need to do. These function could then be independently tested with specific values to ensure that they properly handle all the edge cases. For an end-to-end / integration test a seeded engine can be provided.

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.


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/50958ef2-3ba1-8be3-856e-78b1c1fbea58%40bastelstu.be.

Reply via email to