Skip to content

Commit

Permalink
add model test renderer for java
Browse files Browse the repository at this point in the history
  • Loading branch information
jenschude committed Sep 15, 2023
1 parent 929556b commit 9973bc1
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package io.vrap.codegen.languages.javalang.client.builder.test

import io.vrap.codegen.languages.extensions.deprecated
import io.vrap.codegen.languages.extensions.isPatternProperty
import io.vrap.codegen.languages.java.base.extensions.*
import io.vrap.rmf.codegen.di.AllObjectTypes
import io.vrap.rmf.codegen.firstLowerCase

import io.vrap.rmf.codegen.io.TemplateFile
import io.vrap.rmf.codegen.rendering.FileProducer
import io.vrap.rmf.codegen.rendering.ObjectTypeRenderer
import io.vrap.rmf.codegen.rendering.utils.*
import io.vrap.rmf.codegen.types.VrapEnumType
import io.vrap.rmf.codegen.types.VrapObjectType
import io.vrap.rmf.codegen.types.VrapTypeProvider
import io.vrap.rmf.raml.model.types.*
import javax.lang.model.SourceVersion
import kotlin.random.Random

class JavaBuilderTestRenderer constructor(override val vrapTypeProvider: VrapTypeProvider, @AllObjectTypes private val allObjectTypes: List<ObjectType>): FileProducer, JavaEObjectTypeExtensions, JavaObjectTypeExtensions {

override fun produceFiles(): List<TemplateFile> {
return allObjectTypes.filter { !it.isAbstract() && !it.deprecated() }.map { render(it) }
}

fun render(type: ObjectType): TemplateFile {
val vrapType = vrapTypeProvider.doSwitch(type).toJavaVType() as VrapObjectType

val properties = type.properties.filterNot { it.deprecated() || it.isPatternProperty() || it.name == type.discriminator() }
val content = """
|package ${vrapType.`package`};
|
|import com.tngtech.junit.dataprovider.DataProvider;
|import com.tngtech.junit.dataprovider.DataProviderExtension;
|import com.tngtech.junit.dataprovider.UseDataProvider;
|import com.tngtech.junit.dataprovider.UseDataProviderExtension;
|import org.assertj.core.api.Assertions;
|import org.junit.jupiter.api.Test;
|import org.junit.jupiter.api.TestTemplate;
|import org.junit.jupiter.api.extension.ExtendWith;
|
|import java.time.LocalDate;
|import java.time.LocalTime;
|import java.time.ZonedDateTime;
|import java.util.Collections;
|
|@ExtendWith(UseDataProviderExtension.class)
|@ExtendWith(DataProviderExtension.class)
|public class ${vrapType.simpleClassName}Test {
| ${if (properties.isNotEmpty()) """
| @TestTemplate
| @UseDataProvider("objectBuilder")
| public void buildUnchecked(${vrapType.simpleClassName}Builder builder) {
| ${vrapType.simpleClassName} ${vrapType.simpleClassName.firstLowerCase()} = builder.buildUnchecked();
| Assertions.assertThat(${vrapType.simpleClassName.firstLowerCase()}).isInstanceOf(${vrapType.simpleClassName}.class);
| }
|
| @DataProvider
| public static Object[][] objectBuilder() {
| return new Object[][] {
| <<${properties.joinToString(",\n") { "new Object[] { ${builder(type, it)} }" }}>>
| };
| }
|
| <<${properties.joinToString("\n") { getterSetterTest(type, it) }}>>""" else ""}
|}
""".trimMargin().keepAngleIndent()

return TemplateFile(
relativePath = "${vrapType.`package`}.${vrapType.simpleClassName}Test".replace(".", "/") + ".java",
content = content
)
}

private fun builder(type: ObjectType, property: Property): String {
var propertyName = property.name
val checkedPropertyType = property.type
val vrapType = vrapTypeProvider.doSwitch(type).toJavaVType() as VrapObjectType
if(SourceVersion.isKeyword(propertyName)) {
propertyName = "_$propertyName"
}

return "${vrapType.simpleClassName}.builder().${propertyName}(${propertyValue(propertyName, checkedPropertyType, Random(propertyName.hashCode()))})"
}

private fun getterSetterTest(type: ObjectType, property: Property): String {
val vrapType = vrapTypeProvider.doSwitch(type).toJavaVType() as VrapObjectType
var methodName = property.name.lowerCamelCase()
if(SourceVersion.isKeyword(methodName)) {
methodName = "_$methodName"
}
val propertyValue = propertyValue(property.name, property.type, Random(property.name.hashCode()))
return """
|@Test
|public void ${methodName}() {
| ${vrapType.simpleClassName} value = ${vrapType.simpleClassName}.of();
| value.set${property.name.upperCamelCase()}($propertyValue);
| Assertions.assertThat(value.get${property.name.upperCamelCase()}()).isEqualTo($propertyValue);
|}
""".trimMargin()
}

private fun propertyValue(name: String, type: AnyType, r: Random) : Any {
val vrapType = type.toVrapType();

val checkedType = if (type.isInlineType) type.type else type
return when (type) {
is ArrayType -> "Collections.singletonList(${propertyValue(name, type.items, r)})"
is BooleanType -> true
is IntegerType -> when (type.format) {
NumberFormat.INT64 -> "${r.nextInt(1, 10)}L"
else -> r.nextInt(1, 10)
}
is NumberType -> when (type.format) {
NumberFormat.DOUBLE -> r.nextDouble()
NumberFormat.FLOAT -> r.nextFloat()
NumberFormat.INT64 -> "${r.nextInt(1, 10)}L"
else -> r.nextInt(1, 10)
}
is StringType -> when (vrapType) {
is VrapEnumType -> "${vrapType.fullClassName()}.findEnum(\"${checkedType.enum.firstOrNull()?.value ?: name}\")"
else -> "\"${name}\""
}
is ObjectType -> when(vrapType.fullClassName()) {
"java.lang.Object" -> "\"${name}\""
else -> "new ${vrapType.fullClassName()}Impl()"
}
is DateOnlyType -> "LocalDate.parse(\"2023-06-01\")"
is TimeOnlyType -> "LocalTime.parse(\"12:00\")"
is DateTimeType -> "ZonedDateTime.parse(\"2023-06-01T12:00Z\")"
else -> "\"${name}\""
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ object JavaTestModule: Module {
setOf(
JavaRequestTestRenderer(generatorModule.vrapTypeProvider())
), generatorModule.allResources().filterNot { it.deprecated() }
),
FileGenerator(
setOf(
JavaBuilderTestRenderer(generatorModule.vrapTypeProvider(), generatorModule.allObjectTypes())
)
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class BuilderTestCodeGenerator {
private val apiPath : Path = Paths.get(if (userProvidedPath == null) "../../../../api-spec/api.raml" else userProvidedPath)
private val importApiPath : Path = Paths.get(if (importApiProvidedPath == null) "../../../../api-spec/api.raml" else importApiProvidedPath)
private val outputFolder : Path = Paths.get(if (generatedCodePath == null) "build/gensrc/main/java-generated" else generatedCodePath)
private val testOutputFolder : Path = Paths.get(if (generatedCodePath == null) "build/gensrc/test/java-generated" else generatedTestCodePath)
private val testOutputFolder : Path = Paths.get(if (generatedTestCodePath == null) "build/gensrc/test/java-generated" else generatedTestCodePath)
private val predicateOutputFolder : Path = Paths.get(if (generatedPredicateCodePath == null) "build/gensrc/main/java-predicates-generated" else generatedPredicateCodePath)

val apiProvider: RamlApiProvider = RamlApiProvider(apiPath)
Expand Down

0 comments on commit 9973bc1

Please sign in to comment.