diff --git a/fuzzer/api/src/commonMain/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerFactory.kt b/fuzzer/api/src/commonMain/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerFactory.kt index 028c55b2..4f9e4190 100644 --- a/fuzzer/api/src/commonMain/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerFactory.kt +++ b/fuzzer/api/src/commonMain/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerFactory.kt @@ -4,7 +4,6 @@ import com.github.jcornaz.kwik.ExperimentalKwikApi import com.github.jcornaz.kwik.fuzzer.api.simplifier.Simplifier import com.github.jcornaz.kwik.fuzzer.api.simplifier.pair import com.github.jcornaz.kwik.fuzzer.api.simplifier.triple -import com.github.jcornaz.kwik.generator.api.Generator import com.github.jcornaz.kwik.generator.api.combineWith import kotlin.random.Random @@ -21,6 +20,13 @@ public fun Arbitrary.pair(first: Fuzzer, second: Fuzzer): Fuzzer Arbitrary.pair(fuzzer: Fuzzer): Fuzzer> = + pair(fuzzer, fuzzer) + /** * Returns a [Fuzzer] for triple of [A], [B] and [C]. * @@ -31,7 +37,7 @@ public fun Arbitrary.pair(first: Fuzzer, second: Fuzzer): Fuzzer Arbitrary.triple(first: Fuzzer, second: Fuzzer, third: Fuzzer): Fuzzer> = Fuzzer( - generator = Generator { random: Random -> + generator = { random: Random -> Triple( first.generator.generate(random), second.generator.generate(random), @@ -40,3 +46,10 @@ public fun Arbitrary.triple(first: Fuzzer, second: Fuzzer, third }, simplifier = Simplifier.triple(first.simplifier, second.simplifier, third.simplifier) ) + +/** + * Returns a [Fuzzer] for triple, using [fuzzer] for all elements. + */ +@ExperimentalKwikApi +public fun Arbitrary.triple(fuzzer: Fuzzer): Fuzzer> = + triple(fuzzer, fuzzer, fuzzer) diff --git a/fuzzer/api/src/commonMain/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/SimplifierFactory.kt b/fuzzer/api/src/commonMain/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/SimplifierFactory.kt index 04cd6ad9..8a46654c 100644 --- a/fuzzer/api/src/commonMain/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/SimplifierFactory.kt +++ b/fuzzer/api/src/commonMain/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/SimplifierFactory.kt @@ -25,6 +25,15 @@ public fun Simplifier.Companion.pair( } } +/** + * Create a [Simplifier] that can simplify pairs using [simplifier] for both elements of the pair. + * + * This is essentially an alias for `Simplifier.pair(simplifier, simplifier)` + */ +@ExperimentalKwikApi +public fun Simplifier.Companion.pair(simplifier: Simplifier): Simplifier> = + pair(simplifier, simplifier) + /** * Create a [Simplifier] that can simplify triples. * @@ -51,3 +60,12 @@ public fun Simplifier.Companion.triple( } } } + +/** + * Create a [Simplifier] that can simplify triples using [simplifier] for all elements of the triple. + * + * This is essentially an alias for `Simplifier.triple(simplifier, simplifier, simplifier)` + */ +@ExperimentalKwikApi +public fun Simplifier.Companion.triple(simplifier: Simplifier): Simplifier> = + triple(simplifier, simplifier, simplifier) diff --git a/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerPairTest.kt b/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerPairTest.kt index 67b46484..f35b160f 100644 --- a/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerPairTest.kt +++ b/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerPairTest.kt @@ -40,4 +40,17 @@ class FuzzerPairTest { assertEquals(listOf(3 to 50, 10 to 42), pair.simplifier.simplify(10 to 50).toList()) } -} \ No newline at end of file + + @Test + fun canCreatePairWithSingleItemFuzzer() { + val itemFuzz = Generator.of(1).toFuzzer { sequenceOf(it - 1) } + assertEquals( + Arbitrary.pair(itemFuzz).generator.generate(Random(0)), + Arbitrary.pair(itemFuzz, itemFuzz).generator.generate(Random(0)) + ) + assertEquals( + Arbitrary.pair(itemFuzz).simplifier.simplify(2 to 3).toList(), + Arbitrary.pair(itemFuzz, itemFuzz).simplifier.simplify(2 to 3).toList() + ) + } +} diff --git a/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerTripleTest.kt b/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerTripleTest.kt index 0068146b..fc53af31 100644 --- a/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerTripleTest.kt +++ b/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/FuzzerTripleTest.kt @@ -53,4 +53,19 @@ class FuzzerTripleTest { pair.simplifier.simplify(Triple(10, 20, 30)).toList() ) } + + @Test + fun canCreatePairWithSingleItemFuzzer() { + val itemFuzz = Generator.of(1).toFuzzer { sequenceOf(it - 1) } + assertEquals( + Arbitrary.triple(itemFuzz).generator.generate(Random(0)), + Arbitrary.triple(itemFuzz, itemFuzz, itemFuzz).generator.generate(Random(0)) + ) + assertEquals( + Arbitrary.triple(itemFuzz).simplifier + .simplify(Triple(1, 2, 3)).toList(), + Arbitrary.triple(itemFuzz, itemFuzz, itemFuzz).simplifier + .simplify(Triple(1, 2, 3)).toList() + ) + } } diff --git a/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/PairTest.kt b/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/PairTest.kt index ea0fcfaa..4f9900f8 100644 --- a/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/PairTest.kt +++ b/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/PairTest.kt @@ -1,6 +1,8 @@ package com.github.jcornaz.kwik.fuzzer.api.simplifier import com.github.jcornaz.kwik.ExperimentalKwikApi +import kotlin.random.Random +import kotlin.random.nextUInt import kotlin.test.Test import kotlin.test.assertEquals @@ -33,6 +35,19 @@ class PairTest { ) } + @Test + fun canUseSameSimplifierForBothElements() { + val itemSimplifier = Simplifier { it: Int -> if (it > 0) sequenceOf(it - 1) else emptySequence() } + + repeat(100) { + val initialValue = Random.nextInt(0, 5) to Random.nextInt(0, 5) + assertEquals( + Simplifier.pair(itemSimplifier).simplify(initialValue).toList(), + Simplifier.pair(itemSimplifier, itemSimplifier).simplify(initialValue).toList(), + ) + } + } + @Test fun returnEmptySequenceIfBothHaveNoSimplerValue() { val pair = Simplifier.pair( diff --git a/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/TripleTest.kt b/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/TripleTest.kt index c5ae9d75..f77d04c2 100644 --- a/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/TripleTest.kt +++ b/fuzzer/api/src/commonTest/kotlin/com/github/jcornaz/kwik/fuzzer/api/simplifier/TripleTest.kt @@ -1,6 +1,7 @@ package com.github.jcornaz.kwik.fuzzer.api.simplifier import com.github.jcornaz.kwik.ExperimentalKwikApi +import kotlin.random.Random import kotlin.test.Test import kotlin.test.assertEquals @@ -37,6 +38,18 @@ class TripleTest { ) } + @Test + fun canUseSameSimplifierForAllElements() { + val itemSimplifier = Simplifier { it: Int -> if (it > 0) sequenceOf(it - 1) else emptySequence() } + + repeat(100) { + val initialValue = Triple(Random.nextInt(0, 5), Random.nextInt(0, 5), Random.nextInt(0, 5)) + assertEquals( + Simplifier.triple(itemSimplifier).simplify(initialValue).toList(), + Simplifier.triple(itemSimplifier, itemSimplifier, itemSimplifier).simplify(initialValue).toList(), + ) + } + } @Test fun returnEmptySequenceIfNoneHaveSimplerValue() { diff --git a/generator/api/src/commonMain/kotlin/com/github/jcornaz/kwik/generator/api/GeneratorCombination.kt b/generator/api/src/commonMain/kotlin/com/github/jcornaz/kwik/generator/api/GeneratorCombination.kt index 6c3131a4..0c8b2c0e 100644 --- a/generator/api/src/commonMain/kotlin/com/github/jcornaz/kwik/generator/api/GeneratorCombination.kt +++ b/generator/api/src/commonMain/kotlin/com/github/jcornaz/kwik/generator/api/GeneratorCombination.kt @@ -32,13 +32,29 @@ public fun Generator.Companion.combine( CombinedGenerators(generator1, generator2, transform) /** - * Returns a generator of combining the elements of [generator1] and [generator2] + * Returns a generator of pairs using [generator1] (for the left) and [generator2] (for the right) */ +@Deprecated("Use pair instead", ReplaceWith("pair(generator1, generator2)")) public fun Generator.Companion.combine( generator1: Generator, generator2: Generator ): Generator> = - combine(generator1, generator2, ::Pair) + pair(generator1, generator2) + +/** + * Returns a generator of pairs using [leftGen] and [rightGen] + */ +public fun Generator.Companion.pair( + leftGen: Generator, + rightGen: Generator +): Generator> = + combine(leftGen, rightGen, ::Pair) + +/** + * Returns a generator of pairs using the same [generator] for left and right elements. + */ +public fun Generator.Companion.pair(generator: Generator): Generator> = + pair(generator, generator) private class CombinedGenerators( private val generator1: Generator, diff --git a/generator/api/src/commonTest/kotlin/com/github/jcornaz/kwik/generator/api/CombineTest.kt b/generator/api/src/commonTest/kotlin/com/github/jcornaz/kwik/generator/api/CombineTest.kt index 59028d33..0f300d53 100644 --- a/generator/api/src/commonTest/kotlin/com/github/jcornaz/kwik/generator/api/CombineTest.kt +++ b/generator/api/src/commonTest/kotlin/com/github/jcornaz/kwik/generator/api/CombineTest.kt @@ -1,15 +1,16 @@ package com.github.jcornaz.kwik.generator.api import com.github.jcornaz.kwik.generator.test.AbstractGeneratorTest -import kotlin.random.Random import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.test.assertTrue +@Suppress("DEPRECATION") class CombineTest : AbstractGeneratorTest() { override val generator: Generator<*> = Generator.combine( - Generator { it: Random -> it.nextInt() }, - Generator { it: Random -> it.nextDouble() } + { it.nextInt() }, + { it.nextDouble() } ) @Test @@ -20,20 +21,53 @@ class CombineTest : AbstractGeneratorTest() { @Test fun combineDifferentValues() { val gen = Generator.combine( - Generator { it: Random -> it.nextInt() }, - Generator { it: Random -> it.nextInt() } + { it.nextInt() }, + { it.nextInt() } ) assertTrue(gen.randomSequence(123).take(200).count { (a, b) -> a != b } > 150) } } +class PairTest : AbstractGeneratorTest() { + + override val generator: Generator<*> = Generator.pair( + { it.nextInt() }, + { it.nextDouble() } + ) + + @Test + fun combineTheValues() { + assertTrue(generator.randomSequence(0).take(200).distinct().count() > 190) + } + + @Test + fun combineDifferentValues() { + val gen = Generator.pair( + { it.nextInt() }, + { it.nextInt() } + ) + + assertTrue(gen.randomSequence(123).take(200).count { (a, b) -> a != b } > 150) + } + + @Test + fun canUseSameGeneratorForBothElements() { + val itemGen = Generator { it.nextInt() } + + assertEquals( + Generator.pair(itemGen).randomSequence(0).take(100).toList(), + Generator.pair(itemGen, itemGen).randomSequence(0).take(100).toList() + ) + } +} + class CombineWithTransformTest : AbstractGeneratorTest() { override val generator: Generator<*> = Generator.combine( - Generator { it: Random -> it.nextInt() }, - Generator { it: Random -> it.nextDouble() } + { it.nextInt() }, + { it.nextDouble() } ) { x, y -> CombinedValues(x, y) } @Test @@ -44,8 +78,8 @@ class CombineWithTransformTest : AbstractGeneratorTest() { @Test fun combineDifferentValues() { val gen = Generator.combine( - Generator { it: Random -> it.nextInt() }.withSamples(1, 2), - Generator { it: Random -> it.nextDouble() }.withSamples(3.0, 4.0) + Generator { it.nextInt() }.withSamples(1, 2), + Generator { it.nextDouble() }.withSamples(3.0, 4.0) ) { a, b -> CombinedValues(a, b) } assertTrue(gen.randomSequence(0).take(200).count { (a, b) -> a != b.toInt() } > 150) @@ -57,7 +91,7 @@ class CombineWithTransformTest : AbstractGeneratorTest() { class CombineWithTest : AbstractGeneratorTest() { override val generator: Generator<*> = - Generator { it: Random -> it.nextInt() }.combineWith(Generator { it: Random -> it.nextDouble() }) + Generator { it.nextInt() }.combineWith { it.nextDouble() } @Test fun combineTheValues() { @@ -66,7 +100,7 @@ class CombineWithTest : AbstractGeneratorTest() { @Test fun combineDifferentValues() { - val gen = Generator { it: Random -> it.nextInt() }.combineWith(Generator { it: Random -> it.nextInt() }) + val gen = Generator { it.nextInt() }.combineWith { it.nextInt() } assertTrue(gen.randomSequence(123).take(200).count { (a, b) -> a != b } > 150) } @@ -75,8 +109,8 @@ class CombineWithTest : AbstractGeneratorTest() { class CombineWithWithTransformTest : AbstractGeneratorTest() { override val generator: Generator<*> = - Generator { it: Random -> it.nextInt() } - .combineWith(Generator { it: Random -> it.nextDouble() }) { x, y -> + Generator { it.nextInt() } + .combineWith({ it.nextDouble() }) { x, y -> CombinedValues( x, y @@ -90,8 +124,8 @@ class CombineWithWithTransformTest : AbstractGeneratorTest() { @Test fun combineDifferentValues() { - val gen = Generator { it: Random -> it.nextInt() } - .combineWith(Generator { it: Random -> it.nextInt() }) { a, b -> a to b } + val gen = Generator { it.nextInt() } + .combineWith({ it.nextInt() }) { a, b -> a to b } assertTrue(gen.randomSequence(123).take(200).count { (a, b) -> a != b } > 150) }