Skip to content

Commit

Permalink
Add some compile tests
Browse files Browse the repository at this point in the history
  • Loading branch information
clementetb committed Dec 5, 2023
1 parent f64bdf3 commit b5b6a20
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ import org.jetbrains.kotlin.ir.interpreter.getAnnotation
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeArgument
import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.impl.IrAbstractSimpleType
import org.jetbrains.kotlin.ir.types.isBoolean
Expand Down Expand Up @@ -752,7 +753,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
// TODO extract the type from the annotation, by now hardcoded one

val schemaProperty =
retrieveSchemaProperty(declaration, realmType.typeOrNull!!)
retrieveSchemaProperty(declaration, realmType.typeOrNull!!.makeNotNull())

if(schemaProperty!= null) {
fields[name] = schemaProperty!!
Expand Down Expand Up @@ -826,6 +827,11 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {

private fun retrieveSchemaProperty(property: IrProperty, type: IrType): SchemaProperty? =
when {
// TODO should we allow these realm int subtypes?
type.isChar() ||
type.isByte() ||
type.isShort() ||
type.isInt() ||
type.isLong() -> SchemaProperty(
propertyType = PropertyType.RLM_PROPERTY_TYPE_INT,
declaration = property,
Expand Down Expand Up @@ -873,7 +879,8 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
declaration = property,
collectionType = CollectionType.NONE
)
type.isObjectId() -> SchemaProperty(
type.isObjectId() ||
type.isRealmObjectId() -> SchemaProperty(
propertyType = PropertyType.RLM_PROPERTY_TYPE_OBJECT_ID,
declaration = property,
collectionType = CollectionType.NONE
Expand All @@ -885,7 +892,7 @@ class AccessorModifierIrGeneration(private val pluginContext: IrPluginContext) {
)
else -> {
logError(
"Invalid type parameter, only Realm types are supported", // TODO find a better error message
"Invalid type parameter '${type.classFqName}', only Realm types are supported", // TODO find a better error message
property.locationOf()
)
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ import com.tschuchort.compiletesting.KotlinCompilation
import com.tschuchort.compiletesting.SourceFile
import io.realm.kotlin.internal.interop.CollectionType
import io.realm.kotlin.test.util.Compiler.compileFromSource
import io.realm.kotlin.test.util.TypeDescriptor
import io.realm.kotlin.test.util.TypeDescriptor.allFieldTypes
import io.realm.kotlin.types.MutableRealmInt
import io.realm.kotlin.types.ObjectId
import io.realm.kotlin.types.RealmAny
import io.realm.kotlin.types.RealmInstant
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.RealmUUID
import org.junit.Test
import org.mongodb.kbson.BsonObjectId
Expand All @@ -33,13 +35,17 @@ import kotlin.reflect.KClassifier
import kotlin.test.assertEquals
import kotlin.test.assertTrue

/**
* These tests should validate:
* - [x] Adapter with a non-realm type should fail
* - [x] Adapter annotation on unsupported types: delegate, function etc
* - [ ] Adapters type supportness
* - [ ] Instanced and singleton adapters
*/
class TypeAdaptersTests {
// TODO: Add tests to validate type adapter definitions
// TODO: Q. Shall we fail with declaring type adapters or when we apply them?


// TODO: Can we make it fail when declaring type adapters rather than when we apply them?
@Test
fun nonRealmTypesThrow() {
fun `adapters don't support R-types that are not Realm types`() {
val result = compileFromSource(
plugins = listOf(io.realm.kotlin.compiler.Registrar()),
source = SourceFile.kotlin(
Expand Down Expand Up @@ -68,8 +74,125 @@ class TypeAdaptersTests {
)
)
assertEquals(KotlinCompilation.ExitCode.COMPILATION_ERROR, result.exitCode, result.messages)
assertTrue(result.messages.contains("Invalid type parameter, only Realm types are supported"), result.messages)
assertTrue(
result.messages.contains("Invalid type parameter 'NonRealmType', only Realm types are supported"),
result.messages
)
}

@Test
fun `applying adapter on backlinked property should fail`() {
val result = compileFromSource(
plugins = listOf(io.realm.kotlin.compiler.Registrar()),
source = SourceFile.kotlin(
"typeAdapter_on_backlinks_fail.kt",
"""
import io.realm.kotlin.ext.backlinks
import io.realm.kotlin.types.RealmInstant
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.RealmTypeAdapter
import io.realm.kotlin.types.annotations.TypeAdapter
class UserType
class TestObject1: RealmObject {
var myObject: TestObject2 = TestObject2()
}
class TestObject2 : RealmObject {
@TypeAdapter(adapter = ValidRealmTypeAdapter::class)
val userType by backlinks(TestObject1::myObject)
}
object ValidRealmTypeAdapter : RealmTypeAdapter<String, UserType> {
override fun fromRealm(realmValue: String): UserType = TODO()
override fun toRealm(value: UserType): String = TODO()
}
""".trimIndent()
)
)
assertEquals(KotlinCompilation.ExitCode.COMPILATION_ERROR, result.exitCode, result.messages)
assertTrue(
result.messages.contains("Invalid type parameter, only Realm types are supported"),
result.messages
)
}

// TODO: What happens if we apply the annotation to: Delegates backlinks
@Test
fun `type adapters supportness`() {
val defaults = mapOf<KClassifier, Any>(
Boolean::class to true,
Byte::class to "1",
Char::class to "\'c\'",
Short::class to "1",
Int::class to "1",
Long::class to "1",
Float::class to "1.4f",
Double::class to "1.4",
Decimal128::class to "BsonDecimal128(\"1.4E100\")",
String::class to "\"Realm\"",
RealmInstant::class to "RealmInstant.from(42, 420)",
ObjectId::class to "ObjectId.create()",
BsonObjectId::class to "BsonObjectId()",
RealmUUID::class to "RealmUUID.random()",
ByteArray::class to "byteArrayOf(42)",
MutableRealmInt::class to "MutableRealmInt.create(42)"
)

allFieldTypes
.filter { type: TypeDescriptor.RealmFieldType ->
// TODO at some point test collections
type.collectionType == CollectionType.RLM_COLLECTION_TYPE_NONE
}
.filterNot { type ->
// TODO tidy list unsupported types in TypeDescriptor
type.elementType.classifier == MutableRealmInt::class ||
type.elementType.classifier == RealmObject::class
}
.forEach { type ->
val elementType = type.elementType
val default = if (!elementType.nullable) defaults[elementType.classifier]
?: error("unmapped default") else null

val kotlinLiteral = type.toKotlinLiteral()

val result = compileFromSource(
plugins = listOf(io.realm.kotlin.compiler.Registrar()),
source = SourceFile.kotlin(
"typeadapter_supportness_$kotlinLiteral.kt",
"""
import io.realm.kotlin.types.RealmAny
import io.realm.kotlin.types.RealmInstant
import io.realm.kotlin.types.MutableRealmInt
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.RealmTypeAdapter
import io.realm.kotlin.types.RealmUUID
import io.realm.kotlin.types.annotations.TypeAdapter
import io.realm.kotlin.types.ObjectId
import org.mongodb.kbson.BsonDecimal128
import org.mongodb.kbson.BsonObjectId
class UserType
class NonRealmType
class TestObject : RealmObject {
@TypeAdapter(adapter = ValidRealmTypeAdapter::class)
var userType: UserType = UserType()
}
object ValidRealmTypeAdapter : RealmTypeAdapter<$kotlinLiteral, UserType> {
override fun fromRealm(realmValue: $kotlinLiteral): UserType = TODO()
override fun toRealm(value: UserType): $kotlinLiteral = TODO()
}
""".trimIndent()
)
)
assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode, result.messages)
// assertTrue(result.messages.contains("Invalid type parameter, only Realm types are supported"), result.messages)
}

}
}

0 comments on commit b5b6a20

Please sign in to comment.