Add multi-platform support

Converts the unit tests to use kotlin-test, allowing them to target both
the jvm and js platforms.
This commit is contained in:
Michael Bull 2017-12-16 19:30:54 +00:00
parent 416c0950b2
commit 9ddac98e0c
14 changed files with 754 additions and 500 deletions

View File

@ -7,15 +7,16 @@ buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokkaVersion"
classpath "org.junit.platform:junit-platform-gradle-plugin:$junitPlatformVersion"
classpath "net.researchgate:gradle-release:$gradleReleaseVersion"
}
}
apply plugin: 'kotlin'
plugins {
id 'com.github.ben-manes.versions' version '0.17.0'
}
apply plugin: 'kotlin-platform-common'
apply plugin: 'maven-publish'
apply plugin: 'org.jetbrains.dokka'
apply plugin: 'org.junit.platform.gradle.plugin'
apply plugin: 'net.researchgate.release'
description = 'A Result monad for modelling success or failure operations.'
@ -25,31 +26,9 @@ repositories {
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlinVersion"
testCompile "com.natpryce:hamkrest:$hamkrestVersion"
testCompile "org.junit.jupiter:junit-jupiter-params:$junitVersion"
testCompile "org.junit.jupiter:junit-jupiter-api:$junitVersion"
testRuntime "org.junit.jupiter:junit-jupiter-engine:$junitVersion"
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
dokka {
outputFormat = 'javadoc'
outputDirectory = "$buildDir/docs"
}
task javadocJar(type: Jar, dependsOn: dokka) {
group = LifecycleBasePlugin.BUILD_GROUP
description = 'Assembles a jar archive containing the Javadoc API documentation.'
classifier = 'javadoc'
from dokka.outputDirectory
compile "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion"
testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlinVersion"
testCompile "org.jetbrains.kotlin:kotlin-test-common:$kotlinVersion"
}
task sourcesJar(type: Jar) {
@ -62,8 +41,6 @@ task sourcesJar(type: Jar) {
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact javadocJar
artifact sourcesJar
}
}

View File

@ -4,6 +4,5 @@ version=1.0.3-SNAPSHOT
dokkaVersion=0.9.15
gradleReleaseVersion=2.6.0
hamkrestVersion=1.4.2.0
junitVersion=5.0.1
junitPlatformVersion=1.0.0
junitVersion=4.12
kotlinVersion=1.2.10

11
js/build.gradle Normal file
View File

@ -0,0 +1,11 @@
apply plugin: 'kotlin-platform-js'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlinVersion"
expectedBy project(":")
testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlinVersion"
}

35
jvm/build.gradle Normal file
View File

@ -0,0 +1,35 @@
apply plugin: 'kotlin-platform-jvm'
apply plugin: 'org.jetbrains.dokka'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
expectedBy project(":")
testCompile "junit:junit:$junitVersion"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion"
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
}
dokka {
outputFormat = 'javadoc'
outputDirectory = "$buildDir/docs"
}
task javadocJar(type: Jar, dependsOn: dokka) {
group = LifecycleBasePlugin.BUILD_GROUP
description = 'Assembles a jar archive containing the Javadoc API documentation.'
classifier = 'javadoc'
from dokka.outputDirectory
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact javadocJar
}
}
}

View File

@ -1,2 +1,3 @@
rootProject.name = 'kotlin-result'
include 'js', 'jvm'

View File

@ -1,34 +1,45 @@
package com.github.michaelbull.result
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import com.natpryce.hamkrest.sameInstance
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertSame
internal class AndTest {
private object AndError
@Test
internal fun `and should return the result value if ok`() {
val value = Ok(230).and(Ok(500)).get()
assertThat(value, equalTo(500))
internal class `and` {
@Test
internal fun returnsValueIfOk() {
assertEquals(
expected = 500,
actual = Ok(230).and(Ok(500)).get()
)
}
@Test
internal fun returnsValueIfErr() {
assertEquals(
expected = "hello world",
actual = Ok(300).and(Err("hello world")).getError()
)
}
}
@Test
internal fun `and should return the result value if not ok`() {
val error = Ok(300).and(Err("hello world")).getError()
assertThat(error, equalTo("hello world"))
}
internal class `andThen` {
@Test
internal fun returnsTransformedValueIfOk() {
assertEquals(
expected = 12,
actual = Ok(5).andThen { Ok(it + 7) }.get()
)
}
@Test
internal fun `andThen should return the transformed result value if ok`() {
val value = Ok(5).andThen { Ok(it + 7) }.get()
assertThat(value, equalTo(12))
}
@Test
internal fun `andThen should return the result error if not ok`() {
val error = Ok(20).andThen { Ok(it + 43) }.andThen { Err(AndError) }.getError()!!
assertThat(error, sameInstance(AndError))
@Test
internal fun returnsErrorIfErr() {
assertSame(
expected = AndError,
actual = Ok(20).andThen { Ok(it + 43) }.andThen { Err(AndError) }.getError()!!
)
}
}
}

View File

@ -1,79 +1,109 @@
package com.github.michaelbull.result
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull
internal class GetTest {
@Test
internal fun `get should return the result value if ok`() {
val value = Ok(12).get()
assertThat(value, equalTo(12))
internal class `get` {
@Test
internal fun returnsValueIfOk() {
assertEquals(
expected = 12,
actual = Ok(12).get()
)
}
@Test
internal fun returnsNullIfErr() {
assertNull(Err("error").get())
}
}
@Test
internal fun `get should return null if not ok`() {
val value = Err("error").get()
assertThat(value, equalTo(null))
internal class `getError` {
@Test
internal fun returnsNullIfOk() {
assertNull(Ok("example").getError())
}
@Test
internal fun returnsErrorIfErr() {
assertEquals(
expected = "example",
actual = Err("example").getError()
)
}
}
@Test
internal fun `getError should return null if ok`() {
val error = Ok("example").getError()
assertThat(error, equalTo(null))
internal class `getOr` {
@Test
internal fun returnsValueIfOk() {
assertEquals(
expected = "hello",
actual = Ok("hello").getOr("world")
)
}
@Test
internal fun returnsDefaultValueIfErr() {
assertEquals(
expected = "default",
actual = Err("error").getOr("default")
)
}
}
@Test
internal fun `getError should return the result error if not ok`() {
val error = Err("example").getError()
assertThat(error, equalTo("example"))
internal class `getErrorOr` {
@Test
internal fun returnsDefaultValueIfOk() {
assertEquals(
expected = "world",
actual = Ok("hello").getErrorOr("world")
)
}
@Test
internal fun returnsErrorIfErr() {
assertEquals(
expected = "hello",
actual = Err("hello").getErrorOr("world")
)
}
}
@Test
internal fun `getOr should return the result value if ok`() {
val value = Ok("hello").getOr("world")
assertThat(value, equalTo("hello"))
internal class `getOrElse` {
@Test
internal fun returnsValueIfOk() {
assertEquals(
expected = "hello",
actual = Ok("hello").getOrElse { "world" }
)
}
@Test
internal fun returnsTransformedErrorIfErr() {
assertEquals(
expected = "world",
actual = Err("hello").getOrElse { "world" }
)
}
}
@Test
internal fun `getOr should return default value if not ok`() {
val value = Err("error").getOr("default")
assertThat(value, equalTo("default"))
}
internal class `getErrorOrElse` {
@Test
internal fun returnsTransformedValueIfOk() {
assertEquals(
expected = "world",
actual = Ok("hello").getErrorOrElse { "world" }
)
}
@Test
internal fun `getErrorOr should return the default value if ok`() {
val error = Ok("hello").getErrorOr("world")
assertThat(error, equalTo("world"))
}
@Test
internal fun `getErrorOr should return the result error if not ok`() {
val error = Err("hello").getErrorOr("world")
assertThat(error, equalTo("hello"))
}
@Test
internal fun `getOrElse should return the result value if ok`() {
val value = Ok("hello").getOrElse { "world" }
assertThat(value, equalTo("hello"))
}
@Test
internal fun `getOrElse should return the transformed result error if ok`() {
val value = Err("hello").getOrElse { "world" }
assertThat(value, equalTo("world"))
}
@Test
internal fun `getErrorOrElse should return the transformed result value if ok`() {
val error = Ok("hello").getErrorOrElse { "world" }
assertThat(error, equalTo("world"))
}
@Test
internal fun `getErrorOrElse should return the result error if not ok`() {
val error = Err("hello").getErrorOrElse { "world" }
assertThat(error, equalTo("hello"))
@Test
internal fun returnsErrorIfErr() {
assertEquals(
expected = "hello",
actual = Err("hello").getErrorOrElse { "world" }
)
}
}
}

View File

@ -1,10 +1,8 @@
package com.github.michaelbull.result
import com.natpryce.hamkrest.Matcher
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import com.natpryce.hamkrest.sameInstance
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertSame
internal class IterableTest {
private sealed class IterableError {
@ -12,168 +10,291 @@ internal class IterableTest {
object IterableError2 : IterableError()
}
private fun sameError(error: IterableError): Matcher<IterableError> {
return sameInstance(error)
}
internal class `fold` {
@Test
internal fun returnAccumulatedValueIfOk() {
val result = listOf(20, 30, 40, 50).fold(
initial = 10,
operation = { a, b -> Ok(a + b) }
)
@Test
internal fun `fold should return the accumulated value if ok`() {
val result = listOf(20, 30, 40, 50).fold(
initial = 10,
operation = { a, b -> Ok(a + b) }
)
result as Ok
result as Ok
assertEquals(
expected = 150,
actual = result.value
)
}
assertThat(result.value, equalTo(150))
}
@Test
internal fun `fold should return the first error if not ok`() {
val result: Result<Int, IterableError> = listOf(5, 10, 15, 20, 25).fold(
initial = 1,
operation = { a, b ->
when (b) {
(5 + 10) -> Err(IterableError.IterableError1)
(5 + 10 + 15 + 20) -> Err(IterableError.IterableError2)
else -> Ok(a * b)
@Test
internal fun returnsFirstErrorIfErr() {
val result: Result<Int, IterableError> = listOf(5, 10, 15, 20, 25).fold(
initial = 1,
operation = { a, b ->
when (b) {
(5 + 10) -> Err(IterableError.IterableError1)
(5 + 10 + 15 + 20) -> Err(IterableError.IterableError2)
else -> Ok(a * b)
}
}
}
)
)
result as Err
result as Err
val matcher: Matcher<IterableError> = sameInstance(IterableError.IterableError1)
assertThat(result.error, matcher)
assertSame(
expected = IterableError.IterableError1,
actual = result.error
)
}
}
@Test
internal fun `foldRight should return the accumulated value if ok`() {
val result = listOf(2, 5, 10, 20).foldRight(
initial = 100,
operation = { a, b -> Ok(b - a) }
)
internal class `foldRight` {
@Test
internal fun returnsAccumulatedValueIfOk() {
val result = listOf(2, 5, 10, 20).foldRight(
initial = 100,
operation = { a, b -> Ok(b - a) }
)
result as Ok
result as Ok
assertThat(result.value, equalTo(63))
}
assertEquals(
expected = 63,
actual = result.value
)
}
@Test
internal fun `foldRight should return the last error if not ok`() {
val result = listOf(2, 5, 10, 20, 40).foldRight(
initial = 38500,
operation = { a, b ->
when (b) {
(((38500 / 40) / 20) / 10) -> Err(IterableError.IterableError1)
((38500 / 40) / 20) -> Err(IterableError.IterableError2)
else -> Ok(b / a)
@Test
internal fun returnsLastErrorIfErr() {
val result = listOf(2, 5, 10, 20, 40).foldRight(
initial = 38500,
operation = { a, b ->
when (b) {
(((38500 / 40) / 20) / 10) -> Err(IterableError.IterableError1)
((38500 / 40) / 20) -> Err(IterableError.IterableError2)
else -> Ok(b / a)
}
}
}
)
)
result as Err
result as Err
assertThat(result.error, sameError(IterableError.IterableError2))
assertSame(
expected = IterableError.IterableError2,
actual = result.error
)
}
}
@Test
internal fun `combine should return the combined list of values if results are ok`() {
val values = combine(
Ok(10),
Ok(20),
Ok(30)
).get()!!
internal class `combine` {
@Test
internal fun returnsValuesIfAllOk() {
val values = combine(
Ok(10),
Ok(20),
Ok(30)
).get()!!
assertThat(values.size, equalTo(3))
assertThat(values[0], equalTo(10))
assertThat(values[1], equalTo(20))
assertThat(values[2], equalTo(30))
assertEquals(
expected = 3,
actual = values.size
)
assertEquals(
expected = 10,
actual = values[0]
)
assertEquals(
expected = 20,
actual = values[1]
)
assertEquals(
expected = 30,
actual = values[2]
)
}
@Test
internal fun returnsFirstErrorIfErr() {
val result = combine(
Ok(20),
Ok(40),
Err(IterableError.IterableError1),
Ok(60),
Err(IterableError.IterableError2),
Ok(80)
)
result as Err
assertSame(
expected = IterableError.IterableError1,
actual = result.error
)
}
}
@Test
internal fun `combine should return the first error if results are not ok`() {
val result = combine(
Ok(20),
Ok(40),
Err(IterableError.IterableError1),
Ok(60),
Err(IterableError.IterableError2),
Ok(80)
)
internal class `getAll` {
@Test
internal fun returnsAllValues() {
val values = getAll(
Ok("hello"),
Ok("big"),
Err(IterableError.IterableError2),
Ok("wide"),
Err(IterableError.IterableError1),
Ok("world")
)
result as Err
assertEquals(
expected = 4,
actual = values.size
)
assertThat(result.error, sameError(IterableError.IterableError1))
assertEquals(
expected = "hello",
actual = values[0]
)
assertEquals(
expected = "big",
actual = values[1]
)
assertEquals(
expected = "wide",
actual = values[2]
)
assertEquals(
expected = "world",
actual = values[3]
)
}
}
@Test
internal fun `getAll should return all of the result values`() {
val values = getAll(
Ok("hello"),
Ok("big"),
Err(IterableError.IterableError2),
Ok("wide"),
Err(IterableError.IterableError1),
Ok("world")
)
internal class `getAllErrors` {
@Test
internal fun returnsAllErrors() {
val errors = getAllErrors(
Err(IterableError.IterableError2),
Ok("haskell"),
Err(IterableError.IterableError2),
Ok("f#"),
Err(IterableError.IterableError1),
Ok("elm"),
Err(IterableError.IterableError1),
Ok("clojure"),
Err(IterableError.IterableError2)
)
assertThat(values.size, equalTo(4))
assertThat(values[0], equalTo("hello"))
assertThat(values[1], equalTo("big"))
assertThat(values[2], equalTo("wide"))
assertThat(values[3], equalTo("world"))
assertEquals(
expected = 5,
actual = errors.size
)
assertSame(
expected = IterableError.IterableError2,
actual = errors[0]
)
assertSame(
expected = IterableError.IterableError2,
actual = errors[1]
)
assertSame(
expected = IterableError.IterableError1,
actual = errors[2]
)
assertSame(
expected = IterableError.IterableError1,
actual = errors[3]
)
assertSame(
expected = IterableError.IterableError2,
actual = errors[4]
)
}
}
@Test
internal fun `getAllErrors should return all of the result errors`() {
val errors = getAllErrors(
Err(IterableError.IterableError2),
Ok("haskell"),
Err(IterableError.IterableError2),
Ok("f#"),
Err(IterableError.IterableError1),
Ok("elm"),
Err(IterableError.IterableError1),
Ok("clojure"),
Err(IterableError.IterableError2)
)
internal class `partition` {
@Test
internal fun returnsPairOfValuesAndErrors() {
val pairs = partition(
Err(IterableError.IterableError2),
Ok("haskell"),
Err(IterableError.IterableError2),
Ok("f#"),
Err(IterableError.IterableError1),
Ok("elm"),
Err(IterableError.IterableError1),
Ok("clojure"),
Err(IterableError.IterableError2)
)
assertThat(errors.size, equalTo(5))
assertThat(errors[0], sameError(IterableError.IterableError2))
assertThat(errors[1], sameError(IterableError.IterableError2))
assertThat(errors[2], sameError(IterableError.IterableError1))
assertThat(errors[3], sameError(IterableError.IterableError1))
assertThat(errors[4], sameError(IterableError.IterableError2))
}
val values = pairs.first
@Test
internal fun `partition should return a pair of all the result values and errors`() {
val pairs = partition(
Err(IterableError.IterableError2),
Ok("haskell"),
Err(IterableError.IterableError2),
Ok("f#"),
Err(IterableError.IterableError1),
Ok("elm"),
Err(IterableError.IterableError1),
Ok("clojure"),
Err(IterableError.IterableError2)
)
assertEquals(
expected = 4,
actual = values.size
)
val values = pairs.first
assertThat(values.size, equalTo(4))
assertThat(values[0], equalTo("haskell"))
assertThat(values[1], equalTo("f#"))
assertThat(values[2], equalTo("elm"))
assertThat(values[3], equalTo("clojure"))
assertEquals(
expected = "haskell",
actual = values[0]
)
val errors = pairs.second
assertThat(errors.size, equalTo(5))
assertThat(errors[0], sameError(IterableError.IterableError2))
assertThat(errors[1], sameError(IterableError.IterableError2))
assertThat(errors[2], sameError(IterableError.IterableError1))
assertThat(errors[3], sameError(IterableError.IterableError1))
assertThat(errors[4], sameError(IterableError.IterableError2))
assertEquals(
expected = "f#",
actual = values[1]
)
assertEquals(
expected = "elm",
actual = values[2]
)
assertEquals(
expected = "clojure",
actual = values[3]
)
val errors = pairs.second
assertEquals(
expected = 5,
actual = errors.size
)
assertSame(
expected = IterableError.IterableError2,
actual = errors[0]
)
assertSame(
expected = IterableError.IterableError2,
actual = errors[1]
)
assertSame(
expected = IterableError.IterableError1,
actual = errors[2]
)
assertSame(
expected = IterableError.IterableError1,
actual = errors[3]
)
assertSame(
expected = IterableError.IterableError2,
actual = errors[4]
)
}
}
}

View File

@ -1,10 +1,8 @@
package com.github.michaelbull.result
import com.natpryce.hamkrest.Matcher
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import com.natpryce.hamkrest.sameInstance
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertSame
internal class MapTest {
private sealed class MapError(val reason: String) {
@ -13,93 +11,121 @@ internal class MapTest {
class CustomError(reason: String) : MapError(reason)
}
private fun sameError(error: MapError): Matcher<MapError> {
return sameInstance(error)
internal class `map` {
@Test
internal fun returnsTransformedValueIfOk() {
assertEquals(
expected = 30,
actual = Ok(10).map { it + 20 }.get()
)
}
@Test
@Suppress("UNREACHABLE_CODE")
internal fun returnsErrorIfErr() {
val result = Err(MapError.HelloError).map { "hello $it" }
result as Err
assertSame(
expected = MapError.HelloError,
actual = result.error
)
}
}
@Test
internal fun `map should return the transformed result value if ok`() {
val value = Ok(10).map { it + 20 }.get()
assertThat(value, equalTo(30))
}
internal class `mapError` {
@Test
internal fun returnsValueIfOk() {
val value = Ok(55).map { it + 15 }.mapError { MapError.WorldError }.get()
@Test
@Suppress("UNREACHABLE_CODE")
internal fun `map should return the result error if not ok`() {
val result = Err(MapError.HelloError).map { "hello $it" }
assertEquals(
expected = 70,
actual = value
)
}
result as Err
assertThat(result.error, sameError(MapError.HelloError))
}
@Test
internal fun `mapError should return the result value if ok`() {
val value = Ok(55).map { it + 15 }.mapError { MapError.WorldError }.get()
assertThat(value, equalTo(70))
}
@Test
internal fun `mapError should return the transformed result error if not ok`() {
val result: Result<String, MapError> = Ok("let")
.map { "$it me" }
.andThen {
when (it) {
"let me" -> Err(MapError.CustomError("$it $it"))
else -> Ok("$it get")
@Test
internal fun returnsErrorIfErr() {
val result: Result<String, MapError> = Ok("let")
.map { "$it me" }
.andThen {
when (it) {
"let me" -> Err(MapError.CustomError("$it $it"))
else -> Ok("$it get")
}
}
}
.mapError { MapError.CustomError("${it.reason} get what i want") }
.mapError { MapError.CustomError("${it.reason} get what i want") }
result as Err
result as Err
assertThat(result.error.reason, equalTo("let me let me get what i want"))
assertEquals(
expected = "let me let me get what i want",
actual = result.error.reason
)
}
}
@Test
@Suppress("UNREACHABLE_CODE")
internal fun `mapBoth should return the transformed result value if ok`() {
val value = Ok("there is").mapBoth(
success = { "$it a light" },
failure = { "$it that never" }
)
internal class `mapBoth` {
@Test
@Suppress("UNREACHABLE_CODE")
internal fun returnsTransformedValueIfOk() {
val value = Ok("there is").mapBoth(
success = { "$it a light" },
failure = { "$it that never" }
)
assertThat(value, equalTo("there is a light"))
assertEquals(
expected = "there is a light",
actual = value
)
}
@Test
@Suppress("UNREACHABLE_CODE")
internal fun returnsTransformedErrorIfErr() {
val error = Err(MapError.CustomError("this")).mapBoth(
success = { "$it charming" },
failure = { "${it.reason} man" }
)
assertEquals(
expected = "this man",
actual = error
)
}
}
@Test
@Suppress("UNREACHABLE_CODE")
internal fun `mapBoth should return the transformed result error if not ok`() {
val error = Err(MapError.CustomError("this")).mapBoth(
success = { "$it charming" },
failure = { "${it.reason} man" }
)
internal class `mapEither` {
@Test
@Suppress("UNREACHABLE_CODE")
internal fun returnsTransformedValueIfOk() {
val result = Ok(500).mapEither(
success = { it + 500 },
failure = { MapError.CustomError("$it") }
)
assertThat(error, equalTo("this man"))
}
result as Ok
@Test
@Suppress("UNREACHABLE_CODE")
internal fun `mapEither should return the transformed result value if ok`() {
val result = Ok(500).mapEither(
success = { it + 500 },
failure = { MapError.CustomError("$it") }
)
assertEquals(
expected = 1000,
actual = result.value
)
}
result as Ok
@Test
internal fun returnsTransformedErrorIfErr() {
val result = Err("the reckless").mapEither(
success = { "the wild youth" },
failure = { MapError.CustomError("the truth") }
)
assertThat(result.value, equalTo(1000))
}
result as Err
@Test
internal fun `mapEither should return the transformed result error if not ok`() {
val result = Err("the reckless").mapEither(
success = { "the wild youth" },
failure = { MapError.CustomError("the truth") }
)
result as Err
assertThat(result.error.reason, equalTo("the truth"))
assertEquals(
expected = "the truth",
actual = result.error.reason
)
}
}
}

View File

@ -1,38 +1,61 @@
package com.github.michaelbull.result
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
internal class OnTest {
object CounterError
class Counter(var count: Int)
@Test
internal fun `onSuccess should invoke the callback when result is ok`() {
val counter = Counter(50)
Ok(counter).onSuccess { it.count += 50 }
assertThat(counter.count, equalTo(100))
internal class `onSuccess` {
@Test
internal fun invokesCallbackIfOk() {
val counter = Counter(50)
Ok(counter).onSuccess { it.count += 50 }
assertEquals(
expected = 100,
actual = counter.count
)
}
@Test
internal fun invokesNothingIfErr() {
val counter = Counter(200)
Err(CounterError).onSuccess { counter.count -= 50 }
assertEquals(
expected = 200,
actual = counter.count
)
}
}
@Test
internal fun `onSuccess should not invoke the callback when result is not ok`() {
val counter = Counter(200)
Err(CounterError).onSuccess { counter.count -= 50 }
assertThat(counter.count, equalTo(200))
}
internal class `onFailure` {
@Test
internal fun invokesCallbackIfErr() {
val counter = Counter(555)
@Test
internal fun `onFailure should invoke the callback when result is not ok`() {
val counter = Counter(555)
Err(CounterError).onFailure { counter.count += 100 }
assertThat(counter.count, equalTo(655))
}
Err(CounterError).onFailure { counter.count += 100 }
@Test
internal fun `onFailure should not invoke the callback when result is ok`() {
val counter = Counter(1020)
Ok("hello").onFailure { counter.count = 1030 }
assertThat(counter.count, equalTo(1020))
assertEquals(
expected = 655,
actual = counter.count
)
}
@Test
internal fun invokesNothingIfOk() {
val counter = Counter(1020)
Ok("hello").onFailure { counter.count = 1030 }
assertEquals(
expected = 1020,
actual = counter.count
)
}
}
}

View File

@ -1,33 +1,44 @@
package com.github.michaelbull.result
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
internal class OrTest {
private object OrError
@Test
internal fun `or should return the result value if ok`() {
val value = Ok(500).or(Ok(1000)).get()
assertThat(value, equalTo(500))
internal class `or` {
@Test
internal fun returnsValueIfOk() {
assertEquals(
expected = 500,
actual = Ok(500).or(Ok(1000)).get()
)
}
@Test
internal fun returnsDefaultValueIfErr() {
assertEquals(
expected = 5000,
actual = Err(OrError).or(Ok(5000)).get()
)
}
}
@Test
internal fun `or should return the default value if not ok`() {
val value = Err(OrError).or(Ok(5000)).get()
assertThat(value, equalTo(5000))
}
internal class `orElse` {
@Test
internal fun returnsValueIfOk() {
assertEquals(
expected = 3000,
actual = Ok(3000).orElse { Ok(4000) }.get()
)
}
@Test
internal fun `orElse should return the result value if ok`() {
val value = Ok(3000).orElse { Ok(4000) }.get()
assertThat(value, equalTo(3000))
}
@Test
internal fun `orElse should return the transformed value if not ok`() {
val value = Err(4000).orElse { Ok(2000) }.get()
assertThat(value, equalTo(2000))
@Test
internal fun returnsTransformedValueIfErr() {
assertEquals(
expected = 2000,
actual = Err(4000).orElse { Ok(2000) }.get()
)
}
}
}

View File

@ -1,69 +1,65 @@
package com.github.michaelbull.result
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Test
import kotlin.test.*
internal class ResultIteratorTest {
@Test
internal fun `hasNext should return true if unyielded and result is ok`() {
val iterator = Ok("hello").iterator()
assertThat(iterator.hasNext(), equalTo(true))
}
internal class `hasNext` {
@Test
internal fun returnsTrueIfUnyieldedAndOk() {
val iterator = Ok("hello").iterator()
assertTrue { iterator.hasNext() }
}
@Test
internal fun `hasNext should return false if result is not ok`() {
val iterator = Err("hello").iterator()
assertThat(iterator.hasNext(), equalTo(false))
}
@Test
internal fun returnsFalseIfErr() {
val iterator = Err("hello").iterator()
assertFalse { iterator.hasNext() }
}
@Test
internal fun `hasNext should return false if yielded`() {
val iterator = Ok("hello").iterator()
iterator.next()
assertThat(iterator.hasNext(), equalTo(false))
}
@Test
internal fun `next should return the result value if unyielded and result is ok`() {
val value = Ok("hello").iterator().next()
assertThat(value, equalTo("hello"))
}
@Test
internal fun `next should throw NoSuchElementException if unyielded and result is not ok`() {
val iterator = Err("hello").iterator()
assertThrows(NoSuchElementException::class.java) {
@Test
internal fun returnsFalseIfYielded() {
val iterator = Ok("hello").iterator()
iterator.next()
assertFalse { iterator.hasNext() }
}
}
@Test
internal fun `next should throw NoSuchElementException if yielded and result is ok`() {
val iterator = Ok("hello").iterator()
iterator.next()
internal class `next` {
@Test
internal fun returnsValueIfUnyieldedAndOk() {
assertEquals(
expected = "hello",
actual = Ok("hello").iterator().next()
)
}
assertThrows(NoSuchElementException::class.java) {
@Test
internal fun throwsExceptionIfUnyieldedAndErr() {
val iterator = Err("hello").iterator()
assertFailsWith<NoSuchElementException> { iterator.next() }
}
@Test
internal fun throwsExceptionIfYieldedAndOk() {
val iterator = Ok("hello").iterator()
iterator.next()
assertFailsWith<NoSuchElementException> { iterator.next() }
}
}
@Test
internal fun `remove should make hasNext return false`() {
val iterator = Ok("hello").mutableIterator()
iterator.remove()
assertThat(iterator.hasNext(), equalTo(false))
}
internal class `remove` {
@Test
internal fun makesHasNextReturnFalse() {
val iterator = Ok("hello").mutableIterator()
iterator.remove()
assertFalse { iterator.hasNext() }
}
@Test
internal fun `remove should make next throw NoSuchElementException`() {
val iterator = Ok("hello").mutableIterator()
iterator.remove()
assertThrows(NoSuchElementException::class.java) {
iterator.next()
@Test
internal fun makesNextThrowException() {
val iterator = Ok("hello").mutableIterator()
iterator.remove()
assertFailsWith<NoSuchElementException> { iterator.next() }
}
}
}

View File

@ -1,25 +1,31 @@
package com.github.michaelbull.result
import com.natpryce.hamkrest.Matcher
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import com.natpryce.hamkrest.sameInstance
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertSame
internal class ResultTest {
@Test
internal fun `of should return ok if invocation did not throw anything`() {
val callback = { "example" }
val value = Result.of(callback).get()
assertThat(value, equalTo("example"))
}
internal class `of` {
@Test
internal fun returnsOkIfInvocationSuccessful() {
val callback = { "example" }
@Test
internal fun `of should return error if invocation threw something`() {
val throwable = IllegalArgumentException("throw me")
val callback = { throw throwable }
val error = Result.of(callback).getError()!!
val matcher: Matcher<Throwable> = sameInstance(throwable)
assertThat(error, matcher)
assertEquals(
expected = "example",
actual = Result.of(callback).get()
)
}
@Test
internal fun returnsErrIfInvocationFails() {
val throwable = IllegalArgumentException("throw me")
val callback = { throw throwable }
val error = Result.of(callback).getError()!!
assertSame(
expected = throwable,
actual = error
)
}
}
}

View File

@ -1,76 +1,83 @@
package com.github.michaelbull.result
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.equalTo
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Test
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
internal class UnwrapTest {
@Test
internal fun `unwrap should return the result value if ok`() {
val value = Ok(5000).unwrap()
assertThat(value, equalTo(5000))
}
@Test
internal fun `unwrap should throw an UnwrapException if not ok`() {
val throwable = assertThrows(UnwrapException::class.java) {
Err(5000).unwrap()
internal class `unwrap` {
@Test
internal fun returnsValueIfOk() {
assertEquals(
expected = 5000,
actual = Ok(5000).unwrap()
)
}
assertThat(throwable.message, equalTo("called Result.wrap on an Err value 5000"))
@Test
internal fun throwsExceptionIfErr() {
assertFailsWith<UnwrapException>("called Result.wrap on an Err value 5000") {
Err(5000).unwrap()
}
}
}
@Test
internal fun `expect should return the result value if ok`() {
val value = Ok(1994).expect { "the year should be" }
assertThat(value, equalTo(1994))
}
@Test
internal fun `expect should throw an UnwrapException with a specified message if not ok`() {
val message = object {
override fun toString() = "the year should be"
internal class `expect` {
@Test
internal fun returnsValueIfOk() {
assertEquals(
expected = 1994,
actual = Ok(1994).expect { "the year should be" }
)
}
val throwable = assertThrows(UnwrapException::class.java) {
Err(1994).expect { message }
}
@Test
internal fun throwsExceptionIfErr() {
val message = object {
override fun toString() = "the year should be"
}
assertThat(throwable.message, equalTo("the year should be 1994"))
assertFailsWith<UnwrapException>("the year should be 1994") {
Err(1994).expect { message }
}
}
}
@Test
internal fun `unwrapError should throw an UnwrapException if ok`() {
val throwable = assertThrows(UnwrapException::class.java) {
Ok("example").unwrapError()
internal class `unwrapError` {
@Test
internal fun throwsExceptionIfOk() {
assertFailsWith<UnwrapException>("called Result.unwrapError on an Ok value example") {
Ok("example").unwrapError()
}
}
assertThat(throwable.message, equalTo("called Result.unwrapError on an Ok value example"))
@Test
internal fun returnsErrorIfErr() {
assertEquals(
expected = "example",
actual = Err("example").unwrapError()
)
}
}
@Test
internal fun `unwrapError should return the result error if not ok`() {
val error = Err("example").unwrapError()
assertThat(error, equalTo("example"))
}
internal class `expectError` {
@Test
internal fun throwsExceptionIfOk() {
val message = object {
override fun toString() = "the year should be"
}
@Test
internal fun `expectError should throw an UnwrapException with a specified message if ok`() {
val message = object {
override fun toString() = "the year should be"
assertFailsWith<UnwrapException>("the year should be 2010") {
Ok(2010).expectError { message }
}
}
val throwable = assertThrows(UnwrapException::class.java) {
Ok(2010).expectError { message }
@Test
internal fun returnsErrorIfErr() {
assertEquals(
expected = 2010,
actual = Err(2010).expectError { "the year should be" }
)
}
assertThat(throwable.message, equalTo("the year should be 2010"))
}
@Test
internal fun `expectError should return the result error if not ok`() {
val error = Err(2010).expectError { "the year should be" }
assertThat(error, equalTo(2010))
}
}