Skip to content
Merged
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
1 change: 1 addition & 0 deletions docs/supported-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ For types not listed here, register a [custom factory](custom-factories.md).
| `Char` | `some<Char>()` | |
| `Byte` | `some<Byte>()` | |
| `Short` | `some<Short>()` | |
| `Number` | `some<Number>()` | Resolves to a random concrete numeric type (`Int`, `Long`, `Double`, `Float`, or `Short`) |
| **Standard Library** | | |
| `kotlin.uuid.Uuid` | `some<Uuid>()` | Requires `@OptIn(ExperimentalUuidApi::class)` |
| `java.util.UUID` | `some<UUID>()` | |
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/dev/appoutlet/some/config/SomeConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import dev.appoutlet.some.resolver.LocalDateTimeResolver
import dev.appoutlet.some.resolver.LongResolver
import dev.appoutlet.some.resolver.MapResolver
import dev.appoutlet.some.resolver.NullableResolver
import dev.appoutlet.some.resolver.NumberResolver
import dev.appoutlet.some.resolver.ObjectResolver
import dev.appoutlet.some.resolver.SealedClassResolver
import dev.appoutlet.some.resolver.SetResolver
Expand Down Expand Up @@ -109,6 +110,7 @@ data class SomeConfig(
CharResolver(random),
ByteResolver(random),
ShortResolver(random),
NumberResolver(random),
KotlinUuidResolver(),
KotlinInstantResolver(random),
KotlinDurationResolver(random),
Expand Down
53 changes: 53 additions & 0 deletions src/main/kotlin/dev/appoutlet/some/resolver/NumberResolver.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package dev.appoutlet.some.resolver

import dev.appoutlet.some.core.ResolverChain
import dev.appoutlet.some.core.TypeResolver
import kotlin.random.Random
import kotlin.reflect.KType
import kotlin.reflect.typeOf

/**
* The concrete numeric types that can be randomly chosen when resolving a [Number] request.
*
* This list contains [Int], [Long], [Double], [Float], and [Short]. A random entry is picked
* on each resolution and delegated back to the [ResolverChain].
*/
private val numberTypes = listOf(
typeOf<Int>(),
typeOf<Long>(),
typeOf<Double>(),
typeOf<Float>(),
typeOf<Short>()
)

/**
* Resolves the abstract [Number] type by randomly picking one of the supported concrete numeric
* types and delegating its generation back to the [ResolverChain].
*
* @param random Random source used to select which concrete numeric type is generated.
*/
class NumberResolver(
private val random: Random
) : TypeResolver {

/**
* Returns `true` when [type] is exactly [Number].
*
* @param type The type to inspect.
* @return `true` if the type is [Number], `false` otherwise.
*/
override fun canResolve(type: KType): Boolean = type == typeOf<Number>()

/**
* Picks a random concrete numeric type from [numberTypes] and asks [chain] to resolve it.
*
* @param type The requested type. Expected to be [Number], but the actual value is produced
* by delegating to a concrete numeric resolver through [chain].
* @param chain Resolver chain used to generate the selected concrete numeric type.
* @return A randomly chosen numeric value among [Int], [Long], [Double], [Float], or [Short].
*/
override fun resolve(type: KType, chain: ResolverChain): Any? {
val selectedType = numberTypes.random(random)
return chain.resolve(selectedType)
}
Comment thread
MessiasLima marked this conversation as resolved.
}
36 changes: 36 additions & 0 deletions src/test/kotlin/dev/appoutlet/some/resolver/NumberResolverTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package dev.appoutlet.some.resolver

import dev.appoutlet.some.test.defaultTestChain
import kotlin.random.Random
import kotlin.reflect.typeOf
import kotlin.test.Test
import kotlin.test.assertFalse
import kotlin.test.assertIs
import kotlin.test.assertTrue

class NumberResolverTest {
@Test
fun `NumberResolver generates a value of type Number`() {
val resolver = NumberResolver(Random.Default)
val result = resolver.resolve(typeOf<Number>(), defaultTestChain)
assertIs<Number>(result)
}

@Test
fun `NumberResolver canResolve detects Number type`() {
val resolver = NumberResolver(Random.Default)
assertTrue(resolver.canResolve(typeOf<Number>()))
}

@Test
fun `NumberResolver rejects non-Number types`() {
val resolver = NumberResolver(Random.Default)
assertFalse(resolver.canResolve(typeOf<String>()))
assertFalse(resolver.canResolve(typeOf<Int>()))
assertFalse(resolver.canResolve(typeOf<Long>()))
assertFalse(resolver.canResolve(typeOf<Double>()))
assertFalse(resolver.canResolve(typeOf<Float>()))
assertFalse(resolver.canResolve(typeOf<Short>()))
assertFalse(resolver.canResolve(typeOf<Byte>()))
}
}