Skip to content

Support seeded random number generators#148

Open
julasamer wants to merge 1 commit intovadymmarkov:masterfrom
CaperWhite:master
Open

Support seeded random number generators#148
julasamer wants to merge 1 commit intovadymmarkov:masterfrom
CaperWhite:master

Conversation

@julasamer
Copy link

Hi!

I've added support for seeded RNG by allowing the passing of any RandomNumberGenerator to Faker.

Caveats:

  • I ignored Swift <= 4.2. It might not compile with the older swift versions; if it does, it won't used the RNG that was passed in. Not sure if dropping support for 4.2 is an option at this point.
  • I didn't write a unit test (I'm not familiar with QuickSpec and don't have more time to spend on this right now).

That being said, you can use this like this:

let faker = Faker(randomNumberGenerator: SomeAdvancedRandomNumberGenerator())

Unfortunately, seeded RNG is somewhat hidden in iOS; my first idea was to use the RNG provided by GameKit:

 import GameKit

 extension GKMersenneTwisterRandomSource: RandomNumberGenerator {}
 let faker = Faker(randomNumberGenerator: GKMersenneTwisterRandomSource(seed: 42))

We need to make GKMersenneTwisterRandomSource conform to RandomNumberGenerator, which is fortunately quite easy. We can then use it as the seeded RNG.

However, this requires that GameKit is available. In the end, I didn't want introduce a GameKit dependency, and the whole thing is overkill anyway for my testing purposes, so I implemented a custom "RNG" which works fine for my case:

public class AdvancedRandomNumberGenerator: RandomNumberGenerator {
    var currentIndex = 0
    
    // chosen by fair dice roll
    // guaranteed to be random
    lazy var randomValues: [UInt64] = [4151371853236615391, 7134936793715064765, 8637388537612094686, ...]
    
    public func next() -> UInt64 {
        currentIndex += 1
        return randomValues[currentIndex % randomValues.count]
    }
}

@mrylmz
Copy link

mrylmz commented Jul 6, 2021

Isn't the Swift random API seedable, like UInt64.random(in:)

@julasamer
Copy link
Author

julasamer commented Jul 6, 2021

@mrylmz: That's the API I used. You have to pass something to the in parameter though. That's where the GKMersenneTwisterRandomSource comes in: a seedable RNG. The Swift random API itself doesn't have a seedable RNG afaik, you can just specify some RNG to use.

@crayment
Copy link

crayment commented Nov 9, 2023

Would love to have this! Would be nice to have predictably random mock data for use in tests.

@Tyler-Keith-Thompson
Copy link

What ever happened here? Determinism in these tests would be amazing. I'd be happy to take another crack at this, if the only thing preventing moving forward is that it's out of date.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants