diff --git a/arrow-libs/ank/gradle.properties b/arrow-libs/ank/gradle.properties index 6c21d28a87b..4decaec9c15 100644 --- a/arrow-libs/ank/gradle.properties +++ b/arrow-libs/ank/gradle.properties @@ -8,7 +8,7 @@ systemProp.org.gradle.internal.publish.checksums.insecure=true kotlin.incremental=true # Kotlin Test configuration #Parallelism needs to be set to 1 since the concurrent tests in arrow-effects become flaky otherwise -kotlintest.parallelism=1 +kotest.framework.parallelism=1 # Reason: https://youtrack.jetbrains.com/issue/KT-46847 # kotlin.stdlib.default.dependency=false diff --git a/arrow-libs/core/arrow-continuations/build.gradle b/arrow-libs/core/arrow-continuations/build.gradle index 8758bc34bac..7a60a1abb5c 100644 --- a/arrow-libs/core/arrow-continuations/build.gradle +++ b/arrow-libs/core/arrow-continuations/build.gradle @@ -25,7 +25,6 @@ kotlin { jvmTest { dependencies { runtimeOnly "org.junit.vintage:junit-vintage-engine:$JUNIT_VINTAGE_VERSION" - compileOnly "io.kotlintest:kotlintest-runner-junit5:$KOTLIN_TEST_VERSION", excludeArrow implementation project(":arrow-core-test") } } diff --git a/arrow-libs/core/arrow-continuations/src/jvmTest/kotlin/generic/SuspendingComputationTest.kt b/arrow-libs/core/arrow-continuations/src/jvmTest/kotlin/generic/SuspendingComputationTest.kt index 247c5468a9a..ef4c09cdd70 100644 --- a/arrow-libs/core/arrow-continuations/src/jvmTest/kotlin/generic/SuspendingComputationTest.kt +++ b/arrow-libs/core/arrow-continuations/src/jvmTest/kotlin/generic/SuspendingComputationTest.kt @@ -3,10 +3,10 @@ package generic import arrow.core.computations.either import arrow.core.Either.Right import arrow.core.Either.Left -import io.kotlintest.fail -import io.kotlintest.shouldBe -import io.kotlintest.shouldThrow -import io.kotlintest.specs.StringSpec +import io.kotest.assertions.fail +import io.kotest.matchers.shouldBe +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.StringSpec import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Deferred diff --git a/arrow-libs/core/arrow-continuations/src/jvmTest/kotlin/generic/TestSuite.kt b/arrow-libs/core/arrow-continuations/src/jvmTest/kotlin/generic/TestSuite.kt index 86b5f3a4adc..2de62bd57f3 100644 --- a/arrow-libs/core/arrow-continuations/src/jvmTest/kotlin/generic/TestSuite.kt +++ b/arrow-libs/core/arrow-continuations/src/jvmTest/kotlin/generic/TestSuite.kt @@ -6,7 +6,7 @@ import arrow.continuations.generic.RestrictedScope import arrow.core.Either import arrow.core.Either.Left import arrow.core.test.UnitSpec -import io.kotlintest.shouldBe +import io.kotest.matchers.shouldBe abstract class ContTestSuite : UnitSpec() { abstract suspend fun runScope(func: (suspend RestrictedScope.() -> A)): A diff --git a/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowEitherCallAdapterTest.kt b/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowEitherCallAdapterTest.kt index 762bf3a309f..3089af5b731 100644 --- a/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowEitherCallAdapterTest.kt +++ b/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowEitherCallAdapterTest.kt @@ -6,9 +6,7 @@ import arrow.core.test.UnitSpec import arrow.retrofit.adapter.mock.ErrorMock import arrow.retrofit.adapter.mock.ResponseMock import arrow.retrofit.adapter.retrofit.SuspedApiClientTest -import io.kotlintest.Spec -import io.kotlintest.shouldBe -import kotlinx.coroutines.runBlocking +import io.kotest.matchers.shouldBe import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockWebServer import okhttp3.mockwebserver.SocketPolicy @@ -28,22 +26,15 @@ class ArrowEitherCallAdapterTest : UnitSpec() { .create(SuspedApiClientTest::class.java) } - override fun beforeSpec(spec: Spec) { - super.beforeSpec(spec) - server.start() - } - - override fun afterSpec(spec: Spec) { - server.shutdown() - super.afterSpec(spec) - } - init { + beforeSpec { server.start() } + afterSpec { server.shutdown() } + "should return ResponseMock for 200 with valid JSON" { server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}""")) - val body = runBlocking { service.getEither() } + val body = service.getEither() body shouldBe ResponseMock("Arrow rocks").right() } @@ -51,7 +42,7 @@ class ArrowEitherCallAdapterTest : UnitSpec() { "should return ErrorMock for 400 with valid JSON" { server.enqueue(MockResponse().setBody("""{"errorCode":666}""").setResponseCode(400)) - val body = runBlocking { service.getEither() } + val body = service.getEither() body shouldBe ErrorMock(666).left() } @@ -59,7 +50,7 @@ class ArrowEitherCallAdapterTest : UnitSpec() { "should throw for 200 with invalid JSON" { server.enqueue(MockResponse().setBody("""not a valid JSON""")) - val body = kotlin.runCatching { service.getEither() } + val body = runCatching { service.getEither() } body.isFailure shouldBe true } @@ -67,7 +58,7 @@ class ArrowEitherCallAdapterTest : UnitSpec() { "should throw for 400 and invalid JSON" { server.enqueue(MockResponse().setBody("""not a valid JSON""").setResponseCode(400)) - val body = kotlin.runCatching { service.getEither() } + val body = runCatching { service.getEither() } body.isFailure shouldBe true } diff --git a/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowResponseEAdapterTest.kt b/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowResponseEAdapterTest.kt index c55d077f742..9681c76704f 100644 --- a/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowResponseEAdapterTest.kt +++ b/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowResponseEAdapterTest.kt @@ -6,9 +6,7 @@ import arrow.core.test.UnitSpec import arrow.retrofit.adapter.mock.ErrorMock import arrow.retrofit.adapter.mock.ResponseMock import arrow.retrofit.adapter.retrofit.SuspedApiClientTest -import io.kotlintest.Spec -import io.kotlintest.shouldBe -import kotlinx.coroutines.runBlocking +import io.kotest.matchers.shouldBe import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockWebServer import okhttp3.mockwebserver.SocketPolicy @@ -28,22 +26,15 @@ class ArrowResponseEAdapterTest : UnitSpec() { .create(SuspedApiClientTest::class.java) } - override fun beforeSpec(spec: Spec) { - super.beforeSpec(spec) - server.start() - } - - override fun afterSpec(spec: Spec) { - server.shutdown() - super.afterSpec(spec) - } - init { + beforeSpec { server.start() } + afterSpec { server.shutdown() } + "should return ResponseMock for 200 with valid JSON" { server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}""")) - val responseE = runBlocking { service.getResponseE() } + val responseE = service.getResponseE() with(responseE) { code shouldBe 200 @@ -54,7 +45,7 @@ class ArrowResponseEAdapterTest : UnitSpec() { "should return ErrorMock for 400 with valid JSON" { server.enqueue(MockResponse().setBody("""{"errorCode":42}""").setResponseCode(400)) - val responseE = runBlocking { service.getResponseE() } + val responseE = service.getResponseE() with(responseE) { code shouldBe 400 @@ -65,7 +56,7 @@ class ArrowResponseEAdapterTest : UnitSpec() { "should throw for 200 with invalid JSON" { server.enqueue(MockResponse().setBody("""not a valid JSON""")) - val responseE = kotlin.runCatching { service.getResponseE() } + val responseE = runCatching { service.getResponseE() } responseE.isFailure shouldBe true } @@ -73,7 +64,7 @@ class ArrowResponseEAdapterTest : UnitSpec() { "should throw for 400 and invalid JSON" { server.enqueue(MockResponse().setBody("""not a valid JSON""").setResponseCode(400)) - val responseE = kotlin.runCatching { service.getResponseE() } + val responseE = runCatching { service.getResponseE() } responseE.isFailure shouldBe true } diff --git a/arrow-libs/core/arrow-core-test/build.gradle b/arrow-libs/core/arrow-core-test/build.gradle index 71a6ccae3fc..bf8b6ffc514 100644 --- a/arrow-libs/core/arrow-core-test/build.gradle +++ b/arrow-libs/core/arrow-core-test/build.gradle @@ -12,6 +12,7 @@ dependencies { api project(":arrow-core") api project(":arrow-continuations") api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$KOTLINX_COROUTINES_VERSION" - api "io.kotlintest:kotlintest-runner-junit5:$KOTLIN_TEST_VERSION", excludeArrow - testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$JUNIT_VINTAGE_VERSION" + api "io.kotest:kotest-runner-junit5-jvm:$KOTEST_VERSION" // for kotest framework + api "io.kotest:kotest-assertions-core-jvm:$KOTEST_VERSION" // for kotest core jvm assertions + api "io.kotest:kotest-property-jvm:$KOTEST_VERSION" // for kotest property test } diff --git a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/UnitSpec.kt b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/UnitSpec.kt index dacb960e731..1969789862d 100644 --- a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/UnitSpec.kt +++ b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/UnitSpec.kt @@ -3,95 +3,102 @@ package arrow.core.test import arrow.core.Tuple4 import arrow.core.Tuple5 import arrow.core.test.laws.Law -import io.kotlintest.TestCase -import io.kotlintest.TestType -import io.kotlintest.properties.Gen -import io.kotlintest.properties.PropertyContext -import io.kotlintest.properties.assertAll -import io.kotlintest.shouldBe -import io.kotlintest.specs.AbstractStringSpec +import io.kotest.core.spec.style.StringSpec +import io.kotest.core.test.createTestName +import io.kotest.property.Arb +import io.kotest.property.PropertyContext +import io.kotest.property.arbitrary.bind +import io.kotest.property.checkAll /** * Base class for unit tests */ -abstract class UnitSpec : AbstractStringSpec() { +abstract class UnitSpec : StringSpec() { - private val lawTestCases = mutableListOf() - - fun testLaws(vararg laws: List): List = laws + fun testLaws(vararg laws: List): Unit = laws .flatMap { list: List -> list.asIterable() } .distinctBy { law: Law -> law.name } - .map { law: Law -> - val lawTestCase = createTestCase(law.name, law.test, defaultTestCaseConfig, TestType.Test) - lawTestCases.add(lawTestCase) - lawTestCase + .forEach { law: Law -> + registration().addTest(createTestName(law.name), xdisabled = false, law.test) } - override fun testCases(): List = super.testCases() + lawTestCases + fun testLaws(prefix: String, vararg laws: List): Unit = laws + .flatMap { list: List -> list.asIterable() } + .distinctBy { law: Law -> law.name } + .forEach { law: Law -> + registration().addTest(createTestName(prefix, law.name, true), xdisabled = false, law.test) + } - fun forAll( - gena: Gen, - genb: Gen, - genc: Gen, - gend: Gen, - gene: Gen, - genf: Gen, - geng: Gen, - fn: PropertyContext.(a: A, b: B, c: C, d: D, e: E, f: F, g: G) -> Boolean + suspend fun checkAll( + gena: Arb, + genb: Arb, + genc: Arb, + gend: Arb, + gene: Arb, + genf: Arb, + geng: Arb, + fn: suspend PropertyContext.(a: A, b: B, c: C, d: D, e: E, f: F, g: G) -> Unit ) { - assertAll(gena, genb, genc, gend, gene, Gen.bind(genf, geng, ::Pair)) { a, b, c, d, e, (f, g) -> - fn(a, b, c, d, e, f, g) shouldBe true + checkAll(gena, genb, genc, gend, gene, Arb.bind(genf, geng, ::Pair)) { a, b, c, d, e, (f, g) -> + fn(a, b, c, d, e, f, g) } } - fun forAll( - gena: Gen, - genb: Gen, - genc: Gen, - gend: Gen, - gene: Gen, - genf: Gen, - geng: Gen, - genh: Gen, - fn: PropertyContext.(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) -> Boolean + suspend fun checkAll( + gena: Arb, + genb: Arb, + genc: Arb, + gend: Arb, + gene: Arb, + genf: Arb, + geng: Arb, + genh: Arb, + fn: suspend PropertyContext.(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) -> Unit ) { - assertAll(gena, genb, genc, gend, gene, Gen.bind(genf, geng, genh, ::Triple)) { a, b, c, d, e, (f, g, h) -> - fn(a, b, c, d, e, f, g, h) shouldBe true + checkAll(gena, genb, genc, gend, gene, Arb.bind(genf, geng, genh, ::Triple)) { a, b, c, d, e, (f, g, h) -> + fn(a, b, c, d, e, f, g, h) } } - fun forAll( - gena: Gen, - genb: Gen, - genc: Gen, - gend: Gen, - gene: Gen, - genf: Gen, - geng: Gen, - genh: Gen, - geni: Gen, - fn: PropertyContext.(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) -> Boolean + suspend fun checkAll( + gena: Arb, + genb: Arb, + genc: Arb, + gend: Arb, + gene: Arb, + genf: Arb, + geng: Arb, + genh: Arb, + geni: Arb, + fn: suspend PropertyContext.(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) -> Unit ) { - assertAll(gena, genb, genc, gend, gene, Gen.bind(genf, geng, genh, geni, ::Tuple4)) { a, b, c, d, e, (f, g, h, i) -> - fn(a, b, c, d, e, f, g, h, i) shouldBe true + checkAll(gena, genb, genc, gend, gene, Arb.bind(genf, geng, genh, geni, ::Tuple4)) { a, b, c, d, e, (f, g, h, i) -> + fn(a, b, c, d, e, f, g, h, i) } } - fun forAll( - gena: Gen, - genb: Gen, - genc: Gen, - gend: Gen, - gene: Gen, - genf: Gen, - geng: Gen, - genh: Gen, - geni: Gen, - genj: Gen, - fn: PropertyContext.(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) -> Boolean + suspend fun checkAll( + gena: Arb, + genb: Arb, + genc: Arb, + gend: Arb, + gene: Arb, + genf: Arb, + geng: Arb, + genh: Arb, + geni: Arb, + genj: Arb, + fn: suspend PropertyContext.(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) -> Unit ) { - assertAll(gena, genb, genc, gend, gene, Gen.bind(genf, geng, genh, geni, genj, ::Tuple5)) { a, b, c, d, e, (f, g, h, i, j) -> - fn(a, b, c, d, e, f, g, h, i, j) shouldBe true + checkAll( + gena, + genb, + genc, + gend, + gene, + Arb.bind(genf, geng, genh, geni, genj, ::Tuple5) + ) { a, b, c, d, e, (f, g, h, i, j) -> + fn(a, b, c, d, e, f, g, h, i, j) } } } diff --git a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/generators/Generators.kt b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/generators/Generators.kt index 4e4fc355dd4..42d5268136c 100644 --- a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/generators/Generators.kt +++ b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/generators/Generators.kt @@ -16,83 +16,171 @@ import arrow.core.Tuple7 import arrow.core.Tuple8 import arrow.core.Tuple9 import arrow.core.Validated -import arrow.core.align import arrow.core.left import arrow.core.right import arrow.core.toOption -import io.kotlintest.properties.Gen -import io.kotlintest.properties.shrinking.DoubleShrinker -import io.kotlintest.properties.shrinking.FloatShrinker -import io.kotlintest.properties.shrinking.Shrinker - -fun Gen.Companion.short(): Gen = - Gen.choose(Short.MIN_VALUE.toInt(), Short.MAX_VALUE.toInt()).map { it.toShort() } - -fun Gen.Companion.byte(): Gen = - Gen.choose(Byte.MIN_VALUE.toInt(), Byte.MAX_VALUE.toInt()).map { it.toByte() } - -fun Gen.Companion.functionAToB(gen: Gen): Gen<(A) -> B> = gen.map { b: B -> { _: A -> b } } - -fun Gen.Companion.functionAAToA(gen: Gen): Gen<(A, A) -> A> = gen.map { a: A -> { _: A, _: A -> a } } - -fun Gen.Companion.functionBAToB(gen: Gen): Gen<(B, A) -> B> = gen.map { b: B -> { _: B, _: A -> b } } - -fun Gen.Companion.functionABToB(gen: Gen): Gen<(A, B) -> B> = gen.map { b: B -> { _: A, _: B -> b } } - -fun Gen.Companion.functionToA(gen: Gen): Gen<() -> A> = gen.map { a: A -> { a } } - -fun Gen.Companion.throwable(): Gen = Gen.from(listOf(RuntimeException(), NoSuchElementException(), IllegalArgumentException())) - -fun Gen.Companion.fatalThrowable(): Gen = Gen.from(listOf(ThreadDeath(), StackOverflowError(), OutOfMemoryError(), InterruptedException())) - -fun Gen.Companion.doubleSmall(): Gen = object : Gen { - override fun constants(): Iterable = emptyList() - override fun random(): Sequence = (0 until 10_000).asSequence().map { it / 100.0 } - override fun shrinker(): Shrinker = DoubleShrinker +import io.kotest.property.Arb +import io.kotest.property.arbitrary.bind +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.byte +import io.kotest.property.arbitrary.choice +import io.kotest.property.arbitrary.constant +import io.kotest.property.arbitrary.double +import io.kotest.property.arbitrary.file +import io.kotest.property.arbitrary.filter +import io.kotest.property.arbitrary.flatMap +import io.kotest.property.arbitrary.float +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.localDate +import io.kotest.property.arbitrary.localDateTime +import io.kotest.property.arbitrary.localTime +import io.kotest.property.arbitrary.long +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.numericDoubles +import io.kotest.property.arbitrary.numericFloats +import io.kotest.property.arbitrary.of +import io.kotest.property.arbitrary.orNull +import io.kotest.property.arbitrary.period +import io.kotest.property.arbitrary.short +import io.kotest.property.arbitrary.string +import io.kotest.property.arbitrary.uuid +import kotlin.math.abs + +fun Arb.Companion.functionAToB(arb: Arb): Arb<(A) -> B> = + arb.map { b: B -> { _: A -> b } } + +fun Arb.Companion.functionAAToA(arb: Arb): Arb<(A, A) -> A> = + arb.map { a: A -> { _: A, _: A -> a } } + +fun Arb.Companion.functionBAToB(arb: Arb): Arb<(B, A) -> B> = + arb.map { b: B -> { _: B, _: A -> b } } + +fun Arb.Companion.functionABToB(arb: Arb): Arb<(A, B) -> B> = + arb.map { b: B -> { _: A, _: B -> b } } + +fun Arb.Companion.functionToA(arb: Arb): Arb<() -> A> = + arb.map { a: A -> { a } } + +fun Arb.Companion.throwable(): Arb = + Arb.of(listOf(RuntimeException(), NoSuchElementException(), IllegalArgumentException())) + +fun Arb.Companion.fatalThrowable(): Arb = + Arb.of(listOf(ThreadDeath(), StackOverflowError(), OutOfMemoryError(), InterruptedException())) + +fun Arb.Companion.doubleSmall(): Arb = + Arb.numericDoubles(from = 0.0, to = 100.0) + +fun Arb.Companion.floatSmall(): Arb = + Arb.numericFloats(from = 0F, to = 100F) + +fun Arb.Companion.intSmall(factor: Int = 10000): Arb = + Arb.int((Int.MIN_VALUE / factor)..(Int.MAX_VALUE / factor)) + +fun Arb.Companion.byteSmall(): Arb = + Arb.byte(min = (Byte.MIN_VALUE / 10).toByte(), max = (Byte.MAX_VALUE / 10).toByte()) + +fun Arb.Companion.shortSmall(): Arb { + val range = (Short.MIN_VALUE / 1000)..(Short.MAX_VALUE / 1000) + return Arb.short().filter { it in range } } -fun Gen.Companion.floatSmall(): Gen = object : Gen { - val literals = listOf(0F) - override fun constants(): Iterable = literals - override fun random(): Sequence = (0 until 10_000).asSequence().map { it / 100.0f } - override fun shrinker() = FloatShrinker -} - -fun Gen.Companion.intSmall(): Gen = Gen.oneOf(Gen.choose(Int.MIN_VALUE / 10000, -1), Gen.choose(0, Int.MAX_VALUE / 10000)) - -fun Gen.Companion.byteSmall(): Gen = Gen.oneOf(Gen.choose(Byte.MIN_VALUE / 10, -1), Gen.choose(0, Byte.MAX_VALUE / 10)).map { it.toByte() } - -fun Gen.Companion.shortSmall(): Gen = Gen.oneOf(Gen.choose(Short.MIN_VALUE / 1000, -1), Gen.choose(0, Short.MAX_VALUE / 1000)).map { it.toShort() } - -fun Gen.Companion.longSmall(): Gen = Gen.oneOf(Gen.choose(Long.MIN_VALUE / 100000L, -1L), Gen.choose(0L, Long.MAX_VALUE / 100000L)) - -fun Gen.Companion.tuple4(genA: Gen, genB: Gen, genC: Gen, genD: Gen): Gen> = - Gen.bind(genA, genB, genC, genD) { a: A, b: B, c: C, d: D -> Tuple4(a, b, c, d) } - -fun Gen.Companion.tuple5(genA: Gen, genB: Gen, genC: Gen, genD: Gen, genE: Gen): Gen> = - Gen.bind(genA, genB, genC, genD, genE) { a: A, b: B, c: C, d: D, e: E -> Tuple5(a, b, c, d, e) } - -fun Gen.Companion.tuple6(genA: Gen, genB: Gen, genC: Gen, genD: Gen, genE: Gen, genF: Gen): Gen> = - Gen.bind(genA, genB, genC, genD, genE, genF) { a: A, b: B, c: C, d: D, e: E, f: F -> Tuple6(a, b, c, d, e, f) } - -fun Gen.Companion.tuple7(genA: Gen, genB: Gen, genC: Gen, genD: Gen, genE: Gen, genF: Gen, genG: Gen): Gen> = - Gen.bind(genA, genB, genC, genD, genE, genF, genG) { a: A, b: B, c: C, d: D, e: E, f: F, g: G -> Tuple7(a, b, c, d, e, f, g) } - -fun Gen.Companion.tuple8(genA: Gen, genB: Gen, genC: Gen, genD: Gen, genE: Gen, genF: Gen, genG: Gen, genH: Gen): Gen> = - Gen.bind(Gen.tuple7(genA, genB, genC, genD, genE, genF, genG), genH) { tuple: Tuple7, h: H -> Tuple8(tuple.first, tuple.second, tuple.third, tuple.fourth, tuple.fifth, tuple.sixth, tuple.seventh, h) } +fun Arb.Companion.longSmall(): Arb = + Arb.long((Long.MIN_VALUE / 100000L)..(Long.MAX_VALUE / 100000L)) + +fun Arb.Companion.tuple4(arbA: Arb, arbB: Arb, arbC: Arb, arbD: Arb): Arb> = + Arb.bind(arbA, arbB, arbC, arbD, ::Tuple4) + +fun Arb.Companion.tuple5( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb +): Arb> = + Arb.bind(arbA, arbB, arbC, arbD, arbE, ::Tuple5) + +fun Arb.Companion.tuple6( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb, + arbF: Arb +): Arb> = + Arb.bind(arbA, arbB, arbC, arbD, arbE, arbF, ::Tuple6) + +fun Arb.Companion.tuple7( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb, + arbF: Arb, + arbG: Arb +): Arb> = + Arb.bind(arbA, arbB, arbC, arbD, arbE, arbF, arbG, ::Tuple7) + +fun Arb.Companion.tuple8( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb, + arbF: Arb, + arbG: Arb, + arbH: Arb +): Arb> = + Arb.bind( + Arb.tuple7(arbA, arbB, arbC, arbD, arbE, arbF, arbG), + arbH + ) { (a, b, c, d, e, f, g), h -> + Tuple8(a, b, c, d, e, f, g, h) + } -fun Gen.Companion.tuple9(genA: Gen, genB: Gen, genC: Gen, genD: Gen, genE: Gen, genF: Gen, genG: Gen, genH: Gen, genI: Gen): Gen> = - Gen.bind(Gen.tuple8(genA, genB, genC, genD, genE, genF, genG, genH), genI) { tuple: Tuple8, i: I -> Tuple9(tuple.first, tuple.second, tuple.third, tuple.fourth, tuple.fifth, tuple.sixth, tuple.seventh, tuple.eighth, i) } +fun Arb.Companion.tuple9( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb, + arbF: Arb, + arbG: Arb, + arbH: Arb, + arbI: Arb +): Arb> = + Arb.bind( + Arb.tuple8(arbA, arbB, arbC, arbD, arbE, arbF, arbG, arbH), + arbI + ) { (a, b, c, d, e, f, g, h), i -> + Tuple9(a, b, c, d, e, f, g, h, i) + } -fun Gen.Companion.tuple10(genA: Gen, genB: Gen, genC: Gen, genD: Gen, genE: Gen, genF: Gen, genG: Gen, genH: Gen, genI: Gen, genJ: Gen): Gen> = - Gen.bind(Gen.tuple9(genA, genB, genC, genD, genE, genF, genG, genH, genI), genJ) { tuple: Tuple9, j: J -> Tuple10(tuple.first, tuple.second, tuple.third, tuple.fourth, tuple.fifth, tuple.sixth, tuple.seventh, tuple.eighth, tuple.ninth, j) } +fun Arb.Companion.tuple10( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb, + arbF: Arb, + arbG: Arb, + arbH: Arb, + arbI: Arb, + arbJ: Arb +): Arb> = + Arb.bind( + Arb.tuple9(arbA, arbB, arbC, arbD, arbE, arbF, arbG, arbH, arbI), + arbJ + ) { (a, b, c, d, e, f, g, h, i), j -> + Tuple10(a, b, c, d, e, f, g, h, i, j) + } -fun Gen.Companion.nonZeroInt(): Gen = Gen.int().filter { it != 0 } +fun Arb.Companion.nonZeroInt(): Arb = Arb.int().filter { it != 0 } -fun Gen.Companion.intPredicate(): Gen<(Int) -> Boolean> = - Gen.nonZeroInt().flatMap { num -> - val absNum = Math.abs(num) - Gen.from( +fun Arb.Companion.intPredicate(): Arb<(Int) -> Boolean> = + Arb.nonZeroInt().flatMap { num -> + val absNum = abs(num) + Arb.of( listOf<(Int) -> Boolean>( { it > num }, { it <= num }, @@ -102,90 +190,77 @@ fun Gen.Companion.intPredicate(): Gen<(Int) -> Boolean> = ) } -fun Gen.Companion.endo(gen: Gen): Gen> = gen.map { a: A -> Endo { a } } +fun Arb.Companion.endo(arb: Arb): Arb> = arb.map { a: A -> Endo { a } } -fun Gen.Companion.option(gen: Gen): Gen> = - gen.orNull().map { it.toOption() } +fun Arb.Companion.option(arb: Arb): Arb> = + arb.orNull().map { it.toOption() } -fun Gen.Companion.either(genE: Gen, genA: Gen): Gen> { - val genLeft = genE.map> { Either.Left(it) } - val genRight = genA.map> { Either.Right(it) } - return Gen.oneOf(genLeft, genRight) +fun Arb.Companion.either(arbE: Arb, arbA: Arb): Arb> { + val arbLeft = arbE.map { Either.Left(it) } + val arbRight = arbA.map { Either.Right(it) } + return Arb.choice(arbLeft, arbRight) } -fun Gen.or(genA: Gen): Gen> = Gen.either(this, genA) +fun Arb.or(arbA: Arb): Arb> = Arb.either(this, arbA) -fun Gen.Companion.validated(genE: Gen, genA: Gen): Gen> = - Gen.either(genE, genA).map { Validated.fromEither(it) } +fun Arb.Companion.validated(arbE: Arb, arbA: Arb): Arb> = + Arb.either(arbE, arbA).map { Validated.fromEither(it) } -fun Gen.Companion.nonEmptyList(gen: Gen): Gen> = - Gen.list(gen).filter(List::isNotEmpty).map(::fromListUnsafe) +fun Arb.Companion.nonEmptyList(arb: Arb): Arb> = + Arb.list(arb).filter(List::isNotEmpty).map(::fromListUnsafe) -fun Gen.Companion.sequence(genA: Gen): Gen> = - Gen.list(genA).map { it.asSequence() } +fun Arb.Companion.sequence(arbA: Arb): Arb> = + Arb.list(arbA).map { it.asSequence() } -fun Gen.Companion.unit(): Gen = - create { Unit } +fun Arb.Companion.unit(): Arb = + Arb.constant(Unit) -fun Gen.Companion.ior(genA: Gen, genB: Gen): Gen> = - genA.alignWith(genB) { it } +fun Arb.Companion.ior(arbA: Arb, arbB: Arb): Arb> = + arbA.alignWith(arbB) { it } -fun Gen.Companion.genConst(gen: Gen): Gen> = - gen.map { - Const(it) - } +fun Arb.Companion.arbConst(arb: Arb): Arb> = + arb.map { Const(it) } -fun Gen.eval(): Gen> = +fun Arb.eval(): Arb> = map { Eval.now(it) } -fun Gen.Companion.char(): Gen = - Gen.from(('A'..'Z') + ('a'..'z') + ('0'..'9') + "!@#$%%^&*()_-~`,<.?/:;}{][±§".toList()) - -private fun Gen.alignWith(genB: Gen, transform: (Ior) -> R): Gen = - object : Gen { - override fun constants(): Iterable = - this@alignWith.constants() - .align(genB.constants(), transform) - - override fun random(): Sequence = - this@alignWith.random() - .align(genB.random(), transform) - } +private fun Arb.alignWith(arbB: Arb, transform: (Ior) -> R): Arb = + Arb.bind(this, arbB) { a, b -> transform(Ior.Both(a, b)) } -fun Gen.Companion.suspendFunThatReturnsEitherAnyOrAnyOrThrows(): Gen Either> = - oneOf( +fun Arb.Companion.suspendFunThatReturnsEitherAnyOrAnyOrThrows(): Arb Either> = + choice( suspendFunThatReturnsAnyRight(), suspendFunThatReturnsAnyLeft(), suspendFunThatThrows() ) -fun Gen.Companion.suspendFunThatReturnsAnyRight(): Gen Either> = +fun Arb.Companion.suspendFunThatReturnsAnyRight(): Arb Either> = any().map { suspend { it.right() } } -fun Gen.Companion.suspendFunThatReturnsAnyLeft(): Gen Either> = +fun Arb.Companion.suspendFunThatReturnsAnyLeft(): Arb Either> = any().map { suspend { it.left() } } -fun Gen.Companion.suspendFunThatThrows(): Gen Either> = - throwable().map { suspend { throw it } } as Gen Either> - -fun Gen.Companion.suspendFunThatThrowsFatalThrowable(): Gen Either> = - fatalThrowable().map { suspend { throw it } } as Gen Either> - -fun Gen.Companion.any(): Gen = - oneOf( - string() as Gen, - int() as Gen, - long() as Gen, - float() as Gen, - double() as Gen, - bool() as Gen, - uuid() as Gen, - file() as Gen, - localDate() as Gen, - localTime() as Gen, - localDateTime() as Gen, - period() as Gen, - throwable() as Gen, - fatalThrowable() as Gen, - unit() as Gen +fun Arb.Companion.suspendFunThatThrows(): Arb Either> = + throwable().map { suspend { throw it } } as Arb Either> + +fun Arb.Companion.suspendFunThatThrowsFatalThrowable(): Arb Either> = + fatalThrowable().map { suspend { throw it } } as Arb Either> + +fun Arb.Companion.any(): Arb = + choice( + Arb.string() as Arb, + Arb.int() as Arb, + Arb.long() as Arb, + Arb.float() as Arb, + Arb.double() as Arb, + Arb.bool() as Arb, + Arb.uuid() as Arb, + Arb.file() as Arb, + Arb.localDate() as Arb, + Arb.localTime() as Arb, + Arb.localDateTime() as Arb, + Arb.period() as Arb, + Arb.throwable() as Arb, + Arb.fatalThrowable() as Arb, + Arb.unit() as Arb ) diff --git a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/FxLaws.kt b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/FxLaws.kt index 178025f7be3..927968864ff 100644 --- a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/FxLaws.kt +++ b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/FxLaws.kt @@ -2,11 +2,12 @@ package arrow.core.test.laws import arrow.continuations.Effect import arrow.core.test.generators.throwable -import io.kotlintest.fail -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe -import io.kotlintest.shouldThrow +import io.kotest.assertions.fail +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.bind +import io.kotest.property.checkAll import kotlinx.coroutines.Dispatchers import kotlin.coroutines.Continuation import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED @@ -20,36 +21,54 @@ private typealias SuspendFxBlock = suspend (suspend Eff.() -> A) -> F object FxLaws { fun , F, A> suspended( - pureGen: Gen, - G: Gen, + pureArb: Arb, + G: Arb, eq: (F, F) -> Boolean, fxSuspend: SuspendFxBlock, invoke: suspend Eff.(F) -> A ): List = listOf( Law("suspended fx can bind immediate values") { suspendedCanBindImmediateValues(G, eq, fxSuspend, invoke) }, Law("suspended fx can bind suspended values") { suspendedCanBindSuspendedValues(G, eq, fxSuspend, invoke) }, - Law("suspended fx can bind immediate exceptions") { suspendedCanBindImmediateExceptions(pureGen, fxSuspend, invoke) }, - Law("suspended fx can bind suspended exceptions") { suspendedCanBindSuspendedExceptions(pureGen, fxSuspend, invoke) } + Law("suspended fx can bind immediate exceptions") { + suspendedCanBindImmediateExceptions( + pureArb, + fxSuspend, + invoke + ) + }, + Law("suspended fx can bind suspended exceptions") { + suspendedCanBindSuspendedExceptions( + pureArb, + fxSuspend, + invoke + ) + } ) fun , F, A> eager( - pureGen: Gen, - G: Gen, + pureArb: Arb, + G: Arb, eq: (F, F) -> Boolean, fxEager: EagerFxBlock, invoke: suspend Eff.(F) -> A ): List = listOf( Law("non-suspended fx can bind immediate values") { nonSuspendedCanBindImmediateValues(G, eq, fxEager, invoke) }, - Law("non-suspended fx can bind immediate exceptions") { nonSuspendedCanBindImmediateException(pureGen, fxEager, invoke) } + Law("non-suspended fx can bind immediate exceptions") { + nonSuspendedCanBindImmediateException( + pureArb, + fxEager, + invoke + ) + } ) private suspend fun , F, A> nonSuspendedCanBindImmediateValues( - G: Gen, + G: Arb, eq: (F, F) -> Boolean, fxBlock: EagerFxBlock, invoke: suspend Eff.(F) -> A ) { - forAll(G) { f: F -> + checkAll(G) { f: F -> fxBlock { val res = invoke(f) res @@ -57,12 +76,12 @@ object FxLaws { } } - private fun , F, A> nonSuspendedCanBindImmediateException( - G: Gen, + private suspend fun , F, A> nonSuspendedCanBindImmediateException( + G: Arb, fxBlock: EagerFxBlock, invoke: suspend Eff.(F) -> A ) { - forAll(G, Gen.throwable()) { f, exception -> + checkAll(G, Arb.throwable()) { f, exception -> shouldThrow { fxBlock { val res = invoke(f) @@ -76,74 +95,74 @@ object FxLaws { } private suspend fun , F, A> suspendedCanBindImmediateValues( - G: Gen, + G: Arb, eq: (F, F) -> Boolean, fxBlock: SuspendFxBlock, invoke: suspend Eff.(F) -> A ) { - G.random() + G.samples() .take(1001) .forEach { f -> fxBlock { - val res = invoke(f) + val res = invoke(f.value) res - }.equalUnderTheLaw(f, eq) + }.equalUnderTheLaw(f.value, eq) } } private suspend fun , F, A> suspendedCanBindSuspendedValues( - G: Gen, + G: Arb, eq: (F, F) -> Boolean, fxBlock: SuspendFxBlock, invoke: suspend Eff.(F) -> A ) { - G.random() + G.samples() .take(10) .forEach { f -> fxBlock { - val res = invoke(f.suspend()) + val res = invoke(f.value.suspend()) res - }.equalUnderTheLaw(f, eq) + }.equalUnderTheLaw(f.value, eq) } } private suspend fun , F, A> suspendedCanBindImmediateExceptions( - G: Gen, + G: Arb, fxBlock: SuspendFxBlock, invoke: suspend Eff.(F) -> A ) { - Gen.bind(G, Gen.throwable(), ::Pair) - .random() + Arb.bind(G, Arb.throwable(), ::Pair) + .samples() .take(1001) - .forEach { (f, exception) -> + .forEach { (f, _) -> shouldThrow { fxBlock { - val res = invoke(f) - throw exception + val res = invoke(f.first) + throw f.second res } - fail("It should never reach here. fx should've thrown $exception") - } shouldBe exception + fail("It should never reach here. fx should've thrown ${f.second}") + } shouldBe f.second } } private suspend fun , F, A> suspendedCanBindSuspendedExceptions( - G: Gen, + G: Arb, fxBlock: SuspendFxBlock, invoke: suspend Eff.(F) -> A ) { - Gen.bind(G, Gen.throwable(), ::Pair) - .random() + Arb.bind(G, Arb.throwable(), ::Pair) + .samples() .take(10) - .forEach { (f, exception) -> + .forEach { (f, _) -> shouldThrow { fxBlock { - val res = invoke(f) - exception.suspend() + val res = invoke(f.first) + f.second.suspend() res } - fail("It should never reach here. fx should've thrown $exception") - } shouldBe exception + fail("It should never reach here. fx should've thrown ${f.second}") + } shouldBe f.second } } } diff --git a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/Law.kt b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/Law.kt index ee11ae2ab16..46816d92bca 100644 --- a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/Law.kt +++ b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/Law.kt @@ -1,8 +1,9 @@ package arrow.core.test.laws -import io.kotlintest.TestContext +import io.kotest.assertions.fail +import io.kotest.core.test.TestContext data class Law(val name: String, val test: suspend TestContext.() -> Unit) fun A.equalUnderTheLaw(b: A, f: (A, A) -> Boolean = { a, b -> a == b }): Boolean = - f(this, b) + if (f(this, b)) true else fail("Found $this but expected: $b") diff --git a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/MonoidLaws.kt b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/MonoidLaws.kt index 1131350385f..0212aa7f855 100644 --- a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/MonoidLaws.kt +++ b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/MonoidLaws.kt @@ -1,13 +1,15 @@ package arrow.core.test.laws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.PropertyContext +import io.kotest.property.arbitrary.list object MonoidLaws { - fun laws(M: Monoid, GEN: Gen, eq: (F, F) -> Boolean = { a, b -> a == b }): List = + fun laws(M: Monoid, GEN: Arb, eq: (F, F) -> Boolean = { a, b -> a == b }): List = SemigroupLaws.laws(M, GEN, eq) + listOf( Law("Monoid Laws: Left identity") { M.monoidLeftIdentity(GEN, eq) }, @@ -16,18 +18,18 @@ object MonoidLaws { Law("Monoid Laws: combineAll of empty list is empty") { M.combineAllOfEmptyIsEmpty(eq) } ) - fun Monoid.monoidLeftIdentity(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(GEN) { a -> + suspend fun Monoid.monoidLeftIdentity(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(GEN) { a -> (empty().combine(a)).equalUnderTheLaw(a, eq) } - fun Monoid.monoidRightIdentity(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(GEN) { a -> + suspend fun Monoid.monoidRightIdentity(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(GEN) { a -> a.combine(empty()).equalUnderTheLaw(a, eq) } - fun Monoid.combineAllIsDerived(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(5, Gen.list(GEN)) { list -> + suspend fun Monoid.combineAllIsDerived(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(5, Arb.list(GEN)) { list -> list.combineAll().equalUnderTheLaw(if (list.isEmpty()) empty() else list.reduce { acc, f -> acc.combine(f) }, eq) } diff --git a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/SemigroupLaws.kt b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/SemigroupLaws.kt index 13390d0decc..7e188071f9d 100644 --- a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/SemigroupLaws.kt +++ b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/SemigroupLaws.kt @@ -1,16 +1,17 @@ package arrow.core.test.laws import arrow.typeclasses.Semigroup -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.PropertyContext +import io.kotest.property.checkAll object SemigroupLaws { - fun laws(SG: Semigroup, G: Gen, eq: (F, F) -> Boolean = { a, b -> a == b }): List = + fun laws(SG: Semigroup, G: Arb, eq: (F, F) -> Boolean = { a, b -> a == b }): List = listOf(Law("Semigroup: associativity") { SG.semigroupAssociative(G, eq) }) - fun Semigroup.semigroupAssociative(G: Gen, eq: (F, F) -> Boolean): Unit = - forAll(G, G, G) { A, B, C -> + suspend fun Semigroup.semigroupAssociative(G: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(G, G, G) { A, B, C -> A.combine(B).combine(C).equalUnderTheLaw(A.combine(B.combine(C)), eq) } } diff --git a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/SemiringLaws.kt b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/SemiringLaws.kt index 49c72c12c33..2cb2abe7e29 100644 --- a/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/SemiringLaws.kt +++ b/arrow-libs/core/arrow-core-test/src/main/kotlin/arrow/core/test/laws/SemiringLaws.kt @@ -1,13 +1,14 @@ package arrow.core.test.laws import arrow.typeclasses.Semiring -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.PropertyContext object SemiringLaws { - fun laws(SG: Semiring, GEN: Gen, eq: (F, F) -> Boolean = { a, b -> a == b }): List = + fun laws(SG: Semiring, GEN: Arb, eq: (F, F) -> Boolean = { a, b -> a == b }): List = listOf( Law("Semiring: Additive commutativity") { SG.semiringAdditiveCommutativity(GEN, eq) }, Law("Semiring: Additive left identity") { SG.semiringAdditiveLeftIdentity(GEN, eq) }, @@ -34,117 +35,117 @@ object SemiringLaws { ) // a + b = b + a - fun Semiring.semiringAdditiveCommutativity(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN, GEN) { a, b -> + suspend fun Semiring.semiringAdditiveCommutativity(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN, GEN) { a, b -> a.combine(b).equalUnderTheLaw(b.combine(a), eq) } // 0 + a = a - fun Semiring.semiringAdditiveLeftIdentity(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN) { A -> + suspend fun Semiring.semiringAdditiveLeftIdentity(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN) { A -> (zero().combine(A)).equalUnderTheLaw(A, eq) } // a + 0 = a - fun Semiring.semiringAdditiveRightIdentity(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN) { A -> + suspend fun Semiring.semiringAdditiveRightIdentity(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN) { A -> A.combine(zero()).equalUnderTheLaw(A, eq) } // a + (b + c) = (a + b) + c - fun Semiring.semiringAdditiveAssociativity(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN, GEN, GEN) { A, B, C -> + suspend fun Semiring.semiringAdditiveAssociativity(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN, GEN, GEN) { A, B, C -> A.combine(B.combine(C)).equalUnderTheLaw((A.combine(B)).combine(C), eq) } // a · b = b · a - fun Semiring.semiringMultiplicativeCommutativity(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN, GEN) { a, b -> + suspend fun Semiring.semiringMultiplicativeCommutativity(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN, GEN) { a, b -> a.combineMultiplicate(b).equalUnderTheLaw(b.combineMultiplicate(a), eq) } // 1 · a = a - fun Semiring.semiringMultiplicativeLeftIdentity(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN) { A -> + suspend fun Semiring.semiringMultiplicativeLeftIdentity(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN) { A -> (one().combineMultiplicate(A)).equalUnderTheLaw(A, eq) } // a · 1 = a - fun Semiring.semiringMultiplicativeRightIdentity(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN) { A -> + suspend fun Semiring.semiringMultiplicativeRightIdentity(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN) { A -> A.combineMultiplicate(one()).equalUnderTheLaw(A, eq) } // a · (b · c) = (a · b) · c - fun Semiring.semiringMultiplicativeAssociativity(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN, GEN, GEN) { A, B, C -> + suspend fun Semiring.semiringMultiplicativeAssociativity(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN, GEN, GEN) { A, B, C -> A.combineMultiplicate(B.combineMultiplicate(C)).equalUnderTheLaw((B.combineMultiplicate(A)).combineMultiplicate(C), eq) } // (a + b) · c = a · c + b · c - fun Semiring.semiringRightDistributivity(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN, GEN, GEN) { A, B, C -> + suspend fun Semiring.semiringRightDistributivity(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN, GEN, GEN) { A, B, C -> (A.combine(B)).combineMultiplicate(C).equalUnderTheLaw((A.combineMultiplicate(C)).combine(B.combineMultiplicate(C)), eq) } // a · (b + c) = a · b + a · c - fun Semiring.semiringLeftDistributivity(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN, GEN, GEN) { A, B, C -> + suspend fun Semiring.semiringLeftDistributivity(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN, GEN, GEN) { A, B, C -> A.combineMultiplicate(B.combine(C)).equalUnderTheLaw((A.combineMultiplicate(B)).combine(A.combineMultiplicate(C)), eq) } // 0 · a = 0 - fun Semiring.semiringMultiplicativeLeftAbsorption(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN) { A -> + suspend fun Semiring.semiringMultiplicativeLeftAbsorption(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN) { A -> (zero().combineMultiplicate(A)).equalUnderTheLaw(zero(), eq) } // a · 0 = 0 - fun Semiring.semiringMultiplicativeRightAbsorption(GEN: Gen, eq: (F, F) -> Boolean) = - forAll(GEN) { A -> + suspend fun Semiring.semiringMultiplicativeRightAbsorption(GEN: Arb, eq: (F, F) -> Boolean) = + checkAll(GEN) { A -> A.combineMultiplicate(zero()).equalUnderTheLaw(zero(), eq) } - fun Semiring.timesIsDerived(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(GEN, GEN) { A, B -> + suspend fun Semiring.timesIsDerived(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(GEN, GEN) { A, B -> A.times(B).equalUnderTheLaw(A.combineMultiplicate(B), eq) } - fun Semiring.plusIsDerived(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(GEN, GEN) { A, B -> + suspend fun Semiring.plusIsDerived(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(GEN, GEN) { A, B -> A.plus(B).equalUnderTheLaw(A.combine(B), eq) } - fun Semiring.maybeCombineAdditionIsDerived(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(GEN, GEN) { A, B -> + suspend fun Semiring.maybeCombineAdditionIsDerived(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(GEN, GEN) { A, B -> A.maybeCombineAddition(B).equalUnderTheLaw(A.combine(B), eq) } - fun Semiring.maybeCombineAdditionLeftNull(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(GEN) { A -> + suspend fun Semiring.maybeCombineAdditionLeftNull(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(GEN) { A -> null.maybeCombineAddition(A).equalUnderTheLaw(zero(), eq) } - fun Semiring.maybeCombineAdditionRightNull(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(GEN) { A -> + suspend fun Semiring.maybeCombineAdditionRightNull(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(GEN) { A -> A.maybeCombineAddition(null).equalUnderTheLaw(A, eq) } fun Semiring.maybeCombineAdditionBothNull(eq: (F, F) -> Boolean): Unit = null.maybeCombineAddition(null).equalUnderTheLaw(zero(), eq) shouldBe true - fun Semiring.maybeCombineMultiplicateIsDerived(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(GEN, GEN) { A, B -> + suspend fun Semiring.maybeCombineMultiplicateIsDerived(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(GEN, GEN) { A, B -> A.maybeCombineMultiplicate(B).equalUnderTheLaw(A.combineMultiplicate(B), eq) } - fun Semiring.maybeCombineMultiplicateLeftNull(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(GEN) { A -> + suspend fun Semiring.maybeCombineMultiplicateLeftNull(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(GEN) { A -> null.maybeCombineMultiplicate(A).equalUnderTheLaw(one(), eq) } - fun Semiring.maybeCombineMultiplicateRightNull(GEN: Gen, eq: (F, F) -> Boolean): Unit = - forAll(GEN) { A -> + suspend fun Semiring.maybeCombineMultiplicateRightNull(GEN: Arb, eq: (F, F) -> Boolean): PropertyContext = + checkAll(GEN) { A -> A.maybeCombineMultiplicate(null).equalUnderTheLaw(A, eq) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/AndThenTests.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/AndThenTests.kt index 7ac27183573..8de84336f97 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/AndThenTests.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/AndThenTests.kt @@ -1,10 +1,12 @@ package arrow.core import arrow.core.test.generators.functionAToB -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe -import io.kotlintest.specs.FreeSpec +import io.kotest.core.spec.style.FreeSpec +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list class AndThenTests : FreeSpec() { @@ -13,7 +15,7 @@ class AndThenTests : FreeSpec() { "AndThen0" - { "compose a chain of functions with andThen should be same with AndThen" { - forAll(Gen.int(), Gen.list(Gen.functionAToB(Gen.int()))) { i, fs -> + checkAll(Arb.int(), Arb.list(Arb.functionAToB(Arb.int()))) { i, fs -> val result = fs.fold({ i }) { acc, f -> { f(acc()) } }.invoke() @@ -22,12 +24,12 @@ class AndThenTests : FreeSpec() { acc.andThen(f) }.invoke() - result == expect + result shouldBe expect } } "compose a chain of function with compose should be same with AndThen" { - forAll(Gen.int(), Gen.list(Gen.functionAToB(Gen.int()))) { i, fs -> + checkAll(Arb.int(), Arb.list(Arb.functionAToB(Arb.int()))) { i, fs -> val result = fs.fold({ x: Int -> x }) { acc, f -> { x: Int -> acc(f(x)) } }.invoke(i) @@ -36,7 +38,7 @@ class AndThenTests : FreeSpec() { acc.compose(b) }.invoke(i) - result == expect + result shouldBe expect } } @@ -59,7 +61,7 @@ class AndThenTests : FreeSpec() { "AndThen1" - { "compose a chain of functions with andThen should be same with AndThen" { - forAll(Gen.int(), Gen.list(Gen.functionAToB(Gen.int()))) { i, fs -> + checkAll(Arb.int(), Arb.list(Arb.functionAToB(Arb.int()))) { i, fs -> val result = fs.fold({ x: Int -> x }) { acc, f -> { x: Int -> f(acc(x)) } }.invoke(i) @@ -68,12 +70,12 @@ class AndThenTests : FreeSpec() { acc.andThen(f) }.invoke(i) - result == expect + result shouldBe expect } } "compose a chain of function with compose should be same with AndThen" { - forAll(Gen.int(), Gen.list(Gen.functionAToB(Gen.int()))) { i, fs -> + checkAll(Arb.int(), Arb.list(Arb.functionAToB(Arb.int()))) { i, fs -> val result = fs.fold({ x: Int -> x }) { acc, f -> { x: Int -> acc(f(x)) } }.invoke(i) @@ -82,7 +84,7 @@ class AndThenTests : FreeSpec() { acc.compose(b) }.invoke(i) - result == expect + result shouldBe expect } } @@ -111,7 +113,7 @@ class AndThenTests : FreeSpec() { "AndThen2" - { "compose a chain of functions with andThen should be same with AndThen" { - forAll(Gen.int(), Gen.int(), Gen.list(Gen.functionAToB(Gen.int()))) { i, j, fs -> + checkAll(Arb.int(), Arb.int(), Arb.list(Arb.functionAToB(Arb.int()))) { i, j, fs -> val result = fs.fold({ x: Int, y: Int -> x + y }) { acc, f -> { x: Int, y: Int -> f(acc(x, y)) } }.invoke(i, j) @@ -120,7 +122,7 @@ class AndThenTests : FreeSpec() { acc.andThen(f) }.invoke(i, j) - result == expect + result shouldBe expect } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/BooleanTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/BooleanTest.kt index 6ddc6e04cf4..48c406a3d77 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/BooleanTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/BooleanTest.kt @@ -3,12 +3,13 @@ package arrow.core import arrow.core.test.UnitSpec import arrow.core.test.laws.MonoidLaws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.bool class BooleanTest : UnitSpec() { init { testLaws( - MonoidLaws.laws(Monoid.boolean(), Gen.bool()) + MonoidLaws.laws(Monoid.boolean(), Arb.bool()) ) } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/CollectionsSyntaxTests.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/CollectionsSyntaxTests.kt index 08a3ab4f6f4..d55d788fb19 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/CollectionsSyntaxTests.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/CollectionsSyntaxTests.kt @@ -17,7 +17,7 @@ package arrow.core import arrow.core.test.UnitSpec -import io.kotlintest.shouldBe +import io.kotest.matchers.shouldBe class CollectionsSyntaxTests : UnitSpec() { diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ComparisonKtTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ComparisonKtTest.kt index 52fce7a7e4a..f7ae30cdd4d 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ComparisonKtTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ComparisonKtTest.kt @@ -1,11 +1,19 @@ package arrow.core -import arrow.core.test.generators.byte -import arrow.core.test.generators.short -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe -import io.kotlintest.specs.StringSpec +import io.kotest.assertions.assertSoftly +import io.kotest.core.spec.style.StringSpec +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.arbitrary.bind +import io.kotest.property.arbitrary.byte +import io.kotest.property.arbitrary.double +import io.kotest.property.arbitrary.float +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.long +import io.kotest.property.arbitrary.short +import io.kotest.property.arbitrary.string data class Person(val age: Int, val name: String) : Comparable { companion object { @@ -18,13 +26,13 @@ data class Person(val age: Int, val name: String) : Comparable { comparator.compare(this, other) } -fun Gen.Companion.person(): Gen = - bind(int(), string(), ::Person) +fun Arb.Companion.person(): Arb = + Arb.bind(Arb.int(), Arb.string(), ::Person) class ComparisonKtTest : StringSpec() { init { - "Generic - sort2" { - forAll(Gen.person(), Gen.person()) { a, b -> + "Arberic - sort2" { + checkAll(Arb.person(), Arb.person()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -35,8 +43,8 @@ class ComparisonKtTest : StringSpec() { } } - "Generic - sort3" { - forAll(Gen.person(), Gen.person(), Gen.person()) { a, b, c -> + "Arberic - sort3" { + checkAll(Arb.person(), Arb.person(), Arb.person()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -48,17 +56,17 @@ class ComparisonKtTest : StringSpec() { } } - "Generic - sortAll" { - forAll(Gen.person(), Gen.list(Gen.person())) { a, aas -> + "Arberic - sortAll" { + checkAll(Arb.person(), Arb.list(Arb.person())) { a, aas -> val res = sort(a, *aas.toTypedArray()) val expected = listOf(a, *aas.toTypedArray()).sorted() - res == expected + res shouldBe expected } } - "Generic - comparator - sort2" { - forAll(Gen.person(), Gen.person()) { a, b -> + "Arberic - comparator - sort2" { + checkAll(Arb.person(), Arb.person()) { a, b -> val (first, second) = sort(a, b, Person.comparator) val (aa, bb) = listOf(a, b).sorted() @@ -69,8 +77,8 @@ class ComparisonKtTest : StringSpec() { } } - "Generic - comparator - sort3" { - forAll(Gen.person(), Gen.person(), Gen.person()) { a, b, c -> + "Arberic - comparator - sort3" { + checkAll(Arb.person(), Arb.person(), Arb.person()) { a, b, c -> val (first, second, third) = sort(a, b, c, Person.comparator) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -83,7 +91,7 @@ class ComparisonKtTest : StringSpec() { } "Byte - sort2" { - forAll(Gen.byte(), Gen.byte()) { a, b -> + checkAll(Arb.byte(), Arb.byte()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -95,7 +103,7 @@ class ComparisonKtTest : StringSpec() { } "Byte - sort3" { - forAll(Gen.byte(), Gen.byte(), Gen.byte()) { a, b, c -> + checkAll(Arb.byte(), Arb.byte(), Arb.byte()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -108,16 +116,16 @@ class ComparisonKtTest : StringSpec() { } "Byte - sortAll" { - forAll(Gen.byte(), Gen.byte(), Gen.byte(), Gen.byte()) { a, b, c, d -> + checkAll(Arb.byte(), Arb.byte(), Arb.byte(), Arb.byte()) { a, b, c, d -> val res = sort(a, b, c, d) val expected = listOf(a, b, c, d).sorted() - res == expected + res shouldBe expected } } "Short - sort2" { - forAll(Gen.short(), Gen.short()) { a, b -> + checkAll(Arb.short(), Arb.short()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -129,7 +137,7 @@ class ComparisonKtTest : StringSpec() { } "Short - sort3" { - forAll(Gen.short(), Gen.short(), Gen.short()) { a, b, c -> + checkAll(Arb.short(), Arb.short(), Arb.short()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -142,25 +150,26 @@ class ComparisonKtTest : StringSpec() { } "Short - sortAll" { - forAll(Gen.short(), Gen.short(), Gen.short(), Gen.short()) { a, b, c, d -> + checkAll(Arb.short(), Arb.short(), Arb.short(), Arb.short()) { a, b, c, d -> val res = sort(a, b, c, d) val expected = listOf(a, b, c, d).sorted() - res == expected + res shouldBe expected } } "Int - sort2" { - forAll(Gen.int(), Gen.int()) { a, b -> + checkAll(Arb.int(), Arb.int()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() - first == aa && second == bb + first shouldBe aa + second shouldBe bb } } "Int - sort3" { - forAll(Gen.int(), Gen.int(), Gen.int()) { a, b, c -> + checkAll(Arb.int(), Arb.int(), Arb.int()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -173,16 +182,16 @@ class ComparisonKtTest : StringSpec() { } "Int - sortAll" { - forAll(Gen.int(), Gen.int(), Gen.int(), Gen.int()) { a, b, c, d -> + checkAll(Arb.int(), Arb.int(), Arb.int(), Arb.int()) { a, b, c, d -> val res = sort(a, b, c, d) val expected = listOf(a, b, c, d).sorted() - res == expected + res shouldBe expected } } "Long - sort2" { - forAll(Gen.long(), Gen.long()) { a, b -> + checkAll(Arb.long(), Arb.long()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -194,7 +203,7 @@ class ComparisonKtTest : StringSpec() { } "Long - sort3" { - forAll(Gen.long(), Gen.long(), Gen.long()) { a, b, c -> + checkAll(Arb.long(), Arb.long(), Arb.long()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -207,16 +216,16 @@ class ComparisonKtTest : StringSpec() { } "Long - sortAll" { - forAll(Gen.long(), Gen.long(), Gen.long(), Gen.long()) { a, b, c, d -> + checkAll(Arb.long(), Arb.long(), Arb.long(), Arb.long()) { a, b, c, d -> val res = sort(a, b, c, d) val expected = listOf(a, b, c, d).sorted() - res == expected + res shouldBe expected } } "Float - sort2" { - forAll(Gen.float(), Gen.float()) { a, b -> + checkAll(Arb.float(), Arb.float()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -225,7 +234,7 @@ class ComparisonKtTest : StringSpec() { } "Float - sort3" { - forAll(Gen.float(), Gen.float(), Gen.float()) { a, b, c -> + checkAll(Arb.float(), Arb.float(), Arb.float()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -238,16 +247,16 @@ class ComparisonKtTest : StringSpec() { } "Float - sortAll" { - forAll(Gen.float(), Gen.float(), Gen.float(), Gen.float()) { a, b, c, d -> + checkAll(Arb.float(), Arb.float(), Arb.float(), Arb.float()) { a, b, c, d -> val res = sort(a, b, c, d) val expected = listOf(a, b, c, d).sorted() - res == expected + res shouldBe expected } } "Double - sort2" { - forAll(Gen.double(), Gen.double()) { a, b -> + checkAll(Arb.double(), Arb.double()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -256,7 +265,7 @@ class ComparisonKtTest : StringSpec() { } "Double - sort3" { - forAll(Gen.double(), Gen.double(), Gen.double()) { a, b, c -> + checkAll(Arb.double(), Arb.double(), Arb.double()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -265,22 +274,16 @@ class ComparisonKtTest : StringSpec() { } "Double - sortAll" { - forAll(Gen.double(), Gen.double(), Gen.double(), Gen.double()) { a, b, c, d -> + checkAll(Arb.double(), Arb.double(), Arb.double(), Arb.double()) { a, b, c, d -> val res = sort(a, b, c, d) val expected = listOf(a, b, c, d).sorted() - res == expected + res shouldBe expected } } } } -fun assertSoftly(f: () -> Unit): Boolean = - io.kotlintest.assertSoftly { - f() - true - } - /** * Equality for Float to check sorting order. * So we need `NaN == NaN` to be true. diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EitherTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EitherTest.kt index 5474737c766..6918e76ded7 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EitherTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EitherTest.kt @@ -17,31 +17,36 @@ import arrow.core.test.generators.suspendFunThatThrowsFatalThrowable import arrow.core.test.laws.FxLaws import arrow.core.test.laws.MonoidLaws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.PropertyContext -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe -import io.kotlintest.shouldThrow -import kotlinx.coroutines.runBlocking +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.property.arbitrary.choice +import io.kotest.property.arbitrary.constant +import io.kotest.property.arbitrary.filter +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.negativeInts +import io.kotest.property.arbitrary.string class EitherTest : UnitSpec() { - val GEN = Gen.either(Gen.string(), Gen.int()) + private val ARB = Arb.either(Arb.string(), Arb.int()) init { testLaws( - MonoidLaws.laws(Monoid.either(Monoid.string(), Monoid.int()), GEN), + MonoidLaws.laws(Monoid.either(Monoid.string(), Monoid.int()), ARB), FxLaws.suspended, Either, Int>( - Gen.int().map(::Right), - GEN.map { it }, + Arb.int().map(::Right), + ARB.map { it }, Either::equals, either::invoke ) { it.bind() }, FxLaws.eager, Either, Int>( - Gen.int().map(::Right), - GEN.map { it }, + Arb.int().map(::Right), + ARB.map { it }, Either::equals, either::eager ) { @@ -50,63 +55,63 @@ class EitherTest : UnitSpec() { ) "isLeft should return true if Left and false if Right" { - forAll { a: Int -> + checkAll { a: Int -> Left(a).isLeft() && !Right(a).isLeft() } } "isRight should return false if Left and true if Right" { - forAll { a: Int -> + checkAll { a: Int -> !Left(a).isRight() && Right(a).isRight() } } "fold should apply first op if Left and second op if Right" { - forAllSmallInt { a: Int, b: Int -> + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> val right: Either = Right(a) val left: Either = Left(b) - right.fold({ it + 2 }, { it + 1 }) == a + 1 && - left.fold({ it + 2 }, { it + 1 }) == b + 2 + right.fold({ it + 2 }, { it + 1 }) shouldBe a + 1 + left.fold({ it + 2 }, { it + 1 }) shouldBe b + 2 } } "foldLeft should return initial if Left and apply op if Right" { - forAllSmallInt { a: Int, b: Int, c: Int -> - Right(a).foldLeft(c, Int::plus) == c + a && - Left(b).foldLeft(c, Int::plus) == c + checkAll(Arb.intSmall(), Arb.intSmall(), Arb.intSmall()) { a, b, c -> + Right(a).foldLeft(c, Int::plus) shouldBe c + a + Left(b).foldLeft(c, Int::plus) shouldBe c } } "foldMap should return the empty of the inner type if Left and apply op if Right" { - forAllSmallInt { a: Int, b: Int -> + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> val left: Either = Left(b) - Right(a).foldMap(Monoid.int()) { it + 1 } == a + 1 && - left.foldMap(Monoid.int()) { it + 1 } == Monoid.int().empty() + Right(a).foldMap(Monoid.int()) { it + 1 } shouldBe a + 1 + left.foldMap(Monoid.int()) { it + 1 } shouldBe Monoid.int().empty() } } "bifoldLeft should apply first op if Left and apply second op if Right" { - forAllSmallInt { a: Int, b: Int, c: Int -> - Right(a).bifoldLeft(c, Int::plus, Int::times) == a * c && - Left(b).bifoldLeft(c, Int::plus, Int::times) == b + c + checkAll(Arb.intSmall(), Arb.intSmall(), Arb.intSmall()) { a, b, c -> + Right(a).bifoldLeft(c, Int::plus, Int::times) shouldBe a * c + Left(b).bifoldLeft(c, Int::plus, Int::times) shouldBe b + c } } "bifoldMap should apply first op if Left and apply second op if Right" { - forAllSmallInt { a: Int, b: Int -> + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> val right: Either = Right(a) val left: Either = Left(b) - right.bifoldMap(Monoid.int(), { it + 2 }, { it + 1 }) == a + 1 && - left.bifoldMap(Monoid.int(), { it + 2 }, { it + 1 }) == b + 2 + right.bifoldMap(Monoid.int(), { it + 2 }, { it + 1 }) shouldBe a + 1 + left.bifoldMap(Monoid.int(), { it + 2 }, { it + 1 }) shouldBe b + 2 } } "fromNullable should lift value as a Right if it is not null" { - forAll { a: Int -> - Either.fromNullable(a) == Right(a) + checkAll { a: Int -> + Either.fromNullable(a) shouldBe Right(a) } } @@ -119,345 +124,329 @@ class EitherTest : UnitSpec() { } "combine two rights should return a right of the combine of the inners" { - forAll { a: String, b: String -> - Monoid.string().run { Right(a.combine(b)) } == Right(a).combine(Monoid.string(), Monoid.string(), Right(b)) + checkAll { a: String, b: String -> + Monoid.string().run { Right(a.combine(b)) } shouldBe Right(a).combine( + Monoid.string(), + Monoid.string(), + Right(b) + ) } } "combine two lefts should return a left of the combine of the inners" { - forAll { a: String, b: String -> - Monoid.string().run { Left(a.combine(b)) } == Left(a).combine(Monoid.string(), Monoid.string(), Left(b)) + checkAll { a: String, b: String -> + Monoid.string().run { Left(a.combine(b)) } shouldBe Left(a).combine(Monoid.string(), Monoid.string(), Left(b)) } } "combine a right and a left should return left" { - forAll { a: String, b: String -> - Left(a) == Left(a).combine(Monoid.string(), Monoid.string(), Right(b)) && - Left(a) == Right(b).combine(Monoid.string(), Monoid.string(), Left(a)) + checkAll { a: String, b: String -> + Left(a) shouldBe Left(a).combine(Monoid.string(), Monoid.string(), Right(b)) + Left(a) shouldBe Right(b).combine(Monoid.string(), Monoid.string(), Left(a)) } } "getOrElse should return value" { - forAll { a: Int, b: Int -> - Right(a).getOrElse { b } == a && - Left(a).getOrElse { b } == b + checkAll { a: Int, b: Int -> + Right(a).getOrElse { b } shouldBe a + Left(a).getOrElse { b } shouldBe b } } "orNull should return value" { - forAll { a: Int -> - Right(a).orNull() == a + checkAll { a: Int -> + Right(a).orNull() shouldBe a } } "orNone should return Some(value)" { - forAll { a: Int -> - Either.Right(a).orNone() == Some(a) + checkAll { a: Int -> + Right(a).orNone() shouldBe Some(a) } } "orNone should return None when left" { - forAll { a: String -> - Left(a).orNone() == None + checkAll { a: String -> + Left(a).orNone() shouldBe None } } "getOrHandle should return value" { - forAll { a: Int, b: Int -> - Right(a).getOrHandle { b } == a && - Left(a).getOrHandle { it + b } == a + b + checkAll { a: Int, b: Int -> + Right(a).getOrHandle { b } shouldBe a + Left(a).getOrHandle { it + b } shouldBe a + b } } "filterOrElse should filter values" { - forAllSmallInt { a: Int, b: Int -> + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> val left: Either = Left(a) - Right(a).filterOrElse({ it > a - 1 }, { b }) == Right(a) && - Right(a).filterOrElse({ it > a + 1 }, { b }) == Left(b) && - left.filterOrElse({ it > a - 1 }, { b }) == Left(a) && - left.filterOrElse({ it > a + 1 }, { b }) == Left(a) + Right(a).filterOrElse({ it > a - 1 }, { b }) shouldBe Right(a) + Right(a).filterOrElse({ it > a + 1 }, { b }) shouldBe Left(b) + left.filterOrElse({ it > a - 1 }, { b }) shouldBe Left(a) + left.filterOrElse({ it > a + 1 }, { b }) shouldBe Left(a) } } "filterOrOther should filter values" { - forAllSmallInt { a: Int, b: Int -> + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> val left: Either = Left(a) - Right(a).filterOrOther({ it > a - 1 }, { b + a }) == Right(a) && - Right(a).filterOrOther({ it > a + 1 }, { b + a }) == Left(b + a) && - left.filterOrOther({ it > a - 1 }, { b + a }) == Left(a) && - left.filterOrOther({ it > a + 1 }, { b + a }) == Left(a) + Right(a).filterOrOther({ it > a - 1 }, { b + a }) shouldBe Right(a) + Right(a).filterOrOther({ it > a + 1 }, { b + a }) shouldBe Left(b + a) + left.filterOrOther({ it > a - 1 }, { b + a }) shouldBe Left(a) + left.filterOrOther({ it > a + 1 }, { b + a }) shouldBe Left(a) } } "leftIfNull should return Left if Right value is null of if Either is Left" { - forAll { a: Int, b: Int -> - Right(a).leftIfNull { b } == Right(a) && - Right(null).leftIfNull { b } == Left(b) && - Left(a).leftIfNull { b } == Left(a) + checkAll { a: Int, b: Int -> + Right(a).leftIfNull { b } shouldBe Right(a) + Right(null).leftIfNull { b } shouldBe Left(b) + Left(a).leftIfNull { b } shouldBe Left(a) } } "exists should apply predicate to Right only" { - forAllSmallInt { a: Int -> + checkAll(Arb.intSmall()) { a -> val left: Either = Left(a) - Right(a).exists { it > a - 1 } && - !Right(a).exists { it > a + 1 } && - !left.exists { it > a - 1 } && - !left.exists { it > a + 1 } + Right(a).exists { it > a - 1 } shouldBe true + !Right(a).exists { it > a + 1 } shouldBe true + !left.exists { it > a - 1 } shouldBe true + !left.exists { it > a + 1 } shouldBe true } } "rightIfNotNull should return Left if value is null or Right of value when not null" { - forAll { a: Int, b: Int -> - null.rightIfNotNull { b } == Left(b) && - a.rightIfNotNull { b } == Right(a) + checkAll { a: Int, b: Int -> + null.rightIfNotNull { b } shouldBe Left(b) + a.rightIfNotNull { b } shouldBe Right(a) } } "rightIfNull should return Left if value is not null or Right of value when null" { - forAll { a: Int, b: Int -> - a.rightIfNull { b } == Left(b) && - null.rightIfNull { b } == Right(null) + checkAll { a: Int, b: Int -> + a.rightIfNull { b } shouldBe Left(b) + null.rightIfNull { b } shouldBe Right(null) } } "swap should interchange values" { - forAll { a: Int -> - Left(a).swap() == Right(a) && - Right(a).swap() == Left(a) + checkAll { a: Int -> + Left(a).swap() shouldBe Right(a) + Right(a).swap() shouldBe Left(a) } } "orNull should convert" { - forAll { a: Int -> + checkAll { a: Int -> val left: Either = Left(a) - Right(a).orNull() == a && - left.orNull() == null + Right(a).orNull() shouldBe a + left.orNull() shouldBe null } } "contains should check value" { - forAllSmallInt { a: Int, b: Int -> - val rightContains = Right(a).contains(a) + // We need to check that a != b or this test will result in a false negative + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> + Right(a).contains(a) shouldBe true // We need to check that a != b or this test will result in a false negative - val rightDoesntContains = if (a != b) !Right(a).contains(b) else true - val leftNeverContains = !Left(a).contains(a) - - rightContains && rightDoesntContains && leftNeverContains + Right(a).contains(b) shouldBe (a == b) + !Left(a).contains(a) shouldBe false } } "map should alter right instance only" { - forAllSmallInt { a: Int, b: Int -> + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> val right: Either = Right(a) val left: Either = Left(b) - right.map { it + 1 } == Right(a + 1) && left.map { it + 1 } == left + right.map { it + 1 } shouldBe Right(a + 1) + left.map { it + 1 } shouldBe left } } "mapLeft should alter left instance only" { - forAllSmallInt { a: Int, b: Int -> + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> val right: Either = Right(a) val left: Either = Left(b) - right.mapLeft { it + 1 } == right && left.mapLeft { it + 1 } == Left(b + 1) + right.mapLeft { it + 1 } shouldBe right + left.mapLeft { it + 1 } shouldBe Left(b + 1) } } "bimap should alter left or right instance accordingly" { - forAllSmallInt { a: Int, b: Int -> + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> val right: Either = Right(a) val left: Either = Left(b) - right.bimap({ it + 2 }, { it + 1 }) == Right(a + 1) && - left.bimap({ it + 2 }, { it + 1 }) == Left(b + 2) + right.bimap({ it + 2 }, { it + 1 }) shouldBe Right(a + 1) + left.bimap({ it + 2 }, { it + 1 }) shouldBe Left(b + 2) } } "replicate should return Right(empty list) when n <= 0" { - forAll( - Gen.oneOf(Gen.negativeIntegers(), Gen.constant(0)), - Gen.int() + checkAll( + Arb.choice(Arb.negativeInts(), Arb.constant(0)), + Arb.int() ) { n: Int, a: Int -> val expected: Either> = Right(emptyList()) - Right(a).replicate(n) == expected && - Left(a).replicate(n) == expected + Right(a).replicate(n) shouldBe expected + Left(a).replicate(n) shouldBe expected } } "replicate should return Right(list of repeated value size n) when Right and n is positive" { - forAll( - Gen.intSmall().filter { it > 0 }, - Gen.int() + checkAll( + Arb.intSmall().filter { it > 0 }, + Arb.int() ) { n: Int, a: Int -> - Right(a).replicate(n) == Right(List(n) { a }) && - Left(a).replicate(n) == Left(a) + Right(a).replicate(n) shouldBe Right(List(n) { a }) + Left(a).replicate(n) shouldBe Left(a) } } "traverse should return list of Right when Right and empty list when Left" { - forAll( - Gen.int(), - Gen.int(), - Gen.int() + checkAll( + Arb.int(), + Arb.int(), + Arb.int() ) { a: Int, b: Int, c: Int -> - Right(a).traverse { emptyList() } == emptyList() && - Right(a).traverse { listOf(b, c) } == listOf(Right(b), Right(c)) && - Left(a).traverse { listOf(b, c) } == emptyList() + Right(a).traverse { emptyList() } shouldBe emptyList() + Right(a).traverse { listOf(b, c) } shouldBe listOf(Right(b), Right(c)) + Left(a).traverse { listOf(b, c) } shouldBe emptyList() } } "flatMap should map right instance only" { - forAllSmallInt { a: Int, b: Int -> + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> val right: Either = Right(a) val left: Either = Left(b) - right.flatMap { Right(it + 1) } == Right(a + 1) && - left.flatMap { Right(it + 1) } == left + right.flatMap { Right(it + 1) } shouldBe Right(a + 1) + left.flatMap { Right(it + 1) } shouldBe left } } "conditionally should create right instance only if test is true" { - forAll { t: Boolean, i: Int, s: String -> + checkAll { t: Boolean, i: Int, s: String -> val expected = if (t) Right(i) else Left(s) - Either.conditionally(t, { s }, { i }) == expected + Either.conditionally(t, { s }, { i }) shouldBe expected } } "handleErrorWith should handle left instance otherwise return Right" { - forAll { a: Int, b: String -> - Left(a).handleErrorWith { Right(b) } == Right(b) && - Right(a).handleErrorWith { Right(b) } == Right(a) && - Left(a).handleErrorWith { Left(b) } == Left(b) + checkAll { a: Int, b: String -> + Left(a).handleErrorWith { Right(b) } shouldBe Right(b) + Right(a).handleErrorWith { Right(b) } shouldBe Right(a) + Left(a).handleErrorWith { Left(b) } shouldBe Left(b) } } "catch should return Right(result) when f does not throw" { - suspend fun loadFromNetwork(): Int = 1 - Either.catch { loadFromNetwork() } shouldBe Right(1) + Either.catch { 1 } shouldBe Right(1) } "catch should return Left(result) when f throws" { val exception = Exception("Boom!") - suspend fun loadFromNetwork(): Int = throw exception - Either.catch { loadFromNetwork() } shouldBe Left(exception) + Either.catch { throw exception } shouldBe Left(exception) } "catchAndFlatten should return Right(result) when f does not throw" { - suspend fun loadFromNetwork(): Either = Right(1) - Either.catchAndFlatten { loadFromNetwork() } shouldBe Right(1) + Either.catchAndFlatten { Right(1) } shouldBe Right(1) } "catchAndFlatten should return Left(result) when f throws" { val exception = Exception("Boom!") - suspend fun loadFromNetwork(): Either = throw exception - Either.catchAndFlatten { loadFromNetwork() } shouldBe Left(exception) + Either.catchAndFlatten { throw exception } shouldBe Left(exception) } "resolve should yield a result when deterministic functions are used as handlers" { - forAll( - Gen.suspendFunThatReturnsEitherAnyOrAnyOrThrows(), - Gen.any() + checkAll( + Arb.suspendFunThatReturnsEitherAnyOrAnyOrThrows(), + Arb.any() ) { f: suspend () -> Either, returnObject: Any -> - - runBlocking { - val result = - Either.resolve( - f = { f() }, - success = { a -> handleWithPureFunction(a, returnObject) }, - error = { e -> handleWithPureFunction(e, returnObject) }, - throwable = { t -> handleWithPureFunction(t, returnObject) }, - unrecoverableState = { handleWithPureFunction(it) } - ) - result == returnObject - } + val result = + Either.resolve( + f = { f() }, + success = { a -> handleWithPureFunction(a, returnObject) }, + error = { e -> handleWithPureFunction(e, returnObject) }, + throwable = { t -> handleWithPureFunction(t, returnObject) }, + unrecoverableState = { handleWithPureFunction(it) } + ) + result shouldBe returnObject } } "resolve should throw a Throwable when a fatal Throwable is thrown" { - forAll( - Gen.suspendFunThatThrowsFatalThrowable(), - Gen.any() + checkAll( + Arb.suspendFunThatThrowsFatalThrowable(), + Arb.any() ) { f: suspend () -> Either, returnObject: Any -> - - runBlocking { - shouldThrow { - Either.resolve( - f = { f() }, - success = { a -> handleWithPureFunction(a, returnObject) }, - error = { e -> handleWithPureFunction(e, returnObject) }, - throwable = { t -> handleWithPureFunction(t, returnObject) }, - unrecoverableState = { handleWithPureFunction(it) } - ) - } + shouldThrow { + Either.resolve( + f = { f() }, + success = { a -> handleWithPureFunction(a, returnObject) }, + error = { e -> handleWithPureFunction(e, returnObject) }, + throwable = { t -> handleWithPureFunction(t, returnObject) }, + unrecoverableState = { handleWithPureFunction(it) } + ) } - true } } "resolve should yield a result when an exception is thrown in the success supplied function" { - forAll( - Gen.suspendFunThatReturnsAnyRight(), - Gen.any() + checkAll( + Arb.suspendFunThatReturnsAnyRight(), + Arb.any() ) { f: suspend () -> Either, returnObject: Any -> - - runBlocking { - val result = - Either.resolve( - f = { f() }, - success = { throwException(it) }, - error = { e -> handleWithPureFunction(e, returnObject) }, - throwable = { t -> handleWithPureFunction(t, returnObject) }, - unrecoverableState = { handleWithPureFunction(it) } - ) - result == returnObject - } + val result = + Either.resolve( + f = { f() }, + success = { throwException(it) }, + error = { e -> handleWithPureFunction(e, returnObject) }, + throwable = { t -> handleWithPureFunction(t, returnObject) }, + unrecoverableState = { handleWithPureFunction(it) } + ) + result shouldBe returnObject } } "resolve should yield a result when an exception is thrown in the error supplied function" { - forAll( - Gen.suspendFunThatReturnsAnyLeft(), - Gen.any() + checkAll( + Arb.suspendFunThatReturnsAnyLeft(), + Arb.any() ) { f: suspend () -> Either, returnObject: Any -> - - runBlocking { - val result = - Either.resolve( - f = { f() }, - success = { a -> handleWithPureFunction(a, returnObject) }, - error = { throwException(it) }, - throwable = { t -> handleWithPureFunction(t, returnObject) }, - unrecoverableState = { handleWithPureFunction(it) } - ) - result == returnObject - } + val result = + Either.resolve( + f = { f() }, + success = { a -> handleWithPureFunction(a, returnObject) }, + error = { throwException(it) }, + throwable = { t -> handleWithPureFunction(t, returnObject) }, + unrecoverableState = { handleWithPureFunction(it) } + ) + result shouldBe returnObject } } "resolve should throw a Throwable when any exception is thrown in the throwable supplied function" { - forAll( - Gen.suspendFunThatThrows() + checkAll( + Arb.suspendFunThatThrows() ) { f: suspend () -> Either -> - - runBlocking { - shouldThrow { - Either.resolve( - f = { f() }, - success = { throwException(it) }, - error = { throwException(it) }, - throwable = { throwException(it) }, - unrecoverableState = { handleWithPureFunction(it) } - ) - } + shouldThrow { + Either.resolve( + f = { f() }, + success = { throwException(it) }, + error = { throwException(it) }, + throwable = { throwException(it) }, + unrecoverableState = { handleWithPureFunction(it) } + ) } - true } } @@ -470,8 +459,8 @@ class EitherTest : UnitSpec() { } "sequence should be consistent with traverse" { - forAll(Gen.either(Gen.string(), Gen.int())) { either -> - either.map { listOf(it) }.sequence() == either.traverse { listOf(it) } + checkAll(Arb.either(Arb.string(), Arb.int())) { either -> + either.map { listOf(it) }.sequence() shouldBe either.traverse { listOf(it) } } } @@ -484,8 +473,8 @@ class EitherTest : UnitSpec() { } "sequenceOption should be consistent with traverseOption" { - forAll(Gen.either(Gen.string(), Gen.int())) { either -> - either.map { Some(it) }.sequenceOption() == either.traverseOption { Some(it) } + checkAll(Arb.either(Arb.string(), Arb.int())) { either -> + either.map { Some(it) }.sequenceOption() shouldBe either.traverseOption { Some(it) } } } @@ -498,8 +487,8 @@ class EitherTest : UnitSpec() { } "sequenceValidated should be consistent with traverseValidated" { - forAll(Gen.either(Gen.string(), Gen.int())) { either -> - either.map { it.valid() }.sequenceValidated() == either.traverseValidated { it.valid() } + checkAll(Arb.either(Arb.string(), Arb.int())) { either -> + either.map { it.valid() }.sequenceValidated() shouldBe either.traverseValidated { it.valid() } } } @@ -513,8 +502,10 @@ class EitherTest : UnitSpec() { } "bisequence should be consistent with bitraverse" { - forAll(Gen.either(Gen.string(), Gen.int())) { either -> - either.bimap({ listOf(it) }, { listOf(it) }).bisequence() == either.bitraverse({ listOf(it) }, { listOf(it) }) + checkAll(Arb.either(Arb.string(), Arb.int())) { either -> + either.bimap({ listOf(it) }, { listOf(it) }).bisequence() shouldBe either.bitraverse( + { listOf(it) }, + { listOf(it) }) } } @@ -527,8 +518,8 @@ class EitherTest : UnitSpec() { } "bisequenceOption should be consistent with bitraverseOption" { - forAll(Gen.either(Gen.string(), Gen.int())) { either -> - either.bimap({ Some(it) }, { Some(it) }).bisequenceOption() == + checkAll(Arb.either(Arb.string(), Arb.int())) { either -> + either.bimap({ Some(it) }, { Some(it) }).bisequenceOption() shouldBe either.bitraverseOption({ Some(it) }, { Some(it) }) } } @@ -542,8 +533,8 @@ class EitherTest : UnitSpec() { } "bisequenceValidated should be consistent with bitraverseValidated" { - forAll(Gen.either(Gen.string(), Gen.int())) { either -> - either.bimap({ it.invalid() }, { it.valid() }).bisequenceValidated() == + checkAll(Arb.either(Arb.string(), Arb.int())) { either -> + either.bimap({ it.invalid() }, { it.valid() }).bisequenceValidated() shouldBe either.bitraverseValidated({ it.invalid() }, { it.valid() }) } } @@ -563,12 +554,3 @@ private suspend fun throwException( a: A ): Either = throw RuntimeException("An Exception is thrown while handling the result of the supplied function.") - -private fun forAllSmallInt(fn: PropertyContext.(a: Int) -> Boolean) = - forAll(Gen.intSmall(), fn) - -private fun forAllSmallInt(fn: PropertyContext.(a: Int, b: Int) -> Boolean) = - forAll(Gen.intSmall(), Gen.intSmall(), fn) - -private fun forAllSmallInt(fn: PropertyContext.(a: Int, b: Int, c: Int) -> Boolean) = - forAll(Gen.intSmall(), Gen.intSmall(), Gen.intSmall(), fn) diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EndoTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EndoTest.kt index 2f0d9dc2c38..ad1bc172d2e 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EndoTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EndoTest.kt @@ -4,12 +4,13 @@ import arrow.core.test.UnitSpec import arrow.core.test.generators.endo import arrow.core.test.laws.MonoidLaws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.int class EndoTest : UnitSpec() { init { testLaws( - MonoidLaws.laws(Monoid.endo(), Gen.endo(Gen.int())) { a, b -> + MonoidLaws.laws(Monoid.endo(), Arb.endo(Arb.int())) { a, b -> a.f(1) == b.f(1) } ) diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EvalTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EvalTest.kt index 1842d993db6..2e6b019e591 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EvalTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/EvalTest.kt @@ -6,20 +6,25 @@ import arrow.core.computations.eval import arrow.core.test.UnitSpec import arrow.core.test.concurrency.SideEffect import arrow.core.test.laws.FxLaws -import io.kotlintest.fail -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe +import io.kotest.assertions.fail +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.Sample +import io.kotest.property.arbitrary.arbitrary +import io.kotest.property.arbitrary.choice +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.map class EvalTest : UnitSpec() { init { testLaws( - FxLaws.suspended, Eval, Int>(Gen.int().map(Eval.Companion::now), Gen.int().map(Eval.Companion::now), Eval::equals, eval::invoke) { + FxLaws.suspended, Eval, Int>(Arb.int().map(Eval.Companion::now), Arb.int().map(Eval.Companion::now), Eval::equals, eval::invoke) { it.bind() }, - FxLaws.eager, Eval, Int>(Gen.int().map(Eval.Companion::now), Gen.int().map(Eval.Companion::now), Eval::equals, eval::eager) { + FxLaws.eager, Eval, Int>(Arb.int().map(Eval.Companion::now), Arb.int().map(Eval.Companion::now), Eval::equals, eval::eager) { it.bind() } ) @@ -131,10 +136,9 @@ class EvalTest : UnitSpec() { } "stack safety stress test" { - forAll(DeepEval.gen) { d: DeepEval -> + checkAll(DeepEval.gen) { d: DeepEval -> try { d.eval.value() - true } catch (e: StackOverflowError) { fail("stack overflowed with eval-depth ${DeepEval.maxDepth}") } @@ -150,11 +154,11 @@ class EvalTest : UnitSpec() { class Defer : O() companion object { - val gen = Gen.oneOf( - Gen.create { O.Map { it + 1 } }, - Gen.create { O.FlatMap { Eval.Now(it) } }, - Gen.create { O.Memoize() }, - Gen.create { O.Defer() } + val gen = Arb.choice( + arbitrary { O.Map { it + 1 } }, + arbitrary { O.FlatMap { Eval.Now(it) } }, + arbitrary { O.Memoize() }, + arbitrary { O.Defer() } ) } } @@ -182,9 +186,9 @@ class EvalTest : UnitSpec() { step(0, leaf, mutableListOf()) } - val gen = Gen.create { + val gen = arbitrary { rs -> val leaf = { Eval.Now(0) } - val eval = build(leaf, O.gen.random().take(maxDepth).toList()) + val eval = build(leaf, O.gen.samples().map(Sample::value).take(maxDepth).toList()) DeepEval(eval) } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/FunctionSyntaxTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/FunctionSyntaxTest.kt index 0db69bb7a69..8e5746353a8 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/FunctionSyntaxTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/FunctionSyntaxTest.kt @@ -1,7 +1,7 @@ package arrow.core import arrow.core.test.UnitSpec -import io.kotlintest.shouldBe +import io.kotest.matchers.shouldBe class FunctionSyntaxTest : UnitSpec() { diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/IorTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/IorTest.kt index f2cb1285f43..c91a748518f 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/IorTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/IorTest.kt @@ -4,19 +4,24 @@ import arrow.core.test.UnitSpec import arrow.core.test.generators.ior import arrow.core.test.laws.SemigroupLaws import arrow.typeclasses.Semigroup -import io.kotlintest.forAll -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe +import io.kotest.data.forAll +import io.kotest.data.row +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.long +import io.kotest.property.arbitrary.orNull +import io.kotest.property.arbitrary.string class IorTest : UnitSpec() { init { - val GEN = Gen.ior(Gen.string(), Gen.int()) + val ARB = Arb.ior(Arb.string(), Arb.int()) testLaws( - SemigroupLaws.laws(Semigroup.ior(Semigroup.string(), Semigroup.int()), GEN) + SemigroupLaws.laws(Semigroup.ior(Semigroup.string(), Semigroup.int()), ARB) ) val nullableLongSemigroup = object : Semigroup { @@ -25,24 +30,24 @@ class IorTest : UnitSpec() { } "zip identity" { - forAll(Gen.ior(Gen.long().orNull(), Gen.int().orNull())) { ior -> + checkAll(Arb.ior(Arb.long().orNull(), Arb.int().orNull())) { ior -> val res = ior.zip(nullableLongSemigroup, Ior.Right(Unit)) { a, _ -> a } - res == ior + res shouldBe ior } } "zip is derived from flatMap" { - forAll( - Gen.ior(Gen.long().orNull(), Gen.int().orNull()), - Gen.ior(Gen.long().orNull(), Gen.int().orNull()), - Gen.ior(Gen.long().orNull(), Gen.int().orNull()), - Gen.ior(Gen.long().orNull(), Gen.int().orNull()), - Gen.ior(Gen.long().orNull(), Gen.int().orNull()), - Gen.ior(Gen.long().orNull(), Gen.int().orNull()), - Gen.ior(Gen.long().orNull(), Gen.int().orNull()), - Gen.ior(Gen.long().orNull(), Gen.int().orNull()), - Gen.ior(Gen.long().orNull(), Gen.int().orNull()), - Gen.ior(Gen.long().orNull(), Gen.int().orNull()) + checkAll( + Arb.ior(Arb.long().orNull(), Arb.int().orNull()), + Arb.ior(Arb.long().orNull(), Arb.int().orNull()), + Arb.ior(Arb.long().orNull(), Arb.int().orNull()), + Arb.ior(Arb.long().orNull(), Arb.int().orNull()), + Arb.ior(Arb.long().orNull(), Arb.int().orNull()), + Arb.ior(Arb.long().orNull(), Arb.int().orNull()), + Arb.ior(Arb.long().orNull(), Arb.int().orNull()), + Arb.ior(Arb.long().orNull(), Arb.int().orNull()), + Arb.ior(Arb.long().orNull(), Arb.int().orNull()), + Arb.ior(Arb.long().orNull(), Arb.int().orNull()) ) { a, b, c, d, e, f, g, h, i, j -> val res = a.zip( nullableLongSemigroup, @@ -68,7 +73,7 @@ class IorTest : UnitSpec() { mid } - res == expected + res shouldBe expected } } @@ -81,96 +86,96 @@ class IorTest : UnitSpec() { } "bimap() should allow modify both value" { - forAll { a: Int, b: String -> - Ior.Right(b).bimap({ "5" }, { a * 2 }) == Ior.Right(a * 2) && - Ior.Left(a).bimap({ a * 3 }, { "5" }) == Ior.Left(a * 3) && - Ior.Both(a, b).bimap({ 2 }, { "power of $it" }) == Ior.Both(2, "power of $b") + checkAll { a: Int, b: String -> + Ior.Right(b).bimap({ "5" }, { a * 2 }) shouldBe Ior.Right(a * 2) + Ior.Left(a).bimap({ a * 3 }, { "5" }) shouldBe Ior.Left(a * 3) + Ior.Both(a, b).bimap({ 2 }, { "power of $it" }) shouldBe Ior.Both(2, "power of $b") } } "mapLeft() should modify only left value" { - forAll { a: Int, b: String -> - Ior.Right(b).mapLeft { a * 2 } == Ior.Right(b) && - Ior.Left(a).mapLeft { b } == Ior.Left(b) && - Ior.Both(a, b).mapLeft { "power of $it" } == Ior.Both("power of $a", b) + checkAll { a: Int, b: String -> + Ior.Right(b).mapLeft { a * 2 } shouldBe Ior.Right(b) + Ior.Left(a).mapLeft { b } shouldBe Ior.Left(b) + Ior.Both(a, b).mapLeft { "power of $it" } shouldBe Ior.Both("power of $a", b) } } "swap() should interchange value" { - forAll { a: Int, b: String -> - Ior.Both(a, b).swap() == Ior.Both(b, a) + checkAll { a: Int, b: String -> + Ior.Both(a, b).swap() shouldBe Ior.Both(b, a) } } "swap() should interchange entity" { - forAll { a: Int -> - Ior.Left(a).swap() == Ior.Right(a) && - Ior.Right(a).swap() == Ior.Left(a) + checkAll { a: Int -> + Ior.Left(a).swap() shouldBe Ior.Right(a) + Ior.Right(a).swap() shouldBe Ior.Left(a) } } "unwrap() should return the isomorphic either" { - forAll { a: Int, b: String -> - Ior.Left(a).unwrap() == Either.Left(Either.Left(a)) && - Ior.Right(b).unwrap() == Either.Left(Either.Right(b)) && - Ior.Both(a, b).unwrap() == Either.Right(Pair(a, b)) + checkAll { a: Int, b: String -> + Ior.Left(a).unwrap() shouldBe Either.Left(Either.Left(a)) + Ior.Right(b).unwrap() shouldBe Either.Left(Either.Right(b)) + Ior.Both(a, b).unwrap() shouldBe Either.Right(Pair(a, b)) } } "padNull() should return the correct Pair of nullables" { - forAll { a: Int, b: String -> - Ior.Left(a).padNull() == Pair(a, null) && - Ior.Right(b).padNull() == Pair(null, b) && - Ior.Both(a, b).padNull() == Pair(a, b) + checkAll { a: Int, b: String -> + Ior.Left(a).padNull() shouldBe Pair(a, null) + Ior.Right(b).padNull() shouldBe Pair(null, b) + Ior.Both(a, b).padNull() shouldBe Pair(a, b) } } "toEither() should convert values into a valid Either" { - forAll { a: Int, b: String -> - Ior.Left(a).toEither() == Either.Left(a) && - Ior.Right(b).toEither() == Either.Right(b) && - Ior.Both(a, b).toEither() == Either.Right(b) + checkAll { a: Int, b: String -> + Ior.Left(a).toEither() shouldBe Either.Left(a) + Ior.Right(b).toEither() shouldBe Either.Right(b) + Ior.Both(a, b).toEither() shouldBe Either.Right(b) } } "orNull() should convert right values into a nullable" { - forAll { a: Int, b: String -> - Ior.Left(a).orNull() == null && - Ior.Right(b).orNull() == b && - Ior.Both(a, b).orNull() == b + checkAll { a: Int, b: String -> + Ior.Left(a).orNull() shouldBe null + Ior.Right(b).orNull() shouldBe b + Ior.Both(a, b).orNull() shouldBe b } } "leftOrNull() should convert left values into a nullable" { - forAll { a: Int, b: String -> - Ior.Left(a).leftOrNull() == a && - Ior.Right(b).leftOrNull() == null && - Ior.Both(a, b).leftOrNull() == a + checkAll { a: Int, b: String -> + Ior.Left(a).leftOrNull() shouldBe a + Ior.Right(b).leftOrNull() shouldBe null + Ior.Both(a, b).leftOrNull() shouldBe a } } "toValidated() should convert values into a valid Validated" { - forAll { a: Int, b: String -> - Ior.Left(a).toValidated() == Invalid(a) && - Ior.Right(b).toValidated() == Valid(b) && - Ior.Both(a, b).toValidated() == Valid(b) + checkAll { a: Int, b: String -> + Ior.Left(a).toValidated() shouldBe Invalid(a) + Ior.Right(b).toValidated() shouldBe Valid(b) + Ior.Both(a, b).toValidated() shouldBe Valid(b) } } "fromNullables() should build a correct Ior" { - forAll { a: Int, b: String -> - Ior.fromNullables(a, null) == Ior.Left(a) && - Ior.fromNullables(a, b) == Ior.Both(a, b) && - Ior.fromNullables(null, b) == Ior.Right(b) && - Ior.fromNullables(null, null) == null + checkAll { a: Int, b: String -> + Ior.fromNullables(a, null) shouldBe Ior.Left(a) + Ior.fromNullables(a, b) shouldBe Ior.Both(a, b) + Ior.fromNullables(null, b) shouldBe Ior.Right(b) + Ior.fromNullables(null, null) shouldBe null } } "getOrElse() should return value" { - forAll { a: Int, b: Int -> - Ior.Right(a).getOrElse { b } == a && - Ior.Left(a).getOrElse { b } == b && - Ior.Both(a, b).getOrElse { a * 2 } == b + checkAll { a: Int, b: Int -> + Ior.Right(a).getOrElse { b } shouldBe a + Ior.Left(a).getOrElse { b } shouldBe b + Ior.Both(a, b).getOrElse { a * 2 } shouldBe b } } @@ -181,136 +186,133 @@ class IorTest : UnitSpec() { } "combine cases for Semigroup" { - fun case(a: Ior, b: Ior, result: Ior) = listOf(a, b, result) Semigroup.ior(Semigroup.string(), Semigroup.int()).run { forAll( - listOf( - case("Hello, ".leftIor(), Ior.Left("Arrow!"), Ior.Left("Hello, Arrow!")), - case(Ior.Left("Hello"), Ior.Right(2020), Ior.Both("Hello", 2020)), - case(Ior.Left("Hello, "), Ior.Both("number", 1), Ior.Both("Hello, number", 1)), - case(Ior.Right(9000), Ior.Left("Over"), Ior.Both("Over", 9000)), - case(Ior.Right(9000), Ior.Right(1), Ior.Right(9001)), - case(Ior.Right(8000), Ior.Both("Over", 1000), Ior.Both("Over", 9000)), - case(Ior.Both("Hello ", 1), Ior.Left("number"), Ior.Both("Hello number", 1)), - case(Ior.Both("Hello number", 1), Ior.Right(1), Ior.Both("Hello number", 2)), - case(Ior.Both("Hello ", 1), Ior.Both("number", 1), Ior.Both("Hello number", 2)) - ) - ) { (a, b, expectedResult) -> + row("Hello, ".leftIor(), Ior.Left("Arrow!"), Ior.Left("Hello, Arrow!")), + row(Ior.Left("Hello"), Ior.Right(2020), Ior.Both("Hello", 2020)), + row(Ior.Left("Hello, "), Ior.Both("number", 1), Ior.Both("Hello, number", 1)), + row(Ior.Right(9000), Ior.Left("Over"), Ior.Both("Over", 9000)), + row(Ior.Right(9000), Ior.Right(1), Ior.Right(9001)), + row(Ior.Right(8000), Ior.Both("Over", 1000), Ior.Both("Over", 9000)), + row(Ior.Both("Hello ", 1), Ior.Left("number"), Ior.Both("Hello number", 1)), + row(Ior.Both("Hello number", 1), Ior.Right(1), Ior.Both("Hello number", 2)), + row(Ior.Both("Hello ", 1), Ior.Both("number", 1), Ior.Both("Hello number", 2)) + ) { a, b, expectedResult -> a + b shouldBe expectedResult } } } "traverse should wrap ior in a list" { - forAll { a: Int, b: String -> + checkAll { a: Int, b: String -> val iorL: Ior = a.leftIor() val iorR: Ior = b.rightIor() val iorBoth: Ior = (a to b).bothIor() - iorL.traverse { listOf(it) } == listOf(Ior.Left(a)) && - iorR.traverse { listOf(it) } == listOf(Ior.Right(b)) && - iorBoth.traverse { listOf(it) } == listOf(Ior.Both(a, b)) + iorL.traverse { listOf(it) } shouldBe listOf(Ior.Left(a)) + iorR.traverse { listOf(it) } shouldBe listOf(Ior.Right(b)) + iorBoth.traverse { listOf(it) } shouldBe listOf(Ior.Both(a, b)) } } "sequence should be consistent with traverse" { - forAll(Gen.ior(Gen.int(), Gen.string())) { ior -> - ior.map { listOf(it) }.sequence() == ior.traverse { listOf(it) } + checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> + ior.map { listOf(it) }.sequence() shouldBe ior.traverse { listOf(it) } } } "traverseOption should wrap ior in an Option" { - forAll { a: Int, b: String -> + checkAll { a: Int, b: String -> val iorL: Ior = a.leftIor() val iorR: Ior = b.rightIor() val iorBoth: Ior = (a to b).bothIor() - iorL.traverseOption { Some(it) } == Some(Ior.Left(a)) && - iorR.traverseOption { Some(it) } == Some(Ior.Right(b)) && - iorBoth.traverseOption { Some(it) } == Some(Ior.Both(a, b)) + iorL.traverseOption { Some(it) } shouldBe Some(Ior.Left(a)) + iorR.traverseOption { Some(it) } shouldBe Some(Ior.Right(b)) + iorBoth.traverseOption { Some(it) } shouldBe Some(Ior.Both(a, b)) } } "sequenceOption should be consistent with traverseOption" { - forAll(Gen.ior(Gen.int(), Gen.string())) { ior -> - ior.map { Some(it) }.sequenceOption() == ior.traverseOption { Some(it) } + checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> + ior.map { Some(it) }.sequenceOption() shouldBe ior.traverseOption { Some(it) } } } "traverseEither should wrap ior in an Option" { - forAll { a: Int, b: String -> + checkAll { a: Int, b: String -> val iorL: Ior = a.leftIor() val iorR: Ior = b.rightIor() val iorBoth: Ior = (a to b).bothIor() - iorL.traverseEither { it.right() } == Either.Right(Ior.Left(a)) && - iorR.traverseEither { it.right() } == Either.Right(Ior.Right(b)) && - iorBoth.traverseEither { it.right() } == Either.Right(Ior.Both(a, b)) + iorL.traverseEither { it.right() } shouldBe Either.Right(Ior.Left(a)) + iorR.traverseEither { it.right() } shouldBe Either.Right(Ior.Right(b)) + iorBoth.traverseEither { it.right() } shouldBe Either.Right(Ior.Both(a, b)) } } "sequenceEither should be consistent with traverseEither" { - forAll(Gen.ior(Gen.int(), Gen.string())) { ior -> - ior.map { it.right() }.sequenceEither() == ior.traverseEither { it.right() } + checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> + ior.map { it.right() }.sequenceEither() shouldBe ior.traverseEither { it.right() } } } "bitraverse should wrap ior in a list" { - forAll { a: Int, b: String -> + checkAll { a: Int, b: String -> val iorL: Ior = a.leftIor() val iorR: Ior = b.rightIor() val iorBoth: Ior = (a to b).bothIor() println(iorBoth.bitraverse({ listOf(it, 2, 3) }, { listOf(it) })) - iorL.bitraverse({ listOf(it, 2, 3) }, { listOf(it) }) == listOf(Ior.Left(a), Ior.Left(2), Ior.Left(3)) && - iorR.bitraverse({ listOf(it, 2, 3) }, { listOf(it) }) == listOf(Ior.Right(b)) && - iorBoth.bitraverse({ listOf(it, 2, 3) }, { listOf(it, 4, 5) }) == + iorL.bitraverse({ listOf(it, 2, 3) }, { listOf(it) }) shouldBe listOf(Ior.Left(a), Ior.Left(2), Ior.Left(3)) + iorR.bitraverse({ listOf(it, 2, 3) }, { listOf(it) }) shouldBe listOf(Ior.Right(b)) + iorBoth.bitraverse({ listOf(it, 2, 3) }, { listOf(it, 4, 5) }) shouldBe listOf(Ior.Both(a, b), Ior.Both(2, 4), Ior.Both(3, 5)) } } "bisequence should be consistent with bitraverse" { - forAll(Gen.ior(Gen.int(), Gen.string())) { ior -> - ior.bimap({ listOf(it) }, { listOf(it) }).bisequence() == + checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> + ior.bimap({ listOf(it) }, { listOf(it) }).bisequence() shouldBe ior.bitraverse({ listOf(it) }, { listOf(it) }) } } "bitraverseOption should wrap ior in an Option" { - forAll { a: Int, b: String -> + checkAll { a: Int, b: String -> val iorL: Ior = a.leftIor() val iorR: Ior = b.rightIor() val iorBoth: Ior = (a to b).bothIor() - iorL.bitraverseOption({ None }, { Some(it) }) == None && - iorR.bitraverseOption({ None }, { Some(it) }) == Some(Ior.Right(b)) && - iorBoth.bitraverseOption({ None }, { Some(it) }) == None + iorL.bitraverseOption({ None }, { Some(it) }) shouldBe None + iorR.bitraverseOption({ None }, { Some(it) }) shouldBe Some(Ior.Right(b)) + iorBoth.bitraverseOption({ None }, { Some(it) }) shouldBe None } } "bisequenceOption should be consistent with bitraverseOption" { - forAll(Gen.ior(Gen.int(), Gen.string())) { ior -> - ior.bimap({ None }, { Some(it) }).bisequenceOption() == + checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> + ior.bimap({ None }, { Some(it) }).bisequenceOption() shouldBe ior.bitraverseOption({ None }, { Some(it) }) } } "bitraverseEither should wrap ior in an Either" { - forAll { a: Int, b: String -> + checkAll { a: Int, b: String -> val iorL: Ior = a.leftIor() val iorR: Ior = b.rightIor() val iorBoth: Ior = (a to b).bothIor() - iorL.bitraverseEither({ it.left() }, { it.right() }) == Either.Left(a) && - iorR.bitraverseEither({ it.left() }, { it.right() }) == Either.Right(Ior.Right(b)) && - iorBoth.bitraverseEither({ it.left() }, { it.right() }) == Either.Left(a) + iorL.bitraverseEither({ it.left() }, { it.right() }) shouldBe Either.Left(a) + iorR.bitraverseEither({ it.left() }, { it.right() }) shouldBe Either.Right(Ior.Right(b)) + iorBoth.bitraverseEither({ it.left() }, { it.right() }) shouldBe Either.Left(a) } } "bisequenceEither should be consistent with bitraverseEither" { - forAll(Gen.ior(Gen.int(), Gen.string())) { ior -> - ior.bimap({ it.left() }, { it.right() }).bisequenceEither() == + checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> + ior.bimap({ it.left() }, { it.right() }).bisequenceEither() shouldBe ior.bitraverseEither({ it.left() }, { it.right() }) } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/IterableTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/IterableTest.kt index 66aee8a6c3c..e571b0fe1d3 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/IterableTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/IterableTest.kt @@ -2,11 +2,13 @@ package arrow.core import arrow.core.test.UnitSpec import arrow.core.test.generators.option -import arrow.core.test.laws.equalUnderTheLaw import arrow.typeclasses.Semigroup -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list import kotlin.math.max import kotlin.math.min @@ -24,7 +26,7 @@ class IterableTest : UnitSpec() { } "traverseEither short-circuit" { - forAll(Gen.list(Gen.int())) { ints -> + checkAll(Arb.list(Arb.int())) { ints -> val acc = mutableListOf() val evens = ints.traverseEither { if (it % 2 == 0) { @@ -32,17 +34,17 @@ class IterableTest : UnitSpec() { Either.Right(it) } else Either.Left(it) } - acc == ints.takeWhile { it % 2 == 0 } && - when (evens) { - is Either.Right -> evens.value == ints - is Either.Left -> evens.value == ints.first { it % 2 != 0 } - } + acc shouldBe ints.takeWhile { it % 2 == 0 } + when (evens) { + is Either.Right -> evens.value shouldBe ints + is Either.Left -> evens.value shouldBe ints.first { it % 2 != 0 } + } } } "sequenceEither should be consistent with traverseEither" { - forAll(Gen.list(Gen.int())) { ints -> - ints.map { it.right() }.sequenceEither() == ints.traverseEither { it.right() } + checkAll(Arb.list(Arb.int())) { ints -> + ints.map { it.right() }.sequenceEither() shouldBe ints.traverseEither { it.right() } } } @@ -58,7 +60,7 @@ class IterableTest : UnitSpec() { } "traverseOption short-circuits" { - forAll(Gen.list(Gen.int())) { ints -> + checkAll(Arb.list(Arb.int())) { ints -> val acc = mutableListOf() val evens = ints.traverseOption { (it % 2 == 0).maybe { @@ -66,20 +68,21 @@ class IterableTest : UnitSpec() { it } } - acc == ints.takeWhile { it % 2 == 0 } && evens.all { it == ints } + acc shouldBe ints.takeWhile { it % 2 == 0 } + evens.fold({ Unit }) { it shouldBe ints } } } "sequenceOption yields some when all entries in the list are some" { - forAll(Gen.list(Gen.int())) { ints -> + checkAll(Arb.list(Arb.int())) { ints -> val evens = ints.map { (it % 2 == 0).maybe { it } }.sequenceOption() - evens.all { it == ints } + evens.fold({ Unit }) { it shouldBe ints } } } "sequenceOption should be consistent with traverseOption" { - forAll(Gen.list(Gen.int())) { ints -> - ints.map { Some(it) }.sequenceOption() == ints.traverseOption { Some(it) } + checkAll(Arb.list(Arb.int())) { ints -> + ints.map { Some(it) }.sequenceOption() shouldBe ints.traverseOption { Some(it) } } } @@ -95,50 +98,50 @@ class IterableTest : UnitSpec() { } "traverseValidated acummulates" { - forAll(Gen.list(Gen.int())) { ints -> + checkAll(Arb.list(Arb.int())) { ints -> val res: ValidatedNel> = ints.map { i -> if (i % 2 == 0) i.validNel() else i.invalidNel() } .sequenceValidated() val expected: ValidatedNel> = NonEmptyList.fromList(ints.filterNot { it % 2 == 0 }) .fold({ ints.filter { it % 2 == 0 }.validNel() }, { it.invalid() }) - res == expected + res shouldBe expected } } "sequenceValidated should be consistent with traverseValidated" { - forAll(Gen.list(Gen.int())) { ints -> - ints.map { it.valid() as Validated }.sequenceValidated(Semigroup.string()) == - ints.traverseValidated(Semigroup.string()) { it.valid() as Validated } + checkAll(Arb.list(Arb.int())) { ints -> + ints.map { it.valid() }.sequenceValidated(Semigroup.string()) shouldBe + ints.traverseValidated(Semigroup.string()) { it.valid() } } } "zip3" { - forAll(Gen.list(Gen.int()), Gen.list(Gen.int()), Gen.list(Gen.int())) { a, b, c -> + checkAll(Arb.list(Arb.int()), Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b, c -> val result = a.zip(b, c, ::Triple) val expected = a.zip(b, ::Pair).zip(c) { (a, b), c -> Triple(a, b, c) } - result == expected + result shouldBe expected } } "zip4" { - forAll(Gen.list(Gen.int()), Gen.list(Gen.int()), Gen.list(Gen.int()), Gen.list(Gen.int())) { a, b, c, d -> + checkAll(Arb.list(Arb.int()), Arb.list(Arb.int()), Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b, c, d -> val result = a.zip(b, c, d, ::Tuple4) val expected = a.zip(b, ::Pair) .zip(c) { (a, b), c -> Triple(a, b, c) } .zip(d) { (a, b, c), d -> Tuple4(a, b, c, d) } - result == expected + result shouldBe expected } } "zip5" { - forAll( - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()) + checkAll( + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()) ) { a, b, c, d, e -> val result = a.zip(b, c, d, e, ::Tuple5) val expected = a.zip(b, ::Pair) @@ -146,18 +149,18 @@ class IterableTest : UnitSpec() { .zip(d) { (a, b, c), d -> Tuple4(a, b, c, d) } .zip(e) { (a, b, c, d), e -> Tuple5(a, b, c, d, e) } - result == expected + result shouldBe expected } } "zip6" { - forAll( - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()) + checkAll( + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()) ) { a, b, c, d, e, f -> val result = a.zip(b, c, d, e, f, ::Tuple6) val expected = a.zip(b, ::Pair) @@ -166,19 +169,19 @@ class IterableTest : UnitSpec() { .zip(e) { (a, b, c, d), e -> Tuple5(a, b, c, d, e) } .zip(f) { (a, b, c, d, e), f -> Tuple6(a, b, c, d, e, f) } - result == expected + result shouldBe expected } } "zip7" { - forAll( - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()) + checkAll( + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()) ) { a, b, c, d, e, f, g -> val result = a.zip(b, c, d, e, f, g, ::Tuple7) val expected = a.zip(b, ::Pair) @@ -188,20 +191,20 @@ class IterableTest : UnitSpec() { .zip(f) { (a, b, c, d, e), f -> Tuple6(a, b, c, d, e, f) } .zip(g) { (a, b, c, d, e, f), g -> Tuple7(a, b, c, d, e, f, g) } - result == expected + result shouldBe expected } } "zip8" { - forAll( - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()) + checkAll( + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()) ) { a, b, c, d, e, f, g, h -> val result = a.zip(b, c, d, e, f, g, h, ::Tuple8) val expected = a.zip(b, ::Pair) @@ -212,21 +215,21 @@ class IterableTest : UnitSpec() { .zip(g) { (a, b, c, d, e, f), g -> Tuple7(a, b, c, d, e, f, g) } .zip(h) { (a, b, c, d, e, f, g), h -> Tuple8(a, b, c, d, e, f, g, h) } - result == expected + result shouldBe expected } } "zip9" { - forAll( - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()) + checkAll( + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()) ) { a, b, c, d, e, f, g, h, i -> val result = a.zip(b, c, d, e, f, g, h, i, ::Tuple9) val expected = a.zip(b, ::Pair) @@ -238,22 +241,22 @@ class IterableTest : UnitSpec() { .zip(h) { (a, b, c, d, e, f, g), h -> Tuple8(a, b, c, d, e, f, g, h) } .zip(i) { (a, b, c, d, e, f, g, h), i -> Tuple9(a, b, c, d, e, f, g, h, i) } - result == expected + result shouldBe expected } } "zip10" { - forAll( - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()), - Gen.list(Gen.int()) + checkAll( + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()), + Arb.list(Arb.int()) ) { a, b, c, d, e, f, g, h, i, j -> val result = a.zip(b, c, d, e, f, g, h, i, j, ::Tuple10) val expected = a.zip(b, ::Pair) @@ -266,104 +269,104 @@ class IterableTest : UnitSpec() { .zip(i) { (a, b, c, d, e, f, g, h), i -> Tuple9(a, b, c, d, e, f, g, h, i) } .zip(j) { (a, b, c, d, e, f, g, h, i), j -> Tuple10(a, b, c, d, e, f, g, h, i, j) } - result == expected + result shouldBe expected } } "can align lists with different lengths" { - forAll(Gen.list(Gen.bool()), Gen.list(Gen.bool())) { a, b -> - a.align(b).size == max(a.size, b.size) + checkAll(Arb.list(Arb.bool()), Arb.list(Arb.bool())) { a, b -> + a.align(b).size shouldBe max(a.size, b.size) } - forAll(Gen.list(Gen.bool()), Gen.list(Gen.bool())) { a, b -> - a.align(b).take(min(a.size, b.size)).all { - it.isBoth + checkAll(Arb.list(Arb.bool()), Arb.list(Arb.bool())) { a, b -> + a.align(b).take(min(a.size, b.size)).forEach { + it.isBoth shouldBe true } } - forAll(Gen.list(Gen.bool()), Gen.list(Gen.bool())) { a, b -> - a.align(b).drop(min(a.size, b.size)).all { + checkAll(Arb.list(Arb.bool()), Arb.list(Arb.bool())) { a, b -> + a.align(b).drop(min(a.size, b.size)).forEach { if (a.size < b.size) { - it.isRight + it.isRight shouldBe true } else { - it.isLeft + it.isLeft shouldBe true } } } } "leftPadZip (with map)" { - forAll(Gen.list(Gen.int()), Gen.list(Gen.int())) { a, b -> + checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } val result = a.leftPadZip(b) { a, b -> a to b } - result == left.zip(right) { l, r -> l to r }.filter { it.second != null } + result shouldBe left.zip(right) { l, r -> l to r }.filter { it.second != null } } } "leftPadZip (without map)" { - forAll(Gen.list(Gen.int()), Gen.list(Gen.int())) { a, b -> + checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } val result = a.leftPadZip(b) - result == left.zip(right) { l, r -> l to r }.filter { it.second != null } + result shouldBe left.zip(right) { l, r -> l to r }.filter { it.second != null } } } "rightPadZip (without map)" { - forAll(Gen.list(Gen.int()), Gen.list(Gen.int())) { a, b -> + checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } val result = a.rightPadZip(b) - result == left.zip(right) { l, r -> l to r }.filter { it.first != null } && - result.map { it.first }.equalUnderTheLaw(a) + result shouldBe left.zip(right) { l, r -> l to r }.filter { it.first != null } + result.map { it.first } shouldBe a } } "rightPadZip (with map)" { - forAll(Gen.list(Gen.int()), Gen.list(Gen.int())) { a, b -> + checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } val result = a.rightPadZip(b) { a, b -> a to b } - result == left.zip(right) { l, r -> l to r }.filter { it.first != null } && - result.map { it.first }.equalUnderTheLaw(a) + result shouldBe left.zip(right) { l, r -> l to r }.filter { it.first != null } + result.map { it.first } shouldBe a } } "padZip" { - forAll(Gen.list(Gen.int()), Gen.list(Gen.int())) { a, b -> + checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } - a.padZip(b) { l, r -> Ior.fromNullables(l, r) } == left.zip(right) { l, r -> Ior.fromNullables(l, r) } + a.padZip(b) { l, r -> Ior.fromNullables(l, r) } shouldBe left.zip(right) { l, r -> Ior.fromNullables(l, r) } } } "padZipWithNull" { - forAll(Gen.list(Gen.int()), Gen.list(Gen.int())) { a, b -> + checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } - a.padZip(b) == left.zip(right) { l, r -> l to r } + a.padZip(b) shouldBe left.zip(right) { l, r -> l to r } } } "filterOption" { - forAll(Gen.list(Gen.option(Gen.int()))) { listOfOption -> - listOfOption.filterOption() == listOfOption.mapNotNull { it.orNull() } + checkAll(Arb.list(Arb.option(Arb.int()))) { listOfOption -> + listOfOption.filterOption() shouldBe listOfOption.mapNotNull { it.orNull() } } } "flattenOption" { - forAll(Gen.list(Gen.option(Gen.int()))) { listOfOption -> - listOfOption.flattenOption() == listOfOption.mapNotNull { it.orNull() } + checkAll(Arb.list(Arb.option(Arb.int()))) { listOfOption -> + listOfOption.flattenOption() shouldBe listOfOption.mapNotNull { it.orNull() } } } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ListKTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ListKTest.kt index 04596cd8b40..784df77e0a9 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ListKTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ListKTest.kt @@ -3,23 +3,26 @@ package arrow.core import arrow.core.test.UnitSpec import arrow.core.test.laws.MonoidLaws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.checkAll class ListKTest : UnitSpec() { init { - testLaws(MonoidLaws.laws(Monoid.list(), Gen.list(Gen.int()))) + testLaws(MonoidLaws.laws(Monoid.list(), Arb.list(Arb.int()))) "mapNotNull() should map list and filter out null values" { - forAll(Gen.list(Gen.int())) { listk -> + checkAll(Arb.list(Arb.int())) { listk -> listk.mapNotNull { when (it % 2 == 0) { true -> it.toString() else -> null } - } == listk.toList().filter { it % 2 == 0 }.map { it.toString() } + } shouldBe listk.toList().filter { it % 2 == 0 }.map { it.toString() } } } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/MapKTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/MapKTest.kt index 63713771997..414dab8d1e3 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/MapKTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/MapKTest.kt @@ -7,14 +7,20 @@ import arrow.core.test.generators.nonEmptyList import arrow.core.test.laws.MonoidLaws import arrow.typeclasses.Monoid import arrow.typeclasses.Semigroup -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.long +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.string class MapKTest : UnitSpec() { init { - testLaws(MonoidLaws.laws(Monoid.map(Semigroup.int()), Gen.map(Gen.longSmall(), Gen.intSmall()))) + testLaws(MonoidLaws.laws(Monoid.map(Semigroup.int()), Arb.map(Arb.longSmall(), Arb.intSmall()))) "traverseEither is stacksafe" { val acc = mutableListOf() @@ -27,7 +33,7 @@ class MapKTest : UnitSpec() { } "traverseEither short-circuit" { - forAll(Gen.map(Gen.int(), Gen.int())) { ints -> + checkAll(Arb.map(Arb.int(), Arb.int())) { ints -> val acc = mutableListOf() val evens = ints.traverseEither { if (it % 2 == 0) { @@ -35,11 +41,11 @@ class MapKTest : UnitSpec() { Either.Right(it) } else Either.Left(it) } - acc == ints.values.takeWhile { it % 2 == 0 } && - when (evens) { - is Either.Right -> evens.value == ints - is Either.Left -> evens.value == ints.values.first { it % 2 != 0 } - } + acc shouldBe ints.values.takeWhile { it % 2 == 0 } + when (evens) { + is Either.Right -> evens.value shouldBe ints + is Either.Left -> evens.value shouldBe ints.values.first { it % 2 != 0 } + } } } @@ -55,7 +61,7 @@ class MapKTest : UnitSpec() { } "traverseOption short-circuits" { - forAll(Gen.nonEmptyList(Gen.int())) { ints -> + checkAll(Arb.nonEmptyList(Arb.int())) { ints -> val acc = mutableListOf() val evens = ints.traverseOption { (it % 2 == 0).maybe { @@ -63,14 +69,15 @@ class MapKTest : UnitSpec() { it } } - acc == ints.takeWhile { it % 2 == 0 } && evens.all { it == ints } + acc shouldBe ints.takeWhile { it % 2 == 0 } + evens.fold({ Unit }) { it shouldBe ints } } } "sequenceOption yields some when all entries in the list are some" { - forAll(Gen.list(Gen.int())) { ints -> + checkAll(Arb.list(Arb.int())) { ints -> val evens = ints.map { (it % 2 == 0).maybe { it } }.sequenceOption() - evens.all { it == ints } + evens.fold({ Unit }) { it shouldBe ints } } } @@ -85,68 +92,70 @@ class MapKTest : UnitSpec() { } "traverseValidated acummulates" { - forAll(Gen.map(Gen.int(), Gen.int())) { ints -> + checkAll(Arb.map(Arb.int(), Arb.int())) { ints -> val res: ValidatedNel> = ints.traverseValidated(Semigroup.nonEmptyList()) { i -> if (i % 2 == 0) i.validNel() else i.invalidNel() } val expected: ValidatedNel> = NonEmptyList.fromList(ints.values.filterNot { it % 2 == 0 }) - .fold({ ints.entries.filter { (_, v) -> v % 2 == 0 }.map { (k, v) -> k to v }.toMap().validNel() }, { it.invalid() }) + .fold( + { ints.entries.filter { (_, v) -> v % 2 == 0 }.map { (k, v) -> k to v }.toMap().validNel() }, + { it.invalid() }) - res == expected + res shouldBe expected } } "can align maps" { // aligned keySet is union of a's and b's keys - forAll(Gen.map(Gen.long(), Gen.bool()), Gen.map(Gen.long(), Gen.bool())) { a, b -> + checkAll(Arb.map(Arb.long(), Arb.bool()), Arb.map(Arb.long(), Arb.bool())) { a, b -> val aligned = a.align(b) - aligned.size == (a.keys + b.keys).size + aligned.size shouldBe (a.keys + b.keys).size } // aligned map contains Both for all entries existing in a and b - forAll(Gen.map(Gen.long(), Gen.bool()), Gen.map(Gen.long(), Gen.bool())) { a, b -> + checkAll(Arb.map(Arb.long(), Arb.bool()), Arb.map(Arb.long(), Arb.bool())) { a, b -> val aligned = a.align(b) - a.keys.intersect(b.keys).all { - aligned[it]?.isBoth ?: false + a.keys.intersect(b.keys).forEach { + aligned[it]?.isBoth shouldBe true } } // aligned map contains Left for all entries existing only in a - forAll(Gen.map(Gen.long(), Gen.bool()), Gen.map(Gen.long(), Gen.bool())) { a, b -> + checkAll(Arb.map(Arb.long(), Arb.bool()), Arb.map(Arb.long(), Arb.bool())) { a, b -> val aligned = a.align(b) - (a.keys - b.keys).all { key -> - aligned[key]?.let { it.isLeft } ?: false + (a.keys - b.keys).forEach { key -> + aligned[key]?.isLeft shouldBe true } } // aligned map contains Right for all entries existing only in b - forAll(Gen.map(Gen.long(), Gen.bool()), Gen.map(Gen.long(), Gen.bool())) { a, b -> + checkAll(Arb.map(Arb.long(), Arb.bool()), Arb.map(Arb.long(), Arb.bool())) { a, b -> val aligned = a.align(b) - (b.keys - a.keys).all { key -> - aligned[key]?.isRight ?: false + (b.keys - a.keys).forEach { key -> + aligned[key]?.isRight shouldBe true } } } "zip2" { - forAll( - Gen.map(Gen.intSmall(), Gen.intSmall()), - Gen.map(Gen.intSmall(), Gen.intSmall()) + checkAll( + Arb.map(Arb.intSmall(), Arb.intSmall()), + Arb.map(Arb.intSmall(), Arb.intSmall()) ) { a, b -> val result = a.zip(b) { _, aa, bb -> Pair(aa, bb) } val expected = a.filter { (k, _) -> b.containsKey(k) } .map { (k, v) -> Pair(k, Pair(v, b[k]!!)) } .toMap() - result == expected + result shouldBe expected } } "zip3" { - forAll( - Gen.map(Gen.intSmall(), Gen.intSmall()), - Gen.map(Gen.intSmall(), Gen.intSmall()) + checkAll( + Arb.map(Arb.intSmall(), Arb.intSmall()), + Arb.map(Arb.intSmall(), Arb.intSmall()) ) { a, b -> val result = a.zip(b, b) { _, aa, bb, cc -> Triple(aa, bb, cc) } @@ -154,14 +163,14 @@ class MapKTest : UnitSpec() { .map { (k, v) -> Pair(k, Triple(v, b[k]!!, b[k]!!)) } .toMap() - result == expected + result shouldBe expected } } "zip4" { - forAll( - Gen.map(Gen.intSmall(), Gen.intSmall()), - Gen.map(Gen.intSmall(), Gen.intSmall()), + checkAll( + Arb.map(Arb.intSmall(), Arb.intSmall()), + Arb.map(Arb.intSmall(), Arb.intSmall()), ) { a, b -> val result = a.zip(b, b, b) { _, aa, bb, cc, dd -> Tuple4(aa, bb, cc, dd) } @@ -169,14 +178,14 @@ class MapKTest : UnitSpec() { .map { (k, v) -> Pair(k, Tuple4(v, b[k]!!, b[k]!!, b[k]!!)) } .toMap() - result == expected + result shouldBe expected } } "zip5" { - forAll( - Gen.map(Gen.intSmall(), Gen.intSmall()), - Gen.map(Gen.intSmall(), Gen.intSmall()), + checkAll( + Arb.map(Arb.intSmall(), Arb.intSmall()), + Arb.map(Arb.intSmall(), Arb.intSmall()), ) { a, b -> val result = a.zip(b, b, b, b) { _, aa, bb, cc, dd, ee -> Tuple5(aa, bb, cc, dd, ee) } @@ -184,14 +193,14 @@ class MapKTest : UnitSpec() { .map { (k, v) -> Pair(k, Tuple5(v, b[k]!!, b[k]!!, b[k]!!, b[k]!!)) } .toMap() - result == expected + result shouldBe expected } } "zip6" { - forAll( - Gen.map(Gen.intSmall(), Gen.intSmall()), - Gen.map(Gen.intSmall(), Gen.intSmall()), + checkAll( + Arb.map(Arb.intSmall(), Arb.intSmall()), + Arb.map(Arb.intSmall(), Arb.intSmall()), ) { a, b -> val result = a.zip(b, b, b, b, b) { _, aa, bb, cc, dd, ee, ff -> Tuple6(aa, bb, cc, dd, ee, ff) } @@ -199,14 +208,14 @@ class MapKTest : UnitSpec() { .map { (k, v) -> Pair(k, Tuple6(v, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!)) } .toMap() - result == expected + result shouldBe expected } } "zip7" { - forAll( - Gen.map(Gen.intSmall(), Gen.intSmall()), - Gen.map(Gen.intSmall(), Gen.intSmall()) + checkAll( + Arb.map(Arb.intSmall(), Arb.intSmall()), + Arb.map(Arb.intSmall(), Arb.intSmall()) ) { a, b -> val result = a.zip(b, b, b, b, b, b) { _, aa, bb, cc, dd, ee, ff, gg -> Tuple7(aa, bb, cc, dd, ee, ff, gg) } @@ -214,14 +223,14 @@ class MapKTest : UnitSpec() { .map { (k, v) -> Pair(k, Tuple7(v, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!)) } .toMap() - result == expected + result shouldBe expected } } "zip8" { - forAll( - Gen.map(Gen.intSmall(), Gen.intSmall()), - Gen.map(Gen.intSmall(), Gen.intSmall()) + checkAll( + Arb.map(Arb.intSmall(), Arb.intSmall()), + Arb.map(Arb.intSmall(), Arb.intSmall()) ) { a, b -> val result = a.zip(b, b, b, b, b, b, b) { _, aa, bb, cc, dd, ee, ff, gg, hh -> Tuple8(aa, bb, cc, dd, ee, ff, gg, hh) } @@ -230,14 +239,14 @@ class MapKTest : UnitSpec() { .map { (k, v) -> Pair(k, Tuple8(v, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!)) } .toMap() - result == expected + result shouldBe expected } } "zip9" { - forAll( - Gen.map(Gen.intSmall(), Gen.intSmall()), - Gen.map(Gen.intSmall(), Gen.intSmall()) + checkAll( + Arb.map(Arb.intSmall(), Arb.intSmall()), + Arb.map(Arb.intSmall(), Arb.intSmall()) ) { a, b -> val result = a.zip(b, b, b, b, b, b, b, b) { _, aa, bb, cc, dd, ee, ff, gg, hh, ii -> Tuple9( @@ -257,14 +266,14 @@ class MapKTest : UnitSpec() { .map { (k, v) -> Pair(k, Tuple9(v, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!)) } .toMap() - result == expected + result shouldBe expected } } "zip10" { - forAll( - Gen.map(Gen.intSmall(), Gen.intSmall()), - Gen.map(Gen.intSmall(), Gen.intSmall()) + checkAll( + Arb.map(Arb.intSmall(), Arb.intSmall()), + Arb.map(Arb.intSmall(), Arb.intSmall()) ) { a, b -> val result = a.zip(b, b, b, b, b, b, b, b, b) { _, aa, bb, cc, dd, ee, ff, gg, hh, ii, jj -> Tuple10( @@ -285,20 +294,20 @@ class MapKTest : UnitSpec() { .map { (k, v) -> Pair(k, Tuple10(v, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!)) } .toMap() - result == expected + result shouldBe expected } } "flatMap" { - forAll( - Gen.map(Gen.string(), Gen.intSmall()), - Gen.map(Gen.string(), Gen.string()) + checkAll( + Arb.map(Arb.string(), Arb.intSmall()), + Arb.map(Arb.string(), Arb.string()) ) { a, b -> val result: Map = a.flatMap { b } val expected: Map = a.filter { (k, _) -> b.containsKey(k) } - .map { (k, v) -> Pair(k, b[k]!!) } + .map { (k, _) -> Pair(k, b[k]!!) } .toMap() - result == expected + result shouldBe expected } } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/MemoizationTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/MemoizationTest.kt index ec4d0cfd63b..ba09b4821f5 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/MemoizationTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/MemoizationTest.kt @@ -1,31 +1,28 @@ package arrow.core -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe -import io.kotlintest.specs.FreeSpec +import io.kotest.core.spec.style.FreeSpec +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.runBlocking import kotlin.random.Random class MemoizationTest : FreeSpec() { init { "Memoize races" { - forAll { - runBlocking { - fun sum(): Int = - Random.nextInt(Int.MAX_VALUE) + checkAll { + fun sum(): Int = + Random.nextInt(Int.MAX_VALUE) - val memoized = ::sum.memoize() + val memoized = ::sum.memoize() - val (first, second) = listOf( - async { memoized() }, - async { memoized() } - ).awaitAll() + val (first, second) = listOf( + async { memoized() }, + async { memoized() } + ).awaitAll() - first == second - } + first shouldBe second } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NonEmptyListTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NonEmptyListTest.kt index 27e2cff8a60..1184a04b05e 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NonEmptyListTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NonEmptyListTest.kt @@ -4,16 +4,18 @@ import arrow.core.test.UnitSpec import arrow.core.test.generators.nonEmptyList import arrow.core.test.laws.SemigroupLaws import arrow.typeclasses.Semigroup -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.int import kotlin.math.max import kotlin.math.min class NonEmptyListTest : UnitSpec() { init { - testLaws(SemigroupLaws.laws(Semigroup.nonEmptyList(), Gen.nonEmptyList(Gen.int()))) + testLaws(SemigroupLaws.laws(Semigroup.nonEmptyList(), Arb.nonEmptyList(Arb.int()))) "traverseEither stack-safe" { // also verifies result order and execution order (l to r) @@ -27,7 +29,7 @@ class NonEmptyListTest : UnitSpec() { } "traverseEither short-circuit" { - forAll(Gen.nonEmptyList(Gen.int())) { ints -> + checkAll(Arb.nonEmptyList(Arb.int())) { ints -> val acc = mutableListOf() val evens = ints.traverseEither { if (it % 2 == 0) { @@ -35,17 +37,17 @@ class NonEmptyListTest : UnitSpec() { Either.Right(it) } else Either.Left(it) } - acc == ints.takeWhile { it % 2 == 0 } && - when (evens) { - is Either.Right -> evens.value == ints - is Either.Left -> evens.value == ints.first { it % 2 != 0 } - } + acc shouldBe ints.takeWhile { it % 2 == 0 } + when (evens) { + is Either.Right -> evens.value shouldBe ints + is Either.Left -> evens.value shouldBe ints.first { it % 2 != 0 } + } } } "sequenceEither should be consistent with traverseEither" { - forAll(Gen.nonEmptyList(Gen.int())) { ints -> - ints.map { Either.conditionally(it % 2 == 0, { it }, { it }) }.sequenceEither() == + checkAll(Arb.nonEmptyList(Arb.int())) { ints -> + ints.map { Either.conditionally(it % 2 == 0, { it }, { it }) }.sequenceEither() shouldBe ints.traverseEither { Either.conditionally(it % 2 == 0, { it }, { it }) } } } @@ -62,7 +64,7 @@ class NonEmptyListTest : UnitSpec() { } "traverseOption short-circuits" { - forAll(Gen.nonEmptyList(Gen.int())) { ints -> + checkAll(Arb.nonEmptyList(Arb.int())) { ints -> val acc = mutableListOf() val evens = ints.traverseOption { (it % 2 == 0).maybe { @@ -70,20 +72,21 @@ class NonEmptyListTest : UnitSpec() { it } } - acc == ints.takeWhile { it % 2 == 0 } && evens.all { it == ints } + acc shouldBe ints.takeWhile { it % 2 == 0 } + evens.fold({ Unit }) { it shouldBe ints } } } "sequenceOption yields some when all entries in the list are some" { - forAll(Gen.nonEmptyList(Gen.int())) { ints -> + checkAll(Arb.nonEmptyList(Arb.int())) { ints -> val evens = ints.map { (it % 2 == 0).maybe { it } }.sequenceOption() - evens.all { it == ints } + evens.fold({ Unit }) { it shouldBe ints } } } "sequenceOption should be consistent with traverseOption" { - forAll(Gen.nonEmptyList(Gen.int())) { ints -> - ints.map { (it % 2 == 0).maybe { it } }.sequenceOption() == + checkAll(Arb.nonEmptyList(Arb.int())) { ints -> + ints.map { (it % 2 == 0).maybe { it } }.sequenceOption() shouldBe ints.traverseOption { (it % 2 == 0).maybe { it } } } } @@ -100,165 +103,170 @@ class NonEmptyListTest : UnitSpec() { } "traverseValidated acummulates" { - forAll(Gen.nonEmptyList(Gen.int())) { ints -> + checkAll(Arb.nonEmptyList(Arb.int())) { ints -> val res: ValidatedNel> = ints.traverseValidated(Semigroup.nonEmptyList()) { i -> if (i % 2 == 0) i.validNel() else i.invalidNel() } val expected: ValidatedNel> = NonEmptyList.fromList(ints.filterNot { it % 2 == 0 }) .fold({ NonEmptyList.fromListUnsafe(ints.filter { it % 2 == 0 }).validNel() }, { it.invalid() }) - res == expected + res shouldBe expected } } "sequenceValidated should be consistent with traverseValidated" { - forAll(Gen.nonEmptyList(Gen.int())) { ints -> - ints.map { if (it % 2 == 0) it.valid() else it.invalid() }.sequenceValidated(Semigroup.int()) == + checkAll(Arb.nonEmptyList(Arb.int())) { ints -> + ints.map { if (it % 2 == 0) it.valid() else it.invalid() }.sequenceValidated(Semigroup.int()) shouldBe ints.traverseValidated(Semigroup.int()) { if (it % 2 == 0) it.valid() else it.invalid() } } } "can align lists with different lengths" { - forAll(Gen.nonEmptyList(Gen.bool()), Gen.nonEmptyList(Gen.bool())) { a, b -> - a.align(b).size == max(a.size, b.size) + checkAll(Arb.nonEmptyList(Arb.bool()), Arb.nonEmptyList(Arb.bool())) { a, b -> + a.align(b).size shouldBe max(a.size, b.size) } - forAll(Gen.nonEmptyList(Gen.bool()), Gen.nonEmptyList(Gen.bool())) { a, b -> - a.align(b).all.take(min(a.size, b.size)).all { - it.isBoth + checkAll(Arb.nonEmptyList(Arb.bool()), Arb.nonEmptyList(Arb.bool())) { a, b -> + a.align(b).all.take(min(a.size, b.size)).forEach { + it.isBoth shouldBe true } } } "zip2" { - forAll(Gen.nonEmptyList(Gen.int()), Gen.nonEmptyList(Gen.int())) { a, b -> + checkAll(Arb.nonEmptyList(Arb.int()), Arb.nonEmptyList(Arb.int())) { a, b -> val result = a.zip(b) val expected = a.all.zip(b.all).let(NonEmptyList.Companion::fromListUnsafe) - result == expected + result shouldBe expected } } "zip3" { - forAll( - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()) + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) ) { a, b, c -> val result = a.zip(b, c, ::Triple) val expected = a.all.zip(b.all, c.all, ::Triple).let(NonEmptyList.Companion::fromListUnsafe) - result == expected + result shouldBe expected } } "zip4" { - forAll( - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()) + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) ) { a, b, c, d -> val result = a.zip(b, c, d, ::Tuple4) val expected = a.all.zip(b.all, c.all, d.all, ::Tuple4).let(NonEmptyList.Companion::fromListUnsafe) - result == expected + result shouldBe expected } } "zip5" { - forAll( - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()) + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) ) { a, b, c, d, e -> val result = a.zip(b, c, d, e, ::Tuple5) val expected = a.all.zip(b.all, c.all, d.all, e.all, ::Tuple5).let(NonEmptyList.Companion::fromListUnsafe) - result == expected + result shouldBe expected } } "zip6" { - forAll( - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()) + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) ) { a, b, c, d, e, f -> val result = a.zip(b, c, d, e, f, ::Tuple6) - val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, ::Tuple6).let(NonEmptyList.Companion::fromListUnsafe) - result == expected + val expected = + a.all.zip(b.all, c.all, d.all, e.all, f.all, ::Tuple6).let(NonEmptyList.Companion::fromListUnsafe) + result shouldBe expected } } "zip7" { - forAll( - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()) + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) ) { a, b, c, d, e, f, g -> val result = a.zip(b, c, d, e, f, g, ::Tuple7) - val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, ::Tuple7).let(NonEmptyList.Companion::fromListUnsafe) - result == expected + val expected = + a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, ::Tuple7).let(NonEmptyList.Companion::fromListUnsafe) + result shouldBe expected } } "zip8" { - forAll( - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()) + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) ) { a, b, c, d, e, f, g, h -> val result = a.zip(b, c, d, e, f, g, h, ::Tuple8) - val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, ::Tuple8).let(NonEmptyList.Companion::fromListUnsafe) - result == expected + val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, ::Tuple8) + .let(NonEmptyList.Companion::fromListUnsafe) + result shouldBe expected } } "zip9" { - forAll( - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()) + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) ) { a, b, c, d, e, f, g, h, i -> val result = a.zip(b, c, d, e, f, g, h, i, ::Tuple9) - val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, ::Tuple9).let(NonEmptyList.Companion::fromListUnsafe) - result == expected + val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, ::Tuple9) + .let(NonEmptyList.Companion::fromListUnsafe) + result shouldBe expected } } "zip10" { - forAll( - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()), - Gen.nonEmptyList(Gen.int()) + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) ) { a, b, c, d, e, f, g, h, i, j -> val result = a.zip(b, c, d, e, f, g, h, i, j, ::Tuple10) - val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, j.all, ::Tuple10).let(NonEmptyList.Companion::fromListUnsafe) - result == expected + val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, j.all, ::Tuple10) + .let(NonEmptyList.Companion::fromListUnsafe) + result shouldBe expected } } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NonFatalTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NonFatalTest.kt index 6d40e9440e0..072333ff422 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NonFatalTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NonFatalTest.kt @@ -1,8 +1,8 @@ package arrow.core import arrow.core.test.UnitSpec -import io.kotlintest.shouldBe -import io.kotlintest.shouldThrowAny +import io.kotest.matchers.shouldBe +import io.kotest.assertions.throwables.shouldThrowAny class NonFatalTest : UnitSpec() { init { diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NullableTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NullableTest.kt index 5ca33610a22..17589c2117d 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NullableTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/NullableTest.kt @@ -3,12 +3,13 @@ package arrow.core import arrow.core.test.generators.intSmall -import io.kotlintest.matchers.collections.shouldContainAll -import io.kotlintest.matchers.types.shouldBeNull -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe -import io.kotlintest.specs.StringSpec +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.collections.shouldContainAll +import io.kotest.matchers.nulls.shouldBeNull +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.arbitrary.of class NullableTest : StringSpec({ "map1 short circuits if any arg is null" { @@ -16,103 +17,104 @@ class NullableTest : StringSpec({ } "map1 performs action when arg is not null" { - forAll(Gen.intSmall()) { a -> - Nullable.zip(a) { it + 1 } == a + 1 + checkAll(Arb.intSmall()) { a -> + Nullable.zip(a) { it + 1 } shouldBe a + 1 } } "map2 only performs action when all arguments are not null" { - forAll(combGen("a", null, 2)) { (a: String?, b: String?) -> + checkAll(combArb("a", null, 2)) { (a: String?, b: String?) -> if (listOf(a, b).all { it != null }) { Nullable.zip(a, b, { a, b -> a + b }).let { - it == a!! + b!! + it shouldBe a!! + b!! } } else { - Nullable.zip(a, b, { _, _ -> Unit }) == null + Nullable.zip(a, b, { _, _ -> Unit }) shouldBe null } } } "map3 only performs action when all arguments are not null" { - forAll(combGen("a", null, 3)) { (a: String?, b: String?, c: String?) -> + checkAll(combArb("a", null, 3)) { (a: String?, b: String?, c: String?) -> if (listOf(a, b, c).all { it != null }) { Nullable.zip(a, b, c, { a, b, c -> a + b + c }).let { - it == a!! + b!! + c!! + it shouldBe a!! + b!! + c!! } } else { - Nullable.zip(a, b, c, { _, _, _ -> Unit }) == null + Nullable.zip(a, b, c, { _, _, _ -> Unit }) shouldBe null } } } "map4 only performs action when all arguments are not null" { - forAll(combGen(1, null, 4)) { (a: Int?, b: Int?, c: Int?, d: Int?) -> + checkAll(combArb(1, null, 4)) { (a: Int?, b: Int?, c: Int?, d: Int?) -> if (listOf(a, b, c, d).all { it != null }) { Nullable.zip(a, b, c, d, { a, b, c, d -> a + b + c + d }).let { - it == a!! + b!! + c!! + d!! + it shouldBe a!! + b!! + c!! + d!! } } else { - Nullable.zip(a, b, c, d, { _, _, _, _ -> Unit }) == null + Nullable.zip(a, b, c, d, { _, _, _, _ -> Unit }) shouldBe null } } } "map5 only performs action when all arguments are not null" { - forAll(combGen(1, null, 5)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?) -> + checkAll(combArb(1, null, 5)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?) -> if (listOf(a, b, c, d, e).all { it != null }) { Nullable.zip(a, b, c, d, e, { a, b, c, d, e -> a + b + c + d + e }).let { - it == a!! + b!! + c!! + d!! + e!! + it shouldBe a!! + b!! + c!! + d!! + e!! } } else { - Nullable.zip(a, b, c, d, e, { _, _, _, _, _ -> Unit }) == null + Nullable.zip(a, b, c, d, e, { _, _, _, _, _ -> Unit }) shouldBe null } } } "map6 only performs action when all arguments are not null" { - forAll(combGen(1, null, 6)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?) -> + checkAll(combArb(1, null, 6)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?) -> if (listOf(a, b, c, d, e, f).all { it != null }) { Nullable.zip(a, b, c, d, e, f, { a, b, c, d, e, f -> a + b + c + d + e + f }).let { - it == a!! + b!! + c!! + d!! + e!! + f!! + it shouldBe a!! + b!! + c!! + d!! + e!! + f!! } } else { - Nullable.zip(a, b, c, d, e, f, { _, _, _, _, _, _ -> Unit }) == null + Nullable.zip(a, b, c, d, e, f, { _, _, _, _, _, _ -> Unit }) shouldBe null } } } "map7 only performs action when all arguments are not null" { - forAll(combGen(1, null, 7)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?, g: Int?) -> + checkAll(combArb(1, null, 7)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?, g: Int?) -> if (listOf(a, b, c, d, e, f, g).all { it != null }) { Nullable.zip(a, b, c, d, e, f, g, { a, b, c, d, e, f, g -> a + b + c + d + e + f + g }).let { - it == a!! + b!! + c!! + d!! + e!! + f!! + g!! + it shouldBe a!! + b!! + c!! + d!! + e!! + f!! + g!! } } else { - Nullable.zip(a, b, c, d, e, f, g, { _, _, _, _, _, _, _ -> Unit }) == null + Nullable.zip(a, b, c, d, e, f, g, { _, _, _, _, _, _, _ -> Unit }) shouldBe null } } } "map8 only performs action when all arguments are not null" { - forAll(combGen(1, null, 8)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?, g: Int?, h: Int?) -> + checkAll(combArb(1, null, 8)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?, g: Int?, h: Int?) -> if (listOf(a, b, c, d, e, f, g, h).all { it != null }) { Nullable.zip(a, b, c, d, e, f, g, h, { a, b, c, d, e, f, g, h -> a + b + c + d + e + f + g + h }).let { - it == a!! + b!! + c!! + d!! + e!! + f!! + g!! + h!! + it shouldBe a!! + b!! + c!! + d!! + e!! + f!! + g!! + h!! } } else { - Nullable.zip(a, b, c, d, e, f, g, h, { _, _, _, _, _, _, _, _ -> Unit }) == null + Nullable.zip(a, b, c, d, e, f, g, h, { _, _, _, _, _, _, _, _ -> Unit }) shouldBe null } } } "map9 only performs action when all arguments are not null" { - forAll(combGen(1, null, 9)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?, g: Int?, h: Int?, i: Int?) -> + checkAll(combArb(1, null, 9)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?, g: Int?, h: Int?, i: Int?) -> if (listOf(a, b, c, d, e, f, g, h, i).all { it != null }) { - Nullable.zip(a, b, c, d, e, f, g, h, i, { a, b, c, d, e, f, g, h, i -> a + b + c + d + e + f + g + h + i }).let { - it == a!! + b!! + c!! + d!! + e!! + f!! + g!! + h!! + i!! - } + Nullable.zip(a, b, c, d, e, f, g, h, i, { a, b, c, d, e, f, g, h, i -> a + b + c + d + e + f + g + h + i }) + .let { + it shouldBe a!! + b!! + c!! + d!! + e!! + f!! + g!! + h!! + i!! + } } else { - Nullable.zip(a, b, c, d, e, f, g, h, i, { _, _, _, _, _, _, _, _, _ -> Unit }) == null + Nullable.zip(a, b, c, d, e, f, g, h, i, { _, _, _, _, _, _, _, _, _ -> Unit }) shouldBe null } } } @@ -132,13 +134,10 @@ private fun generateAllPathsForNForks(choice1: A, choice2: A, n: Int): List< acc.forkPaths(choice1, choice2) } -private fun combGen(choice1: A, choice2: A, n: Int) = object : Gen> { - override fun constants(): Iterable> = emptyList() - - override fun random(): Sequence> = generateAllPathsForNForks(choice1, choice2, n).asSequence() -} +private fun combArb(choice1: A, choice2: A, n: Int): Arb> = + Arb.of(generateAllPathsForNForks(choice1, choice2, n)) -class GenerateAllPathsForNForksTest : StringSpec({ +class ArberateAllPathsForNForksTest : StringSpec({ "for 0 forks" { generateAllPathsForNForks("a", "b", 0) shouldContainAll emptyList() } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/OptionTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/OptionTest.kt index f383b5c5cdc..7102ce4e9ca 100755 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/OptionTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/OptionTest.kt @@ -8,10 +8,13 @@ import arrow.core.test.generators.option import arrow.core.test.laws.FxLaws import arrow.core.test.laws.MonoidLaws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe -import io.kotlintest.shouldNotBe +import io.kotest.matchers.shouldBe +import io.kotest.matchers.shouldNotBe +import io.kotest.property.checkAll +import io.kotest.property.Arb +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.string class OptionTest : UnitSpec() { @@ -21,18 +24,18 @@ class OptionTest : UnitSpec() { init { testLaws( - MonoidLaws.laws(Monoid.option(Monoid.int()), Gen.option(Gen.int())), + MonoidLaws.laws(Monoid.option(Monoid.int()), Arb.option(Arb.int())), FxLaws.suspended, Option, String>( - Gen.string().map(Option.Companion::invoke), - Gen.option(Gen.string()), + Arb.string().map(Option.Companion::invoke), + Arb.option(Arb.string()), Option::equals, option::invoke ) { it.bind() }, FxLaws.eager, Option, String>( - Gen.string().map(Option.Companion::invoke), - Gen.option(Gen.string()), + Arb.string().map(Option.Companion::invoke), + Arb.option(Arb.string()), Option::equals, option::eager ) { @@ -55,10 +58,10 @@ class OptionTest : UnitSpec() { } "fromNullable should work for both null and non-null values of nullable types" { - forAll { a: Int? -> + checkAll { a: Int? -> // This seems to be generating only non-null values, so it is complemented by the next test val o: Option = Option.fromNullable(a) - if (a == null) o == None else o == Some(a) + if (a == null) o shouldBe None else o shouldBe Some(a) } } @@ -83,11 +86,11 @@ class OptionTest : UnitSpec() { } "zip" { - forAll { a: Int -> + checkAll { a: Int -> val op: Option = a.some() - some.zip(op) { a, b -> a + b } == Some("kotlin$a") && - none.zip(op) { a, b -> a + b } == None && - some.zip(op) == Some(Pair("kotlin", a)) + some.zip(op) { a, b -> a + b } shouldBe Some("kotlin$a") + none.zip(op) { a, b -> a + b } shouldBe None + some.zip(op) shouldBe Some(Pair("kotlin", a)) } } @@ -199,8 +202,8 @@ class OptionTest : UnitSpec() { } "sequence should be consistent with traverse" { - forAll(Gen.option(Gen.int())) { option -> - option.map { listOf(it) }.sequence() == option.traverse { listOf(it) } + checkAll(Arb.option(Arb.int())) { option -> + option.map { listOf(it) }.sequence() shouldBe option.traverse { listOf(it) } } } @@ -212,8 +215,8 @@ class OptionTest : UnitSpec() { } "sequenceEither should be consistent with traverseEither" { - forAll(Gen.option(Gen.int())) { option -> - option.map { it.right() }.sequenceEither() == option.traverseEither { it.right() } + checkAll(Arb.option(Arb.int())) { option -> + option.map { it.right() }.sequenceEither() shouldBe option.traverseEither { it.right() } } } @@ -225,8 +228,8 @@ class OptionTest : UnitSpec() { } "sequenceValidated should be consistent with traverseValidated" { - forAll(Gen.option(Gen.int())) { option -> - option.map { it.valid() }.sequenceValidated() == option.traverseValidated { it.valid() } + checkAll(Arb.option(Arb.int())) { option -> + option.map { it.valid() }.sequenceValidated() shouldBe option.traverseValidated { it.valid() } } } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/SequenceKTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/SequenceKTest.kt index f886790b704..04946beadf4 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/SequenceKTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/SequenceKTest.kt @@ -6,10 +6,14 @@ import arrow.core.test.generators.sequence import arrow.core.test.laws.MonoidLaws import arrow.typeclasses.Monoid import arrow.typeclasses.Semigroup -import io.kotlintest.matchers.sequences.shouldBeEmpty -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe +import io.kotest.matchers.sequences.shouldBeEmpty +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.positiveInts +import io.kotest.property.arbitrary.string import kotlin.math.max import kotlin.math.min @@ -17,7 +21,7 @@ class SequenceKTest : UnitSpec() { init { - testLaws(MonoidLaws.laws(Monoid.sequence(), Gen.sequence(Gen.int())) { s1, s2 -> s1.toList() == s2.toList() }) + testLaws(MonoidLaws.laws(Monoid.sequence(), Arb.sequence(Arb.int())) { s1, s2 -> s1.toList() == s2.toList() }) "traverseEither stack-safe" { // also verifies result order and execution order (l to r) @@ -59,49 +63,48 @@ class SequenceKTest : UnitSpec() { } "traverseValidated acummulates" { - forAll(Gen.list(Gen.int())) { ints -> - val ints = ints.asSequence() + checkAll(Arb.sequence(Arb.int())) { ints -> val res: ValidatedNel> = ints.map { i -> if (i % 2 == 0) i.validNel() else i.invalidNel() } .sequenceValidated(Semigroup.nonEmptyList()) val expected: ValidatedNel> = NonEmptyList.fromList(ints.filterNot { it % 2 == 0 }.toList()) .fold({ ints.filter { it % 2 == 0 }.validNel() }, { it.invalid() }) - res.map { it.toList() } == expected.map { it.toList() } + res.map { it.toList() } shouldBe expected.map { it.toList() } } } "zip3" { - forAll(Gen.sequence(Gen.int()), Gen.sequence(Gen.int()), Gen.sequence(Gen.int())) { a, b, c -> + checkAll(Arb.sequence(Arb.int()), Arb.sequence(Arb.int()), Arb.sequence(Arb.int())) { a, b, c -> val result = a.zip(b, c, ::Triple) val expected = a.zip(b, ::Pair).zip(c) { (a, b), c -> Triple(a, b, c) } - result.toList() == expected.toList() + result.toList() shouldBe expected.toList() } } "zip4" { - forAll( - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()) + checkAll( + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()) ) { a, b, c, d -> val result = a.zip(b, c, d, ::Tuple4) val expected = a.zip(b, ::Pair) .zip(c) { (a, b), c -> Triple(a, b, c) } .zip(d) { (a, b, c), d -> Tuple4(a, b, c, d) } - result.toList() == expected.toList() + result.toList() shouldBe expected.toList() } } "zip5" { - forAll( - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()) + checkAll( + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()) ) { a, b, c, d, e -> val result = a.zip(b, c, d, e, ::Tuple5) val expected = a.zip(b, ::Pair) @@ -109,18 +112,18 @@ class SequenceKTest : UnitSpec() { .zip(d) { (a, b, c), d -> Tuple4(a, b, c, d) } .zip(e) { (a, b, c, d), e -> Tuple5(a, b, c, d, e) } - result.toList() == expected.toList() + result.toList() shouldBe expected.toList() } } "zip6" { - forAll( - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()) + checkAll( + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()) ) { a, b, c, d, e, f -> val result = a.zip(b, c, d, e, f, ::Tuple6) val expected = a.zip(b, ::Pair) @@ -129,19 +132,19 @@ class SequenceKTest : UnitSpec() { .zip(e) { (a, b, c, d), e -> Tuple5(a, b, c, d, e) } .zip(f) { (a, b, c, d, e), f -> Tuple6(a, b, c, d, e, f) } - result.toList() == expected.toList() + result.toList() shouldBe expected.toList() } } "zip7" { - forAll( - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()) + checkAll( + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()) ) { a, b, c, d, e, f, g -> val result = a.zip(b, c, d, e, f, g, ::Tuple7) val expected = a.zip(b, ::Pair) @@ -151,20 +154,20 @@ class SequenceKTest : UnitSpec() { .zip(f) { (a, b, c, d, e), f -> Tuple6(a, b, c, d, e, f) } .zip(g) { (a, b, c, d, e, f), g -> Tuple7(a, b, c, d, e, f, g) } - result.toList() == expected.toList() + result.toList() shouldBe expected.toList() } } "zip8" { - forAll( - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()) + checkAll( + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()) ) { a, b, c, d, e, f, g, h -> val result = a.zip(b, c, d, e, f, g, h, ::Tuple8) val expected = a.zip(b, ::Pair) @@ -175,21 +178,21 @@ class SequenceKTest : UnitSpec() { .zip(g) { (a, b, c, d, e, f), g -> Tuple7(a, b, c, d, e, f, g) } .zip(h) { (a, b, c, d, e, f, g), h -> Tuple8(a, b, c, d, e, f, g, h) } - result.toList() == expected.toList() + result.toList() shouldBe expected.toList() } } "zip9" { - forAll( - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()) + checkAll( + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()) ) { a, b, c, d, e, f, g, h, i -> val result = a.zip(b, c, d, e, f, g, h, i, ::Tuple9) val expected = a.zip(b, ::Pair) @@ -201,22 +204,22 @@ class SequenceKTest : UnitSpec() { .zip(h) { (a, b, c, d, e, f, g), h -> Tuple8(a, b, c, d, e, f, g, h) } .zip(i) { (a, b, c, d, e, f, g, h), i -> Tuple9(a, b, c, d, e, f, g, h, i) } - result.toList() == expected.toList() + result.toList() shouldBe expected.toList() } } "zip10" { - forAll( - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()), - Gen.sequence(Gen.int()) + checkAll( + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()), + Arb.sequence(Arb.int()) ) { a, b, c, d, e, f, g, h, i, j -> val result = a.zip(b, c, d, e, f, g, h, i, j, ::Tuple10) val expected = a.zip(b, ::Pair) @@ -229,29 +232,29 @@ class SequenceKTest : UnitSpec() { .zip(i) { (a, b, c, d, e, f, g, h), i -> Tuple9(a, b, c, d, e, f, g, h, i) } .zip(j) { (a, b, c, d, e, f, g, h, i), j -> Tuple10(a, b, c, d, e, f, g, h, i, j) } - result.toList() == expected.toList() + result.toList() shouldBe expected.toList() } } "can align sequences" { - forAll(Gen.sequence(Gen.int()), Gen.sequence(Gen.string())) { a, b -> - a.align(b).toList().size == max(a.toList().size, b.toList().size) + checkAll(Arb.sequence(Arb.int()), Arb.sequence(Arb.string())) { a, b -> + a.align(b).toList().size shouldBe max(a.toList().size, b.toList().size) } - forAll(Gen.sequence(Gen.int()), Gen.sequence(Gen.string())) { a, b -> - a.align(b).take(min(a.toList().size, b.toList().size)).all { - it.isBoth + checkAll(Arb.sequence(Arb.int()), Arb.sequence(Arb.string())) { a, b -> + a.align(b).take(min(a.toList().size, b.toList().size)).forEach { + it.isBoth shouldBe true } } - forAll(Gen.sequence(Gen.int()), Gen.sequence(Gen.string())) { a, b -> + checkAll(Arb.sequence(Arb.int()), Arb.sequence(Arb.string())) { a, b -> val ls = a.toList() val rs = b.toList() - a.align(b).drop(min(ls.size, rs.size)).all { + a.align(b).drop(min(ls.size, rs.size)).forEach { if (ls.size < rs.size) { - it.isRight + it.isRight shouldBe true } else { - it.isLeft + it.isLeft shouldBe true } } } @@ -267,15 +270,15 @@ class SequenceKTest : UnitSpec() { val seq2 = generateSequence(0) { it + 1 } - forAll(10, Gen.positiveIntegers().filter { it < 10_000 }) { idx: Int -> + checkAll(10, Arb.positiveInts(max = 10_000)) { idx: Int -> val element = seq1.align(seq2).drop(idx).first() - element == Ior.Both("A", idx) + element shouldBe Ior.Both("A", idx) } } "mapNotNull" { - forAll(Gen.sequence(Gen.int())) { a -> + checkAll(Arb.sequence(Arb.int())) { a -> val result = a.mapNotNull { when (it % 2 == 0) { true -> it.toString() @@ -292,13 +295,13 @@ class SequenceKTest : UnitSpec() { } .asSequence() - result.toList() == expected.toList() + result.toList() shouldBe expected.toList() } } "filterOption should filter None" { - forAll(Gen.list(Gen.option(Gen.int()))) { ints -> - ints.asSequence().filterOption().toList() == ints.filterOption() + checkAll(Arb.list(Arb.option(Arb.int()))) { ints -> + ints.asSequence().filterOption().toList() shouldBe ints.filterOption() } } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ValidatedTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ValidatedTest.kt index b36662821b9..2769e75e383 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ValidatedTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/ValidatedTest.kt @@ -6,10 +6,13 @@ import arrow.core.test.UnitSpec import arrow.typeclasses.Monoid import arrow.typeclasses.Semigroup import arrow.core.test.generators.validated -import io.kotlintest.fail -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll -import io.kotlintest.shouldBe +import io.kotest.assertions.fail +import io.kotest.property.Arb +import io.kotest.property.checkAll +import io.kotest.matchers.shouldBe +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.long +import io.kotest.property.arbitrary.orNull @Suppress("RedundantSuspendModifier") class ValidatedTest : UnitSpec() { @@ -127,24 +130,24 @@ class ValidatedTest : UnitSpec() { } "zip identity" { - forAll(Gen.validated(Gen.long().orNull(), Gen.int().orNull())) { validated -> + checkAll(Arb.validated(Arb.long().orNull(), Arb.int().orNull())) { validated -> val res = validated.zip(nullableLongSemigroup, Valid(Unit)) { a, _ -> a } - res == validated + res shouldBe validated } } "zip is derived from flatMap" { - forAll( - Gen.validated(Gen.long().orNull(), Gen.int().orNull()), - Gen.validated(Gen.long().orNull(), Gen.int().orNull()), - Gen.validated(Gen.long().orNull(), Gen.int().orNull()), - Gen.validated(Gen.long().orNull(), Gen.int().orNull()), - Gen.validated(Gen.long().orNull(), Gen.int().orNull()), - Gen.validated(Gen.long().orNull(), Gen.int().orNull()), - Gen.validated(Gen.long().orNull(), Gen.int().orNull()), - Gen.validated(Gen.long().orNull(), Gen.int().orNull()), - Gen.validated(Gen.long().orNull(), Gen.int().orNull()), - Gen.validated(Gen.long().orNull(), Gen.int().orNull()) + checkAll( + Arb.validated(Arb.long().orNull(), Arb.int().orNull()), + Arb.validated(Arb.long().orNull(), Arb.int().orNull()), + Arb.validated(Arb.long().orNull(), Arb.int().orNull()), + Arb.validated(Arb.long().orNull(), Arb.int().orNull()), + Arb.validated(Arb.long().orNull(), Arb.int().orNull()), + Arb.validated(Arb.long().orNull(), Arb.int().orNull()), + Arb.validated(Arb.long().orNull(), Arb.int().orNull()), + Arb.validated(Arb.long().orNull(), Arb.int().orNull()), + Arb.validated(Arb.long().orNull(), Arb.int().orNull()), + Arb.validated(Arb.long().orNull(), Arb.int().orNull()) ) { a, b, c, d, e, f, g, h, i, j -> val res = a.zip( nullableLongSemigroup, @@ -177,7 +180,7 @@ class ValidatedTest : UnitSpec() { all.filterIsInstance>().map(Invalid::value).combineAll(nullableLongSemigroup) ) - res == expected + res shouldBe expected } } @@ -321,12 +324,12 @@ class ValidatedTest : UnitSpec() { } "sequence should yield consistent result with traverse" { - forAll { a: String, b: String -> + checkAll { a: String, b: String -> val valid = Valid(a) val invalid = Invalid(b) - valid.traverse { listOf(it) } == valid.map { listOf(it) }.sequence() && - invalid.traverse { listOf(it) } == invalid.map { listOf(it) }.sequence() + valid.traverse { listOf(it) } shouldBe valid.map { listOf(it) }.sequence() + invalid.traverse { listOf(it) } shouldBe invalid.map { listOf(it) }.sequence() } } @@ -339,12 +342,12 @@ class ValidatedTest : UnitSpec() { } "sequenceOption should yield consistent result with traverseOption" { - forAll { a: String, b: String -> + checkAll { a: String, b: String -> val valid = Valid(a) val invalid = Invalid(b) - valid.traverseOption { Some(it) } == valid.map { Some(it) }.sequenceOption() && - invalid.traverseOption { Some(it) } == invalid.map { Some(it) }.sequenceOption() + valid.traverseOption { Some(it) } shouldBe valid.map { Some(it) }.sequenceOption() + invalid.traverseOption { Some(it) } shouldBe invalid.map { Some(it) }.sequenceOption() } } @@ -357,12 +360,12 @@ class ValidatedTest : UnitSpec() { } "sequenceEither should yield consistent result with traverseEither" { - forAll { a: String, b: String -> + checkAll { a: String, b: String -> val valid = Valid(a) val invalid = Invalid(b) - valid.traverseEither { Right(it) } == valid.map { Right(it) }.sequenceEither() && - invalid.traverseEither { Right(it) } == invalid.map { Right(it) }.sequenceEither() + valid.traverseEither { Right(it) } shouldBe valid.map { Right(it) }.sequenceEither() + invalid.traverseEither { Right(it) } shouldBe invalid.map { Right(it) }.sequenceEither() } } @@ -375,12 +378,14 @@ class ValidatedTest : UnitSpec() { } "bisequence should yield consistent result with bitraverse" { - forAll { a: String, b: String -> + checkAll { a: String, b: String -> val valid: Validated = Valid(a) val invalid: Validated = Invalid(b) - valid.bimap({ listOf(it) }, { listOf(it) }).bisequence() == valid.bitraverse({ listOf(it) }, { listOf(it) }) && - invalid.bimap({ listOf(it) }, { listOf(it) }).bisequence() == invalid.bitraverse( + valid.bimap({ listOf(it) }, { listOf(it) }).bisequence() shouldBe valid.bitraverse( + { listOf(it) }, + { listOf(it) }) + invalid.bimap({ listOf(it) }, { listOf(it) }).bisequence() shouldBe invalid.bitraverse( { listOf(it) }, { listOf(it) }) } @@ -395,13 +400,13 @@ class ValidatedTest : UnitSpec() { } "bisequenceOption should yield consistent result with bitraverseOption" { - forAll { a: String, b: String -> + checkAll { a: String, b: String -> val valid: Validated = Valid(a) val invalid: Validated = Invalid(b) - valid.bimap({ Some(it) }, { Some(it) }).bisequenceOption() == - valid.bitraverseOption({ Some(it) }, { Some(it) }) && - invalid.bimap({ Some(it) }, { Some(it) }).bisequenceOption() == + valid.bimap({ Some(it) }, { Some(it) }).bisequenceOption() shouldBe + valid.bitraverseOption({ Some(it) }, { Some(it) }) + invalid.bimap({ Some(it) }, { Some(it) }).bisequenceOption() shouldBe invalid.bitraverseOption({ Some(it) }, { Some(it) }) } } @@ -415,13 +420,13 @@ class ValidatedTest : UnitSpec() { } "bisequenceEither should yield consistent result with bitraverseEither" { - forAll { a: String, b: String -> + checkAll { a: String, b: String -> val valid: Validated = Valid(a) val invalid: Validated = Invalid(b) - valid.bimap({ it.left() }, { it.right() }).bisequenceEither() == - valid.bitraverseEither({ it.left() }, { it.right() }) && - invalid.bimap({ it.left() }, { it.right() }).bisequenceEither() == + valid.bimap({ it.left() }, { it.right() }).bisequenceEither() shouldBe + valid.bitraverseEither({ it.left() }, { it.right() }) + invalid.bimap({ it.left() }, { it.right() }).bisequenceEither() shouldBe invalid.bitraverseEither({ it.left() }, { it.right() }) } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/computations/NullableTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/computations/NullableTest.kt index 67e17d708f3..0c648e3998a 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/computations/NullableTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/computations/NullableTest.kt @@ -2,7 +2,7 @@ package arrow.core.computations import arrow.core.Some import arrow.core.test.UnitSpec -import io.kotlintest.shouldBe +import io.kotest.matchers.shouldBe class NullableTest : UnitSpec() { diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/extensions/NumberInstancesTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/extensions/NumberInstancesTest.kt index 46cf217b97f..ef48d9e8694 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/extensions/NumberInstancesTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/extensions/NumberInstancesTest.kt @@ -1,89 +1,92 @@ package arrow.core.extensions import arrow.core.test.UnitSpec -import arrow.core.test.generators.byte import arrow.core.test.generators.byteSmall import arrow.core.test.generators.doubleSmall import arrow.core.test.generators.floatSmall import arrow.core.test.generators.intSmall import arrow.core.test.generators.longSmall -import arrow.core.test.generators.short import arrow.core.test.generators.shortSmall import arrow.core.test.laws.MonoidLaws import arrow.core.test.laws.SemiringLaws import arrow.typeclasses.Monoid import arrow.typeclasses.Semiring -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.byte +import io.kotest.property.arbitrary.numericDoubles +import io.kotest.property.arbitrary.numericFloats +import io.kotest.property.arbitrary.short +import io.kotest.property.checkAll class NumberInstancesTest : UnitSpec() { - fun testAllLaws(SG: Semiring, M: Monoid, GEN: Gen) { + fun testAllLaws(SG: Semiring, M: Monoid, GEN: Arb) { testLaws(SemiringLaws.laws(SG, GEN)) testLaws(MonoidLaws.laws(M, GEN)) } init { - testAllLaws(Semiring.byte(), Monoid.byte(), Gen.byteSmall()) - testAllLaws(Semiring.double(), Monoid.double(), Gen.doubleSmall()) - testAllLaws(Semiring.int(), Monoid.int(), Gen.intSmall()) - testAllLaws(Semiring.short(), Monoid.short(), Gen.shortSmall()) - testAllLaws(Semiring.float(), Monoid.float(), Gen.floatSmall()) - testAllLaws(Semiring.long(), Monoid.long(), Gen.longSmall()) + testAllLaws(Semiring.byte(), Monoid.byte(), Arb.byteSmall()) + testAllLaws(Semiring.double(), Monoid.double(), Arb.doubleSmall()) + testAllLaws(Semiring.int(), Monoid.int(), Arb.intSmall()) + testAllLaws(Semiring.short(), Monoid.short(), Arb.shortSmall()) + testAllLaws(Semiring.float(), Monoid.float(), Arb.floatSmall()) + testAllLaws(Semiring.long(), Monoid.long(), Arb.longSmall()) /** Semigroup specific instance check */ "should semigroup with the instance passed - int" { - forAll { value: Int -> + checkAll { value: Int -> val seen = Monoid.int().run { value.combine(value) } val expected = value + value - expected == seen + expected shouldBe seen } } "should semigroup with the instance passed - float" { - forAll(Gen.numericFloats()) { value: Float -> + checkAll(Arb.numericFloats()) { value: Float -> val seen = Monoid.float().run { value.combine(value) } val expected = value + value - expected == seen + expected shouldBe seen } } "should semigroup with the instance passed - double" { - forAll(Gen.numericDoubles()) { value: Double -> + checkAll(Arb.numericDoubles()) { value: Double -> val seen = Monoid.double().run { value.combine(value) } val expected = value + value - expected == seen + expected shouldBe seen } } "should semigroup with the instance passed - long" { - forAll { value: Long -> + checkAll { value: Long -> val seen = Monoid.long().run { value.combine(value) } val expected = value + value - expected == seen + expected shouldBe seen } } "should semigroup with the instance passed - short" { - forAll(Gen.short()) { value: Short -> + checkAll(Arb.short()) { value: Short -> val seen = Monoid.short().run { value.combine(value) } val expected = (value + value).toShort() - expected == seen + expected shouldBe seen } } "should semigroup with the instance passed - byte" { - forAll(Gen.byte()) { value: Byte -> + checkAll(Arb.byte()) { value: Byte -> val seen = Monoid.byte().run { value.combine(value) } val expected = (value + value).toByte() - expected == seen + expected shouldBe seen } } } diff --git a/arrow-libs/core/gradle.properties b/arrow-libs/core/gradle.properties index 5ed6b2dc4f6..fd07b46dc0b 100644 --- a/arrow-libs/core/gradle.properties +++ b/arrow-libs/core/gradle.properties @@ -8,7 +8,7 @@ systemProp.org.gradle.internal.publish.checksums.insecure=true kotlin.incremental=true # Kotlin Test configuration #Parallelism needs to be set to 1 since the concurrent tests in arrow-effects become flaky otherwise -kotlintest.parallelism=1 +kotest.framework.parallelism=1 kapt.incremental.apt=false # Reason: https://youtrack.jetbrains.com/issue/KT-46847 diff --git a/arrow-libs/examples/build.gradle b/arrow-libs/examples/build.gradle index 47c82299aca..8db1d007d9f 100644 --- a/arrow-libs/examples/build.gradle +++ b/arrow-libs/examples/build.gradle @@ -13,8 +13,9 @@ dependencies { testImplementation project(":arrow-core") testImplementation project(":arrow-optics") testImplementation project(":arrow-meta") - testImplementation "io.kotlintest:kotlintest-runner-junit5:$KOTLIN_TEST_VERSION", excludeArrow - testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$JUNIT_VINTAGE_VERSION" + testImplementation "io.kotest:kotest-runner-junit5-jvm:$KOTEST_VERSION" // for kotest framework + testImplementation "io.kotest:kotest-assertions-core-jvm:$KOTEST_VERSION" // for kotest core jvm assertions + testImplementation "io.kotest:kotest-property-jvm:$KOTEST_VERSION" // for kotest property test } test { diff --git a/arrow-libs/examples/gradle.properties b/arrow-libs/examples/gradle.properties index 2b64ec061c6..3460fc52726 100644 --- a/arrow-libs/examples/gradle.properties +++ b/arrow-libs/examples/gradle.properties @@ -5,4 +5,4 @@ org.gradle.parallel=true kotlin.incremental=true # Kotlin Test configuration #Parallelism needs to be set to 1 since the concurrent tests in arrow-effects become flaky otherwise -kotlintest.parallelism=1 +kotest.framework.parallelism=1 diff --git a/arrow-libs/examples/src/test/kotlin/arrow/DataTypeExamples.kt b/arrow-libs/examples/src/test/kotlin/arrow/DataTypeExamples.kt index ff60476a46c..ac27a1760ac 100644 --- a/arrow-libs/examples/src/test/kotlin/arrow/DataTypeExamples.kt +++ b/arrow-libs/examples/src/test/kotlin/arrow/DataTypeExamples.kt @@ -14,8 +14,8 @@ import arrow.core.flatMap import arrow.core.getOrElse import arrow.core.handleError import arrow.core.handleErrorWith -import io.kotlintest.shouldBe -import io.kotlintest.specs.FreeSpec +import io.kotest.core.spec.style.FreeSpec +import io.kotest.matchers.shouldBe /*** Arrow.io documentation as runnable code ***/ class DataTypeExamples : FreeSpec() { diff --git a/arrow-libs/fx/gradle.properties b/arrow-libs/fx/gradle.properties index 5ed6b2dc4f6..fd07b46dc0b 100644 --- a/arrow-libs/fx/gradle.properties +++ b/arrow-libs/fx/gradle.properties @@ -8,7 +8,7 @@ systemProp.org.gradle.internal.publish.checksums.insecure=true kotlin.incremental=true # Kotlin Test configuration #Parallelism needs to be set to 1 since the concurrent tests in arrow-effects become flaky otherwise -kotlintest.parallelism=1 +kotest.framework.parallelism=1 kapt.incremental.apt=false # Reason: https://youtrack.jetbrains.com/issue/KT-46847 diff --git a/arrow-libs/gradle.properties b/arrow-libs/gradle.properties index 7983ded8f72..143e206d830 100644 --- a/arrow-libs/gradle.properties +++ b/arrow-libs/gradle.properties @@ -25,7 +25,7 @@ JMH_REPORT_PLUGIN_VERSION=0.9.0 JUNIT_VERSION=4.12 JUNIT_VINTAGE_VERSION=5.5.2 KINDEDJ_VERSION=1.1.0 -KOTEST_VERSION=4.3.1 +KOTEST_VERSION=4.6.0 KOTLIN_POET_VERSION=1.5.0 KOTLIN_TEST_VERSION=3.3.3 KOTLIN_VERSION=1.4.32 @@ -65,7 +65,7 @@ systemProp.org.gradle.internal.publish.checksums.insecure=true kotlin.incremental=true # Kotlin Test configuration #Parallelism needs to be set to 1 since the concurrent tests in arrow-effects become flaky otherwise -kotlintest.parallelism=1 +kotest.framework.parallelism=1 kapt.incremental.apt=false # Reason: https://youtrack.jetbrains.com/issue/KT-46847 diff --git a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/GetterTest.kt b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/GetterTest.kt index dc954da645b..5ec324e3d33 100644 --- a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/GetterTest.kt +++ b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/GetterTest.kt @@ -13,33 +13,33 @@ import arrow.optics.mtl.extract import arrow.optics.mtl.extractMap import arrow.optics.mtl.toReader import arrow.optics.mtl.toState -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.checkAll class GetterTest : UnitSpec() { init { "Asking for the focus in a Reader" { - forAll(genToken) { token: Token -> + checkAll(genToken) { token: Token -> tokenGetter.ask().runId(token) == token.value } } "toReader is an alias for ask" { - forAll(genToken) { token: Token -> + checkAll(genToken) { token: Token -> tokenGetter.ask().runId(token) == tokenLens.toReader().runId(token) } } "Asks with f is the same as applying f to the focus of the lens" { - forAll(genToken, Gen.functionAToB(Gen.string())) { token, f -> + checkAll(genToken, Arb.functionAToB(Arb.string())) { token, f -> tokenGetter.asks(f).runId(token) == f(token.value) } } "Extract should extract the focus from the state" { - forAll(genToken) { generatedToken -> + checkAll(genToken) { generatedToken -> tokenGetter.extract().run(generatedToken) == State { token: Token -> token toT tokenGetter.get(token) @@ -48,13 +48,13 @@ class GetterTest : UnitSpec() { } "toState should be an alias to extract" { - forAll(genToken) { token -> + checkAll(genToken) { token -> tokenGetter.toState().run(token) == tokenGetter.extract().run(token) } } "extractMap with f should be same as extract and map" { - forAll(genToken, Gen.functionAToB(Gen.string())) { token, f -> + checkAll(genToken, Arb.functionAToB(Arb.string())) { token, f -> tokenGetter.extractMap(f).run(token) == tokenGetter.extract().map(f).run(token) } } diff --git a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/LensTest.kt b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/LensTest.kt index 827c12c60a7..5d146f4af2e 100644 --- a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/LensTest.kt +++ b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/LensTest.kt @@ -19,33 +19,33 @@ import arrow.optics.mtl.toState import arrow.optics.mtl.update import arrow.optics.mtl.updateOld import arrow.optics.mtl.update_ -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.checkAll class LensTest : UnitSpec() { init { "Asking for the focus in a Reader" { - forAll(genToken) { token: Token -> + checkAll(genToken) { token: Token -> tokenLens.ask().runId(token) == token.value } } "toReader is an alias for ask" { - forAll(genToken) { token: Token -> + checkAll(genToken) { token: Token -> tokenLens.ask().runId(token) == tokenLens.toReader().runId(token) } } "Asks with f is the same as applying f to the focus of the lens" { - forAll(genToken, Gen.functionAToB(Gen.string())) { token, f -> + checkAll(genToken, Arb.functionAToB(Arb.string())) { token, f -> tokenLens.asks(f).runId(token) == f(token.value) } } "Extract should extract the focus from the state" { - forAll(genToken) { generatedToken -> + checkAll(genToken) { generatedToken -> tokenLens.extract().run(generatedToken) == State { token: Token -> token toT tokenLens.get(token) @@ -54,19 +54,19 @@ class LensTest : UnitSpec() { } "toState should be an alias to extract" { - forAll(genToken) { token -> + checkAll(genToken) { token -> tokenLens.toState().run(token) == tokenLens.extract().run(token) } } "Extracts with f should be same as extract and map" { - forAll(genToken, Gen.functionAToB(Gen.string())) { generatedToken, f -> + checkAll(genToken, Arb.functionAToB(Arb.string())) { generatedToken, f -> tokenLens.extractMap(f).run(generatedToken) == tokenLens.extract().map(f).run(generatedToken) } } "update f should be same modify f within State and returning new state" { - forAll(genToken, Gen.functionAToB(Gen.string())) { generatedToken, f -> + checkAll(genToken, Arb.functionAToB(Arb.string())) { generatedToken, f -> tokenLens.update(f).run(generatedToken) == State { token: Token -> tokenLens.modify(token, f) @@ -76,7 +76,7 @@ class LensTest : UnitSpec() { } "updateOld f should be same as modify f within State and returning old state" { - forAll(genToken, Gen.functionAToB(Gen.string())) { generatedToken, f -> + checkAll(genToken, Arb.functionAToB(Arb.string())) { generatedToken, f -> tokenLens.updateOld(f).run(generatedToken) == State { token: Token -> tokenLens.modify(token, f) toT tokenLens.get(token) @@ -85,7 +85,7 @@ class LensTest : UnitSpec() { } "update_ f should be as modify f within State and returning Unit" { - forAll(genToken, Gen.functionAToB(Gen.string())) { generatedToken, f -> + checkAll(genToken, Arb.functionAToB(Arb.string())) { generatedToken, f -> tokenLens.update_(f).run(generatedToken) == State { token: Token -> tokenLens.modify(token, f) toT Unit @@ -94,7 +94,7 @@ class LensTest : UnitSpec() { } "assign a should be same set a within State and returning new value" { - forAll(genToken, Gen.string()) { generatedToken, string -> + checkAll(genToken, Arb.string()) { generatedToken, string -> tokenLens.assign(string).run(generatedToken) == State { token: Token -> tokenLens.set(token, string) @@ -104,7 +104,7 @@ class LensTest : UnitSpec() { } "assignOld f should be same as modify f within State and returning old state" { - forAll(genToken, Gen.string()) { generatedToken, string -> + checkAll(genToken, Arb.string()) { generatedToken, string -> tokenLens.assignOld(string).run(generatedToken) == State { token: Token -> tokenLens.set(token, string) toT tokenLens.get(token) @@ -113,7 +113,7 @@ class LensTest : UnitSpec() { } "assign_ f should be as modify f within State and returning Unit" { - forAll(genToken, Gen.string()) { generatedToken, string -> + checkAll(genToken, Arb.string()) { generatedToken, string -> tokenLens.assign_(string).run(generatedToken) == State { token: Token -> tokenLens.set(token, string) toT Unit diff --git a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/OptionalTest.kt b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/OptionalTest.kt index e0cccd6a46f..b529536e579 100644 --- a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/OptionalTest.kt +++ b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/OptionalTest.kt @@ -17,8 +17,8 @@ import arrow.optics.mtl.toState import arrow.optics.mtl.update import arrow.optics.mtl.updateOld import arrow.optics.mtl.update_ -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.checkAll class OptionalTest : UnitSpec() { @@ -27,7 +27,7 @@ class OptionalTest : UnitSpec() { val successInt = Option.some().asOptional() "Extract should extract the focus from the state" { - forAll(Gen.option(Gen.int())) { tryInt -> + checkAll(Gen.option(Arb.int())) { tryInt -> successInt.extract().run(tryInt) == State { x: Option -> x toT successInt.getOption(x) @@ -36,19 +36,19 @@ class OptionalTest : UnitSpec() { } "toState should be an alias to extract" { - forAll(Gen.option(Gen.int())) { x -> + checkAll(Gen.option(Arb.int())) { x -> successInt.toState().run(x) == successInt.extract().run(x) } } "extractMap with f should be same as extract and map" { - forAll(Gen.option(Gen.int()), Gen.functionAToB(Gen.int())) { x, f -> + checkAll(Gen.option(Arb.int()), Arb.functionAToB(Arb.int())) { x, f -> successInt.extractMap(f).run(x) == successInt.extract().map { it.map(f) }.run(x) } } "update f should be same modify f within State and returning new state" { - forAll(Gen.option(Gen.int()), Gen.functionAToB(Gen.int())) { x, f -> + checkAll(Gen.option(Arb.int()), Arb.functionAToB(Arb.int())) { x, f -> successInt.update(f).run(x) == State { xx: Option -> successInt.modify(xx, f) @@ -58,7 +58,7 @@ class OptionalTest : UnitSpec() { } "updateOld f should be same as modify f within State and returning old state" { - forAll(Gen.option(Gen.int()), Gen.functionAToB(Gen.int())) { x, f -> + checkAll(Gen.option(Arb.int()), Arb.functionAToB(Arb.int())) { x, f -> successInt.updateOld(f).run(x) == State { xx: Option -> successInt.modify(xx, f) toT successInt.getOption(xx) @@ -67,7 +67,7 @@ class OptionalTest : UnitSpec() { } "update_ f should be as modify f within State and returning Unit" { - forAll(Gen.option(Gen.int()), Gen.functionAToB(Gen.int())) { x, f -> + checkAll(Gen.option(Arb.int()), Arb.functionAToB(Arb.int())) { x, f -> successInt.update_(f).run(x) == State { xx: Option -> successInt.modify(xx, f) toT Unit @@ -76,7 +76,7 @@ class OptionalTest : UnitSpec() { } "assign a should be same set a within State and returning new value" { - forAll(Gen.option(Gen.int()), Gen.int()) { x, i -> + checkAll(Gen.option(Arb.int()), Arb.int()) { x, i -> successInt.assign(i).run(x) == State { xx: Option -> successInt.set(xx, i) @@ -86,7 +86,7 @@ class OptionalTest : UnitSpec() { } "assignOld f should be same as modify f within State and returning old state" { - forAll(Gen.option(Gen.int()), Gen.int()) { x, i -> + checkAll(Gen.option(Arb.int()), Arb.int()) { x, i -> successInt.assignOld(i).run(x) == State { xx: Option -> successInt.set(xx, i) toT successInt.getOption(xx) @@ -95,7 +95,7 @@ class OptionalTest : UnitSpec() { } "assign_ f should be as modify f within State and returning Unit" { - forAll(Gen.option(Gen.int()), Gen.int()) { x, i -> + checkAll(Gen.option(Arb.int()), Arb.int()) { x, i -> successInt.assign_(i).run(x) == State { xx: Option -> successInt.set(xx, i) toT Unit diff --git a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/SetterTest.kt b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/SetterTest.kt index 0e179041e20..166ad99c95b 100644 --- a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/SetterTest.kt +++ b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/SetterTest.kt @@ -7,14 +7,14 @@ import arrow.mtl.State import arrow.mtl.run import arrow.optics.mtl.assign_ import arrow.optics.mtl.update_ -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.checkAll class SetterTest : UnitSpec() { init { "update_ f should be as modify f within State and returning Unit" { - forAll(genToken, Gen.functionAToB(Gen.string())) { generatedToken, f -> + checkAll(genToken, Arb.functionAToB(Arb.string())) { generatedToken, f -> tokenSetter.update_(f).run(generatedToken) == State { token: Token -> tokenSetter.modify(token, f) toT Unit @@ -23,7 +23,7 @@ class SetterTest : UnitSpec() { } "assign_ f should be as modify f within State and returning Unit" { - forAll(genToken, Gen.string()) { generatedToken, string -> + checkAll(genToken, Arb.string()) { generatedToken, string -> tokenSetter.assign_(string).run(generatedToken) == State { token: Token -> tokenSetter.set(token, string) toT Unit diff --git a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/TestDomain.kt b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/TestDomain.kt index 503d4d0a2b3..341dfc0b0b7 100644 --- a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/TestDomain.kt +++ b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/TestDomain.kt @@ -5,17 +5,17 @@ import arrow.core.Some import arrow.core.left import arrow.core.right import arrow.typeclasses.Eq -import io.kotlintest.properties.Gen +import io.kotest.property.Arb sealed class SumType { data class A(val string: String) : SumType() data class B(val int: Int) : SumType() } -val genSumTypeA: Gen = Gen.string().map { SumType.A(it) } +val genSumTypeA: Arb = Arb.string().map { SumType.A(it) } -val genSum: Gen = - Gen.oneOf(Gen.string().map { SumType.A(it) }, Gen.int().map { SumType.B(it) }) +val genSum: Arb = + Gen.oneOf(Arb.string().map { SumType.A(it) }, Arb.int().map { SumType.B(it) }) val sumPrism: Prism = Prism( { Option.fromNullable((it as? SumType.A)?.string) }, @@ -58,15 +58,15 @@ internal data class Token(val value: String) { } } -internal val genToken: Gen = Gen.string().map { Token(it) } +internal val genToken: Arb = Arb.string().map { Token(it) } internal data class User(val token: Token) -internal val genUser: Gen = genToken.map { User(it) } +internal val genUser: Arb = genToken.map { User(it) } internal data class IncompleteUser(val token: Token?) -internal val genIncompleteUser: Gen = Gen.constant(IncompleteUser(null)) +internal val genIncompleteUser: Arb = Gen.constant(IncompleteUser(null)) internal val tokenGetter: Getter = Getter(Token::value) diff --git a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/TraversalTest.kt b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/TraversalTest.kt index a5070edd13c..80535b20a5c 100644 --- a/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/TraversalTest.kt +++ b/arrow-libs/optics/arrow-optics-mtl/src/test/kotlin/arrow/optics/TraversalTest.kt @@ -20,8 +20,8 @@ import arrow.optics.mtl.toState import arrow.optics.mtl.update import arrow.optics.mtl.updateOld import arrow.optics.mtl.update_ -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.checkAll class TraversalTest : UnitSpec() { @@ -31,7 +31,7 @@ class TraversalTest : UnitSpec() { with(listKTraverse) { "Extract should extract the focus from the state" { - forAll(Gen.listK(Gen.int())) { ints -> + checkAll(Gen.listK(Arb.int())) { ints -> extract().run(ints) == State { iis: ListK -> iis toT getAll(iis) @@ -40,19 +40,19 @@ class TraversalTest : UnitSpec() { } "toState should be an alias to extract" { - forAll(Gen.listK(Gen.int())) { ints -> + checkAll(Gen.listK(Arb.int())) { ints -> toState().run(ints) == extract().run(ints) } } "Extracts with f should be same as extract and map" { - forAll(Gen.listK(Gen.int()), Gen.functionAToB(Gen.string())) { ints, f -> + checkAll(Gen.listK(Arb.int()), Arb.functionAToB(Arb.string())) { ints, f -> extractMap(f).run(ints) == extract().map { it.map(f) }.run(ints) } } "update f should be same modify f within State and returning new state" { - forAll(Gen.listK(Gen.int()), Gen.functionAToB(Gen.int())) { ints, f -> + checkAll(Gen.listK(Arb.int()), Arb.functionAToB(Arb.int())) { ints, f -> update(f).run(ints) == State, ListK> { iis: ListK -> modify(iis, f) @@ -62,7 +62,7 @@ class TraversalTest : UnitSpec() { } "updateOld f should be same as modify f within State and returning old state" { - forAll(Gen.listK(Gen.int()), Gen.functionAToB(Gen.int())) { ints, f -> + checkAll(Gen.listK(Arb.int()), Arb.functionAToB(Arb.int())) { ints, f -> updateOld(f).run(ints) == State { iis: ListK -> modify(iis, f).fix() toT getAll(iis) @@ -71,7 +71,7 @@ class TraversalTest : UnitSpec() { } "update_ f should be as modify f within State and returning Unit" { - forAll(Gen.listK(Gen.int()), Gen.functionAToB(Gen.int())) { ints, f -> + checkAll(Gen.listK(Arb.int()), Arb.functionAToB(Arb.int())) { ints, f -> update_(f).run(ints) == State { iis: ListK -> modify(iis, f).fix() toT Unit @@ -80,7 +80,7 @@ class TraversalTest : UnitSpec() { } "assign a should be same set a within State and returning new value" { - forAll(Gen.listK(Gen.int()), Gen.int()) { ints, i -> + checkAll(Gen.listK(Arb.int()), Arb.int()) { ints, i -> assign(i).run(ints) == State { iis: ListK -> set(iis, i) @@ -90,7 +90,7 @@ class TraversalTest : UnitSpec() { } "assignOld f should be same as modify f within State and returning old state" { - forAll(Gen.listK(Gen.int()), Gen.int()) { ints, i -> + checkAll(Gen.listK(Arb.int()), Arb.int()) { ints, i -> assignOld(i).run(ints) == State { iis: ListK -> set(iis, i).fix() toT getAll(iis) @@ -99,7 +99,7 @@ class TraversalTest : UnitSpec() { } "assign_ f should be as modify f within State and returning Unit" { - forAll(Gen.listK(Gen.int()), Gen.int()) { ints, i -> + checkAll(Gen.listK(Arb.int()), Arb.int()) { ints, i -> assign_(i).run(ints) == State { iis: ListK -> set(iis, i).fix() toT Unit diff --git a/arrow-libs/optics/arrow-optics-test/build.gradle b/arrow-libs/optics/arrow-optics-test/build.gradle index a1918b28ba1..342b0b1d1cb 100644 --- a/arrow-libs/optics/arrow-optics-test/build.gradle +++ b/arrow-libs/optics/arrow-optics-test/build.gradle @@ -11,6 +11,4 @@ dependencies { compileOnly "org.jetbrains.kotlin:kotlin-stdlib:$KOTLIN_VERSION" compile project(":arrow-optics") compile project(":arrow-core-test") - compile "io.kotlintest:kotlintest-runner-junit5:$KOTLIN_TEST_VERSION", excludeArrow - testRuntime "org.junit.vintage:junit-vintage-engine:$JUNIT_VINTAGE_VERSION" } diff --git a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/generators/Generators.kt b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/generators/Generators.kt deleted file mode 100644 index 5b01fffdb94..00000000000 --- a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/generators/Generators.kt +++ /dev/null @@ -1,6 +0,0 @@ -package arrow.optics.test.generators - -import io.kotlintest.properties.Gen - -fun Gen.Companion.char(): Gen = - Gen.from(('A'..'Z') + ('a'..'z') + ('0'..'9') + "!@#$%%^&*()_-~`,<.?/:;}{][±§".toList()) diff --git a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/IsoLaws.kt b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/IsoLaws.kt index 2ab7a9e05b0..4661676517b 100644 --- a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/IsoLaws.kt +++ b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/IsoLaws.kt @@ -5,16 +5,17 @@ import arrow.core.identity import arrow.optics.Iso import arrow.core.test.laws.Law import arrow.core.test.laws.equalUnderTheLaw -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.PropertyContext +import io.kotest.property.checkAll object IsoLaws { fun laws( iso: Iso, - aGen: Gen, - bGen: Gen, - funcGen: Gen<(B) -> B>, + aGen: Arb, + bGen: Arb, + funcGen: Arb<(B) -> B>, eqa: (A, A) -> Boolean = { a, b -> a == b }, eqb: (B, B) -> Boolean = { a, b -> a == b } ): List = @@ -26,28 +27,28 @@ object IsoLaws { Law("Iso Law: consitent set with modify") { iso.consistentSetModify(aGen, bGen, eqa) } ) - fun Iso.roundTripOneWay(aGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(aGen) { a -> + suspend fun Iso.roundTripOneWay(aGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen) { a -> reverseGet(get(a)).equalUnderTheLaw(a, eq) } - fun Iso.roundTripOtherWay(bGen: Gen, eq: (B, B) -> Boolean): Unit = - forAll(bGen) { b -> + suspend fun Iso.roundTripOtherWay(bGen: Arb, eq: (B, B) -> Boolean): PropertyContext = + checkAll(bGen) { b -> get(reverseGet(b)).equalUnderTheLaw(b, eq) } - fun Iso.modifyIdentity(aGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(aGen) { a -> + suspend fun Iso.modifyIdentity(aGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen) { a -> modify(a, ::identity).equalUnderTheLaw(a, eq) } - fun Iso.composeModify(aGen: Gen, funcGen: Gen<(B) -> B>, eq: (A, A) -> Boolean): Unit = - forAll(aGen, funcGen, funcGen) { a, f, g -> + suspend fun Iso.composeModify(aGen: Arb, funcGen: Arb<(B) -> B>, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen, funcGen, funcGen) { a, f, g -> modify(modify(a, f), g).equalUnderTheLaw(modify(a, g compose f), eq) } - fun Iso.consistentSetModify(aGen: Gen, bGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(aGen, bGen) { a, b -> + suspend fun Iso.consistentSetModify(aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen, bGen) { a, b -> set(b).equalUnderTheLaw(modify(a) { b }, eq) } } diff --git a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/LensLaws.kt b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/LensLaws.kt index ad86a59c90c..0b319f72bc9 100644 --- a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/LensLaws.kt +++ b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/LensLaws.kt @@ -5,16 +5,17 @@ import arrow.core.identity import arrow.optics.Lens import arrow.core.test.laws.Law import arrow.core.test.laws.equalUnderTheLaw -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.arbitrary.constant +import io.kotest.property.checkAll object LensLaws { fun laws( - lensGen: Gen>, - aGen: Gen, - bGen: Gen, - funcGen: Gen<(B) -> B>, + lensGen: Arb>, + aGen: Arb, + bGen: Arb, + funcGen: Arb<(B) -> B>, eqa: (A, A) -> Boolean = { a, b -> a == b }, eqb: (B, B) -> Boolean = { a, b -> a == b } ): List = @@ -32,50 +33,50 @@ object LensLaws { */ fun laws( lens: Lens, - aGen: Gen, - bGen: Gen, - funcGen: Gen<(B) -> B>, + aGen: Arb, + bGen: Arb, + funcGen: Arb<(B) -> B>, eqa: (A, A) -> Boolean = { a, b -> a == b }, eqb: (B, B) -> Boolean = { a, b -> a == b } - ): List = laws(Gen.constant(lens), aGen, bGen, funcGen, eqa, eqb) + ): List = laws(Arb.constant(lens), aGen, bGen, funcGen, eqa, eqb) - fun lensGetSet(lensGen: Gen>, aGen: Gen, eq: (A, A) -> Boolean) = - forAll(lensGen, aGen) { lens, a -> + suspend fun lensGetSet(lensGen: Arb>, aGen: Arb, eq: (A, A) -> Boolean) = + checkAll(lensGen, aGen) { lens, a -> lens.run { set(a, get(a)).equalUnderTheLaw(a, eq) } } - fun lensSetGet(lensGen: Gen>, aGen: Gen, bGen: Gen, eq: (B, B) -> Boolean) = - forAll(lensGen, aGen, bGen) { lens, a, b -> + suspend fun lensSetGet(lensGen: Arb>, aGen: Arb, bGen: Arb, eq: (B, B) -> Boolean) = + checkAll(lensGen, aGen, bGen) { lens, a, b -> lens.run { get(set(a, b)).equalUnderTheLaw(b, eq) } } - fun lensSetIdempotent(lensGen: Gen>, aGen: Gen, bGen: Gen, eq: (A, A) -> Boolean) = - forAll(lensGen, aGen, bGen) { lens, a, b -> + suspend fun lensSetIdempotent(lensGen: Arb>, aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean) = + checkAll(lensGen, aGen, bGen) { lens, a, b -> lens.run { set(set(a, b), b).equalUnderTheLaw(set(a, b), eq) } } - fun lensModifyIdentity(lensGen: Gen>, aGen: Gen, eq: (A, A) -> Boolean) = - forAll(lensGen, aGen) { lens, a -> + suspend fun lensModifyIdentity(lensGen: Arb>, aGen: Arb, eq: (A, A) -> Boolean) = + checkAll(lensGen, aGen) { lens, a -> lens.run { modify(a, ::identity).equalUnderTheLaw(a, eq) } } - fun lensComposeModify(lensGen: Gen>, aGen: Gen, funcGen: Gen<(B) -> B>, eq: (A, A) -> Boolean) = - forAll(lensGen, aGen, funcGen, funcGen) { lens, a, f, g -> + suspend fun lensComposeModify(lensGen: Arb>, aGen: Arb, funcGen: Arb<(B) -> B>, eq: (A, A) -> Boolean) = + checkAll(lensGen, aGen, funcGen, funcGen) { lens, a, f, g -> lens.run { modify(modify(a, f), g).equalUnderTheLaw(modify(a, g compose f), eq) } } - fun lensConsistentSetModify(lensGen: Gen>, aGen: Gen, bGen: Gen, eq: (A, A) -> Boolean) = - forAll(lensGen, aGen, bGen) { lens, a, b -> + suspend fun lensConsistentSetModify(lensGen: Arb>, aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean) = + checkAll(lensGen, aGen, bGen) { lens, a, b -> lens.run { set(a, b).equalUnderTheLaw(modify(a) { b }, eq) } diff --git a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/OptionalLaws.kt b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/OptionalLaws.kt index 6358e3eea60..efd02460e49 100644 --- a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/OptionalLaws.kt +++ b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/OptionalLaws.kt @@ -5,16 +5,18 @@ import arrow.core.identity import arrow.optics.Optional import arrow.core.test.laws.Law import arrow.core.test.laws.equalUnderTheLaw -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.PropertyContext +import io.kotest.property.arbitrary.constant +import io.kotest.property.checkAll object OptionalLaws { fun laws( - optionalGen: Gen>, - aGen: Gen, - bGen: Gen, - funcGen: Gen<(B) -> B>, + optionalGen: Arb>, + aGen: Arb, + bGen: Arb, + funcGen: Arb<(B) -> B>, eqa: (A, A) -> Boolean = { a, b -> a == b }, eqb: (B?, B?) -> Boolean = { a, b -> a == b } ): List = listOf( @@ -31,60 +33,83 @@ object OptionalLaws { */ fun laws( optional: Optional, - aGen: Gen, - bGen: Gen, - funcGen: Gen<(B) -> B>, + aGen: Arb, + bGen: Arb, + funcGen: Arb<(B) -> B>, eqa: (A, A) -> Boolean = { a, b -> a == b }, eqb: (B?, B?) -> Boolean = { a, b -> a == b } - ): List = laws(Gen.constant(optional), aGen, bGen, funcGen, eqa, eqb) + ): List = laws(Arb.constant(optional), aGen, bGen, funcGen, eqa, eqb) - fun getOptionSet(optionalGen: Gen>, aGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(optionalGen, aGen) { optional, a -> + suspend fun getOptionSet( + optionalGen: Arb>, + aGen: Arb, + eq: (A, A) -> Boolean + ): PropertyContext = + checkAll(optionalGen, aGen) { optional, a -> optional.run { getOrModify(a).fold(::identity) { set(a, it) } .equalUnderTheLaw(a, eq) } } - fun setGetOption( - optionalGen: Gen>, - aGen: Gen, - bGen: Gen, + suspend fun setGetOption( + optionalGen: Arb>, + aGen: Arb, + bGen: Arb, eq: (B?, B?) -> Boolean - ): Unit = - forAll(optionalGen, aGen, bGen) { optional, a, b -> + ): PropertyContext = + checkAll(optionalGen, aGen, bGen) { optional, a, b -> optional.run { getOrNull(set(a, b)) .equalUnderTheLaw(getOrNull(a)?.let { b }) { a, b -> eq(a, b) } } } - fun setIdempotent(optionalGen: Gen>, aGen: Gen, bGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(optionalGen, aGen, bGen) { optional, a, b -> + suspend fun setIdempotent( + optionalGen: Arb>, + aGen: Arb, + bGen: Arb, + eq: (A, A) -> Boolean + ): PropertyContext = + checkAll(optionalGen, aGen, bGen) { optional, a, b -> optional.run { set(set(a, b), b) .equalUnderTheLaw(set(a, b), eq) } } - fun modifyIdentity(optionalGen: Gen>, aGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(optionalGen, aGen) { optional, a -> + suspend fun modifyIdentity( + optionalGen: Arb>, + aGen: Arb, + eq: (A, A) -> Boolean + ): PropertyContext = + checkAll(optionalGen, aGen) { optional, a -> optional.run { modify(a, ::identity) .equalUnderTheLaw(a, eq) } } - fun composeModify(optionalGen: Gen>, aGen: Gen, funcGen: Gen<(B) -> B>, eq: (A, A) -> Boolean): Unit = - forAll(optionalGen, aGen, funcGen, funcGen) { optional, a, f, g -> + suspend fun composeModify( + optionalGen: Arb>, + aGen: Arb, + funcGen: Arb<(B) -> B>, + eq: (A, A) -> Boolean + ): PropertyContext = + checkAll(optionalGen, aGen, funcGen, funcGen) { optional, a, f, g -> optional.run { modify(modify(a, f), g) .equalUnderTheLaw(modify(a, g compose f), eq) } } - fun consistentSetModify(optionalGen: Gen>, aGen: Gen, bGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(optionalGen, aGen, bGen) { optional, a, b -> + suspend fun consistentSetModify( + optionalGen: Arb>, + aGen: Arb, + bGen: Arb, + eq: (A, A) -> Boolean + ): PropertyContext = + checkAll(optionalGen, aGen, bGen) { optional, a, b -> optional.run { set(a, b) .equalUnderTheLaw(modify(a) { b }, eq) diff --git a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/PrismLaws.kt b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/PrismLaws.kt index 2d417b1751a..b6003848a98 100644 --- a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/PrismLaws.kt +++ b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/PrismLaws.kt @@ -5,16 +5,17 @@ import arrow.core.identity import arrow.optics.Prism import arrow.core.test.laws.Law import arrow.core.test.laws.equalUnderTheLaw -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.PropertyContext +import io.kotest.property.checkAll object PrismLaws { fun laws( prism: Prism, - aGen: Gen, - bGen: Gen, - funcGen: Gen<(B) -> B>, + aGen: Arb, + bGen: Arb, + funcGen: Arb<(B) -> B>, eqa: (A, A) -> Boolean = { a, b -> a == b }, eqb: (B?, B?) -> Boolean = { a, b -> a == b } ): List = listOf( @@ -25,30 +26,30 @@ object PrismLaws { Law("Prism law: consistent set modify") { prism.consistentSetModify(aGen, bGen, eqa) } ) - fun Prism.partialRoundTripOneWay(aGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(aGen) { a -> + suspend fun Prism.partialRoundTripOneWay(aGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen) { a -> getOrModify(a).fold(::identity, ::reverseGet) .equalUnderTheLaw(a, eq) } - fun Prism.roundTripOtherWay(bGen: Gen, eq: (B?, B?) -> Boolean): Unit = - forAll(bGen) { b -> + suspend fun Prism.roundTripOtherWay(bGen: Arb, eq: (B?, B?) -> Boolean): PropertyContext = + checkAll(bGen) { b -> getOrNull(reverseGet(b)) .equalUnderTheLaw(b, eq) } - fun Prism.modifyIdentity(aGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(aGen) { a -> + suspend fun Prism.modifyIdentity(aGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen) { a -> modify(a, ::identity).equalUnderTheLaw(a, eq) } - fun Prism.composeModify(aGen: Gen, funcGen: Gen<(B) -> B>, eq: (A, A) -> Boolean): Unit = - forAll(aGen, funcGen, funcGen) { a, f, g -> + suspend fun Prism.composeModify(aGen: Arb, funcGen: Arb<(B) -> B>, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen, funcGen, funcGen) { a, f, g -> modify(modify(a, f), g).equalUnderTheLaw(modify(a, g compose f), eq) } - fun Prism.consistentSetModify(aGen: Gen, bGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(aGen, bGen) { a, b -> + suspend fun Prism.consistentSetModify(aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen, bGen) { a, b -> set(a, b).equalUnderTheLaw(modify(a) { b }, eq) } } diff --git a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/SetterLaws.kt b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/SetterLaws.kt index 4a71001efce..5f504d6272a 100644 --- a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/SetterLaws.kt +++ b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/SetterLaws.kt @@ -5,16 +5,17 @@ import arrow.core.identity import arrow.optics.Setter import arrow.core.test.laws.Law import arrow.core.test.laws.equalUnderTheLaw -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.PropertyContext +import io.kotest.property.checkAll object SetterLaws { fun laws( setter: Setter, - aGen: Gen, - bGen: Gen, - funcGen: Gen<(B) -> B>, + aGen: Arb, + bGen: Arb, + funcGen: Arb<(B) -> B>, eq: (A, A) -> Boolean = { a, b -> a == b } ) = listOf( Law("Setter law: set is idempotent") { setter.setIdempotent(aGen, bGen, eq) }, @@ -23,19 +24,23 @@ object SetterLaws { Law("Setter law: consistent set modify") { setter.consistentSetModify(aGen, bGen, eq) } ) - fun Setter.setIdempotent(aGen: Gen, bGen: Gen, eq: (A, A) -> Boolean): Unit = forAll(aGen, bGen) { a, b -> - set(set(a, b), b).equalUnderTheLaw(set(a, b), eq) - } + suspend fun Setter.setIdempotent(aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen, bGen) { a, b -> + set(set(a, b), b).equalUnderTheLaw(set(a, b), eq) + } - fun Setter.modifyIdentity(aGen: Gen, eq: (A, A) -> Boolean): Unit = forAll(aGen) { a -> - modify(a, ::identity).equalUnderTheLaw(a, eq) - } + suspend fun Setter.modifyIdentity(aGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen) { a -> + modify(a, ::identity).equalUnderTheLaw(a, eq) + } - fun Setter.composeModify(aGen: Gen, eq: (A, A) -> Boolean, funcGen: Gen<(B) -> B>): Unit = forAll(aGen, funcGen, funcGen) { a, f, g -> - modify(modify(a, f), g).equalUnderTheLaw(modify(a, g compose f), eq) - } + suspend fun Setter.composeModify(aGen: Arb, eq: (A, A) -> Boolean, funcGen: Arb<(B) -> B>): PropertyContext = + checkAll(aGen, funcGen, funcGen) { a, f, g -> + modify(modify(a, f), g).equalUnderTheLaw(modify(a, g compose f), eq) + } - fun Setter.consistentSetModify(aGen: Gen, bGen: Gen, eq: (A, A) -> Boolean): Unit = forAll(aGen, bGen) { a, b -> - modify(a) { b }.equalUnderTheLaw(set(a, b), eq) - } + suspend fun Setter.consistentSetModify(aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen, bGen) { a, b -> + modify(a) { b }.equalUnderTheLaw(set(a, b), eq) + } } diff --git a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/TraversalLaws.kt b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/TraversalLaws.kt index 5ee5a7ba93a..8a6a6165827 100644 --- a/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/TraversalLaws.kt +++ b/arrow-libs/optics/arrow-optics-test/src/main/kotlin/arrow/optics/test/laws/TraversalLaws.kt @@ -5,16 +5,18 @@ import arrow.core.identity import arrow.optics.Traversal import arrow.core.test.laws.Law import arrow.core.test.laws.equalUnderTheLaw -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.property.Arb +import io.kotest.property.PropertyContext +import io.kotest.property.checkAll +import kotlin.math.max object TraversalLaws { fun laws( traversal: Traversal, - aGen: Gen, - bGen: Gen, - funcGen: Gen<(B) -> B>, + aGen: Arb, + bGen: Arb, + funcGen: Arb<(B) -> B>, eq: (A, A) -> Boolean = { a, b -> a == b } ) = listOf( Law("Traversal law: set is idempotent") { traversal.setIdempotent(aGen, bGen, eq) }, @@ -22,19 +24,28 @@ object TraversalLaws { Law("Traversal law: compose modify") { traversal.composeModify(aGen, funcGen, eq) } ) - fun Traversal.setIdempotent(aGen: Gen, bGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(aGen, bGen) { a, b -> + suspend fun Traversal.setIdempotent(aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(max(aGen.minIterations(), bGen.minIterations()), aGen, bGen) { a, b -> set(set(a, b), b) .equalUnderTheLaw(set(a, b), eq) } - fun Traversal.modifyIdentity(aGen: Gen, eq: (A, A) -> Boolean): Unit = - forAll(aGen) { a -> + suspend fun Traversal.modifyIdentity(aGen: Arb, eq: (A, A) -> Boolean): PropertyContext = + checkAll(aGen.minIterations(), aGen) { a -> modify(a, ::identity).equalUnderTheLaw(a, eq) } - fun Traversal.composeModify(aGen: Gen, funcGen: Gen<(B) -> B>, eq: (A, A) -> Boolean): Unit = - forAll(aGen, funcGen, funcGen) { a, f, g -> + suspend fun Traversal.composeModify( + aGen: Arb, + funcGen: Arb<(B) -> B>, + eq: (A, A) -> Boolean + ): PropertyContext = + checkAll( + max(max(aGen.minIterations(), funcGen.minIterations()), funcGen.minIterations()), + aGen, + funcGen, + funcGen + ) { a, f, g -> modify(modify(a, f), g) .equalUnderTheLaw(modify(a, g compose f), eq) } diff --git a/arrow-libs/optics/arrow-optics/build.gradle b/arrow-libs/optics/arrow-optics/build.gradle index 05a06a0e7d6..596697d0d95 100644 --- a/arrow-libs/optics/arrow-optics/build.gradle +++ b/arrow-libs/optics/arrow-optics/build.gradle @@ -34,4 +34,5 @@ kotlin { dependencies { kaptTest project(":arrow-meta") + testCompile project(":arrow-optics-test") } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/DSLTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/DSLTest.kt index 8369a12c9ed..995a349d7fb 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/DSLTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/DSLTest.kt @@ -4,7 +4,7 @@ import arrow.core.None import arrow.core.test.UnitSpec import arrow.optics.typeclasses.At import arrow.optics.typeclasses.Index -import io.kotlintest.shouldBe +import io.kotest.matchers.shouldBe @optics data class Street(val number: Int, val name: String) { diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/EveryTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/EveryTest.kt index 2dd25f1f824..8ba28cf39f2 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/EveryTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/EveryTest.kt @@ -2,8 +2,11 @@ package arrow.optics import arrow.core.test.UnitSpec import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.checkAll class EveryTest : UnitSpec() { init { @@ -11,50 +14,50 @@ class EveryTest : UnitSpec() { with(Every.list()) { "asFold should behave as valid Fold: size" { - forAll(Gen.list(Gen.int())) { ints -> - size(ints) == ints.size + checkAll(Arb.list(Arb.int())) { ints -> + size(ints) shouldBe ints.size } } "asFold should behave as valid Fold: nonEmpty" { - forAll(Gen.list(Gen.int())) { ints -> - isNotEmpty(ints) == ints.isNotEmpty() + checkAll(Arb.list(Arb.int())) { ints -> + isNotEmpty(ints) shouldBe ints.isNotEmpty() } } "asFold should behave as valid Fold: isEmpty" { - forAll(Gen.list(Gen.int())) { ints -> - isEmpty(ints) == ints.isEmpty() + checkAll(Arb.list(Arb.int())) { ints -> + isEmpty(ints) shouldBe ints.isEmpty() } } "asFold should behave as valid Fold: getAll" { - forAll(Gen.list(Gen.int())) { ints -> - getAll(ints) == ints + checkAll(Arb.list(Arb.int())) { ints -> + getAll(ints) shouldBe ints } } "asFold should behave as valid Fold: combineAll" { - forAll(Gen.list(Gen.int())) { ints -> - combineAll(Monoid.int(), ints) == ints.sum() + checkAll(Arb.list(Arb.int())) { ints -> + combineAll(Monoid.int(), ints) shouldBe ints.sum() } } "asFold should behave as valid Fold: fold" { - forAll(Gen.list(Gen.int())) { ints -> - fold(Monoid.int(), ints) == ints.sum() + checkAll(Arb.list(Arb.int())) { ints -> + fold(Monoid.int(), ints) shouldBe ints.sum() } } "asFold should behave as valid Fold: headOption" { - forAll(Gen.list(Gen.int())) { ints -> - firstOrNull(ints) == ints.firstOrNull() + checkAll(Arb.list(Arb.int())) { ints -> + firstOrNull(ints) shouldBe ints.firstOrNull() } } "asFold should behave as valid Fold: lastOption" { - forAll(Gen.list(Gen.int())) { ints -> - lastOrNull(ints) == ints.lastOrNull() + checkAll(Arb.list(Arb.int())) { ints -> + lastOrNull(ints) shouldBe ints.lastOrNull() } } } @@ -62,32 +65,32 @@ class EveryTest : UnitSpec() { with(Every.list()) { "Getting all targets of a traversal" { - forAll(Gen.list(Gen.int())) { ints -> - getAll(ints) == ints + checkAll(Arb.list(Arb.int())) { ints -> + getAll(ints) shouldBe ints } } "Folding all the values of a traversal" { - forAll(Gen.list(Gen.int())) { ints -> - fold(Monoid.int(), ints) == ints.sum() + checkAll(Arb.list(Arb.int())) { ints -> + fold(Monoid.int(), ints) shouldBe ints.sum() } } "Combining all the values of a traversal" { - forAll(Gen.list(Gen.int())) { ints -> - combineAll(Monoid.int(), ints) == ints.sum() + checkAll(Arb.list(Arb.int())) { ints -> + combineAll(Monoid.int(), ints) shouldBe ints.sum() } } "Finding an number larger than 10" { - forAll(Gen.list(Gen.choose(-100, 100))) { ints -> - findOrNull(ints) { it > 10 } == ints.firstOrNull { it > 10 } + checkAll(Arb.list(Arb.int(-100..100))) { ints -> + findOrNull(ints) { it > 10 } shouldBe ints.firstOrNull { it > 10 } } } "Get the length from a traversal" { - forAll(Gen.list(Gen.int())) { ints -> - size(ints) == ints.size + checkAll(Arb.list(Arb.int())) { ints -> + size(ints) shouldBe ints.size } } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/FoldTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/FoldTest.kt index 1182bbeb6bc..81885de4715 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/FoldTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/FoldTest.kt @@ -2,8 +2,12 @@ package arrow.optics import arrow.core.test.UnitSpec import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.checkAll class FoldTest : UnitSpec() { @@ -12,8 +16,8 @@ class FoldTest : UnitSpec() { "Fold select a list that contains one" { val select = Fold.select> { it.contains(1) } - forAll(Gen.list(Gen.int())) { ints -> - select.run { getAll(ints) }.firstOrNull() == + checkAll(Arb.list(Arb.int())) { ints -> + select.run { getAll(ints) }.firstOrNull() shouldBe ints.let { if (it.contains(1)) it else null } } } @@ -21,63 +25,63 @@ class FoldTest : UnitSpec() { with(Fold.list()) { "Folding a list of ints" { - forAll(Gen.list(Gen.int())) { ints -> - fold(Monoid.int(), ints) == ints.sum() + checkAll(Arb.list(Arb.int())) { ints -> + fold(Monoid.int(), ints) shouldBe ints.sum() } } "Folding a list should yield same result as combineAll" { - forAll(Gen.list(Gen.int())) { ints -> - combineAll(Monoid.int(), ints) == ints.sum() + checkAll(Arb.list(Arb.int())) { ints -> + combineAll(Monoid.int(), ints) shouldBe ints.sum() } } "Folding and mapping a list of strings" { - forAll(Gen.list(Gen.int())) { ints -> + checkAll(Arb.list(Arb.int())) { ints -> Fold.list() - .foldMap(Monoid.int(), ints.map(Int::toString), String::toInt) == ints.sum() + .foldMap(Monoid.int(), ints.map(Int::toString), String::toInt) shouldBe ints.sum() } } "Get all targets" { - forAll(Gen.list(Gen.int())) { ints -> - getAll(ints) == ints + checkAll(Arb.list(Arb.int())) { ints -> + getAll(ints) shouldBe ints } } "Get the size of the fold" { - forAll(Gen.list(Gen.int())) { ints -> - size(ints) == ints.size + checkAll(Arb.list(Arb.int())) { ints -> + size(ints) shouldBe ints.size } } "Find the first element matching the predicate" { - forAll(Gen.list(Gen.choose(-100, 100))) { ints -> - findOrNull(ints) { it > 10 } == ints.firstOrNull { it > 10 } + checkAll(Arb.list(Arb.int(-100..100))) { ints -> + findOrNull(ints) { it > 10 } shouldBe ints.firstOrNull { it > 10 } } } "Checking existence of a target" { - forAll(Gen.list(Gen.int()), Gen.bool()) { ints, predicate -> - exists(ints) { predicate } == (predicate && ints.isNotEmpty()) + checkAll(Arb.list(Arb.int()), Arb.bool()) { ints, predicate -> + exists(ints) { predicate } shouldBe (predicate && ints.isNotEmpty()) } } "Check if all targets match the predicate" { - forAll(Gen.list(Gen.int())) { ints -> - all(ints) { it % 2 == 0 } == ints.all { it % 2 == 0 } + checkAll(Arb.list(Arb.int())) { ints -> + all(ints) { it % 2 == 0 } shouldBe ints.all { it % 2 == 0 } } } "Check if there is no target" { - forAll(Gen.list(Gen.int())) { ints -> - isEmpty(ints) == ints.isEmpty() + checkAll(Arb.list(Arb.int())) { ints -> + isEmpty(ints) shouldBe ints.isEmpty() } } "Check if there is a target" { - forAll(Gen.list(Gen.int())) { ints -> - isNotEmpty(ints) == ints.isNotEmpty() + checkAll(Arb.list(Arb.int())) { ints -> + isNotEmpty(ints) shouldBe ints.isNotEmpty() } } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/GetterTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/GetterTest.kt index baaf8172fdb..bcf8b7817fd 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/GetterTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/GetterTest.kt @@ -4,8 +4,10 @@ import arrow.core.Either.Left import arrow.core.Either.Right import arrow.core.test.UnitSpec import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.int +import io.kotest.property.checkAll class GetterTest : UnitSpec() { @@ -18,50 +20,50 @@ class GetterTest : UnitSpec() { with(tokenGetter) { "asFold should behave as valid Fold: size" { - forAll(genToken) { token -> - size(token) == 1 + checkAll(genToken) { token -> + size(token) shouldBe 1 } } "asFold should behave as valid Fold: nonEmpty" { - forAll(genToken) { token -> - isNotEmpty(token) + checkAll(genToken) { token -> + isNotEmpty(token) shouldBe true } } "asFold should behave as valid Fold: isEmpty" { - forAll(genToken) { token -> - !isEmpty(token) + checkAll(genToken) { token -> + !isEmpty(token) shouldBe true } } "asFold should behave as valid Fold: getAll" { - forAll(genToken) { token -> - getAll(token) == listOf(token.value) + checkAll(genToken) { token -> + getAll(token) shouldBe listOf(token.value) } } "asFold should behave as valid Fold: combineAll" { - forAll(genToken) { token -> - combineAll(Monoid.string(), token) == token.value + checkAll(genToken) { token -> + combineAll(Monoid.string(), token) shouldBe token.value } } "asFold should behave as valid Fold: fold" { - forAll(genToken) { token -> - fold(Monoid.string(), token) == token.value + checkAll(genToken) { token -> + fold(Monoid.string(), token) shouldBe token.value } } "asFold should behave as valid Fold: headOption" { - forAll(genToken) { token -> - firstOrNull(token) == token.value + checkAll(genToken) { token -> + firstOrNull(token) shouldBe token.value } } "asFold should behave as valid Fold: lastOption" { - forAll(genToken) { token -> - lastOrNull(token) == token.value + checkAll(genToken) { token -> + lastOrNull(token) shouldBe token.value } } } @@ -69,27 +71,27 @@ class GetterTest : UnitSpec() { with(tokenGetter) { "Getting the target should always yield the exact result" { - forAll { value: String -> - get(Token(value)) == value + checkAll { value: String -> + get(Token(value)) shouldBe value } } "Finding a target using a predicate within a Getter should be wrapped in the correct option result" { - forAll { value: String, predicate: Boolean -> - findOrNull(Token(value)) { predicate }?.let { true } ?: false == predicate + checkAll { value: String, predicate: Boolean -> + findOrNull(Token(value)) { predicate }?.let { true } ?: false shouldBe predicate } } "Checking existence of a target should always result in the same result as predicate" { - forAll { value: String, predicate: Boolean -> - any(Token(value)) { predicate } == predicate + checkAll { value: String, predicate: Boolean -> + any(Token(value)) { predicate } shouldBe predicate } } } "Zipping two lenses should yield a tuple of the targets" { - forAll { value: String -> - length.zip(upper).get(value) == value.length to value.toUpperCase() + checkAll { value: String -> + length.zip(upper).get(value) shouldBe (value.length to value.toUpperCase()) } } @@ -97,31 +99,31 @@ class GetterTest : UnitSpec() { val userTokenStringGetter = userGetter compose tokenGetter val joinedGetter = tokenGetter.choice(userTokenStringGetter) - forAll { tokenValue: String -> + checkAll { tokenValue: String -> val token = Token(tokenValue) val user = User(token) - joinedGetter.get(Left(token)) == joinedGetter.get(Right(user)) + joinedGetter.get(Left(token)) shouldBe joinedGetter.get(Right(user)) } } "Pairing two disjoint getters should yield a pair of their results" { val splitGetter: Getter, Pair> = tokenGetter.split(userGetter) - forAll(genToken, genUser) { token: Token, user: User -> - splitGetter.get(token to user) == token.value to user.token + checkAll(genToken, genUser) { token: Token, user: User -> + splitGetter.get(token to user) shouldBe (token.value to user.token) } } "Creating a first pair with a type should result in the target to value" { val first = tokenGetter.first() - forAll(genToken, Gen.int()) { token: Token, int: Int -> - first.get(token to int) == token.value to int + checkAll(genToken, Arb.int()) { token: Token, int: Int -> + first.get(token to int) shouldBe (token.value to int) } } "Creating a second pair with a type should result in the value target" { val first = tokenGetter.second() - forAll(Gen.int(), genToken) { int: Int, token: Token -> - first.get(int to token) == int to token.value + checkAll(Arb.int(), genToken) { int: Int, token: Token -> + first.get(int to token) shouldBe (int to token.value) } } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/IsoTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/IsoTest.kt index 83ad096f338..1630db51189 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/IsoTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/IsoTest.kt @@ -10,8 +10,12 @@ import arrow.optics.test.laws.PrismLaws import arrow.optics.test.laws.SetterLaws import arrow.optics.test.laws.TraversalLaws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.string +import io.kotest.property.checkAll class IsoTest : UnitSpec() { @@ -23,96 +27,97 @@ class IsoTest : UnitSpec() { ) testLaws( + "Iso token - ", LensLaws.laws( lens = tokenIso, aGen = genToken, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()) + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()) ), PrismLaws.laws( prism = aIso, aGen = genSumTypeA, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()) + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()) ), TraversalLaws.laws( traversal = tokenIso, aGen = genToken, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()) + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()) ), OptionalLaws.laws( optional = tokenIso, aGen = genToken, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()) + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()) ), SetterLaws.laws( setter = tokenIso, aGen = genToken, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()) + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()) ), IsoLaws.laws( iso = tokenIso, aGen = genToken, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()) + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()) ) ) with(tokenIso) { "asFold should behave as valid Fold: size" { - forAll(genToken) { token -> - size(token) == 1 + checkAll(genToken) { token -> + size(token) shouldBe 1 } } "asFold should behave as valid Fold: nonEmpty" { - forAll(genToken) { token -> - isNotEmpty(token) + checkAll(genToken) { token -> + isNotEmpty(token) shouldBe true } } "asFold should behave as valid Fold: isEmpty" { - forAll(genToken) { token -> - !isEmpty(token) + checkAll(genToken) { token -> + !isEmpty(token) shouldBe true } } "asFold should behave as valid Fold: getAll" { - forAll(genToken) { token -> - getAll(token) == listOf(token.value) + checkAll(genToken) { token -> + getAll(token) shouldBe listOf(token.value) } } "asFold should behave as valid Fold: combineAll" { - forAll(genToken) { token -> - combineAll(Monoid.string(), token) == token.value + checkAll(genToken) { token -> + combineAll(Monoid.string(), token) shouldBe token.value } } "asFold should behave as valid Fold: fold" { - forAll(genToken) { token -> - fold(Monoid.string(), token) == token.value + checkAll(genToken) { token -> + fold(Monoid.string(), token) shouldBe token.value } } "asFold should behave as valid Fold: headOption" { - forAll(genToken) { token -> - firstOrNull(token) == token.value + checkAll(genToken) { token -> + firstOrNull(token) shouldBe token.value } } "asFold should behave as valid Fold: lastOption" { - forAll(genToken) { token -> - lastOrNull(token) == token.value + checkAll(genToken) { token -> + lastOrNull(token) shouldBe token.value } } } @@ -120,89 +125,89 @@ class IsoTest : UnitSpec() { with(tokenIso) { "asGetter should behave as valid Getter: get" { - forAll(genToken) { token -> - get(token) == tokenGetter.get(token) + checkAll(genToken) { token -> + get(token) shouldBe tokenGetter.get(token) } } "asGetter should behave as valid Getter: find" { - forAll(genToken, Gen.functionAToB(Gen.bool())) { token, p -> - findOrNull(token, p) == tokenGetter.findOrNull(token, p) + checkAll(genToken, Arb.functionAToB(Arb.bool())) { token, p -> + findOrNull(token, p) shouldBe tokenGetter.findOrNull(token, p) } } "asGetter should behave as valid Getter: exist" { - forAll(genToken, Gen.functionAToB(Gen.bool())) { token, p -> - any(token, p) == tokenGetter.any(token, p) + checkAll(genToken, Arb.functionAToB(Arb.bool())) { token, p -> + any(token, p) shouldBe tokenGetter.any(token, p) } } } "Lifting a function should yield the same result as not yielding" { - forAll(genToken, Gen.string()) { token, value -> - tokenIso.modify(token) { value } == tokenIso.lift { value }(token) + checkAll(genToken, Arb.string()) { token, value -> + tokenIso.modify(token) { value } shouldBe tokenIso.lift { value }(token) } } "Creating a first pair with a type should result in the target to value" { val first = tokenIso.first() - forAll(genToken, Gen.int()) { token: Token, int: Int -> - first.get(token to int) == token.value to int + checkAll(genToken, Arb.int()) { token: Token, int: Int -> + first.get(token to int) shouldBe (token.value to int) } } "Creating a second pair with a type should result in the value to target" { val second = tokenIso.second() - forAll(Gen.int(), genToken) { int: Int, token: Token -> - second.get(int to token) == int to token.value + checkAll(Arb.int(), genToken) { int: Int, token: Token -> + second.get(int to token) shouldBe (int to token.value) } } "Creating a left with a type should result in a sum target to value" { val left = tokenIso.left() - forAll(genToken, Gen.int()) { token: Token, int: Int -> - left.get(Either.Left(token)) == Either.Left(token.value) && - left.get(Either.Right(int)) == Either.Right(int) + checkAll(genToken, Arb.int()) { token: Token, int: Int -> + left.get(Either.Left(token)) shouldBe Either.Left(token.value) + left.get(Either.Right(int)) shouldBe Either.Right(int) } } "Creating a right with a type should result in a sum value to target" { val left = tokenIso.right() - forAll(genToken, Gen.int()) { token: Token, int: Int -> - left.get(Either.Left(int)) == Either.Left(int) && - left.get(Either.Right(token)) == Either.Right(token.value) + checkAll(genToken, Arb.int()) { token: Token, int: Int -> + left.get(Either.Left(int)) shouldBe Either.Left(int) + left.get(Either.Right(token)) shouldBe Either.Right(token.value) } } "Finding a target using a predicate within a Iso should be wrapped in the correct option result" { - forAll { predicate: Boolean -> - tokenIso.findOrNull(Token("any value")) { predicate }?.let { true } ?: false == predicate + checkAll { predicate: Boolean -> + tokenIso.findOrNull(Token("any value")) { predicate }?.let { true } ?: false shouldBe predicate } } "Checking existence predicate over the target should result in same result as predicate" { - forAll { predicate: Boolean -> - tokenIso.any(Token("any value")) { predicate } == predicate + checkAll { predicate: Boolean -> + tokenIso.any(Token("any value")) { predicate } shouldBe predicate } } "Pairing two disjoint isos together" { val joinedIso = tokenIso split userIso - forAll { tokenValue: String -> + checkAll { tokenValue: String -> val token = Token(tokenValue) val user = User(token) - joinedIso.get(token to user) == tokenValue to token + joinedIso.get(token to user) shouldBe (tokenValue to token) } } "Composing isos should result in an iso of the first iso's value with the second iso's target" { val composedIso = userIso compose tokenIso - forAll { tokenValue: String -> + checkAll { tokenValue: String -> val token = Token(tokenValue) val user = User(token) - composedIso.get(user) == tokenValue + composedIso.get(user) shouldBe tokenValue } } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/LensTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/LensTest.kt index 08063caffb2..6f40a0097e8 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/LensTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/LensTest.kt @@ -9,132 +9,138 @@ import arrow.optics.test.laws.OptionalLaws import arrow.optics.test.laws.SetterLaws import arrow.optics.test.laws.TraversalLaws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.string +import io.kotest.property.checkAll class LensTest : UnitSpec() { init { testLaws( + "TokenLens - ", LensLaws.laws( lens = tokenLens, aGen = genToken, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()) + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()) ), TraversalLaws.laws( traversal = tokenLens, aGen = genToken, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ), OptionalLaws.laws( optional = tokenLens, aGen = genToken, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ), SetterLaws.laws( setter = tokenLens, aGen = genToken, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ) ) testLaws( + "Identity Lens - ", LensLaws.laws( lens = Lens.id(), - aGen = Gen.int(), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.int(), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), ) ) "asFold should behave as valid Fold: size" { - forAll(genToken) { token -> - tokenLens.size(token) == 1 + checkAll(genToken) { token -> + tokenLens.size(token) shouldBe 1 } } "asFold should behave as valid Fold: nonEmpty" { - forAll(genToken) { token -> - tokenLens.isNotEmpty(token) + checkAll(genToken) { token -> + tokenLens.isNotEmpty(token) shouldBe true } } "asFold should behave as valid Fold: isEmpty" { - forAll(genToken) { token -> - !tokenLens.isEmpty(token) + checkAll(genToken) { token -> + !tokenLens.isEmpty(token) shouldBe true } } "asFold should behave as valid Fold: getAll" { - forAll(genToken) { token -> - tokenLens.getAll(token) == listOf(token.value) + checkAll(genToken) { token -> + tokenLens.getAll(token) shouldBe listOf(token.value) } } "asFold should behave as valid Fold: combineAll" { - forAll(genToken) { token -> - tokenLens.combineAll(Monoid.string(), token) == token.value + checkAll(genToken) { token -> + tokenLens.combineAll(Monoid.string(), token) shouldBe token.value } } "asFold should behave as valid Fold: fold" { - forAll(genToken) { token -> - tokenLens.fold(Monoid.string(), token) == token.value + checkAll(genToken) { token -> + tokenLens.fold(Monoid.string(), token) shouldBe token.value } } "asFold should behave as valid Fold: headOption" { - forAll(genToken) { token -> - tokenLens.firstOrNull(token) == token.value + checkAll(genToken) { token -> + tokenLens.firstOrNull(token) shouldBe token.value } } "asFold should behave as valid Fold: lastOption" { - forAll(genToken) { token -> - tokenLens.lastOrNull(token) == token.value + checkAll(genToken) { token -> + tokenLens.lastOrNull(token) shouldBe token.value } } "asGetter should behave as valid Getter: get" { - forAll(genToken) { token -> - tokenLens.get(token) == tokenGetter.get(token) + checkAll(genToken) { token -> + tokenLens.get(token) shouldBe tokenGetter.get(token) } } "asGetter should behave as valid Getter: find" { - forAll(genToken, Gen.functionAToB(Gen.bool())) { token, p -> - tokenLens.findOrNull(token, p) == tokenGetter.findOrNull(token, p) + checkAll(genToken, Arb.functionAToB(Arb.bool())) { token, p -> + tokenLens.findOrNull(token, p) shouldBe tokenGetter.findOrNull(token, p) } } "asGetter should behave as valid Getter: exist" { - forAll(genToken, Gen.functionAToB(Gen.bool())) { token, p -> - tokenLens.any(token, p) == tokenGetter.any(token, p) + checkAll(genToken, Arb.functionAToB(Arb.bool())) { token, p -> + tokenLens.any(token, p) shouldBe tokenGetter.any(token, p) } } "Lifting a function should yield the same result as not yielding" { - forAll(genToken, Gen.string()) { token, value -> - tokenLens.set(token, value) == tokenLens.lift { value }(token) + checkAll(genToken, Arb.string()) { token, value -> + tokenLens.set(token, value) shouldBe tokenLens.lift { value }(token) } } "Finding a target using a predicate within a Lens should be wrapped in the correct option result" { - forAll { predicate: Boolean -> - tokenLens.findOrNull(Token("any value")) { predicate }?.let { true } ?: false == predicate + checkAll { predicate: Boolean -> + tokenLens.findOrNull(Token("any value")) { predicate }?.let { true } ?: false shouldBe predicate } } "Checking existence predicate over the target should result in same result as predicate" { - forAll { predicate: Boolean -> - tokenLens.any(Token("any value")) { predicate } == predicate + checkAll { predicate: Boolean -> + tokenLens.any(Token("any value")) { predicate } shouldBe predicate } } @@ -142,31 +148,31 @@ class LensTest : UnitSpec() { val userTokenStringLens = userLens compose tokenLens val joinedLens = tokenLens choice userTokenStringLens - forAll { tokenValue: String -> + checkAll { tokenValue: String -> val token = Token(tokenValue) val user = User(token) - joinedLens.get(Left(token)) == joinedLens.get(Right(user)) + joinedLens.get(Left(token)) shouldBe joinedLens.get(Right(user)) } } "Pairing two disjoint lenses should yield a pair of their results" { val spiltLens: Lens, Pair> = tokenLens split userLens - forAll(genToken, genUser) { token: Token, user: User -> - spiltLens.get(token to user) == token.value to user.token + checkAll(genToken, genUser) { token: Token, user: User -> + spiltLens.get(token to user) shouldBe (token.value to user.token) } } "Creating a first pair with a type should result in the target to value" { val first = tokenLens.first() - forAll(genToken, Gen.int()) { token: Token, int: Int -> - first.get(token to int) == token.value to int + checkAll(genToken, Arb.int()) { token: Token, int: Int -> + first.get(token to int) shouldBe (token.value to int) } } "Creating a second pair with a type should result in the value target" { val second = tokenLens.second() - forAll(Gen.int(), genToken) { int: Int, token: Token -> - second.get(int to token) == int to token.value + checkAll(Arb.int(), genToken) { int: Int, token: Token -> + second.get(int to token) shouldBe (int to token.value) } } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/OptionalTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/OptionalTest.kt index 4c0a3733254..69d2ad9c7e7 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/OptionalTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/OptionalTest.kt @@ -8,180 +8,166 @@ import arrow.core.test.UnitSpec import arrow.core.test.generators.functionAToB import arrow.core.toOption import arrow.optics.test.laws.OptionalLaws -import arrow.optics.test.laws.SetterLaws -import arrow.optics.test.laws.TraversalLaws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.pair +import io.kotest.property.checkAll class OptionalTest : UnitSpec() { init { - testLaws(OptionalLaws.laws( - optional = Optional.listHead(), - aGen = Gen.list(Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), - )) - - testLaws(OptionalLaws.laws( - optional = Optional.id(), - aGen = Gen.int(), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), - )) - - testLaws(OptionalLaws.laws( - optional = Optional.listHead().first(), - aGen = Gen.pair(Gen.list(Gen.int()), Gen.bool()), - bGen = Gen.pair(Gen.int(), Gen.bool()), - funcGen = Gen.functionAToB(Gen.pair(Gen.int(), Gen.bool())), - )) - - testLaws(OptionalLaws.laws( - optional = Optional.listHead().first(), - aGen = Gen.pair(Gen.list(Gen.int()), Gen.bool()), - bGen = Gen.pair(Gen.int(), Gen.bool()), - funcGen = Gen.functionAToB(Gen.pair(Gen.int(), Gen.bool())), - )) - - testLaws(OptionalLaws.laws( - optional = Optional.listHead().second(), - aGen = Gen.pair(Gen.bool(), Gen.list(Gen.int())), - bGen = Gen.pair(Gen.bool(), Gen.int()), - funcGen = Gen.functionAToB(Gen.pair(Gen.bool(), Gen.int())), - )) - - testLaws(TraversalLaws.laws( - traversal = Optional.listHead(), - aGen = Gen.list(Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), - )) - - testLaws(SetterLaws.laws( - setter = Optional.listHead(), - aGen = Gen.list(Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), - )) + testLaws( + "Optional identity - ", + OptionalLaws.laws( + optional = Optional.id(), + aGen = Arb.int(), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), + ) + ) + + testLaws( + "Optional first head - ", + OptionalLaws.laws( + optional = Optional.listHead().first(), + aGen = Arb.pair(Arb.list(Arb.int()), Arb.bool()), + bGen = Arb.pair(Arb.int(), Arb.bool()), + funcGen = Arb.functionAToB(Arb.pair(Arb.int(), Arb.bool())), + ) + ) + + testLaws( + "Optional second head - ", + OptionalLaws.laws( + optional = Optional.listHead().second(), + aGen = Arb.pair(Arb.bool(), Arb.list(Arb.int())), + bGen = Arb.pair(Arb.bool(), Arb.int()), + funcGen = Arb.functionAToB(Arb.pair(Arb.bool(), Arb.int())), + ) + ) "asSetter should set absent optional" { - forAll(genIncompleteUser, genToken) { user, token -> + checkAll(genIncompleteUser, genToken) { user, token -> val updatedUser = incompleteUserTokenOptional.set(user, token) - incompleteUserTokenOptional.getOrNull(updatedUser) != null + incompleteUserTokenOptional.getOrNull(updatedUser).shouldNotBeNull() } } with(Optional.listHead()) { "asFold should behave as valid Fold: size" { - forAll { ints: List -> - size(ints) == ints.firstOrNull().toOption().map { 1 }.getOrElse { 0 } + checkAll { ints: List -> + size(ints) shouldBe ints.firstOrNull().toOption().map { 1 }.getOrElse { 0 } } } "asFold should behave as valid Fold: nonEmpty" { - forAll { ints: List -> - isNotEmpty(ints) == ints.firstOrNull().toOption().nonEmpty() + checkAll { ints: List -> + isNotEmpty(ints) shouldBe ints.firstOrNull().toOption().nonEmpty() } } "asFold should behave as valid Fold: isEmpty" { - forAll { ints: List -> - isEmpty(ints) == ints.firstOrNull().toOption().isEmpty() + checkAll { ints: List -> + isEmpty(ints) shouldBe ints.firstOrNull().toOption().isEmpty() } } "asFold should behave as valid Fold: getAll" { - forAll { ints: List -> - getAll(ints) == ints.firstOrNull().toOption().toList() + checkAll { ints: List -> + getAll(ints) shouldBe ints.firstOrNull().toOption().toList() } } "asFold should behave as valid Fold: combineAll" { - forAll { ints: List -> - combineAll(Monoid.int(), ints) == + checkAll { ints: List -> + combineAll(Monoid.int(), ints) shouldBe ints.firstOrNull().toOption().fold({ Monoid.int().empty() }, ::identity) } } "asFold should behave as valid Fold: fold" { - forAll { ints: List -> - fold(Monoid.int(), ints) == + checkAll { ints: List -> + fold(Monoid.int(), ints) shouldBe ints.firstOrNull().toOption().fold({ Monoid.int().empty() }, ::identity) } } "asFold should behave as valid Fold: headOption" { - forAll { ints: List -> - firstOrNull(ints) == ints.firstOrNull() + checkAll { ints: List -> + firstOrNull(ints) shouldBe ints.firstOrNull() } } // TODO FIX // "asFold should behave as valid Fold: lastOption" { -// forAll { ints: List -> +// checkAll { ints: List -> // lastOrNull(ints) shouldBe ints.lastOrNull() // } // } } "unit should always " { - forAll { string: String -> - Optional.void().getOrNull(string) == null + checkAll { string: String -> + Optional.void().getOrNull(string) shouldBe null } } "unit should always return source when setting target" { - forAll { int: Int, string: String -> - Optional.void().set(string, int) == string + checkAll { int: Int, string: String -> + Optional.void().set(string, int) shouldBe string } } "Checking if there is no target" { - forAll(Gen.list(Gen.int())) { list -> - Optional.listHead().isNotEmpty(list) == list.isNotEmpty() + checkAll(Arb.list(Arb.int())) { list -> + Optional.listHead().isNotEmpty(list) shouldBe list.isNotEmpty() } } "Lift should be consistent with modify" { - forAll(Gen.list(Gen.int())) { list -> + checkAll(Arb.list(Arb.int())) { list -> val f = { i: Int -> i + 5 } - Optional.listHead().lift(f)(list) == Optional.listHead().modify(list, f) + Optional.listHead().lift(f)(list) shouldBe Optional.listHead().modify(list, f) } } "Checking if a target exists" { - forAll(Gen.list(Gen.int())) { list -> - Optional.listHead().isEmpty(list) == list.isEmpty() + checkAll(Arb.list(Arb.int())) { list -> + Optional.listHead().isEmpty(list) shouldBe list.isEmpty() } } "Finding a target using a predicate should be wrapped in the correct option result" { - forAll(Gen.list(Gen.int()), Gen.bool()) { list, predicate -> - Optional.listHead().findOrNull(list) { predicate }?.let { true } ?: false == (predicate && list.isNotEmpty()) + checkAll(Arb.list(Arb.int()), Arb.bool()) { list, predicate -> + Optional.listHead().findOrNull(list) { predicate }?.let { true } + ?: false shouldBe (predicate && list.isNotEmpty()) } } "Checking existence predicate over the target should result in same result as predicate" { - forAll(Gen.list(Gen.int()), Gen.bool()) { list, predicate -> - Optional.listHead().exists(list) { predicate } == (predicate && list.isNotEmpty()) + checkAll(Arb.list(Arb.int()), Arb.bool()) { list, predicate -> + Optional.listHead().exists(list) { predicate } shouldBe (predicate && list.isNotEmpty()) } } "Checking satisfaction of predicate over the target should result in opposite result as predicate" { - forAll(Gen.list(Gen.int()), Gen.bool()) { list, predicate -> - Optional.listHead().all(list) { predicate } == if (list.isEmpty()) true else predicate + checkAll(Arb.list(Arb.int()), Arb.bool()) { list, predicate -> + Optional.listHead().all(list) { predicate } shouldBe if (list.isEmpty()) true else predicate } } "Joining two optionals together with same target should yield same result" { val joinedOptional = Optional.listHead().choice(defaultHead) - forAll(Gen.int()) { int -> - joinedOptional.getOrNull(Left(listOf(int))) == joinedOptional.getOrNull(Right(int)) + checkAll(Arb.int()) { int -> + joinedOptional.getOrNull(Left(listOf(int))) shouldBe joinedOptional.getOrNull(Right(int)) } } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/PrismTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/PrismTest.kt index f148b02cd37..5d963fc7386 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/PrismTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/PrismTest.kt @@ -8,186 +8,196 @@ import arrow.optics.test.laws.PrismLaws import arrow.optics.test.laws.SetterLaws import arrow.optics.test.laws.TraversalLaws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.pair +import io.kotest.property.arbitrary.string +import io.kotest.property.checkAll class PrismTest : UnitSpec() { init { testLaws( + "Prism sum - ", PrismLaws.laws( prism = sumPrism, aGen = genSum, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ), SetterLaws.laws( setter = sumPrism, aGen = genSum, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ), TraversalLaws.laws( traversal = sumPrism, aGen = genSum, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ), OptionalLaws.laws( optional = sumPrism, aGen = genSum, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ) ) testLaws( + "Prism sum first - ", PrismLaws.laws( prism = sumPrism.first(), - aGen = Gen.pair(genSum, Gen.int()), - bGen = Gen.pair(Gen.string(), Gen.int()), - funcGen = Gen.functionAToB(Gen.pair(Gen.string(), Gen.int())), + aGen = Arb.pair(genSum, Arb.int()), + bGen = Arb.pair(Arb.string(), Arb.int()), + funcGen = Arb.functionAToB(Arb.pair(Arb.string(), Arb.int())), ) ) testLaws( + "Prism sum second - ", PrismLaws.laws( prism = sumPrism.second(), - aGen = Gen.pair(Gen.int(), genSum), - bGen = Gen.pair(Gen.int(), Gen.string()), - funcGen = Gen.functionAToB(Gen.pair(Gen.int(), Gen.string())), + aGen = Arb.pair(Arb.int(), genSum), + bGen = Arb.pair(Arb.int(), Arb.string()), + funcGen = Arb.functionAToB(Arb.pair(Arb.int(), Arb.string())), ) ) testLaws( + "Prism sum right - ", PrismLaws.laws( prism = sumPrism.right(), - aGen = Gen.either(Gen.int(), genSum), - bGen = Gen.either(Gen.int(), Gen.string()), - funcGen = Gen.functionAToB(Gen.either(Gen.int(), Gen.string())), + aGen = Arb.either(Arb.int(), genSum), + bGen = Arb.either(Arb.int(), Arb.string()), + funcGen = Arb.functionAToB(Arb.either(Arb.int(), Arb.string())), ) ) testLaws( + "Prism sum left - ", PrismLaws.laws( prism = sumPrism.left(), - aGen = Gen.either(genSum, Gen.int()), - bGen = Gen.either(Gen.string(), Gen.int()), - funcGen = Gen.functionAToB(Gen.either(Gen.string(), Gen.int())), + aGen = Arb.either(genSum, Arb.int()), + bGen = Arb.either(Arb.string(), Arb.int()), + funcGen = Arb.functionAToB(Arb.either(Arb.string(), Arb.int())), ) ) testLaws( + "Prism identity - ", PrismLaws.laws( prism = Prism.id(), - aGen = Gen.either(Gen.int(), Gen.int()), - bGen = Gen.either(Gen.int(), Gen.int()), - funcGen = Gen.functionAToB(Gen.either(Gen.int(), Gen.int())), + aGen = Arb.either(Arb.int(), Arb.int()), + bGen = Arb.either(Arb.int(), Arb.int()), + funcGen = Arb.functionAToB(Arb.either(Arb.int(), Arb.int())), ) ) with(sumPrism) { - "asFold should behave as valid Fold: size" { - forAll(genSum) { sum: SumType -> - size(sum) == sumPrism.getOrNull(sum)?.let { 1 } ?: 0 + checkAll(genSum) { sum: SumType -> + size(sum) shouldBe (sumPrism.getOrNull(sum)?.let { 1 } ?: 0) } } "asFold should behave as valid Fold: nonEmpty" { - forAll(genSum) { sum: SumType -> - isNotEmpty(sum) == (sumPrism.getOrNull(sum) != null) + checkAll(genSum) { sum: SumType -> + isNotEmpty(sum) shouldBe (sumPrism.getOrNull(sum) != null) } } "asFold should behave as valid Fold: isEmpty" { - forAll(genSum) { sum: SumType -> - isEmpty(sum) == (sumPrism.getOrNull(sum) == null) + checkAll(genSum) { sum: SumType -> + isEmpty(sum) shouldBe (sumPrism.getOrNull(sum) == null) } } "asFold should behave as valid Fold: getAll" { - forAll(genSum) { sum: SumType -> - getAll(sum) == listOfNotNull(sumPrism.getOrNull(sum)) + checkAll(genSum) { sum: SumType -> + getAll(sum) shouldBe listOfNotNull(sumPrism.getOrNull(sum)) } } "asFold should behave as valid Fold: combineAll" { - forAll(genSum) { sum: SumType -> - combineAll(Monoid.string(), sum) == - sumPrism.getOrNull(sum) ?: Monoid.string().empty() + checkAll(genSum) { sum: SumType -> + combineAll(Monoid.string(), sum) shouldBe + (sumPrism.getOrNull(sum) ?: Monoid.string().empty()) } } "asFold should behave as valid Fold: fold" { - forAll(genSum) { sum: SumType -> - fold(Monoid.string(), sum) == - sumPrism.getOrNull(sum) ?: Monoid.string().empty() + checkAll(genSum) { sum: SumType -> + fold(Monoid.string(), sum) shouldBe + (sumPrism.getOrNull(sum) ?: Monoid.string().empty()) } } "asFold should behave as valid Fold: headOption" { - forAll(genSum) { sum: SumType -> - firstOrNull(sum) == sumPrism.getOrNull(sum) + checkAll(genSum) { sum: SumType -> + firstOrNull(sum) shouldBe sumPrism.getOrNull(sum) } } "asFold should behave as valid Fold: lastOption" { - forAll(genSum) { sum: SumType -> - lastOrNull(sum) == sumPrism.getOrNull(sum) + checkAll(genSum) { sum: SumType -> + lastOrNull(sum) shouldBe sumPrism.getOrNull(sum) } } } "Joining two prisms together with same target should yield same result" { - forAll(genSum) { a -> - (sumPrism compose stringPrism).getOrNull(a) == sumPrism.getOrNull(a)?.let(stringPrism::getOrNull) && - (sumPrism + stringPrism).getOrNull(a) == (sumPrism compose stringPrism).getOrNull(a) + checkAll(genSum) { a -> + (sumPrism compose stringPrism).getOrNull(a) shouldBe sumPrism.getOrNull(a)?.let(stringPrism::getOrNull) + (sumPrism + stringPrism).getOrNull(a) shouldBe (sumPrism compose stringPrism).getOrNull(a) } } "Checking if a prism exists with a target" { - forAll(genSum, genSum, Gen.bool()) { a, other, bool -> - Prism.only(a) { _, _ -> bool }.isEmpty(other) == bool + checkAll(genSum, genSum, Arb.bool()) { a, other, bool -> + Prism.only(a) { _, _ -> bool }.isEmpty(other) shouldBe bool } } "Checking if there is no target" { - forAll(genSum) { sum -> - sumPrism.isEmpty(sum) == sum !is SumType.A + checkAll(genSum) { sum -> + sumPrism.isEmpty(sum) shouldBe (sum !is SumType.A) } } "Checking if a target exists" { - forAll(genSum) { sum -> - sumPrism.isNotEmpty(sum) == sum is SumType.A + checkAll(genSum) { sum -> + sumPrism.isNotEmpty(sum) shouldBe (sum is SumType.A) } } "Setting a target on a prism should set the correct target" { - forAll(genSumTypeA, Gen.string()) { a, string -> - (sumPrism.setNullable(a, string)!!) == a.copy(string = string) + checkAll(genSumTypeA, Arb.string()) { a, string -> + (sumPrism.setNullable(a, string)!!) shouldBe a.copy(string = string) } } "Finding a target using a predicate within a Lens should be wrapped in the correct option result" { - forAll(genSum, Gen.bool()) { sum, predicate -> - sumPrism.findOrNull(sum) { predicate }?.let { true } ?: false == (predicate && sum is SumType.A) + checkAll(genSum, Arb.bool()) { sum, predicate -> + sumPrism.findOrNull(sum) { predicate }?.let { true } ?: false shouldBe (predicate && sum is SumType.A) } } "Checking existence predicate over the target should result in same result as predicate" { - forAll(genSum, Gen.bool()) { sum, predicate -> - sumPrism.any(sum) { predicate } == (predicate && sum is SumType.A) + checkAll(genSum, Arb.bool()) { sum, predicate -> + sumPrism.any(sum) { predicate } shouldBe (predicate && sum is SumType.A) } } "Checking satisfaction of predicate over the target should result in opposite result as predicate" { - forAll(genSum, Gen.bool()) { sum, predicate -> - sumPrism.all(sum) { predicate } == (predicate || sum is SumType.B) + checkAll(genSum, Arb.bool()) { sum, predicate -> + sumPrism.all(sum) { predicate } shouldBe (predicate || sum is SumType.B) } } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/SetterTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/SetterTest.kt index 68ca9052914..908d2db9800 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/SetterTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/SetterTest.kt @@ -6,28 +6,33 @@ import arrow.core.right import arrow.core.test.UnitSpec import arrow.core.test.generators.functionAToB import arrow.optics.test.laws.SetterLaws -import io.kotlintest.properties.Gen -import io.kotlintest.properties.forAll +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.string +import io.kotest.property.checkAll class SetterTest : UnitSpec() { init { testLaws( + "Setter identity - ", SetterLaws.laws( setter = Setter.id(), - aGen = Gen.int(), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.int(), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), ) ) testLaws( + "Setter token - ", SetterLaws.laws( setter = tokenSetter, aGen = genToken, - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ) ) @@ -38,15 +43,15 @@ class SetterTest : UnitSpec() { val token = Token(oldValue) val user = User(token) - forAll { value: String -> - joinedSetter.set(token.left(), value).swap().getOrElse { Token("Wrong value") }.value == + checkAll { value: String -> + joinedSetter.set(token.left(), value).swap().getOrElse { Token("Wrong value") }.value shouldBe joinedSetter.set(user.right(), value).getOrElse { User(Token("Wrong value")) }.token.value } } "Lifting a function should yield the same result as direct modify" { - forAll(genToken, Gen.string()) { token, value -> - tokenSetter.modify(token) { value } == tokenSetter.lift { value }(token) + checkAll(genToken, Arb.string()) { token, value -> + tokenSetter.modify(token) { value } shouldBe tokenSetter.lift { value }(token) } } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/TestDomain.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/TestDomain.kt index ee7dfb9e42d..a10467b9e96 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/TestDomain.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/TestDomain.kt @@ -4,19 +4,24 @@ import arrow.core.Option import arrow.core.Some import arrow.core.left import arrow.core.right -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.choice +import io.kotest.property.arbitrary.constant +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.string sealed class SumType { data class A(val string: String) : SumType() data class B(val int: Int) : SumType() } -val genSumTypeA: Gen = Gen.string().map { SumType.A(it) } +val genSumTypeA: Arb = Arb.string().map { SumType.A(it) } -val genSum: Gen = - Gen.oneOf(Gen.string().map { SumType.A(it) }, Gen.int().map { SumType.B(it) }) +val genSum: Arb = + Arb.choice(Arb.string().map { SumType.A(it) }, Arb.int().map { SumType.B(it) }) -val sumPrism: Prism = Prism( +val sumPrism: Prism = Prism( { Option.fromNullable((it as? SumType.A)?.string) }, SumType::A ) @@ -53,15 +58,15 @@ internal data class Token(val value: String) { companion object } -internal val genToken: Gen = Gen.string().map { Token(it) } +internal val genToken: Arb = Arb.string().map { Token(it) } internal data class User(val token: Token) -internal val genUser: Gen = genToken.map { User(it) } +internal val genUser: Arb = genToken.map { User(it) } internal data class IncompleteUser(val token: Token?) -internal val genIncompleteUser: Gen = Gen.constant(IncompleteUser(null)) +internal val genIncompleteUser: Arb = Arb.constant(IncompleteUser(null)) internal val tokenGetter: Getter = Getter(Token::value) diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/TraversalTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/TraversalTest.kt index 5d0b19e8c8e..204f053d0cd 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/TraversalTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/TraversalTest.kt @@ -2,36 +2,87 @@ package arrow.optics import arrow.core.test.UnitSpec import arrow.core.test.generators.functionAToB +import arrow.core.test.generators.nonEmptyList +import arrow.core.test.generators.option +import arrow.core.test.generators.sequence import arrow.optics.test.laws.SetterLaws import arrow.optics.test.laws.TraversalLaws -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.char +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.string class TraversalTest : UnitSpec() { init { testLaws( + "Traversal list - ", TraversalLaws.laws( traversal = Traversal.list(), - aGen = Gen.list(Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.list(Arb.int()), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), ), SetterLaws.laws( setter = Traversal.list(), - aGen = Gen.list(Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.list(Arb.int()), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), ) ) testLaws( + "Traversal Nel - ", TraversalLaws.laws( - traversal = Traversal({ it.first }, { it.second }, { a, b, _ -> a to b }), - aGen = Gen.pair(Gen.float(), Gen.float()), - bGen = Gen.float(), - funcGen = Gen.functionAToB(Gen.float()), + traversal = Traversal.nonEmptyList(), + aGen = Arb.nonEmptyList(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), + ) + ) + + testLaws( + "Traversal sequence - ", + TraversalLaws.laws( + traversal = Traversal.sequence(), + aGen = Arb.sequence(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), + eq = { a, b -> a.toList() == b.toList() } + ) + ) + + testLaws( + "Traversal map - ", + TraversalLaws.laws( + traversal = Traversal.map(), + aGen = Arb.map(Arb.int(), Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), + ) + ) + + testLaws( + "Traversal option - ", + TraversalLaws.laws( + traversal = Traversal.option(), + aGen = Arb.option(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), + ) + ) + + testLaws( + "Traversal string - ", + TraversalLaws.laws( + traversal = Traversal.string(), + aGen = Arb.string(), + bGen = Arb.char(), + funcGen = Arb.functionAToB(Arb.char()), ) ) } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/AtInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/AtInstanceTest.kt new file mode 100644 index 00000000000..86dd8fdf8be --- /dev/null +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/AtInstanceTest.kt @@ -0,0 +1,37 @@ +package arrow.optics.instances + +import arrow.core.test.UnitSpec +import arrow.core.test.generators.functionAToB +import arrow.core.test.generators.option +import arrow.optics.test.laws.LensLaws +import arrow.optics.typeclasses.At +import io.kotest.property.Arb +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.set +import io.kotest.property.arbitrary.string + +class AtInstanceTest : UnitSpec() { + init { + testLaws( + "At map - ", + LensLaws.laws( + lensGen = Arb.string().map { At.map().at(it) }, + aGen = Arb.map(Arb.string(), Arb.int()), + bGen = Arb.option(Arb.int()), + funcGen = Arb.functionAToB(Arb.option(Arb.int())), + ) + ) + + testLaws( + "At set - ", + LensLaws.laws( + lensGen = Arb.string().map { At.set().at(it) }, + aGen = Arb.set(Arb.string()), + bGen = Arb.bool(), + funcGen = Arb.functionAToB(Arb.bool()), + ) + ) + } +} diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/ConsInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/ConsInstanceTest.kt new file mode 100644 index 00000000000..43313bfb6df --- /dev/null +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/ConsInstanceTest.kt @@ -0,0 +1,36 @@ +package arrow.optics.instances + +import arrow.core.test.UnitSpec +import arrow.core.test.generators.functionAToB +import arrow.optics.test.laws.PrismLaws +import arrow.optics.typeclasses.Cons +import io.kotest.property.Arb +import io.kotest.property.arbitrary.char +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.pair +import io.kotest.property.arbitrary.string + +class ConsInstanceTest : UnitSpec() { + init { + testLaws( + "Const list - ", + PrismLaws.laws( + prism = Cons.list().cons(), + aGen = Arb.list(Arb.int()), + bGen = Arb.pair(Arb.int(), Arb.list(Arb.int())), + funcGen = Arb.functionAToB(Arb.pair(Arb.int(), Arb.list(Arb.int()))), + ) + ) + + testLaws( + "Cons string - ", + PrismLaws.laws( + prism = Cons.string().cons(), + aGen = Arb.string(), + bGen = Arb.pair(Arb.char(), Arb.string()), + funcGen = Arb.functionAToB(Arb.pair(Arb.char(), Arb.string())), + ) + ) + } +} diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/EitherInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/EitherInstanceTest.kt index 2b6298d8cf8..d7e14e43d58 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/EitherInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/EitherInstanceTest.kt @@ -5,7 +5,9 @@ import arrow.core.test.generators.either import arrow.core.test.generators.functionAToB import arrow.optics.Traversal import arrow.optics.test.laws.TraversalLaws -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.string class EitherInstanceTest : UnitSpec() { @@ -14,9 +16,9 @@ class EitherInstanceTest : UnitSpec() { testLaws( TraversalLaws.laws( traversal = Traversal.either(), - aGen = Gen.either(Gen.string(), Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.either(Arb.string(), Arb.int()), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), ) ) } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/FilterIndexInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/FilterIndexInstanceTest.kt index 5eb1b0d51eb..b9737a4906b 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/FilterIndexInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/FilterIndexInstanceTest.kt @@ -5,52 +5,66 @@ import arrow.core.test.generators.functionAToB import arrow.core.test.generators.intSmall import arrow.core.test.generators.nonEmptyList import arrow.core.test.generators.sequence -import arrow.optics.test.generators.char import arrow.optics.test.laws.TraversalLaws import arrow.optics.typeclasses.FilterIndex -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.char +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.string class FilterIndexInstanceTest : UnitSpec() { init { - testLaws(TraversalLaws.laws( - traversal = FilterIndex.list().filter { true }, - aGen = Gen.list(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + testLaws( + "FilterIndex list - ", + TraversalLaws.laws( + traversal = FilterIndex.list().filter { true }, + aGen = Arb.list(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ) ) testLaws( + "FilterIndex sequence - ", TraversalLaws.laws( traversal = FilterIndex.sequence().filter { true }, - aGen = Gen.sequence(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + aGen = Arb.sequence(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ) { a, b -> a.toList() == b.toList() } ) - testLaws(TraversalLaws.laws( - traversal = FilterIndex.nonEmptyList().filter { true }, - aGen = Gen.nonEmptyList(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - )) + testLaws( + "FilterIndex Nel - ", + TraversalLaws.laws( + traversal = FilterIndex.nonEmptyList().filter { true }, + aGen = Arb.nonEmptyList(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), + ) + ) testLaws( + "FilterIndex map - ", TraversalLaws.laws( traversal = FilterIndex.map().filter { true }, - aGen = Gen.map(Gen.char(), Gen.intSmall()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.map(Arb.char(), Arb.intSmall()), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), ) ) - testLaws(TraversalLaws.laws( - traversal = FilterIndex.string().filter { true }, - aGen = Gen.string(), - bGen = Gen.char(), - funcGen = Gen.functionAToB(Gen.char()), - )) + testLaws( + "FilterIndex string - ", + TraversalLaws.laws( + traversal = FilterIndex.string().filter { true }, + aGen = Arb.string(), + bGen = Arb.char(), + funcGen = Arb.functionAToB(Arb.char()), + ) + ) } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/IndexInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/IndexInstanceTest.kt index fbe36a94ee3..a3f014b9dd5 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/IndexInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/IndexInstanceTest.kt @@ -2,19 +2,68 @@ package arrow.optics.instances import arrow.core.test.UnitSpec import arrow.core.test.generators.functionAToB +import arrow.core.test.generators.nonEmptyList +import arrow.core.test.generators.sequence import arrow.optics.test.laws.OptionalLaws import arrow.optics.typeclasses.Index -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.char +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.string class IndexInstanceTest : UnitSpec() { init { testLaws( + "Index list - ", OptionalLaws.laws( - optionalGen = Gen.int().map { Index.list().index(it) }, - aGen = Gen.list(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()) + optionalGen = Arb.int().map { Index.list().index(it) }, + aGen = Arb.list(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), + ) + ) + + testLaws( + "Index sequence - ", + OptionalLaws.laws( + optionalGen = Arb.int().map { Index.sequence().index(it) }, + aGen = Arb.sequence(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), + eqa = { a, b -> a.toList() == b.toList() } + ) + ) + + testLaws( + "Index map - ", + OptionalLaws.laws( + optionalGen = Arb.int().map { Index.list().index(it) }, + aGen = Arb.list(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()) + ) + ) + + testLaws( + "Index Nel - ", + OptionalLaws.laws( + optionalGen = Arb.int().map { Index.nonEmptyList().index(it) }, + aGen = Arb.nonEmptyList(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), + ) + ) + + testLaws( + "Index string - ", + OptionalLaws.laws( + optionalGen = Arb.int().map { Index.string().index(it) }, + aGen = Arb.string(), + bGen = Arb.char(), + funcGen = Arb.functionAToB(Arb.char()), ) ) } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/ListInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/ListInstanceTest.kt index 266c34a51dc..e69de29bb2d 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/ListInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/ListInstanceTest.kt @@ -1,73 +0,0 @@ -package arrow.optics.instances - -import arrow.core.test.UnitSpec -import arrow.core.test.generators.functionAToB -import arrow.optics.Traversal -import arrow.optics.test.laws.OptionalLaws -import arrow.optics.test.laws.PrismLaws -import arrow.optics.test.laws.TraversalLaws -import arrow.optics.typeclasses.Cons -import arrow.optics.typeclasses.FilterIndex -import arrow.optics.typeclasses.Index -import arrow.optics.typeclasses.Snoc -import io.kotlintest.properties.Gen - -class ListInstanceTest : UnitSpec() { - - init { - - testLaws( - TraversalLaws.laws( - traversal = Traversal.list(), - aGen = Gen.list(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - ) - ) - - testLaws( - TraversalLaws.laws( - traversal = Traversal.list(), - aGen = Gen.list(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - ) - ) - - testLaws( - TraversalLaws.laws( - traversal = FilterIndex.list().filter { true }, - aGen = Gen.list(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - ) - ) - - testLaws( - OptionalLaws.laws( - optionalGen = Gen.int().map { Index.list().index(it) }, - aGen = Gen.list(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - ) - ) - - testLaws( - PrismLaws.laws( - prism = Cons.list().cons(), - aGen = Gen.list(Gen.int()), - bGen = Gen.pair(Gen.int(), Gen.list(Gen.int())), - funcGen = Gen.functionAToB(Gen.pair(Gen.int(), Gen.list(Gen.int()))), - ) - ) - - testLaws( - PrismLaws.laws( - prism = Snoc.list().snoc(), - aGen = Gen.list(Gen.int()), - bGen = Gen.pair(Gen.list(Gen.int()), Gen.int()), - funcGen = Gen.functionAToB(Gen.pair(Gen.list(Gen.int()), Gen.int())), - ) - ) - } -} diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/MapInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/MapInstanceTest.kt index 3483aa85e62..e69de29bb2d 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/MapInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/MapInstanceTest.kt @@ -1,57 +0,0 @@ -package arrow.optics.instances - -import arrow.core.test.UnitSpec -import arrow.core.test.generators.functionAToB -import arrow.core.test.generators.intSmall -import arrow.core.test.generators.option -import arrow.optics.Traversal -import arrow.optics.test.generators.char -import arrow.optics.test.laws.LensLaws -import arrow.optics.test.laws.OptionalLaws -import arrow.optics.test.laws.TraversalLaws -import arrow.optics.typeclasses.At -import arrow.optics.typeclasses.FilterIndex -import arrow.optics.typeclasses.Index -import io.kotlintest.properties.Gen - -class MapInstanceTest : UnitSpec() { - - init { - - testLaws( - TraversalLaws.laws( - traversal = Traversal.map(), - aGen = Gen.map(Gen.int(), Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - ) - ) - - testLaws( - TraversalLaws.laws( - traversal = FilterIndex.map().filter { true }, - aGen = Gen.map(Gen.char(), Gen.intSmall()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), - ) - ) - - testLaws( - OptionalLaws.laws( - optionalGen = Gen.string().map { Index.map().index(it) }, - aGen = Gen.map(Gen.string(), Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), - ) - ) - - testLaws( - LensLaws.laws( - lensGen = Gen.string().map { At.map().at(it) }, - aGen = Gen.map(Gen.string(), Gen.int()), - bGen = Gen.option(Gen.int()), - funcGen = Gen.functionAToB(Gen.option(Gen.int())), - ) - ) - } -} diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/NonEmptyListInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/NonEmptyListInstanceTest.kt index c8715e0c4b9..e69de29bb2d 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/NonEmptyListInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/NonEmptyListInstanceTest.kt @@ -1,44 +0,0 @@ -package arrow.optics.instances - -import arrow.core.test.UnitSpec -import arrow.core.test.generators.functionAToB -import arrow.core.test.generators.nonEmptyList -import arrow.optics.Traversal -import arrow.optics.test.laws.OptionalLaws -import arrow.optics.test.laws.TraversalLaws -import arrow.optics.typeclasses.FilterIndex -import arrow.optics.typeclasses.Index -import io.kotlintest.properties.Gen - -class NonEmptyListInstanceTest : UnitSpec() { - - init { - - testLaws( - TraversalLaws.laws( - traversal = Traversal.nonEmptyList(), - aGen = Gen.nonEmptyList(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - ) - ) - - testLaws( - TraversalLaws.laws( - traversal = FilterIndex.nonEmptyList().filter { true }, - aGen = Gen.nonEmptyList(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - ) - ) - - testLaws( - OptionalLaws.laws( - optionalGen = Gen.int().map { Index.nonEmptyList().index(it) }, - aGen = Gen.nonEmptyList(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - ) - ) - } -} diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/OptionInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/OptionInstanceTest.kt index e0552b61653..e69de29bb2d 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/OptionInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/OptionInstanceTest.kt @@ -1,23 +0,0 @@ -package arrow.optics.instances - -import arrow.core.test.UnitSpec -import arrow.core.test.generators.functionAToB -import arrow.core.test.generators.option -import arrow.optics.Traversal -import arrow.optics.test.laws.TraversalLaws -import io.kotlintest.properties.Gen - -class OptionInstanceTest : UnitSpec() { - - init { - - testLaws( - TraversalLaws.laws( - traversal = Traversal.option(), - aGen = Gen.option(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - ) - ) - } -} diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SequenceInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SequenceInstanceTest.kt index 85df3bbba70..e69de29bb2d 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SequenceInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SequenceInstanceTest.kt @@ -1,47 +0,0 @@ -package arrow.optics.instances - -import arrow.core.test.UnitSpec -import arrow.core.test.generators.functionAToB -import arrow.core.test.generators.sequence -import arrow.optics.Traversal -import arrow.optics.test.laws.OptionalLaws -import arrow.optics.test.laws.TraversalLaws -import arrow.optics.typeclasses.FilterIndex -import arrow.optics.typeclasses.Index -import io.kotlintest.properties.Gen - -class SequenceInstanceTest : UnitSpec() { - - init { - - testLaws( - TraversalLaws.laws( - traversal = Traversal.sequence(), - aGen = Gen.sequence(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - eq = { a, b -> a.toList() == b.toList() } - ) - ) - - testLaws( - TraversalLaws.laws( - traversal = FilterIndex.sequence().filter { true }, - aGen = Gen.sequence(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - eq = { a, b -> a.toList() == b.toList() } - ) - ) - - testLaws( - OptionalLaws.laws( - optionalGen = Gen.int().map { Index.sequence().index(it) }, - aGen = Gen.sequence(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), - eqa = { a, b -> a.toList() == b.toList() } - ) - ) - } -} diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SetInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SetInstanceTest.kt index 5f6674f5e60..e69de29bb2d 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SetInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SetInstanceTest.kt @@ -1,22 +0,0 @@ -package arrow.optics.instances - -import arrow.core.test.UnitSpec -import arrow.core.test.generators.functionAToB -import arrow.optics.test.laws.LensLaws -import arrow.optics.typeclasses.At -import io.kotlintest.properties.Gen - -class SetInstanceTest : UnitSpec() { - - init { - - testLaws( - LensLaws.laws( - lensGen = Gen.string().map { At.set().at(it) }, - aGen = Gen.set(Gen.string()), - bGen = Gen.bool(), - funcGen = Gen.functionAToB(Gen.bool()), - ) - ) - } -} diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SnocInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SnocInstanceTest.kt new file mode 100644 index 00000000000..dcaa36539df --- /dev/null +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/SnocInstanceTest.kt @@ -0,0 +1,35 @@ +package arrow.optics.instances + +import arrow.core.test.UnitSpec +import arrow.core.test.generators.functionAToB +import arrow.optics.test.laws.PrismLaws +import arrow.optics.typeclasses.Snoc +import io.kotest.property.Arb +import io.kotest.property.arbitrary.char +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.pair +import io.kotest.property.arbitrary.string + +class SnocInstanceTest : UnitSpec() { + init { + testLaws( + "Snoc list - ", + PrismLaws.laws( + prism = Snoc.list().snoc(), + aGen = Arb.list(Arb.int()), + bGen = Arb.pair(Arb.list(Arb.int()), Arb.int()), + funcGen = Arb.functionAToB(Arb.pair(Arb.list(Arb.int()), Arb.int())), + ) + ) + testLaws( + "Snoc string - ", + PrismLaws.laws( + prism = Snoc.string().snoc(), + aGen = Arb.string(), + bGen = Arb.pair(Arb.string(), Arb.char()), + funcGen = Arb.functionAToB(Arb.pair(Arb.string(), Arb.char())), + ) + ) + } +} diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/StringInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/StringInstanceTest.kt index e9f223f5808..e69de29bb2d 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/StringInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/instances/StringInstanceTest.kt @@ -1,65 +0,0 @@ -package arrow.optics.instances - -import arrow.core.test.UnitSpec -import arrow.core.test.generators.functionAToB -import arrow.optics.Traversal -import arrow.optics.test.generators.char -import arrow.optics.test.laws.OptionalLaws -import arrow.optics.test.laws.PrismLaws -import arrow.optics.test.laws.TraversalLaws -import arrow.optics.typeclasses.Cons -import arrow.optics.typeclasses.FilterIndex -import arrow.optics.typeclasses.Index -import arrow.optics.typeclasses.Snoc -import io.kotlintest.properties.Gen - -class StringInstanceTest : UnitSpec() { - - init { - - testLaws( - TraversalLaws.laws( - traversal = Traversal.string(), - aGen = Gen.string(), - bGen = Gen.char(), - funcGen = Gen.functionAToB(Gen.char()), - ) - ) - - testLaws( - TraversalLaws.laws( - traversal = FilterIndex.string().filter { true }, - aGen = Gen.string(), - bGen = Gen.char(), - funcGen = Gen.functionAToB(Gen.char()), - ) - ) - - testLaws( - OptionalLaws.laws( - optionalGen = Gen.int().map { Index.string().index(it) }, - aGen = Gen.string(), - bGen = Gen.char(), - funcGen = Gen.functionAToB(Gen.char()), - ) - ) - - testLaws( - PrismLaws.laws( - prism = Cons.string().cons(), - aGen = Gen.string(), - bGen = Gen.pair(Gen.char(), Gen.string()), - funcGen = Gen.functionAToB(Gen.pair(Gen.char(), Gen.string())), - ) - ) - - testLaws( - PrismLaws.laws( - prism = Snoc.string().snoc(), - aGen = Gen.string(), - bGen = Gen.pair(Gen.string(), Gen.char()), - funcGen = Gen.functionAToB(Gen.pair(Gen.string(), Gen.char())), - ) - ) - } -} diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/EitherTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/EitherTest.kt index f91621d981b..2e5a3e60bda 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/EitherTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/EitherTest.kt @@ -10,7 +10,9 @@ import arrow.core.test.generators.validated import arrow.optics.Iso import arrow.optics.test.laws.IsoLaws import arrow.typeclasses.Monoid -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.string class EitherTest : UnitSpec() { @@ -37,9 +39,9 @@ class EitherTest : UnitSpec() { testLaws( IsoLaws.laws( iso = Iso.eitherToValidated(), - aGen = Gen.either(Gen.string(), Gen.int()), - bGen = Gen.validated(Gen.string(), Gen.int()), - funcGen = Gen.functionAToB(Gen.validated(Gen.string(), Gen.int())), + aGen = Arb.either(Arb.string(), Arb.int()), + bGen = Arb.validated(Arb.string(), Arb.int()), + funcGen = Arb.functionAToB(Arb.validated(Arb.string(), Arb.int())), ) ) } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/ListTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/ListTest.kt index d7f2a8c4c2f..11a5d66cf98 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/ListTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/ListTest.kt @@ -8,35 +8,56 @@ import arrow.optics.Iso import arrow.optics.Optional import arrow.optics.test.laws.IsoLaws import arrow.optics.test.laws.OptionalLaws -import io.kotlintest.properties.Gen +import arrow.optics.test.laws.SetterLaws +import arrow.optics.test.laws.TraversalLaws +import io.kotest.property.Arb +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.list class ListTest : UnitSpec() { init { testLaws( + "Optional list head - ", OptionalLaws.laws( optional = Optional.listHead(), - aGen = Gen.list(Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.list(Arb.int()), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), + ), + TraversalLaws.laws( + traversal = Optional.listHead(), + aGen = Arb.list(Arb.int()), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), + ), + SetterLaws.laws( + setter = Optional.listHead(), + aGen = Arb.list(Arb.int()), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), ) ) testLaws( + "Optional list tail - ", OptionalLaws.laws( optional = Optional.listTail(), - aGen = Gen.list(Gen.int()), - bGen = Gen.list(Gen.int()), - funcGen = Gen.functionAToB(Gen.list(Gen.int())), + aGen = Arb.list(Arb.int()), + bGen = Arb.list(Arb.int()), + funcGen = Arb.functionAToB(Arb.list(Arb.int())), ) ) - testLaws(IsoLaws.laws( - iso = Iso.listToOptionNel(), - aGen = Gen.list(Gen.int()), - bGen = Gen.option(Gen.nonEmptyList(Gen.int())), - funcGen = Gen.functionAToB(Gen.option(Gen.nonEmptyList(Gen.int()))), - )) + testLaws( + "Iso list to Option Nel - ", + IsoLaws.laws( + iso = Iso.listToOptionNel(), + aGen = Arb.list(Arb.int()), + bGen = Arb.option(Arb.nonEmptyList(Arb.int())), + funcGen = Arb.functionAToB(Arb.option(Arb.nonEmptyList(Arb.int()))), + ) + ) } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/MapTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/MapTest.kt index e523ffe1f97..aa02bbab077 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/MapTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/MapTest.kt @@ -4,16 +4,20 @@ import arrow.core.test.UnitSpec import arrow.core.test.generators.functionAToB import arrow.optics.Iso import arrow.optics.test.laws.IsoLaws -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.constant +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.set +import io.kotest.property.arbitrary.string class MapTest : UnitSpec() { init { testLaws(IsoLaws.laws( iso = Iso.mapToSet(), - aGen = Gen.map(Gen.string(), Gen.create { Unit }), - bGen = Gen.set(Gen.string()), - funcGen = Gen.functionAToB(Gen.set(Gen.string())), + aGen = Arb.map(Arb.string(), Arb.constant(Unit)), + bGen = Arb.set(Arb.string()), + funcGen = Arb.functionAToB(Arb.set(Arb.string())), )) } } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/NonEmptyListTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/NonEmptyListTest.kt index 16f724c780d..f7bff7d3e19 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/NonEmptyListTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/NonEmptyListTest.kt @@ -5,27 +5,31 @@ import arrow.core.test.generators.functionAToB import arrow.core.test.generators.nonEmptyList import arrow.optics.Lens import arrow.optics.test.laws.LensLaws -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.string class NonEmptyListTest : UnitSpec() { init { testLaws( + "Lens Nel head - ", LensLaws.laws( lens = Lens.nonEmptyListHead(), - aGen = Gen.nonEmptyList(Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + aGen = Arb.nonEmptyList(Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ) ) testLaws( + "Lens Nel tail - ", LensLaws.laws( lens = Lens.nonEmptyListTail(), - aGen = Gen.nonEmptyList(Gen.string()), - bGen = Gen.list(Gen.string()), - funcGen = Gen.functionAToB(Gen.list(Gen.string())), + aGen = Arb.nonEmptyList(Arb.string()), + bGen = Arb.list(Arb.string()), + funcGen = Arb.functionAToB(Arb.list(Arb.string())), ) ) } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/OptionTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/OptionTest.kt index 8704853ee88..218843b27ac 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/OptionTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/OptionTest.kt @@ -8,38 +8,52 @@ import arrow.optics.Iso import arrow.optics.Prism import arrow.optics.test.laws.IsoLaws import arrow.optics.test.laws.PrismLaws -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.constant +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.orNull class OptionTest : UnitSpec() { init { - testLaws(PrismLaws.laws( - prism = Prism.some(), - aGen = Gen.option(Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), - )) + testLaws( + "Prism some - ", + PrismLaws.laws( + prism = Prism.some(), + aGen = Arb.option(Arb.int()), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), + ) + ) - testLaws(PrismLaws.laws( - prism = Prism.none(), - aGen = Gen.option(Gen.int()), - bGen = Gen.create { Unit }, - funcGen = Gen.functionAToB(Gen.create { Unit }), - )) + testLaws( + "Prism none - ", + PrismLaws.laws( + prism = Prism.none(), + aGen = Arb.option(Arb.int()), + bGen = Arb.constant(Unit), + funcGen = Arb.functionAToB(Arb.constant(Unit)), + ) + ) - testLaws(IsoLaws.laws( - iso = Iso.optionToNullable().reverse(), - aGen = Gen.int().orNull(), - bGen = Gen.option(Gen.int()), - funcGen = Gen.functionAToB(Gen.option(Gen.int())) - )) + testLaws( + "Iso option to nullable - ", + IsoLaws.laws( + iso = Iso.optionToNullable().reverse(), + aGen = Arb.int().orNull(), + bGen = Arb.option(Arb.int()), + funcGen = Arb.functionAToB(Arb.option(Arb.int())) + ) + ) - testLaws(IsoLaws.laws( - iso = Iso.optionToEither(), - aGen = Gen.option(Gen.int()), - bGen = Gen.either(Gen.create { Unit }, Gen.int()), - funcGen = Gen.functionAToB(Gen.either(Gen.create { Unit }, Gen.int())), + testLaws( + "Iso option to either - ", + IsoLaws.laws( + iso = Iso.optionToEither(), + aGen = Arb.option(Arb.int()), + bGen = Arb.either(Arb.constant(Unit), Arb.int()), + funcGen = Arb.functionAToB(Arb.either(Arb.constant(Unit), Arb.int())), ) ) } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/StringTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/StringTest.kt index 8af841f79d9..2bbc8658213 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/StringTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/StringTest.kt @@ -1,21 +1,25 @@ package arrow.optics.std -import arrow.optics.test.generators.char import arrow.core.test.UnitSpec import arrow.optics.Iso import arrow.optics.test.laws.IsoLaws -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.char +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.string class StringTest : UnitSpec() { init { testLaws( + "Iso string to list - ", IsoLaws.laws( iso = Iso.stringToList(), - aGen = Gen.string(), - bGen = Gen.list(Gen.char()), - funcGen = Gen.list(Gen.char()).map { list -> { chars: List -> list + chars } }, + aGen = Arb.string(), + bGen = Arb.list(Arb.char()), + funcGen = Arb.list(Arb.char()).map { list -> { chars: List -> list + chars } }, ) ) } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/TupleTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/TupleTest.kt index f3172200287..ba58911dd10 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/TupleTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/TupleTest.kt @@ -13,156 +13,175 @@ import arrow.optics.Lens import arrow.optics.Traversal import arrow.optics.test.laws.LensLaws import arrow.optics.test.laws.TraversalLaws -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.bool +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.pair +import io.kotest.property.arbitrary.string +import io.kotest.property.arbitrary.triple class TupleTest : UnitSpec() { init { testLaws( + "Lens pair first - ", LensLaws.laws( lens = Lens.pairFirst(), - aGen = Gen.pair(Gen.int(), Gen.string()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.pair(Arb.int(), Arb.string()), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), ) ) testLaws( + "Lens pair second - ", LensLaws.laws( lens = Lens.pairSecond(), - aGen = Gen.pair(Gen.int(), Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + aGen = Arb.pair(Arb.int(), Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ) ) testLaws( + "Lens triple first - ", LensLaws.laws( lens = Lens.tripleFirst(), - aGen = Gen.triple(Gen.int(), Gen.string(), Gen.string()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.triple(Arb.int(), Arb.string(), Arb.string()), + bGen = Arb.int(), + funcGen = Arb.functionAToB(Arb.int()), ) ) testLaws( + "Lens triple second - ", LensLaws.laws( lens = Lens.tripleSecond(), - aGen = Gen.triple(Gen.int(), Gen.string(), Gen.int()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + aGen = Arb.triple(Arb.int(), Arb.string(), Arb.int()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ) ) testLaws( + "Lens triple third - ", LensLaws.laws( lens = Lens.tripleThird(), - aGen = Gen.triple(Gen.int(), Gen.int(), Gen.string()), - bGen = Gen.string(), - funcGen = Gen.functionAToB(Gen.string()), + aGen = Arb.triple(Arb.int(), Arb.int(), Arb.string()), + bGen = Arb.string(), + funcGen = Arb.functionAToB(Arb.string()), ) ) testLaws( + "Traversal pair - ", TraversalLaws.laws( traversal = Traversal.pair(), - aGen = Gen.pair(Gen.int(), Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.pair(Arb.bool(), Arb.bool()), + bGen = Arb.bool(), + funcGen = Arb.functionAToB(Arb.bool()), ) ) testLaws( + "Traversal triple - ", TraversalLaws.laws( traversal = Traversal.triple(), - aGen = Gen.triple(Gen.int(), Gen.int(), Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.triple(Arb.bool(), Arb.bool(), Arb.bool()), + bGen = Arb.bool(), + funcGen = Arb.functionAToB(Arb.bool()), ) ) testLaws( + "Traversal tuple4 - ", TraversalLaws.laws( traversal = Traversal.tuple4(), - aGen = Gen.tuple4(Gen.int(), Gen.int(), Gen.int(), Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.tuple4(Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool()), + bGen = Arb.bool(), + funcGen = Arb.functionAToB(Arb.bool()), ) ) testLaws( + "Traversal tuple5 - ", TraversalLaws.laws( traversal = Traversal.tuple5(), - aGen = Gen.tuple5(Gen.int(), Gen.int(), Gen.int(), Gen.int(), Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.tuple5(Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool()), + bGen = Arb.bool(), + funcGen = Arb.functionAToB(Arb.bool()), ) ) testLaws( + "Traversal tuple6 - ", TraversalLaws.laws( traversal = Traversal.tuple6(), - aGen = Gen.tuple6(Gen.int(), Gen.int(), Gen.int(), Gen.int(), Gen.int(), Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.tuple6(Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool()), + bGen = Arb.bool(), + funcGen = Arb.functionAToB(Arb.bool()), ) ) testLaws( + "Traversal tuple7 - ", TraversalLaws.laws( traversal = Traversal.tuple7(), - aGen = Gen.tuple7(Gen.int(), Gen.int(), Gen.int(), Gen.int(), Gen.int(), Gen.int(), Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.tuple7(Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool()), + bGen = Arb.bool(), + funcGen = Arb.functionAToB(Arb.bool()), ) ) testLaws( + "Traversal tuple8 - ", TraversalLaws.laws( traversal = Traversal.tuple8(), - aGen = Gen.tuple8(Gen.int(), Gen.int(), Gen.int(), Gen.int(), Gen.int(), Gen.int(), Gen.int(), Gen.int()), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + aGen = Arb.tuple8(Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool(), Arb.bool()), + bGen = Arb.bool(), + funcGen = Arb.functionAToB(Arb.bool()), ) ) testLaws( + "Traversal tuple9 - ", TraversalLaws.laws( traversal = Traversal.tuple9(), - aGen = Gen.tuple9( - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int() + aGen = Arb.tuple9( + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool() ), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + bGen = Arb.bool(), + funcGen = Arb.functionAToB(Arb.int()), ) ) testLaws( + "Traversal tuple10 - ", TraversalLaws.laws( traversal = Traversal.tuple10(), - aGen = Gen.tuple10( - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int(), - Gen.int() + aGen = Arb.tuple10( + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool(), + Arb.bool() ), - bGen = Gen.int(), - funcGen = Gen.functionAToB(Gen.int()), + bGen = Arb.bool(), + funcGen = Arb.functionAToB(Arb.bool()), ) ) } diff --git a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/ValidatedTest.kt b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/ValidatedTest.kt index 139dbb17182..fe5b0d1d89f 100644 --- a/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/ValidatedTest.kt +++ b/arrow-libs/optics/arrow-optics/src/jvmTest/kotlin/arrow/optics/std/ValidatedTest.kt @@ -6,18 +6,21 @@ import arrow.core.test.generators.functionAToB import arrow.core.test.generators.validated import arrow.optics.Iso import arrow.optics.test.laws.IsoLaws -import io.kotlintest.properties.Gen +import io.kotest.property.Arb +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.string class ValidatedTest : UnitSpec() { init { testLaws( + "Iso validated to either - ", IsoLaws.laws( iso = Iso.validatedToEither(), - aGen = Gen.validated(Gen.string(), Gen.int()), - bGen = Gen.either(Gen.string(), Gen.int()), - funcGen = Gen.functionAToB(Gen.either(Gen.string(), Gen.int())), + aGen = Arb.validated(Arb.string(), Arb.int()), + bGen = Arb.either(Arb.string(), Arb.int()), + funcGen = Arb.functionAToB(Arb.either(Arb.string(), Arb.int())), ) ) } diff --git a/arrow-libs/optics/gradle.properties b/arrow-libs/optics/gradle.properties index 6c21d28a87b..4decaec9c15 100644 --- a/arrow-libs/optics/gradle.properties +++ b/arrow-libs/optics/gradle.properties @@ -8,7 +8,7 @@ systemProp.org.gradle.internal.publish.checksums.insecure=true kotlin.incremental=true # Kotlin Test configuration #Parallelism needs to be set to 1 since the concurrent tests in arrow-effects become flaky otherwise -kotlintest.parallelism=1 +kotest.framework.parallelism=1 # Reason: https://youtrack.jetbrains.com/issue/KT-46847 # kotlin.stdlib.default.dependency=false