Skip to content

Commit

Permalink
Add Iso law test for optic conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
nomisRev committed Feb 2, 2018
1 parent 911a128 commit 1f01585
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 4 deletions.
1 change: 0 additions & 1 deletion arrow-optics/src/test/kotlin/arrow/optics/GetterTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ class GetterTest : UnitSpec() {
init {

val userGetter = userIso.asGetter()
val tokenGetter = tokenIso.asGetter()
val length = Getter<String, Int> { it.length }
val upper = Getter<String, String> { it.toUpperCase() }

Expand Down
99 changes: 97 additions & 2 deletions arrow-optics/src/test/kotlin/arrow/optics/IsoTest.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
package arrow.optics

import arrow.core.*
import arrow.data.k
import io.kotlintest.KTestJUnitRunner
import io.kotlintest.properties.Gen
import io.kotlintest.properties.forAll
import arrow.instances.StringMonoidInstance
import arrow.syntax.option.some
import org.junit.runner.RunWith
import arrow.test.UnitSpec
import arrow.test.generators.genFunctionAToB
import arrow.test.laws.IsoLaws
import arrow.test.laws.LensLaws
import arrow.test.laws.OptionalLaws
import arrow.test.laws.PrismLaws
import arrow.test.laws.SetterLaws
import arrow.test.laws.TraversalLaws
import arrow.typeclasses.Eq

@RunWith(KTestJUnitRunner::class)
Expand All @@ -29,7 +34,7 @@ class IsoTest : UnitSpec() {
aGen = TokenGen,
bGen = Gen.string(),
funcGen = genFunctionAToB(Gen.string()),
EQA = Eq.any(),
EQA = Token.eq(),
EQB = Eq.any(),
MB = StringMonoidInstance),

Expand All @@ -41,16 +46,106 @@ class IsoTest : UnitSpec() {
EQA = Eq.any(),
EQOptionB = Eq.any()),

TraversalLaws.laws(
traversal = tokenIso.asTraversal(),
aGen = TokenGen,
bGen = Gen.string(),
funcGen = genFunctionAToB(Gen.string()),
EQA = Token.eq()
),

OptionalLaws.laws(
optional = tokenIso.asOptional(),
aGen = TokenGen,
bGen = Gen.string(),
funcGen = genFunctionAToB(Gen.string()),
EQA = Token.eq()
),

SetterLaws.laws(
setter = tokenIso.asSetter(),
aGen = TokenGen,
bGen = Gen.string(),
funcGen = genFunctionAToB(Gen.string()),
EQA = Token.eq()
),

IsoLaws.laws(
iso = tokenIso,
aGen = TokenGen,
bGen = Gen.string(),
funcGen = genFunctionAToB(Gen.string()),
EQA = Eq.any(),
EQA = Token.eq(),
EQB = Eq.any(),
bMonoid = StringMonoidInstance)
)

"asFold should behave as valid Fold: size" {
forAll(TokenGen) { token ->
tokenIso.asFold().size(token) == 1
}
}

"asFold should behave as valid Fold: nonEmpty" {
forAll(TokenGen) { token ->
tokenIso.asFold().nonEmpty(token)
}
}

"asFold should behave as valid Fold: isEmpty" {
forAll(TokenGen) { token ->
!tokenIso.asFold().isEmpty(token)
}
}

"asFold should behave as valid Fold: getAll" {
forAll(TokenGen) { token ->
tokenIso.asFold().getAll(token) == listOf(token.value).k()
}
}

"asFold should behave as valid Fold: combineAll" {
forAll(TokenGen) { token ->
tokenIso.asFold().combineAll(token) == token.value
}
}

"asFold should behave as valid Fold: fold" {
forAll(TokenGen) { token ->
tokenIso.asFold().fold(token) == token.value
}
}

"asFold should behave as valid Fold: headOption" {
forAll(TokenGen) { token ->
tokenIso.asFold().headOption(token) == token.value.some()
}
}

"asFold should behave as valid Fold: lastOption" {
forAll(TokenGen) { token ->
tokenIso.asFold().lastOption(token) == token.value.some()
}
}

"asGetter should behave as valid Getter: get" {
forAll(TokenGen) { token ->
tokenIso.asGetter().get(token) == tokenGetter.get(token)
}
}

"asGetter should behave as valid Getter: find" {
forAll(TokenGen, genFunctionAToB<String, Boolean>(Gen.bool())) { token, p ->
tokenIso.asGetter().find(token, p) == tokenGetter.find(token, p)
}
}

"asGetter should behave as valid Getter: exist" {
forAll(TokenGen, genFunctionAToB<String, Boolean>(Gen.bool())) { token, p ->
tokenIso.asGetter().exist(token, p) == tokenGetter.exist(token, p)
}
}

"Lifting a function should yield the same result as not yielding" {
forAll(TokenGen, Gen.string(), { token, value ->
tokenIso.modify(token) { value } == tokenIso.lift { value }(token)
Expand Down
11 changes: 10 additions & 1 deletion arrow-optics/src/test/kotlin/arrow/optics/TestDomain.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.kotlintest.properties.Gen
import arrow.core.identity
import arrow.syntax.either.left
import arrow.syntax.either.right
import arrow.typeclasses.Eq

sealed class SumType {
data class A(val string: String) : SumType()
Expand Down Expand Up @@ -56,7 +57,13 @@ internal val userSetter: Setter<User, Token> = Setter { s ->
{ user -> user.copy(token = s(user.token)) }
}

internal data class Token(val value: String)
internal data class Token(val value: String) {
companion object {
fun eq() = object : Eq<Token> {
override fun eqv(a: Token, b: Token): Boolean = a == b
}
}
}
internal object TokenGen : Gen<Token> {
override fun generate() = Token(Gen.string().generate())
}
Expand All @@ -66,6 +73,8 @@ internal object UserGen : Gen<User> {
override fun generate() = User(TokenGen.generate())
}

internal val tokenGetter: Getter<Token, String> = Getter(Token::value)

internal val userLens: Lens<User, Token> = Lens(
{ user: User -> user.token },
{ token: Token -> { user: User -> user.copy(token = token) } }
Expand Down

0 comments on commit 1f01585

Please sign in to comment.