[go: nahoru, domu]

blob: 10e43f728ecbd55aa51ee234e26fef946157be70 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* 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 androidx.room.processor
import COMMON
import androidx.room.Dao
import androidx.room.Transaction
import androidx.room.compiler.codegen.CodeLanguage
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.GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
import androidx.room.ext.KotlinTypeNames.FLOW
import androidx.room.ext.LifecyclesTypeNames.COMPUTABLE_LIVE_DATA
import androidx.room.ext.LifecyclesTypeNames.LIVE_DATA
import androidx.room.ext.ReactiveStreamsTypeNames.PUBLISHER
import androidx.room.ext.RxJava2TypeNames
import androidx.room.ext.RxJava3TypeNames
import androidx.room.testing.context
import androidx.room.vo.TransactionMethod
import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.MatcherAssert.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
@RunWith(JUnit4::class)
class TransactionMethodProcessorTest {
companion object {
const val DAO_PREFIX = """
package foo.bar;
import androidx.room.*;
import java.util.*;
import androidx.lifecycle.*;
import com.google.common.util.concurrent.*;
import org.reactivestreams.*;
@Dao
abstract class MyClass {
"""
const val DAO_SUFFIX = "}"
}
@Test
fun simple() {
singleTransactionMethod(
"""
@Transaction
public String doInTransaction(int param) { return null; }
"""
) { transaction, _ ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
}
}
@Test
fun modifier_private() {
singleTransactionMethod(
"""
@Transaction
private String doInTransaction(int param) { return null; }
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.TRANSACTION_METHOD_MODIFIERS
)
}
}
}
@Test
fun modifier_final() {
singleTransactionMethod(
"""
@Transaction
public final String doInTransaction(int param) { return null; }
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(ProcessorErrors.TRANSACTION_METHOD_MODIFIERS)
}
}
}
@Test
fun deferredReturnType_flow() {
singleTransactionMethod(
"""
@Transaction
public kotlinx.coroutines.flow.Flow<String> doInTransaction(int param) {
return null;
}
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
FLOW.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
@Test
fun deferredReturnType_liveData() {
singleTransactionMethod(
"""
@Transaction
public LiveData<String> doInTransaction(int param) { return null; }
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
LIVE_DATA.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
@Test
fun deferredReturnType_computableLiveData() {
singleTransactionMethod(
"""
@Transaction
public ComputableLiveData<String> doInTransaction(int param) { return null; }
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
COMPUTABLE_LIVE_DATA.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
@Test
fun deferredReturnType_rx2_flowable() {
singleTransactionMethod(
"""
@Transaction
public io.reactivex.Flowable<String> doInTransaction(int param) { return null; }
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
RxJava2TypeNames.FLOWABLE.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
@Test
fun deferredReturnType_rx3_flowable() {
singleTransactionMethod(
"""
@Transaction
public io.reactivex.rxjava3.core.Flowable<String> doInTransaction(int param) {
return null;
}
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
RxJava3TypeNames.FLOWABLE.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
@Test
fun deferredReturnType_rx2_completable() {
singleTransactionMethod(
"""
@Transaction
public io.reactivex.Completable doInTransaction(int param) { return null; }
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
RxJava2TypeNames.COMPLETABLE.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
@Test
fun deferredReturnType_rx3_completable() {
singleTransactionMethod(
"""
@Transaction
public io.reactivex.rxjava3.core.Completable doInTransaction(int param) {
return null;
}
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
RxJava3TypeNames.COMPLETABLE.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
@Test
fun deferredReturnType_rx2_single() {
singleTransactionMethod(
"""
@Transaction
public io.reactivex.Single<String> doInTransaction(int param) { return null; }
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
RxJava2TypeNames.SINGLE.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
@Test
fun deferredReturnType_rx3_single() {
singleTransactionMethod(
"""
@Transaction
public io.reactivex.rxjava3.core.Single<String> doInTransaction(int param) {
return null;
}
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
RxJava3TypeNames.SINGLE.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
@Test
fun deferredReturnType_listenableFuture() {
singleTransactionMethod(
"""
@Transaction
public ListenableFuture<String> doInTransaction(int param) { return null; }
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
LISTENABLE_FUTURE.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
@Test
fun deferredReturnType_publisher() {
singleTransactionMethod(
"""
@Transaction
public Publisher<String> doInTransaction(int param) { return null; }
"""
) { transaction, invocation ->
assertThat(transaction.jvmName, `is`("doInTransaction"))
invocation.assertCompilationResult {
hasErrorContaining(
ProcessorErrors.transactionMethodAsync(
PUBLISHER.rawTypeName.toString(CodeLanguage.JAVA)
)
)
}
}
}
private val TransactionMethod.jvmName: String
get() = element.jvmName
private fun singleTransactionMethod(
vararg input: String,
handler: (TransactionMethod, XTestInvocation) -> Unit
) {
val inputSource = listOf(
Source.java(
"foo.bar.MyClass",
DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
)
)
val otherSources = listOf(
COMMON.LIVE_DATA, COMMON.COMPUTABLE_LIVE_DATA, COMMON.RX2_FLOWABLE, COMMON.PUBLISHER,
COMMON.RX2_COMPLETABLE, COMMON.RX2_SINGLE, COMMON.RX3_FLOWABLE, COMMON.RX3_COMPLETABLE,
COMMON.RX3_SINGLE, COMMON.LISTENABLE_FUTURE, COMMON.FLOW
)
runProcessorTest(
sources = inputSource + otherSources,
options = mapOf(Context.BooleanProcessorOptions.GENERATE_KOTLIN.argName to "false")
) { invocation ->
val (owner, methods) = invocation.roundEnv
.getElementsAnnotatedWith(Dao::class.qualifiedName!!)
.filterIsInstance<XTypeElement>()
.map {
Pair(
it,
it.getAllMethods().filter {
it.hasAnnotation(Transaction::class)
}.toList()
)
}.first { it.second.isNotEmpty() }
val processor = TransactionMethodProcessor(
baseContext = invocation.context,
containingElement = owner,
containingType = owner.type,
executableElement = methods.first()
)
val processed = processor.process()
handler(processed, invocation)
}
}
}