Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support seeded random number generators #148

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

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.

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.

3 participants