Skip to content

Commit

Permalink
Finalize PanacheEntityBaseProcessor compile tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Thijsiez committed Oct 25, 2024
1 parent adac36d commit 8a7e9d2
Show file tree
Hide file tree
Showing 4 changed files with 292 additions and 209 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/*
* Copyright 2024 Thijs Koppen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ch.icken.processor

import com.tschuchort.compiletesting.SourceFile.Companion.kotlin
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.junit.jupiter.api.Test

@OptIn(ExperimentalCompilerApi::class)
class PanacheEntityBaseProcessorCompileTests : ProcessorCompileTestCommon() {

@Test
fun testInterface() {

// Given
val compilation = kotlinCompilation("NotAClass.kt", """
import jakarta.persistence.Entity
@Entity
interface NotAClass
""")

// When
val result = compilation.compile()

// Then
result.assertOk()
}

@Test
fun testNotPanacheEntity() {

// Given
val compilation = kotlinCompilation("Department.kt", """
import jakarta.persistence.Entity
@Entity
class Department
""")

// When
val result = compilation.compile()

// Then
result.assertOk()
}

@Test
fun testPanacheEntityBaseWithoutProperties() {

// Given
val compilation = kotlinCompilation("Employee.kt", """
import io.quarkus.hibernate.orm.panache.kotlin.PanacheEntityBase
import jakarta.persistence.Entity
@Entity
class Employee : PanacheEntityBase
""")

// When
val result = compilation.compile()

// Then
result.assertOk()
compilation.assertFileGenerated("EmployeeColumns.kt")

val employeeColumns = result.loadGeneratedClass("EmployeeColumns")
employeeColumns.assertNumberOfProperties(0)
}

@Test
fun testPanacheEntityWithTransientProperty() {

// Given
val compilation = kotlinCompilation("Product.kt", """
import io.quarkus.hibernate.orm.panache.kotlin.PanacheEntityBase
import jakarta.persistence.Entity
import jakarta.persistence.Transient
@Entity
class Product(
@Transient
var name: String
) : PanacheEntityBase
""")

// When
val result = compilation.compile()

// Then
result.assertOk()
compilation.assertFileGenerated("ProductColumns.kt")

val productColumns = result.loadGeneratedClass("ProductColumns")
productColumns.assertNumberOfProperties(0)
}

@Test
fun testPanacheEntitiesWithJoinColumnAndMappedProperty() {

// Given
val compilation = compilation(
kotlin("Post.kt", """
import io.quarkus.hibernate.orm.panache.kotlin.PanacheEntity
import jakarta.persistence.Entity
import jakarta.persistence.OneToMany
@Entity
class Post(
@OneToMany(mappedBy = "post")
val comments: MutableList<Comment> = mutableListOf()
) : PanacheEntity()
"""),
kotlin("Comment.kt", """
import io.quarkus.hibernate.orm.panache.kotlin.PanacheEntity
import jakarta.persistence.Entity
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
@Entity
class Comment(
@JoinColumn(name = "post_id")
@ManyToOne(optional = false)
val post: Post
) : PanacheEntity()
""")
)

// When
val result = compilation.compile()

// Then
result.assertOk()
compilation.assertFileGenerated("PostColumns.kt")
compilation.assertFileGenerated("CommentColumns.kt")

val postColumns = result.loadGeneratedClass("PostColumns")
postColumns.assertNumberOfProperties(1)
postColumns.assertHasColumnOfType("id", Long::class)

val commentColumns = result.loadGeneratedClass("CommentColumns")
commentColumns.assertNumberOfProperties(2)
commentColumns.assertHasColumnOfType("id", Long::class)
commentColumns.assertHasPropertyOfType("post", "PostColumnsBase")
}

@Test
fun testPanacheEntityWithColumnTypeAnnotation() {

// Given
val compilation = kotlinCompilation("User.kt", """
import ch.icken.processor.ColumnType
import io.quarkus.hibernate.orm.panache.kotlin.PanacheEntity
import jakarta.persistence.Entity
@Entity
class User(
@ColumnType(CharSequence::class)
var username: String
) : PanacheEntity()
""")

// When
val result = compilation.compile()

// Then
result.assertOk()
compilation.assertFileGenerated("UserColumns.kt")

val userColumns = result.loadGeneratedClass("UserColumns")
userColumns.assertNumberOfProperties(2)
userColumns.assertHasColumnOfType("id", Long::class)
userColumns.assertHasColumnOfType("username", CharSequence::class)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,9 @@ class PanacheEntityBaseProcessorMockTests : ProcessorMockTestCommon() {
val lastNameColumnTypeParameterName = mockk<KSName>()
every { lastNameColumnTypeParameterName.asString() } returns TYPE

val lastnameColumnTypeParameterValue = mockk<KSType>()
every { lastnameColumnTypeParameterValue.toClassName() } returns StringClassName

val lastNameColumnTypeParameter = mockk<KSValueArgument>()
every { lastNameColumnTypeParameter.name } returns lastNameColumnTypeParameterName
every { lastNameColumnTypeParameter.value } returns lastnameColumnTypeParameterValue
every { lastNameColumnTypeParameter.value } returns null

val lastNameColumnType = mockk<KSAnnotation>()
every { lastNameColumnType.arguments } returns listOf(lastNameColumnTypeParameter)
Expand Down
94 changes: 94 additions & 0 deletions src/test/kotlin/ch/icken/processor/ProcessorCompileTestCommon.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2024 Thijs Koppen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ch.icken.processor

import ch.icken.query.Column
import com.tschuchort.compiletesting.*
import org.intellij.lang.annotations.Language
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.junit.jupiter.api.Assertions.*
import kotlin.reflect.KClass
import kotlin.reflect.full.memberProperties

@OptIn(ExperimentalCompilerApi::class)
abstract class ProcessorCompileTestCommon {

protected fun kotlinResource(resourceName: String, sourceFileName: String = resourceName) =
SourceFile.kotlin(sourceFileName, javaClass.classLoader.getResource(resourceName)?.readText() ?: "")

protected fun compilation(vararg source: SourceFile) = KotlinCompilation().apply {
inheritClassPath = true
kspWithCompilation = true
sources = listOf(*source)
symbolProcessorProviders = listOf(
PanacheCompanionBaseProcessorProvider(),
PanacheEntityBaseProcessorProvider()
)
verbose = false
}

protected fun kotlinCompilation(sourceFileName: String, @Language("kotlin") contents: String) =
compilation(SourceFile.kotlin(sourceFileName, contents))

protected fun KotlinCompilation.Result.assertOk() = assertEquals(KotlinCompilation.ExitCode.OK, exitCode)

protected fun KotlinCompilation.assertFileGenerated(fileName: String, outputDir: String = "generated") =
assertTrue(kspSourcesDir.resolve("kotlin").resolve(outputDir).resolve(fileName).isFile)

protected fun KotlinCompilation.Result.loadGeneratedClass(className: String, outputPackage: String = "generated") =
this.classLoader.loadClass("$outputPackage.$className").kotlin

protected fun KClass<*>.assertNumberOfProperties(expectedNumberOfProperties: Int) {
assertEquals(expectedNumberOfProperties, memberProperties.size)
}

protected fun KClass<*>.assertHasPropertyOfType(propertyName: String, expectedTypeName: String) {
val property = memberProperties.find { it.name == propertyName }
assertNotNull(property)

val returnType = property!!.returnType
returnType.classifier.let { classifier ->
assertNotNull(classifier)
assertTrue(classifier is KClass<*>)
assertEquals(expectedTypeName, (classifier as? KClass<*>)?.simpleName)
}
}

protected fun KClass<*>.assertHasColumnOfType(columnName: String, expectedType: KClass<*>) {
val property = memberProperties.find { it.name == columnName }
assertNotNull(property)

val returnType = property!!.returnType
returnType.classifier.let { classifier ->
assertNotNull(classifier)
assertTrue(classifier is KClass<*>)
assertEquals(Column::class, classifier)
}

val arguments = returnType.arguments
assertNotNull(arguments)
assertEquals(1, arguments.size)

val type = arguments[0].type
assertNotNull(type)
type!!.classifier.let { classifier ->
assertNotNull(classifier)
assertTrue(classifier is KClass<*>)
assertEquals(expectedType, classifier)
}
}
}
Loading

0 comments on commit 8a7e9d2

Please sign in to comment.