All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.net.jqwik.kotlin.api.JqwikGlobals.kt Maven / Gradle / Ivy

There is a newer version: 1.9.1
Show newest version
package net.jqwik.kotlin.api

import kotlinx.coroutines.*
import net.jqwik.api.Arbitraries
import net.jqwik.api.Arbitrary
import net.jqwik.api.Functions
import net.jqwik.api.Tuple
import net.jqwik.api.arbitraries.FunctionArbitrary
import net.jqwik.api.arbitraries.TypeArbitrary
import org.apiguardian.api.API
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.reflect.KClass

/**
 * Function to create an arbitrary for [Pair][Pair].
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.0")
fun  anyPair(firstArbitrary: Arbitrary, secondArbitrary: Arbitrary) =
    combine(firstArbitrary, secondArbitrary) { a, b -> Pair(a, b) }

/**
 * Function to create an arbitrary for [Triple][Triple].
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.0")
fun  anyTriple(firstArbitrary: Arbitrary, secondArbitrary: Arbitrary, thirdArbitrary: Arbitrary) =
    combine(firstArbitrary, secondArbitrary, thirdArbitrary) { a, b, c -> Triple(a, b, c) }


/**
 * Function to create a [Functions.FunctionWrapper].
 *
 * This is a Kotlin convenience for [Functions.function] which requires a Java class instead.
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.0")
fun anyFunction(kClass: KClass<*>): Functions.FunctionWrapper {
    return Functions.function(kClass.java)
}

/**
 * Create a [FunctionArbitrary] for Kotlin function without parameters.
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.0")
fun  anyFunction0(returning: Arbitrary): FunctionArbitrary, out R> {
    return anyFunction(Function0::class).returning(returning)
}

/**
 * Create a [FunctionArbitrary] for Kotlin function with 1 parameter.
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.0")
fun  anyFunction1(returning: Arbitrary): FunctionArbitrary, out R> {
    return anyFunction(Function1::class).returning(returning)
}

/**
 * Create a [FunctionArbitrary] for Kotlin function with 2 parameters.
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.0")
fun  anyFunction2(returning: Arbitrary): FunctionArbitrary, out R> {
    return anyFunction(Function2::class).returning(returning)
}

/**
 * Create a [FunctionArbitrary] for Kotlin function with 3 parameters.
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.0")
fun  anyFunction3(returning: Arbitrary): FunctionArbitrary, out R> {
    return anyFunction(Function3::class).returning(returning)
}

/**
 * Create a [FunctionArbitrary] for Kotlin function with 4 parameters.
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.0")
fun  anyFunction4(returning: Arbitrary): FunctionArbitrary, out R> {
    return anyFunction(Function4::class).returning(returning)
}

/**
 * Wrap a property so that it can use asynchronous functions within.
 *
 * @param block Code block that should return a [Boolean] or [Unit].
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.0")
fun  runBlockingProperty(
    context: CoroutineContext = EmptyCoroutineContext,
    block: suspend CoroutineScope.() -> T
): T {
    return runBlocking(context, block)
}

/**
 * Function to create a [TypeArbitrary].
 *
 * This is a Kotlin convenience for [Arbitraries.forType] which requires a Java class instead.
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.0")
inline fun  anyForType(): TypeArbitrary
    where T : Any {
    return Arbitraries.forType(T::class.java)
}


/**
 * Creates [Arbitrary] with subtypes of a sealed class or interface [T].
 * If a subtype is a sealed class or interface, its subtypes are used to create [Arbitrary]. This is done recursively.
 * [TypeArbitrary] are created by default under the hood, but this can be customized, for each subtype, with [SubtypeScope.provide] .
 * ```kotlin
 * anyForSubtypeOf {
 *     provide { customArbitrary1() }
 *     provide { customArbitrary2() }
 * }
 * ```
 * @param enableArbitraryRecursion is applied to all created [TypeArbitrary].
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.8.4")
inline fun  anyForSubtypeOf(
    enableArbitraryRecursion: Boolean = false,
    crossinline subtypeScope: SubtypeScope.() -> Unit = {}
): Arbitrary where T : Any {
    val scope = SubtypeScope().apply(subtypeScope)
    return Arbitraries.of(T::class.allSealedSubclasses).flatMap {
        scope.getProviderFor(it)
            ?: Arbitraries.forType(it.java).run {
                if (enableArbitraryRecursion) {
                    enableRecursion()
                } else {
                    this
                }
            }
    }.map { obj -> obj }
}

/**
 * Function to create arbitrary that generates one of the provided values with a given frequency.
 *
 * This is a Kotlin convenience for [Arbitraries.frequency] which takes [Pair]s instead of jqwik tuples.
 */
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
@API(status = API.Status.EXPERIMENTAL, since = "1.6.2")
fun  frequency(vararg frequencies: Pair): Arbitrary {
    val listOfFrequencies: List> = frequencies
        .map { pair -> Tuple.of(pair.first, pair.second) }
        .toList()
    return Arbitraries.frequency(listOfFrequencies) as Arbitrary
}

/**
 * Function to choose from one of the provided arbitraries with a given frequency.
 *
 * This is a Kotlin convenience for [Arbitraries.frequencyOf] which takes [Pair]s instead of jqwik tuples.
 */
@API(status = API.Status.EXPERIMENTAL, since = "1.6.2")
fun  frequencyOf(vararg frequencies: Pair>): Arbitrary {
    val listOfFrequencies: List>> = frequencies
        .map { pair -> Tuple.of(pair.first, pair.second) }
        .toList()
    return Arbitraries.frequencyOf(listOfFrequencies) as Arbitrary
}