Skip to content

Commit

Permalink
introduce tuple factories; check in tests same instance
Browse files Browse the repository at this point in the history
... instead of using toEqual. We want to be sure the functions
don't modify the data
  • Loading branch information
robstoll committed Jun 20, 2024
1 parent 5585d28 commit 102cdda
Show file tree
Hide file tree
Showing 32 changed files with 2,295 additions and 584 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,20 @@ val generate: TaskProvider<Task> = tasks.register("generate") {

val map = createStringBuilder(packageName)

val tupleFactory = StringBuilder(dontModifyNotice)
.append("@file:Suppress(\"MethodOverloading\", \"FunctionName\")\n")
.append("package ").append(packageName).append("\n\n")


(2..numOfArgs).forEach { upperNumber ->
val numbers = (1..upperNumber).toList()
val typeArgs = numbers.joinToString(", ") { "A$it" }
val constructorProperties = numbers.joinToString(",\n ") { "val a$it: A$it" }
val parameters = numbers.joinToString(", ") { "a$it: A$it" }
val arguments = numbers.joinToString(", ") { "a$it" }
val tupleName = getTupleName(upperNumber)
val tuple = createStringBuilder(packageName)
val tupleLike = createStringBuilder(packageName)
val tuple = createStringBuilder(packageName)

tupleLike.append(
"""
Expand Down Expand Up @@ -121,6 +128,24 @@ val generate: TaskProvider<Task> = tasks.register("generate") {
tupleFile.writeText(tuple.toString())
}

tupleFactory.append(
"""
|/**
| * Factory method to create a [$tupleName].
| *
| * Alternative to `$tupleName(...)` with the advantage that you can add remove
| * arguments without the need to change function name.
| *
| * @return the newly created [$tupleName]
| *
| * @since 2.1.0
| */${if (upperNumber >= 6) "\n@Suppress(\"LongParameterList\")" else ""}
|fun <$typeArgs> Tuple(
| $parameters
|): $tupleName<$typeArgs> =
| $tupleName($arguments)
""".trimMargin()
).appendLine().appendLine()


(1..numOfArgs - upperNumber).forEach { upperNumber2 ->
Expand Down Expand Up @@ -215,6 +240,9 @@ val generate: TaskProvider<Task> = tasks.register("generate") {

val mapFile = packageDir.resolve("tupleMap.kt")
mapFile.writeText(map.toString())

val tupleFactoryFile = packageDir.resolve("tupleFactory.kt")
tupleFactoryFile.writeText(tupleFactory.toString())
}
}
generationFolder.builtBy(generate)
Expand All @@ -234,7 +262,7 @@ fun StringBuilder.appendTest(testName: String) = this.append(
val generateTest: TaskProvider<Task> = tasks.register("generateTest") {
doFirst {
val packageDir = File(generationTestFolder.asPath + "/" + packageNameAsPath)
val argValues = sequenceOf(
val argValuesNotMapped = sequenceOf(
"\"string\"",
"1",
"2L",
Expand All @@ -245,15 +273,31 @@ val generateTest: TaskProvider<Task> = tasks.register("generateTest") {
"2.toByte()",
"listOf(1, 2)",
)
val argValues = argValuesNotMapped.map { "listOf($it)" }

val argsTypeParameters = sequenceOf(
"String", "Int", "Long", "Float", "Double", "Char", "Short", "Byte", "List<Int>"
)
).map { "List<$it>" }

val factoryTest = createStringBuilder("$packageName")
.appendTest("TupleFactoryTest")

(2..numOfArgs).forEach { upperNumber ->
val numbers = (1..upperNumber)
val typeArgs = argsTypeParameters.take(upperNumber).joinToString(", ")
fun typeArgs(num: Int) = argsTypeParameters.take(num).joinToString(", ")
val typeArgs = typeArgs(upperNumber)
val tupleName = getTupleName(upperNumber)
val tupleCreation = """$tupleName(${argValues.take(upperNumber).joinToString(", ")})"""

fun vals(num: Int) = argValues.take(num).withIndex().joinToString("\n ") { (index, value) ->
"val a${index + 1} = $value"
}
val vals = vals(upperNumber)

val valsAsArgs = numbers.joinToString(", ") { "a$it" }
val tupleCreation = """$tupleName($valsAsArgs)"""
fun sameFeatureCheck(num: Int, indent: String) = (1..num).joinToString("\n$indent") {
"feature { f(it::${getArgName(num, it)}) }.toBeTheInstance(a${it})"
}

val mapTest = createStringBuilder("$packageName.map")
.appendTest("${tupleName}MapTest")
Expand All @@ -267,49 +311,60 @@ val generateTest: TaskProvider<Task> = tasks.register("generateTest") {
val glueTest = createStringBuilder("$packageName.glue")
.appendTest("${tupleName}GlueTest")

factoryTest.append(
"""
| @Test
| fun factory_for_$tupleName() {
| ${vals(upperNumber)}
| expect(Tuple($valsAsArgs))
| .toBeAnInstanceOf<$tupleName<${typeArgs}>> {
| ${sameFeatureCheck(upperNumber, " ")}
| }
| }
""".trimMargin()
).appendLine().appendLine()

numbers.forEach { argNum ->
val argNameToMap = getArgName(upperNumber, argNum)
val argNameCapitalized = argNameToMap.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
}
listOf(1, 2, 3).withIndex()

val vals = argValues.take(upperNumber).withIndex().joinToString("\n ") { (index, value) ->
"val a${index + 1} = listOf($value)"
}
val tupleListCreation =
"""$tupleName(${numbers.joinToString(", ") { "a$it" }})"""
val tupleListResult = """$tupleName(${
argValues.take(upperNumber).withIndex().joinToString(", ") { (index, value) ->
val tupleListResult = "$tupleName(${
argValuesNotMapped.take(upperNumber).withIndex().joinToString(", ") { (index, value) ->
if (index + 1 == argNum) value else "a${index + 1}"
}
})"""
val checkInstances = numbers.filter { it != argNum }.joinToString("\n ") {
"""
|feature { f(it::${getArgName(upperNumber, it)}) }.toBeTheInstance(a${it})
""".trimMargin()
}
})"

mapTest.append(
"""
| @Test
| fun map${argNameCapitalized}__identity__returns_equal_$tupleName() {
| $vals
|
| expect(
| $tupleCreation
| .map${argNameCapitalized}(::identity)
| ).toEqual(
| $tupleCreation
| )
| ) {
| ${sameFeatureCheck(upperNumber, " ")}
| }
| }
|
| @Test
| fun map${argNameCapitalized}__transformation_does_not_touch_other_properties() {
| $vals
|
| expect(
| $tupleListCreation
| $tupleCreation
| .map${argNameCapitalized} { it.first() }
| ) {
| toEqual($tupleListResult)
| $checkInstances
| ${
numbers.filter { it != argNum }.joinToString("\n ") {
"feature { f(it::${getArgName(upperNumber, it)}) }.toBeTheInstance(a${it})"
}
}
| }
| }
""".trimMargin()
Expand All @@ -320,16 +375,12 @@ val generateTest: TaskProvider<Task> = tasks.register("generateTest") {
"""
| @Test
| fun toTuple__returns_${tupleName}_in_correct_order() {
| val dataClass = Dummy$upperNumber(${argValues.take(upperNumber).joinToString(", ")})
| expect(dataClass.toTuple()).toBeAnInstanceOf<$tupleName<$typeArgs>> {
| ${
numbers.joinToString("\n ") {
"feature { f(it::component$it) }.toEqual(${
argValues.drop(it - 1).first()
})"
}
}
| }
| $vals
| val dataClass = Dummy$upperNumber($valsAsArgs)
|
| expect(dataClass.toTuple()).toBeAnInstanceOf<$tupleName<$typeArgs>> {
| ${sameFeatureCheck(upperNumber, " ")}
| }
| }
|
""".trimMargin()
Expand All @@ -338,38 +389,41 @@ val generateTest: TaskProvider<Task> = tasks.register("generateTest") {
(1..numOfArgs - upperNumber).forEach { upperNumber2 ->
val upperNumber3 = upperNumber + upperNumber2
val toTupleName = getTupleName(upperNumber3)

val toTupleNameCreation = """$toTupleName(${argValues.take(upperNumber3).joinToString(", ")})"""
val vals3AsArgs = (upperNumber + 1..upperNumber3).joinToString(", ") { "a$it" }

appendTest.append(
"""
| @Test
| fun append_${upperNumber2}_values__results_in_a_$toTupleName() {
| ${vals(upperNumber3)}
|
| expect(
| $tupleCreation
| .append(${argValues.drop(upperNumber).take(upperNumber2).joinToString(", ")})
| ).toEqual(
| $toTupleNameCreation
| )
| .append($vals3AsArgs)
| ).toBeAnInstanceOf<$toTupleName<${typeArgs(upperNumber3)}>> {
| ${sameFeatureCheck(upperNumber3, " ")}
| }
| }
""".trimMargin()
).appendLine().appendLine()

if (upperNumber2 > 1) {
val tupleNameParam = getTupleName(upperNumber2)
val tupleNameParamCreation =
"""$tupleNameParam(${argValues.drop(upperNumber).take(upperNumber2).joinToString(", ")})"""
"""$tupleNameParam($vals3AsArgs)"""

glueTest.append(
"""
| @Test
| fun glue_${tupleNameParam}__results_in_a_$toTupleName() {
| ${vals(upperNumber3)}
|
| expect(
| $tupleCreation
| .glue($tupleNameParamCreation)
| ).toEqual(
| $toTupleNameCreation
| )
| ).toBeAnInstanceOf<$toTupleName<${typeArgs(upperNumber3)}>> {
| ${sameFeatureCheck(upperNumber3, " ")}
| }
| }
""".trimMargin()
).appendLine().appendLine()
Expand Down Expand Up @@ -413,6 +467,10 @@ val generateTest: TaskProvider<Task> = tasks.register("generateTest") {
glueTestFile.writeText(glueTest.toString())
}
}

factoryTest.append("}")
val factoryTestFile = packageDir.resolve("TupleFactoryTest.kt")
factoryTestFile.writeText(factoryTest.toString())
}
}
generationTestFolder.builtBy(generateTest)
Expand Down
131 changes: 131 additions & 0 deletions src/commonMain/generated/kotlin/ch/tutteli/kbox/tupleFactory.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// --------------------------------------------------------------------------------------------------------------------
// automatically generated, don't modify here but in:
// gradle/code-generation/src/main/kotlin/code-generation.generate.gradle.kts
// --------------------------------------------------------------------------------------------------------------------
@file:Suppress("MethodOverloading", "FunctionName")
package ch.tutteli.kbox

/**
* Factory method to create a [Pair].
*
* Alternative to `Pair(...)` with the advantage that you can add remove
* arguments without the need to change function name.
*
* @return the newly created [Pair]
*
* @since 2.1.0
*/
fun <A1, A2> Tuple(
a1: A1, a2: A2
): Pair<A1, A2> =
Pair(a1, a2)

/**
* Factory method to create a [Triple].
*
* Alternative to `Triple(...)` with the advantage that you can add remove
* arguments without the need to change function name.
*
* @return the newly created [Triple]
*
* @since 2.1.0
*/
fun <A1, A2, A3> Tuple(
a1: A1, a2: A2, a3: A3
): Triple<A1, A2, A3> =
Triple(a1, a2, a3)

/**
* Factory method to create a [Tuple4].
*
* Alternative to `Tuple4(...)` with the advantage that you can add remove
* arguments without the need to change function name.
*
* @return the newly created [Tuple4]
*
* @since 2.1.0
*/
fun <A1, A2, A3, A4> Tuple(
a1: A1, a2: A2, a3: A3, a4: A4
): Tuple4<A1, A2, A3, A4> =
Tuple4(a1, a2, a3, a4)

/**
* Factory method to create a [Tuple5].
*
* Alternative to `Tuple5(...)` with the advantage that you can add remove
* arguments without the need to change function name.
*
* @return the newly created [Tuple5]
*
* @since 2.1.0
*/
fun <A1, A2, A3, A4, A5> Tuple(
a1: A1, a2: A2, a3: A3, a4: A4, a5: A5
): Tuple5<A1, A2, A3, A4, A5> =
Tuple5(a1, a2, a3, a4, a5)

/**
* Factory method to create a [Tuple6].
*
* Alternative to `Tuple6(...)` with the advantage that you can add remove
* arguments without the need to change function name.
*
* @return the newly created [Tuple6]
*
* @since 2.1.0
*/
@Suppress("LongParameterList")
fun <A1, A2, A3, A4, A5, A6> Tuple(
a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6
): Tuple6<A1, A2, A3, A4, A5, A6> =
Tuple6(a1, a2, a3, a4, a5, a6)

/**
* Factory method to create a [Tuple7].
*
* Alternative to `Tuple7(...)` with the advantage that you can add remove
* arguments without the need to change function name.
*
* @return the newly created [Tuple7]
*
* @since 2.1.0
*/
@Suppress("LongParameterList")
fun <A1, A2, A3, A4, A5, A6, A7> Tuple(
a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7
): Tuple7<A1, A2, A3, A4, A5, A6, A7> =
Tuple7(a1, a2, a3, a4, a5, a6, a7)

/**
* Factory method to create a [Tuple8].
*
* Alternative to `Tuple8(...)` with the advantage that you can add remove
* arguments without the need to change function name.
*
* @return the newly created [Tuple8]
*
* @since 2.1.0
*/
@Suppress("LongParameterList")
fun <A1, A2, A3, A4, A5, A6, A7, A8> Tuple(
a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8
): Tuple8<A1, A2, A3, A4, A5, A6, A7, A8> =
Tuple8(a1, a2, a3, a4, a5, a6, a7, a8)

/**
* Factory method to create a [Tuple9].
*
* Alternative to `Tuple9(...)` with the advantage that you can add remove
* arguments without the need to change function name.
*
* @return the newly created [Tuple9]
*
* @since 2.1.0
*/
@Suppress("LongParameterList")
fun <A1, A2, A3, A4, A5, A6, A7, A8, A9> Tuple(
a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8, a9: A9
): Tuple9<A1, A2, A3, A4, A5, A6, A7, A8, A9> =
Tuple9(a1, a2, a3, a4, a5, a6, a7, a8, a9)

Loading

0 comments on commit 102cdda

Please sign in to comment.