Skip to content

Commit

Permalink
Use DeclaredParameter instead of ParameterizeFailure.Argument
Browse files Browse the repository at this point in the history
The two classes filled the same role, introspecting parameters that have
been declared, and especially now that the Parameter delegate is named
"DeclaredParameter", this is a natural change.

`ParameterizeFailure` had its `toString` removed, since `Throwables`
already don;t typically have meaningful `toString` implementations,
and now `parameters` doesn't have a very meaningful representation since
it would render as a list of values without parameters.

Property validation for parameters was moved from `ParameterState` to
`ParameterizeState` since `getDeclaredParameter` is now used in multiple
places, and not necessarily requiring validation. It is also more a
responsibility of the `parameterize` DSL as well, so it makes sense this
way.
  • Loading branch information
BenWoodworth committed Oct 6, 2024
1 parent d33231a commit d7de010
Show file tree
Hide file tree
Showing 14 changed files with 103 additions and 172 deletions.
3 changes: 2 additions & 1 deletion parameterize-core/api/parameterize-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public final class com/benwoodworth/parameterize/ParameterizeConfiguration$OnFai
public final fun getBreakEarly ()Z
public final fun getFailureCount ()J
public final fun getIterationCount ()J
public final fun getParameters ()Ljava/util/List;
public final fun getRecordFailure ()Z
public final fun setBreakEarly (Z)V
public final fun setRecordFailure (Z)V
Expand All @@ -65,7 +66,7 @@ public final class com/benwoodworth/parameterize/ParameterizeFailedError$Compani
public final class com/benwoodworth/parameterize/ParameterizeFailure {
public final fun getArguments ()Ljava/util/List;
public final fun getFailure ()Ljava/lang/Throwable;
public fun toString ()Ljava/lang/String;
public final fun getParameters ()Ljava/util/List;
}

public final class com/benwoodworth/parameterize/ParameterizeFailure$Argument {
Expand Down
6 changes: 4 additions & 2 deletions parameterize-core/api/parameterize-core.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ final class com.benwoodworth.parameterize/ParameterizeConfiguration { // com.ben
final fun <get-failureCount>(): kotlin/Long // com.benwoodworth.parameterize/ParameterizeConfiguration.OnFailureScope.failureCount.<get-failureCount>|<get-failureCount>(){}[0]
final val iterationCount // com.benwoodworth.parameterize/ParameterizeConfiguration.OnFailureScope.iterationCount|{}iterationCount[0]
final fun <get-iterationCount>(): kotlin/Long // com.benwoodworth.parameterize/ParameterizeConfiguration.OnFailureScope.iterationCount.<get-iterationCount>|<get-iterationCount>(){}[0]
final val parameters // com.benwoodworth.parameterize/ParameterizeConfiguration.OnFailureScope.parameters|{}parameters[0]
final fun <get-parameters>(): kotlin.collections/List<com.benwoodworth.parameterize/ParameterizeScope.DeclaredParameter<*>> // com.benwoodworth.parameterize/ParameterizeConfiguration.OnFailureScope.parameters.<get-parameters>|<get-parameters>(){}[0]

final var breakEarly // com.benwoodworth.parameterize/ParameterizeConfiguration.OnFailureScope.breakEarly|{}breakEarly[0]
final fun <get-breakEarly>(): kotlin/Boolean // com.benwoodworth.parameterize/ParameterizeConfiguration.OnFailureScope.breakEarly.<get-breakEarly>|<get-breakEarly>(){}[0]
Expand Down Expand Up @@ -97,8 +99,8 @@ final class com.benwoodworth.parameterize/ParameterizeFailure { // com.benwoodwo
final fun <get-arguments>(): kotlin.collections/List<com.benwoodworth.parameterize/ParameterizeFailure.Argument<*>> // com.benwoodworth.parameterize/ParameterizeFailure.arguments.<get-arguments>|<get-arguments>(){}[0]
final val failure // com.benwoodworth.parameterize/ParameterizeFailure.failure|{}failure[0]
final fun <get-failure>(): kotlin/Throwable // com.benwoodworth.parameterize/ParameterizeFailure.failure.<get-failure>|<get-failure>(){}[0]

final fun toString(): kotlin/String // com.benwoodworth.parameterize/ParameterizeFailure.toString|toString(){}[0]
final val parameters // com.benwoodworth.parameterize/ParameterizeFailure.parameters|{}parameters[0]
final fun <get-parameters>(): kotlin.collections/List<com.benwoodworth.parameterize/ParameterizeScope.DeclaredParameter<*>> // com.benwoodworth.parameterize/ParameterizeFailure.parameters.<get-parameters>|<get-parameters>(){}[0]

final class <#A1: out kotlin/Any?> Argument { // com.benwoodworth.parameterize/ParameterizeFailure.Argument|null[0]
final val argument // com.benwoodworth.parameterize/ParameterizeFailure.Argument.argument|{}argument[0]
Expand Down
19 changes: 1 addition & 18 deletions parameterize-core/src/commonMain/kotlin/ParameterState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,11 @@ internal class ParameterState(
* @throws ParameterizeException if already declared for a different [property].
* @throws IllegalStateException if the argument has not been declared yet.
*/
fun getDeclaredParameter(property: KProperty<*>): DeclaredParameter<*> {
fun getDeclaredParameter(): DeclaredParameter<*> {
val declaredParameter = checkNotNull(this.declaredParameter) {
"Cannot get declared parameter before it's been declared"
}

parameterizeState.checkState(property.equalsProperty(declaredParameter.property)) {
"Cannot use parameter with `${property.name}`, since it was declared for `${declaredParameter.property.name}`."
}

return declaredParameter
}

Expand All @@ -145,17 +141,4 @@ internal class ParameterState(
this.declaredParameter = DeclaredParameter(declaredParameter.property, iterator.next())
argumentIterator = iterator.takeIf { it.hasNext() }
}

/**
* Returns the property and argument.
*
* @throws IllegalStateException if this parameter is not declared.
*/
fun getFailureArgument(): ParameterizeFailure.Argument<*> {
val declaredParameter = checkNotNull(this.declaredParameter) {
"Cannot get failure argument before parameter has been declared"
}

return ParameterizeFailure.Argument(declaredParameter.property, declaredParameter.argument)
}
}
4 changes: 2 additions & 2 deletions parameterize-core/src/commonMain/kotlin/Parameterize.kt
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ internal class SimpleParameterizeScope internal constructor(
prefix = "ParameterizeScope(",
separator = ", ",
postfix = ")"
) { (parameter, argument) ->
"${parameter.name} = $argument"
) { parameter ->
"${parameter.property.name} = ${parameter.argument}"
}

override fun <T> Parameter<T>.provideDelegate(thisRef: Any?, property: KProperty<*>): DeclaredParameter<T> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.benwoodworth.parameterize

import com.benwoodworth.parameterize.ParameterizeConfiguration.Builder
import com.benwoodworth.parameterize.ParameterizeScope.DeclaredParameter
import kotlin.coroutines.Continuation
import kotlin.coroutines.RestrictsSuspension
import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
Expand Down Expand Up @@ -191,7 +192,19 @@ public class ParameterizeConfiguration internal constructor(
/**
* The parameter arguments that resulted in the failure.
*/
public val arguments: List<ParameterizeFailure.Argument<*>> by lazy {
@Deprecated(
"Replaced with parameters",
ReplaceWith("this.parameters"),
DeprecationLevel.ERROR
)
@Suppress("DEPRECATION_ERROR")
public val arguments: List<ParameterizeFailure.Argument<*>>
get() = throw UnsupportedOperationException("Replaced with parameters")

/**
* The parameters that resulted in the failure.
*/
public val parameters: List<DeclaredParameter<*>> by lazy {
state.getFailureArguments()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ private class Failure(
clearStackTrace()
}

override val message: String = when (failure.arguments.size) {
override val message: String = when (failure.parameters.size) {
0 -> "Failed with no arguments"

1 -> failure.arguments.single().let { argument ->
1 -> failure.parameters.single().let { argument ->
"Failed with argument:\n\t\t$argument"
}

else -> failure.arguments.joinToString(
else -> failure.parameters.joinToString(
prefix = "Failed with arguments:\n\t\t",
separator = "\n\t\t"
)
Expand Down Expand Up @@ -116,9 +116,9 @@ internal inline val ParameterizeFailedError.commonMessage
}
}

failure.arguments.forEach { argument ->
failure.parameters.forEach { parameter ->
append("\n\t\t")
append(argument)
append(parameter.argument)
}
}

Expand Down
25 changes: 19 additions & 6 deletions parameterize-core/src/commonMain/kotlin/ParameterizeFailure.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,43 @@

package com.benwoodworth.parameterize

import com.benwoodworth.parameterize.ParameterizeScope.DeclaredParameter
import kotlin.reflect.KProperty

/**
* A [failure] thrown from a [parameterize] iteration, and the [arguments] that caused it.
* A [failure] thrown from a [parameterize] iteration, and the [parameters] that caused it.
*/
public class ParameterizeFailure internal constructor(
/**
* The failure thrown in a [parameterize] iteration.
*/
public val failure: Throwable,

/**
* The parameters when the [failure] occurred.
*/
public val parameters: List<DeclaredParameter<*>>
) {
/**
* The parameter arguments when the [failure] occurred.
*/
@Deprecated(
"Replaced with parameters",
ReplaceWith("this.parameters"),
DeprecationLevel.ERROR
)
@Suppress("DEPRECATION_ERROR")
public val arguments: List<Argument<*>>
) {
/** @suppress */
override fun toString(): String =
"ParameterizeFailure(failure=$failure, arguments=$arguments)"

get() = throw UnsupportedOperationException("Replaced with parameters")

/**
* A [parameter] and its [argument] when the [failure] occurred.
*/
@Deprecated(
"Replaced with DeclaredParameter",
ReplaceWith("ParameterizeScope.DeclaredParameter"),
DeprecationLevel.ERROR
)
public class Argument<out T> internal constructor(
/**
* The Kotlin property for the parameter.
Expand Down
13 changes: 9 additions & 4 deletions parameterize-core/src/commonMain/kotlin/ParameterizeState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,13 @@ internal class ParameterizeState {
lastParameterWithNextArgument = parameter
}

val declaredParameter = parameter.getDeclaredParameter()
checkState(property.equalsProperty(declaredParameter.property)) {
"Cannot use parameter with `${property.name}`, since it was declared for `${declaredParameter.property.name}`."
}

@Suppress("UNCHECKED_CAST") // If declaring the correct parameter, the argument should be T
return parameter.getDeclaredParameter(property) as DeclaredParameter<T>
return declaredParameter as DeclaredParameter<T>
}

private inline fun <T> trackNestedDeclaration(property: KProperty<*>, block: () -> T): T {
Expand All @@ -120,9 +125,9 @@ internal class ParameterizeState {
/**
* Get a list of arguments for reporting a failure.
*/
fun getFailureArguments(): List<ParameterizeFailure.Argument<*>> =
fun getFailureArguments(): List<DeclaredParameter<*>> =
parameters.take(parameterCount)
.map { it.getFailureArgument() }
.map { it.getDeclaredParameter() }

@JvmInline
value class HandleFailureResult(val breakEarly: Boolean)
Expand All @@ -144,7 +149,7 @@ internal class ParameterizeState {
onFailure(failure)

if (recordFailure) {
recordedFailures += ParameterizeFailure(failure, arguments)
recordedFailures += ParameterizeFailure(failure, parameters)
}

return HandleFailureResult(breakEarly)
Expand Down
58 changes: 12 additions & 46 deletions parameterize-core/src/commonTest/kotlin/ParameterStateSpec.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class ParameterStateSpec {

private fun assertUndeclared(parameter: ParameterState) {
val failure = assertFailsWith<IllegalStateException> {
parameter.getDeclaredParameter(::property)
parameter.getDeclaredParameter()
}

assertEquals(getArgumentBeforeDeclaredMessage, failure.message, "message")
Expand Down Expand Up @@ -136,31 +136,17 @@ class ParameterStateSpec {
@Test
fun getting_declared_parameter_before_declared_should_throw_IllegalStateException() {
val failure = assertFailsWith<IllegalStateException> {
parameter.getDeclaredParameter(::property)
parameter.getDeclaredParameter()
}

assertEquals(getArgumentBeforeDeclaredMessage, failure.message, "message")
}

@Test
fun getting_declared_parameter_with_the_wrong_property_should_throw_ParameterizeException() {
parameter.declare(::property, sequenceOf(Unit))

val exception = assertFailsWith<ParameterizeException> {
parameter.getDeclaredParameter(::differentProperty)
}

assertEquals(
"Cannot use parameter with `differentProperty`, since it was declared for `property`.",
exception.message
)
}

@Test
fun getting_declared_parameter_should_initially_return_the_first_argument() {
parameter.declare(::property, sequenceOf("first", "second"))

val declaredParameter = parameter.getDeclaredParameter(::property)
val declaredParameter = parameter.getDeclaredParameter()
assertEquals("first", declaredParameter.argument)
}

Expand All @@ -176,21 +162,21 @@ class ParameterStateSpec {
@Test
fun next_should_move_to_the_next_argument() {
parameter.declare(::property, sequenceOf("first", "second", "third"))
parameter.getDeclaredParameter(::property)
parameter.getDeclaredParameter()

parameter.nextArgument()
val secondDeclaredParameter = parameter.getDeclaredParameter(::property)
val secondDeclaredParameter = parameter.getDeclaredParameter()
assertEquals("second", secondDeclaredParameter.argument)

parameter.nextArgument()
val thirdDeclaredParameter = parameter.getDeclaredParameter(::property)
val thirdDeclaredParameter = parameter.getDeclaredParameter()
assertEquals("third", thirdDeclaredParameter.argument)
}

@Test
fun next_to_a_middle_argument_should_leave_is_last_argument_as_false() {
parameter.declare(::property, sequenceOf("first", "second", "third", "fourth"))
parameter.getDeclaredParameter(::property)
parameter.getDeclaredParameter()

parameter.nextArgument()
assertFalse(parameter.isLastArgument, "second")
Expand All @@ -202,7 +188,7 @@ class ParameterStateSpec {
@Test
fun next_to_the_last_argument_should_set_is_last_argument_to_true() {
parameter.declare(::property, sequenceOf("first", "second", "third", "fourth"))
parameter.getDeclaredParameter(::property)
parameter.getDeclaredParameter()
parameter.nextArgument() // second
parameter.nextArgument() // third
parameter.nextArgument() // forth
Expand All @@ -213,18 +199,18 @@ class ParameterStateSpec {
@Test
fun next_after_the_last_argument_should_loop_back_to_the_first() {
parameter.declare(::property, sequenceOf("first", "second"))
parameter.getDeclaredParameter(::property)
parameter.getDeclaredParameter()
parameter.nextArgument() // second
parameter.nextArgument() // first

val declaredParameter = parameter.getDeclaredParameter(::property)
val declaredParameter = parameter.getDeclaredParameter()
assertEquals("first", declaredParameter.argument)
}

@Test
fun next_after_the_last_argument_should_set_is_last_argument_to_false() {
parameter.declare(::property, sequenceOf("first", "second"))
parameter.getDeclaredParameter(::property)
parameter.getDeclaredParameter()
parameter.nextArgument() // second
parameter.nextArgument() // first

Expand All @@ -240,7 +226,7 @@ class ParameterStateSpec {
}
parameter.declare(::property, newArguments)

val declaredParameter = parameter.getDeclaredParameter(::property)
val declaredParameter = parameter.getDeclaredParameter()
assertEquals("a", declaredParameter.argument)
}

Expand Down Expand Up @@ -270,24 +256,4 @@ class ParameterStateSpec {
}
assertEquals("Parameter has not been declared", failure.message)
}

@Test
fun get_failure_argument_when_not_declared_should_throw_IllegalStateException() {
val failure = assertFailsWith<IllegalStateException> {
parameter.getFailureArgument()
}

assertEquals(getFailureArgumentBeforeDeclaredMessage, failure.message, "message")
}

@Test
fun get_failure_argument_when_declared_should_have_correct_property_and_argument() {
val expectedArgument = "a"
parameter.declare(::property, sequenceOf(expectedArgument))
parameter.getDeclaredParameter(::property)

val (property, argument) = parameter.getFailureArgument()
assertTrue(property.equalsProperty(::property))
assertSame(expectedArgument, argument)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.benwoodworth.parameterize

import com.benwoodworth.parameterize.ParameterizeConfiguration.OnCompleteScope
import com.benwoodworth.parameterize.ParameterizeConfiguration.OnFailureScope
import com.benwoodworth.parameterize.ParameterizeScope.DeclaredParameter
import kotlin.test.*

@Suppress("ClassName")
Expand Down Expand Up @@ -293,19 +294,19 @@ class ParameterizeConfigurationSpec_onComplete {

@Test
fun recorded_failures_should_be_correct() {
val expectedRecordedFailures = mutableListOf<Pair<Throwable, List<ParameterizeFailure.Argument<*>>>>()
val expectedRecordedFailures = mutableListOf<Pair<Throwable, List<DeclaredParameter<*>>>>()

var lastIteration = -1
testParameterize(
onFailure = { failure ->
if (lastIteration % 3 == 0) {
recordFailure = true
expectedRecordedFailures += failure to arguments
expectedRecordedFailures += failure to parameters
}
},
onComplete = {
val actualRecordedFailures = recordedFailures
.map { recordedFailure -> recordedFailure.failure to recordedFailure.arguments }
.map { recordedFailure -> recordedFailure.failure to recordedFailure.parameters }

assertEquals(expectedRecordedFailures, actualRecordedFailures)
}
Expand Down
Loading

0 comments on commit d7de010

Please sign in to comment.