diff --git a/lib/aiken/fuzz.ak b/lib/aiken/fuzz.ak index e88b032..92cdb91 100644 --- a/lib/aiken/fuzz.ak +++ b/lib/aiken/fuzz.ak @@ -425,6 +425,147 @@ fn nub(n: Int, fuzzer: Fuzzer, st: List) -> Fuzzer { } } +/// A convenient way of generating tuples instead of doing [`map2`](#map2) +/// ```aiken +/// map2( +/// fuzzer_a, fuzzer_b, +/// fn(a, b) { (a, b) } +/// ) +/// ``` +pub fn tuple(a: Fuzzer, b: Fuzzer) -> Fuzzer<(a, b)> { + let a, b <- map2(a, b) + (a, b) +} + +/// A convenient way of generating tuple3 instead of doing [`map3`](#map3) +/// ```aiken +/// map3( +/// fuzzer_a, fuzzer_b, fuzzer_c, +/// fn(a, b, c) { (a, b, c) } +/// ) +/// ``` +pub fn tuple3(a: Fuzzer, b: Fuzzer, c: Fuzzer) -> Fuzzer<(a, b, c)> { + let a, b, c <- map3(a, b, c) + (a, b, c) +} + +/// A convenient way of generating tuple4 instead of doing [`map4`](#map4) +/// ```aiken +/// map4( +/// fuzzer_a, fuzzer_b, fuzzer_c, fuzzer_d, +/// fn(a, b, c, d) { (a, b, c, d) } +/// ) +/// ``` +pub fn tuple4( + a: Fuzzer, + b: Fuzzer, + c: Fuzzer, + d: Fuzzer, +) -> Fuzzer<(a, b, c, d)> { + let a, b, c, d <- map4(a, b, c, d) + (a, b, c, d) +} + +/// A convenient way of generating tuple5 instead of doing [`map5`](#map5) +/// ```aiken +/// map5( +/// fuzzer_a, fuzzer_b, fuzzer_c, fuzzer_d, fuzzer_e, +/// fn(a, b, c, d, e) { (a, b, c, d, e) } +/// ) +/// ``` +pub fn tuple5( + a: Fuzzer, + b: Fuzzer, + c: Fuzzer, + d: Fuzzer, + e: Fuzzer, +) -> Fuzzer<(a, b, c, d, e)> { + let a, b, c, d, e <- map5(a, b, c, d, e) + (a, b, c, d, e) +} + +/// A convenient way of generating tuple6 instead of doing [`map6`](#map6) +/// ```aiken +/// map6( +/// fuzzer_a, fuzzer_b, fuzzer_c, fuzzer_d, fuzzer_e, fuzzer_f, +/// fn(a, b, c, d, e, f) { (a, b, c, d, e, f) } +/// ) +/// ``` +pub fn tuple6( + a: Fuzzer, + b: Fuzzer, + c: Fuzzer, + d: Fuzzer, + e: Fuzzer, + f: Fuzzer, +) -> Fuzzer<(a, b, c, d, e, f)> { + let a, b, c, d, e, f <- map6(a, b, c, d, e, f) + (a, b, c, d, e, f) +} + +/// A convenient way of generating tuple7 instead of doing [`map7`](#map7) +/// ```aiken +/// map7( +/// fuzzer_a, fuzzer_b, fuzzer_c, fuzzer_d, fuzzer_e, fuzzer_f, fuzzer_g, +/// fn(a, b, c, d, e, f, g) { (a, b, c, d, e, f, g) } +/// ) +/// ``` +pub fn tuple7( + a: Fuzzer, + b: Fuzzer, + c: Fuzzer, + d: Fuzzer, + e: Fuzzer, + f: Fuzzer, + g: Fuzzer, +) -> Fuzzer<(a, b, c, d, e, f, g)> { + let a, b, c, d, e, f, g <- map7(a, b, c, d, e, f, g) + (a, b, c, d, e, f, g) +} + +/// A convenient way of generating tuple8 instead of doing [`map8`](#map8) +/// ```aiken +/// map8( +/// fuzzer_a, fuzzer_b, fuzzer_c, fuzzer_d, fuzzer_e, fuzzer_f, fuzzer_g, fuzzer_h, +/// fn(a, b, c, d, e, f, g, h) { (a, b, c, d, e, f, g, h) } +/// ) +/// ``` +pub fn tuple8( + a: Fuzzer, + b: Fuzzer, + c: Fuzzer, + d: Fuzzer, + e: Fuzzer, + f: Fuzzer, + g: Fuzzer, + h: Fuzzer, +) -> Fuzzer<(a, b, c, d, e, f, g, h)> { + let a, b, c, d, e, f, g, h <- map8(a, b, c, d, e, f, g, h) + (a, b, c, d, e, f, g, h) +} + +/// A convenient way of generating tuple9 instead of doing [`map9`](#map9) +/// ```aiken +/// map9( +/// fuzzer_a, fuzzer_b, fuzzer_c, fuzzer_d, fuzzer_e, fuzzer_f, fuzzer_g, fuzzer_h, fuzzer_i, +/// fn(a, b, c, d, e, f, g, h, i) { (a, b, c, d, e, f, g, h, i) } +/// ) +/// ``` +pub fn tuple9( + a: Fuzzer, + b: Fuzzer, + c: Fuzzer, + d: Fuzzer, + e: Fuzzer, + f: Fuzzer, + g: Fuzzer, + h: Fuzzer, + i: Fuzzer, +) -> Fuzzer<(a, b, c, d, e, f, g, h, i)> { + let a, b, c, d, e, f, g, h, i <- map9(a, b, c, d, e, f, g, h, i) + (a, b, c, d, e, f, g, h, i) +} + // ## Combining /// Combine a [Fuzzer](https://aiken-lang.github.io/prelude/aiken.html#Fuzzer) with the result of a another one. diff --git a/lib/aiken/fuzz.test.ak b/lib/aiken/fuzz.test.ak index a6e2e2d..dbc2ae5 100644 --- a/lib/aiken/fuzz.test.ak +++ b/lib/aiken/fuzz.test.ak @@ -1,8 +1,10 @@ use aiken/collection/list use aiken/fuzz.{ - and_then, bool, constant, either3, either4, either5, either6, either7, either8, - either9, int, int_between, label, list_between, list_with_elem, map, one_of, - set, set_between, sublist, such_that, + and_then, bool, byte, bytearray, constant, either3, either4, either5, either6, + either7, either8, either9, int, int_between, label, list_between, + list_with_elem, map, map2, map3, map4, map5, map6, map7, map8, map9, one_of, + set, set_between, sublist, such_that, tuple, tuple3, tuple4, tuple5, tuple6, + tuple7, tuple8, tuple9, } use aiken/math use aiken/primitive/bytearray @@ -319,3 +321,324 @@ fn buckets(n, start, end, increment) -> Void { buckets(n, next, end, increment) } } + +// ## Tuple Fuzzer Tests + +fn data_fuzzer() -> Fuzzer { + either4( + { + let bool <- map(bool()) + let data: Data = bool + data + }, + { + let byte <- map(byte()) + let data: Data = byte + data + }, + { + let bytearray <- map(bytearray()) + let data: Data = bytearray + data + }, + { + let int <- map(int()) + let data: Data = int + data + }, + ) +} + +fn prop_tuple2() -> Fuzzer { + let a <- and_then(data_fuzzer()) + let b <- and_then(data_fuzzer()) + + let fuzzer_a = a |> constant + let fuzzer_b = b |> constant + + let l_tuple <- and_then(tuple(fuzzer_a, fuzzer_b)) + let r_tuple <- and_then(map2(fuzzer_a, fuzzer_b, fn(a, b) { (a, b) })) + + constant(l_tuple == r_tuple) +} + +fn prop_tuple3() -> Fuzzer { + let a <- and_then(data_fuzzer()) + let b <- and_then(data_fuzzer()) + let c <- and_then(data_fuzzer()) + + let fuzzer_a = a |> constant + let fuzzer_b = b |> constant + let fuzzer_c = c |> constant + + let l_tuple <- and_then(tuple3(fuzzer_a, fuzzer_b, fuzzer_c)) + let r_tuple <- + and_then(map3(fuzzer_a, fuzzer_b, fuzzer_c, fn(a, b, c) { (a, b, c) })) + + constant(l_tuple == r_tuple) +} + +fn prop_tuple4() -> Fuzzer { + let a <- and_then(data_fuzzer()) + let b <- and_then(data_fuzzer()) + let c <- and_then(data_fuzzer()) + let d <- and_then(data_fuzzer()) + + let fuzzer_a = a |> constant + let fuzzer_b = b |> constant + let fuzzer_c = c |> constant + let fuzzer_d = d |> constant + + let l_tuple <- and_then(tuple4(fuzzer_a, fuzzer_b, fuzzer_c, fuzzer_d)) + let r_tuple <- + and_then( + map4( + fuzzer_a, + fuzzer_b, + fuzzer_c, + fuzzer_d, + fn(a, b, c, d) { (a, b, c, d) }, + ), + ) + + constant(l_tuple == r_tuple) +} + +fn prop_tuple5() -> Fuzzer { + let a <- and_then(data_fuzzer()) + let b <- and_then(data_fuzzer()) + let c <- and_then(data_fuzzer()) + let d <- and_then(data_fuzzer()) + let e <- and_then(data_fuzzer()) + + let fuzzer_a = a |> constant + let fuzzer_b = b |> constant + let fuzzer_c = c |> constant + let fuzzer_d = d |> constant + let fuzzer_e = e |> constant + + let l_tuple <- + and_then(tuple5(fuzzer_a, fuzzer_b, fuzzer_c, fuzzer_d, fuzzer_e)) + let r_tuple <- + and_then( + map5( + fuzzer_a, + fuzzer_b, + fuzzer_c, + fuzzer_d, + fuzzer_e, + fn(a, b, c, d, e) { (a, b, c, d, e) }, + ), + ) + + constant(l_tuple == r_tuple) +} + +fn prop_tuple6() -> Fuzzer { + let a <- and_then(data_fuzzer()) + let b <- and_then(data_fuzzer()) + let c <- and_then(data_fuzzer()) + let d <- and_then(data_fuzzer()) + let e <- and_then(data_fuzzer()) + let f <- and_then(data_fuzzer()) + + let fuzzer_a = a |> constant + let fuzzer_b = b |> constant + let fuzzer_c = c |> constant + let fuzzer_d = d |> constant + let fuzzer_e = e |> constant + let fuzzer_f = f |> constant + + let l_tuple <- + and_then(tuple6(fuzzer_a, fuzzer_b, fuzzer_c, fuzzer_d, fuzzer_e, fuzzer_f)) + let r_tuple <- + and_then( + map6( + fuzzer_a, + fuzzer_b, + fuzzer_c, + fuzzer_d, + fuzzer_e, + fuzzer_f, + fn(a, b, c, d, e, f) { (a, b, c, d, e, f) }, + ), + ) + + constant(l_tuple == r_tuple) +} + +fn prop_tuple7() -> Fuzzer { + let a <- and_then(data_fuzzer()) + let b <- and_then(data_fuzzer()) + let c <- and_then(data_fuzzer()) + let d <- and_then(data_fuzzer()) + let e <- and_then(data_fuzzer()) + let f <- and_then(data_fuzzer()) + let g <- and_then(data_fuzzer()) + + let fuzzer_a = a |> constant + let fuzzer_b = b |> constant + let fuzzer_c = c |> constant + let fuzzer_d = d |> constant + let fuzzer_e = e |> constant + let fuzzer_f = f |> constant + let fuzzer_g = g |> constant + + let l_tuple <- + and_then( + tuple7( + fuzzer_a, + fuzzer_b, + fuzzer_c, + fuzzer_d, + fuzzer_e, + fuzzer_f, + fuzzer_g, + ), + ) + let r_tuple <- + and_then( + map7( + fuzzer_a, + fuzzer_b, + fuzzer_c, + fuzzer_d, + fuzzer_e, + fuzzer_f, + fuzzer_g, + fn(a, b, c, d, e, f, g) { (a, b, c, d, e, f, g) }, + ), + ) + + constant(l_tuple == r_tuple) +} + +fn prop_tuple8() -> Fuzzer { + let a <- and_then(data_fuzzer()) + let b <- and_then(data_fuzzer()) + let c <- and_then(data_fuzzer()) + let d <- and_then(data_fuzzer()) + let e <- and_then(data_fuzzer()) + let f <- and_then(data_fuzzer()) + let g <- and_then(data_fuzzer()) + let h <- and_then(data_fuzzer()) + + let fuzzer_a = a |> constant + let fuzzer_b = b |> constant + let fuzzer_c = c |> constant + let fuzzer_d = d |> constant + let fuzzer_e = e |> constant + let fuzzer_f = f |> constant + let fuzzer_g = g |> constant + let fuzzer_h = h |> constant + + let l_tuple <- + and_then( + tuple8( + fuzzer_a, + fuzzer_b, + fuzzer_c, + fuzzer_d, + fuzzer_e, + fuzzer_f, + fuzzer_g, + fuzzer_h, + ), + ) + let r_tuple <- + and_then( + map8( + fuzzer_a, + fuzzer_b, + fuzzer_c, + fuzzer_d, + fuzzer_e, + fuzzer_f, + fuzzer_g, + fuzzer_h, + fn(a, b, c, d, e, f, g, h) { (a, b, c, d, e, f, g, h) }, + ), + ) + + constant(l_tuple == r_tuple) +} + +fn prop_tuple9() -> Fuzzer { + let a <- and_then(data_fuzzer()) + let b <- and_then(data_fuzzer()) + let c <- and_then(data_fuzzer()) + let d <- and_then(data_fuzzer()) + let e <- and_then(data_fuzzer()) + let f <- and_then(data_fuzzer()) + let g <- and_then(data_fuzzer()) + let h <- and_then(data_fuzzer()) + let i <- and_then(data_fuzzer()) + + let fuzzer_a = a |> constant + let fuzzer_b = b |> constant + let fuzzer_c = c |> constant + let fuzzer_d = d |> constant + let fuzzer_e = e |> constant + let fuzzer_f = f |> constant + let fuzzer_g = g |> constant + let fuzzer_h = h |> constant + let fuzzer_i = i |> constant + + let l_tuple <- + and_then( + tuple9( + fuzzer_a, + fuzzer_b, + fuzzer_c, + fuzzer_d, + fuzzer_e, + fuzzer_f, + fuzzer_g, + fuzzer_h, + fuzzer_i, + ), + ) + let r_tuple <- + and_then( + map9( + fuzzer_a, + fuzzer_b, + fuzzer_c, + fuzzer_d, + fuzzer_e, + fuzzer_f, + fuzzer_g, + fuzzer_h, + fuzzer_i, + fn(a, b, c, d, e, f, g, h, i) { (a, b, c, d, e, f, g, h, i) }, + ), + ) + + constant(l_tuple == r_tuple) +} + +fn prop_tuple2_to_tuple9() -> Fuzzer { + let tuple2_map2 <- and_then(prop_tuple2()) + let tuple3_map3 <- and_then(prop_tuple3()) + let tuple4_map4 <- and_then(prop_tuple4()) + let tuple5_map5 <- and_then(prop_tuple5()) + let tuple6_map6 <- and_then(prop_tuple6()) + let tuple7_map7 <- and_then(prop_tuple7()) + let tuple8_map8 <- and_then(prop_tuple8()) + let tuple9_map9 <- and_then(prop_tuple9()) + + constant(and { + tuple2_map2, + tuple3_map3, + tuple4_map4, + tuple5_map5, + tuple6_map6, + tuple7_map7, + tuple8_map8, + tuple9_map9, + }) +} + +test prop_tuples(match via prop_tuple2_to_tuple9()) { + match +}