Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion core/src/main/kotlin/com/ams/fat12ex/core/Fat12Result.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,32 @@ package com.ams.fat12ex.core
sealed class Fat12Result<out T> {
data class Ok<T>(val value: T) : Fat12Result<T>()
data class NameConflict(val name: String) : Fat12Result<Nothing>()
object DiskFull : Fat12Result<Nothing>()
object DiskFull : Fat12Result<Nothing>() {
// Stable, human-readable rendering (an `object` otherwise inherits the
// Foo@hash default) so getOrThrow()'s message reads "...not Ok: DiskFull".
override fun toString(): String = "DiskFull"
}
data class TooLarge(val actualBytes: Long) : Fat12Result<Nothing>()
data class NotFound(val path: String) : Fat12Result<Nothing>()
data class InvalidName(val name: String, val reason: String) : Fat12Result<Nothing>()
}

/** True when this result is [Fat12Result.Ok]. */
val Fat12Result<*>.isOk: Boolean get() = this is Fat12Result.Ok

/** True when this result is any non-[Fat12Result.Ok] outcome. */
val Fat12Result<*>.isError: Boolean get() = this !is Fat12Result.Ok

/** The success value, or `null` for any non-[Fat12Result.Ok] outcome. */
fun <T> Fat12Result<T>.getOrNull(): T? = (this as? Fat12Result.Ok)?.value

/**
* The success value, or throw [IllegalStateException] describing the non-[Fat12Result.Ok]
* outcome. Use only when a non-Ok result is a programming error at the call site; prefer
* [getOrNull] or an exhaustive `when` for recoverable handling.
*/
fun <T> Fat12Result<T>.getOrThrow(): T =
when (this) {
is Fat12Result.Ok -> value
else -> error("Fat12Result was not Ok: $this")
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.ams.fat12ex.core

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows

/**
* [Fat12Result] convenience-accessor tests — [isOk] / [isError] / [getOrNull] /
* [getOrThrow].
*
* Proves the accessors branch on success without an exhaustive `when` or an
* `is Fat12Result.Ok` cast, for both the [Fat12Result.Ok] case and a couple of
* representative non-Ok variants ([Fat12Result.NotFound], [Fat12Result.DiskFull]).
*/
class Fat12ResultAccessorsTest {

@Test
fun ok_isOk_getOrNull_getOrThrow() {
val result: Fat12Result<String> = Fat12Result.Ok("payload")
assertTrue(result.isOk)
assertFalse(result.isError)
assertEquals("payload", result.getOrNull())
assertEquals("payload", result.getOrThrow())
}

@Test
fun notFound_isNotOk_getOrNull_null_getOrThrow_throws() {
val result: Fat12Result<String> = Fat12Result.NotFound("/MISSING.TXT")
assertFalse(result.isOk)
assertTrue(result.isError)
assertNull(result.getOrNull())
val ex = assertThrows<IllegalStateException> { result.getOrThrow() }
assertTrue(
ex.message?.contains("NotFound(path=/MISSING.TXT)") == true,
"message must describe the non-Ok outcome, was: ${ex.message}",
)
}

@Test
fun diskFull_isNotOk_getOrNull_null_getOrThrow_throws() {
val result: Fat12Result<Unit> = Fat12Result.DiskFull
assertFalse(result.isOk)
assertTrue(result.isError)
assertNull(result.getOrNull())
val ex = assertThrows<IllegalStateException> { result.getOrThrow() }
// DiskFull is a singleton object; its message must be the stable "DiskFull",
// not the inherited Foo@hash default.
assertTrue(
ex.message?.contains("DiskFull") == true && ex.message?.contains("@") != true,
"message must read 'DiskFull', was: ${ex.message}",
)
}

@Test
fun ok_withNullableValue_getOrNull_distinguishesNullValueFromError() {
// An Ok wrapping a null value still reports isOk; getOrNull returns null here
// too, but getOrThrow returns the (null) value rather than throwing.
val result: Fat12Result<String?> = Fat12Result.Ok(null)
assertTrue(result.isOk)
assertNull(result.getOrNull())
assertNull(result.getOrThrow())
}
}
Loading