User Guide¶
Building Generators¶
Use primitive generators and combinators from Gen:
import one.wabbit.random.gen.Gen
data class Point(val x: Int, val y: Int)
val point = Gen.map(
Gen.int(-10..10),
Gen.int(-10..10),
) { x, y -> Point(x, y) }
Use flatMap when later choices depend on earlier values:
import one.wabbit.random.gen.Gen
val boundedList = Gen.int(0..5).flatMap { size ->
Gen.listOf(size, Gen.printableAsciiChar)
}
Choices and Weights¶
Use oneOf, oneOfGen, freq, and freqGen for alternatives:
import one.wabbit.random.gen.Gen
val smallToken = Gen.freq(
listOf(
8 to "ok",
1 to "rare",
)
)
Weights must be non-negative and the total weight must be positive.
Sampling¶
import kotlin.random.Random
import one.wabbit.random.gen.Gen
import one.wabbit.random.gen.sample
val sample = Gen.string(0..8).sample(Random(42))
filter rejects samples. Rejected samples return null from sample.
Property Checks¶
import one.wabbit.random.gen.Gen
Gen.foreach(Gen.int(0..100), count = 100) { value ->
check(value >= 0)
}
Use foreachMin when you want failures minimized and replayable:
import kotlin.random.Random
import one.wabbit.random.gen.Gen
import one.wabbit.random.gen.foreachMin
Gen.int(0..100).foreachMin(Random(1), iters = 100) { value ->
check(value < 50)
}
Replay Seeds¶
TapeSeed stores a PRNG seed plus bit flips. Use toBase58String for compact logging:
import one.wabbit.random.gen.TapeSeed
import one.wabbit.random.gen.util.MutableBitDeque
val seed = TapeSeed(1234L, MutableBitDeque())
val encoded = seed.toBase58String()
val decoded = TapeSeed.fromBase58String(encoded)
check(decoded.seed == seed.seed)
Generated Functions¶
Gen.func and Gen.func2 generate deterministic table-backed functions. CoGen controls how
inputs are hashed into table buckets.
import one.wabbit.random.gen.Gen
val fGen = Gen.func<Int, String>(Gen.oneOf("a", "b", "c"))
Use explicit CoGen instances when platform hashCode behavior is not stable enough for the
domain you are generating.