Run InsertionMethodProcessorTest with KSP
Bug: 160322705
Test: InsertionMethodProcessorTest
Change-Id: Icd465f455beaab6e258ca72c8013e15892d6fe13
diff --git a/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt b/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt
index f753d89..e22402f 100644
--- a/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/processor/InsertionMethodProcessorTest.kt
@@ -21,17 +21,15 @@
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.compiler.processing.XTypeElement
+import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.XTestInvocation
+import androidx.room.compiler.processing.util.runProcessorTest
import androidx.room.ext.CommonTypeNames
import androidx.room.ext.RxJava2TypeNames
import androidx.room.ext.RxJava3TypeNames
import androidx.room.solver.shortcut.result.InsertMethodAdapter
-import androidx.room.testing.TestInvocation
-import androidx.room.testing.TestProcessor
+import androidx.room.testing.context
import androidx.room.vo.InsertionMethod
-import com.google.common.truth.Truth.assertAbout
-import com.google.testing.compile.CompileTester
-import com.google.testing.compile.JavaFileObjects
-import com.google.testing.compile.JavaSourcesSubjectFactory
import com.squareup.javapoet.ArrayTypeName
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.ParameterizedTypeName
@@ -43,8 +41,7 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
-import toJFO
-import javax.tools.JavaFileObject
+import toSources
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
@RunWith(JUnit4::class)
@@ -70,14 +67,17 @@
@Insert
abstract public void foo();
"""
- ) { insertion, _ ->
+ ) { insertion, invocation ->
assertThat(insertion.name, `is`("foo"))
assertThat(insertion.parameters.size, `is`(0))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
assertThat(insertion.entities.size, `is`(0))
- }.failsToCompile().withErrorContaining(
- ProcessorErrors.INSERTION_DOES_NOT_HAVE_ANY_PARAMETERS_TO_INSERT
- )
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.INSERTION_DOES_NOT_HAVE_ANY_PARAMETERS_TO_INSERT
+ )
+ }
+ }
}
@Test
@@ -99,7 +99,7 @@
`is`(ClassName.get("foo.bar", "User") as TypeName)
)
assertThat(insertion.returnType.typeName, `is`(TypeName.LONG))
- }.compilesWithoutError()
+ }
}
@Test
@@ -109,13 +109,16 @@
@Insert
abstract public void foo(NotAnEntity notValid);
"""
- ) { insertion, _ ->
+ ) { insertion, invocation ->
assertThat(insertion.name, `is`("foo"))
assertThat(insertion.parameters.size, `is`(1))
assertThat(insertion.entities.size, `is`(0))
- }.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_ENTITY_FOR_SHORTCUT_QUERY_PARAMETER
- )
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.CANNOT_FIND_ENTITY_FOR_SHORTCUT_QUERY_PARAMETER
+ )
+ }
+ }
}
@Test
@@ -138,7 +141,7 @@
assertThat(insertion.entities["u2"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.parameters.map { it.name }, `is`(listOf("u1", "u2")))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
- }.compilesWithoutError()
+ }
}
@Test
@@ -173,7 +176,7 @@
) as TypeName
)
)
- }.compilesWithoutError()
+ }
}
@Test
@@ -196,7 +199,7 @@
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
- }.compilesWithoutError()
+ }
}
@Test
@@ -222,7 +225,7 @@
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
- }.compilesWithoutError()
+ }
}
@Test
@@ -248,7 +251,7 @@
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
- }.compilesWithoutError()
+ }
}
@Test
@@ -274,7 +277,7 @@
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
- }.compilesWithoutError()
+ }
}
@Test
@@ -301,7 +304,7 @@
assertThat(insertion.entities.size, `is`(1))
assertThat(insertion.entities["users"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.returnType.typeName, `is`(TypeName.VOID))
- }.compilesWithoutError()
+ }
}
@Test
@@ -326,7 +329,7 @@
assertThat(insertion.entities.size, `is`(2))
assertThat(insertion.entities["u1"]?.pojo?.typeName, `is`(USER_TYPE_NAME))
assertThat(insertion.entities["b1"]?.pojo?.typeName, `is`(BOOK_TYPE_NAME))
- }.compilesWithoutError()
+ }
}
@Test
@@ -338,7 +341,7 @@
"""
) { insertion, _ ->
assertThat(insertion.onConflict, `is`(OnConflictStrategy.ABORT))
- }.compilesWithoutError()
+ }
}
@Test
@@ -348,8 +351,13 @@
@Insert(onConflict = -1)
abstract public void foo(User user);
"""
- ) { _, _ ->
- }.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_ON_CONFLICT_VALUE)
+ ) { _, invocation ->
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.INVALID_ON_CONFLICT_VALUE
+ )
+ }
+ }
}
@Test
@@ -368,7 +376,7 @@
"""
) { insertion, _ ->
assertThat(insertion.onConflict, `is`(pair.second))
- }.compilesWithoutError()
+ }
}
}
@@ -388,11 +396,14 @@
@Insert
abstract public $type foo(User user);
"""
- ) { insertion, _ ->
+ ) { insertion, invocation ->
assertThat(insertion.methodBinder.adapter, `is`(nullValue()))
- }.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
- )
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
+ )
+ }
+ }
}
}
@@ -410,11 +421,14 @@
@Insert
abstract public $type foo(User user);
"""
- ) { insertion, _ ->
+ ) { insertion, invocation ->
assertThat(insertion.methodBinder.adapter, `is`(nullValue()))
- }.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
- )
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
+ )
+ }
+ }
}
}
@@ -431,11 +445,14 @@
@Insert
abstract public $type foo(User... user);
"""
- ) { insertion, _ ->
+ ) { insertion, invocation ->
assertThat(insertion.methodBinder.adapter, `is`(nullValue()))
- }.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
- )
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
+ )
+ }
+ }
}
}
@@ -452,11 +469,14 @@
@Insert
abstract public $type foo(User user1, User user2);
"""
- ) { insertion, _ ->
+ ) { insertion, invocation ->
assertThat(insertion.methodBinder.adapter, `is`(nullValue()))
- }.failsToCompile().withErrorContaining(
- ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
- )
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.CANNOT_FIND_INSERT_RESULT_ADAPTER
+ )
+ }
+ }
}
}
@@ -526,13 +546,15 @@
"""
) { insertion, _ ->
assertThat(insertion.methodBinder.adapter, `is`(notNullValue()))
- }.compilesWithoutError()
+ }
}
}
@Test
fun targetEntitySingle() {
- val usernameJfo = """
+ val usernameSource = Source.java(
+ "foo.bar.Username",
+ """
package foo.bar;
import androidx.room.*;
@@ -542,13 +564,14 @@
@ColumnInfo(name = "ageColumn")
int age;
}
- """.toJFO("foo.bar.Username")
+ """
+ )
singleInsertMethod(
"""
@Insert(entity = User.class)
abstract public long foo(Username username);
- """,
- additionalJFOs = listOf(usernameJfo)
+ """,
+ additionalSources = listOf(usernameSource)
) { insertion, _ ->
assertThat(insertion.name, `is`("foo"))
assertThat(insertion.parameters.size, `is`(1))
@@ -559,7 +582,7 @@
assertThat(insertion.entities["username"]?.isPartialEntity, `is`(true))
assertThat(insertion.entities["username"]?.entityTypeName, `is`(USER_TYPE_NAME))
assertThat(insertion.entities["username"]?.pojo?.typeName, `is`(USERNAME_TYPE_NAME))
- }.compilesWithoutError()
+ }
}
@Test
@@ -568,14 +591,16 @@
"""
@Insert(entity = User.class)
abstract public long foo(User user);
- """
+ """
) { _, _ ->
- }.compilesWithoutError()
+ }
}
@Test
fun targetEntityTwo() {
- val usernameJfo = """
+ val usernameSource = Source.java(
+ "foo.bar.Username",
+ """
package foo.bar;
import androidx.room.*;
@@ -585,20 +610,23 @@
@ColumnInfo(name = "ageColumn")
int age;
}
- """.toJFO("foo.bar.Username")
+ """
+ )
singleInsertMethod(
"""
@Insert(entity = User.class)
abstract public void foo(Username usernameA, Username usernameB);
- """,
- additionalJFOs = listOf(usernameJfo)
+ """,
+ additionalSources = listOf(usernameSource)
) { _, _ ->
- }.compilesWithoutError()
+ }
}
@Test
fun targetEntityMissingRequiredColumn() {
- val usernameJfo = """
+ val usernameSource = Source.java(
+ "foo.bar.Username",
+ """
package foo.bar;
import androidx.room.*;
@@ -606,25 +634,31 @@
int uid;
String name;
}
- """.toJFO("foo.bar.Username")
+ """
+ )
singleInsertMethod(
"""
@Insert(entity = User.class)
abstract public void foo(Username username);
- """,
- additionalJFOs = listOf(usernameJfo)
- ) { _, _ ->
- }.failsToCompile().withErrorContaining(
- ProcessorErrors.missingRequiredColumnsInPartialEntity(
- partialEntityName = USERNAME_TYPE_NAME.toString(),
- missingColumnNames = listOf("ageColumn")
- )
- )
+ """,
+ additionalSources = listOf(usernameSource)
+ ) { _, invocation ->
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.missingRequiredColumnsInPartialEntity(
+ partialEntityName = USERNAME_TYPE_NAME.toString(),
+ missingColumnNames = listOf("ageColumn")
+ )
+ )
+ }
+ }
}
@Test
fun targetEntityColumnDefaultValue() {
- val petNameJfo = """
+ val petNameSource = Source.java(
+ "foo.bar.PetName",
+ """
package foo.bar;
import androidx.room.*;
@@ -632,8 +666,11 @@
@ColumnInfo(name = "name")
String string;
}
- """.toJFO("foo.bar.PetName")
- val petJfo = """
+ """
+ )
+ val petSource = Source.java(
+ "foo.bar.Pet",
+ """
package foo.bar;
import androidx.room.*;
@@ -645,20 +682,23 @@
@ColumnInfo(defaultValue = "0")
int age;
}
- """.toJFO("foo.bar.Pet")
+ """
+ )
singleInsertMethod(
"""
@Insert(entity = Pet.class)
abstract public long foo(PetName petName);
- """,
- additionalJFOs = listOf(petNameJfo, petJfo)
+ """,
+ additionalSources = listOf(petNameSource, petSource)
) { _, _ ->
- }.compilesWithoutError()
+ }
}
@Test
fun targetEntityMissingPrimaryKey() {
- val petNameJfo = """
+ val petNameSource = Source.java(
+ "foo.bar.PetName",
+ """
package foo.bar;
import androidx.room.*;
@@ -666,8 +706,11 @@
@ColumnInfo(name = "name")
String string;
}
- """.toJFO("foo.bar.PetName")
- val petJfo = """
+ """
+ )
+ val petSource = Source.java(
+ "foo.bar.Pet",
+ """
package foo.bar;
import androidx.room.*;
@@ -677,25 +720,31 @@
int petId;
String name;
}
- """.toJFO("foo.bar.Pet")
+ """
+ )
singleInsertMethod(
"""
@Insert(entity = Pet.class)
abstract public long foo(PetName petName);
- """,
- additionalJFOs = listOf(petNameJfo, petJfo)
- ) { _, _ ->
- }.failsToCompile().withErrorContaining(
- ProcessorErrors.missingPrimaryKeysInPartialEntityForInsert(
- partialEntityName = "foo.bar.PetName",
- primaryKeyNames = listOf("petId")
- )
- )
+ """,
+ additionalSources = listOf(petNameSource, petSource)
+ ) { _, invocation ->
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.missingPrimaryKeysInPartialEntityForInsert(
+ partialEntityName = "foo.bar.PetName",
+ primaryKeyNames = listOf("petId")
+ )
+ )
+ }
+ }
}
@Test
fun targetEntityAutoGeneratedPrimaryKey() {
- val petNameJfo = """
+ val petNameSource = Source.java(
+ "foo.bar.PetName",
+ """
package foo.bar;
import androidx.room.*;
@@ -703,8 +752,11 @@
@ColumnInfo(name = "name")
String string;
}
- """.toJFO("foo.bar.PetName")
- val petJfo = """
+ """
+ )
+ val petSource = Source.java(
+ "foo.bar.Pet",
+ """
package foo.bar;
import androidx.room.*;
@@ -714,20 +766,23 @@
int petId;
String name;
}
- """.toJFO("foo.bar.Pet")
+ """
+ )
singleInsertMethod(
"""
@Insert(entity = Pet.class)
abstract public long foo(PetName petName);
- """,
- additionalJFOs = listOf(petNameJfo, petJfo)
+ """,
+ additionalSources = listOf(petNameSource, petSource)
) { _, _ ->
- }.compilesWithoutError()
+ }
}
@Test
fun targetEntityExtraColumn() {
- val usernameJfo = """
+ val usernameSource = Source.java(
+ "foo.bar.Username",
+ """
package foo.bar;
import androidx.room.*;
@@ -736,22 +791,28 @@
String name;
long extraField;
}
- """.toJFO("foo.bar.Username")
+ """
+ )
singleInsertMethod(
"""
@Insert(entity = User.class)
abstract public long foo(Username username);
- """,
- additionalJFOs = listOf(usernameJfo)
- ) { _, _ ->
- }.failsToCompile().withErrorContaining(
- ProcessorErrors.cannotFindAsEntityField("foo.bar.User")
- )
+ """,
+ additionalSources = listOf(usernameSource)
+ ) { _, invocation ->
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.cannotFindAsEntityField("foo.bar.User")
+ )
+ }
+ }
}
@Test
fun targetEntityExtraColumnIgnored() {
- val usernameJfo = """
+ val usernameSource = Source.java(
+ "foo.bar.Username",
+ """
package foo.bar;
import androidx.room.*;
@@ -763,20 +824,23 @@
@Ignore
long extraField;
}
- """.toJFO("foo.bar.Username")
+ """
+ )
singleInsertMethod(
"""
@Insert(entity = User.class)
abstract public long foo(Username username);
- """,
- additionalJFOs = listOf(usernameJfo)
+ """,
+ additionalSources = listOf(usernameSource)
) { _, _ ->
- }.compilesWithoutError()
+ }
}
@Test
fun targetEntityWithEmbedded() {
- val usernameJfo = """
+ val usernameSource = Source.java(
+ "foo.bar.Username",
+ """
package foo.bar;
import androidx.room.*;
@@ -787,8 +851,11 @@
@ColumnInfo(name = "ageColumn")
int age;
}
- """.toJFO("foo.bar.Username")
- val fullnameJfo = """
+ """
+ )
+ val fullnameSource = Source.java(
+ "foo.bar.Fullname",
+ """
package foo.bar;
import androidx.room.*;
@@ -797,20 +864,23 @@
String firstName;
String lastName;
}
- """.toJFO("foo.bar.Fullname")
+ """
+ )
singleInsertMethod(
"""
@Insert(entity = User.class)
abstract public long foo(Username username);
- """,
- additionalJFOs = listOf(usernameJfo, fullnameJfo)
+ """,
+ additionalSources = listOf(usernameSource, fullnameSource)
) { _, _ ->
- }.compilesWithoutError()
+ }
}
@Test
fun targetEntityWithRelation() {
- val userPetsJfo = """
+ val userPetsSource = Source.java(
+ "foo.bar.UserPets",
+ """
package foo.bar;
import androidx.room.*;
import java.util.List;
@@ -820,8 +890,11 @@
@Relation(parentColumn = "uid", entityColumn = "ownerId")
List<Pet> pets;
}
- """.toJFO("foo.bar.UserPets")
- val petJfo = """
+ """
+ )
+ val petSource = Source.java(
+ "foo.bar.Pet",
+ """
package foo.bar;
import androidx.room.*;
@@ -831,59 +904,59 @@
int petId;
int ownerId;
}
- """.toJFO("foo.bar.Pet")
+ """
+ )
singleInsertMethod(
"""
@Insert(entity = User.class)
abstract public long foo(UserPets userPets);
""",
- additionalJFOs = listOf(userPetsJfo, petJfo)
- ) { _, _ ->
- }.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_RELATION_IN_PARTIAL_ENTITY)
+ additionalSources = listOf(userPetsSource, petSource)
+ ) { _, invocation ->
+ invocation.assertCompilationResult {
+ hasErrorContaining(
+ ProcessorErrors.INVALID_RELATION_IN_PARTIAL_ENTITY
+ )
+ }
+ }
}
fun singleInsertMethod(
vararg input: String,
- additionalJFOs: List<JavaFileObject> = emptyList(),
- handler: (InsertionMethod, TestInvocation) -> Unit
- ): CompileTester {
- return assertAbout(JavaSourcesSubjectFactory.javaSources())
- .that(
- listOf(
- JavaFileObjects.forSourceString(
- "foo.bar.MyClass",
- DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
- ),
- COMMON.USER, COMMON.BOOK, COMMON.NOT_AN_ENTITY, COMMON.RX2_COMPLETABLE,
- COMMON.RX2_MAYBE, COMMON.RX2_SINGLE, COMMON.RX3_COMPLETABLE,
- COMMON.RX3_MAYBE, COMMON.RX3_SINGLE
- ) + additionalJFOs
+ additionalSources: List<Source> = emptyList(),
+ handler: (InsertionMethod, XTestInvocation) -> Unit
+ ) {
+ val inputSource = Source.java(
+ "foo.bar.MyClass",
+ DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
+ )
+ val commonSources = listOf(
+ COMMON.USER, COMMON.BOOK, COMMON.NOT_AN_ENTITY, COMMON.RX2_COMPLETABLE,
+ COMMON.RX2_MAYBE, COMMON.RX2_SINGLE, COMMON.RX3_COMPLETABLE,
+ COMMON.RX3_MAYBE, COMMON.RX3_SINGLE
+ ).toSources()
+
+ runProcessorTest(
+ sources = commonSources + additionalSources + inputSource
+ ) { invocation ->
+ val (owner, methods) = invocation.roundEnv
+ .getElementsAnnotatedWith(Dao::class.qualifiedName!!)
+ .filterIsInstance<XTypeElement>()
+ .map {
+ Pair(
+ it,
+ it.getAllMethods().filter {
+ it.hasAnnotation(Insert::class)
+ }
+ )
+ }.first { it.second.isNotEmpty() }
+ val processor = InsertionMethodProcessor(
+ baseContext = invocation.context,
+ containing = owner.type,
+ executableElement = methods.first()
)
- .processedWith(
- TestProcessor.builder()
- .forAnnotations(Insert::class, Dao::class)
- .nextRunHandler { invocation ->
- val (owner, methods) = invocation.roundEnv
- .getElementsAnnotatedWith(Dao::class.qualifiedName!!)
- .filterIsInstance<XTypeElement>()
- .map {
- Pair(
- it,
- it.getAllMethods().filter {
- it.hasAnnotation(Insert::class)
- }
- )
- }.first { it.second.isNotEmpty() }
- val processor = InsertionMethodProcessor(
- baseContext = invocation.context,
- containing = owner.type,
- executableElement = methods.first()
- )
- val processed = processor.process()
- handler(processed, invocation)
- true
- }
- .build()
- )
+ val processed = processor.process()
+ handler(processed, invocation)
+ }
}
}