1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package androidx.room.processor 18 19import androidx.room.Dao 20import androidx.room.Transaction 21import androidx.room.testing.TestInvocation 22import androidx.room.testing.TestProcessor 23import androidx.room.vo.TransactionMethod 24import com.google.auto.common.MoreElements 25import com.google.auto.common.MoreTypes 26import com.google.common.truth.Truth 27import com.google.testing.compile.CompileTester 28import com.google.testing.compile.JavaFileObjects 29import com.google.testing.compile.JavaSourcesSubjectFactory 30import org.hamcrest.CoreMatchers.`is` 31import org.hamcrest.MatcherAssert.assertThat 32import org.junit.Test 33import org.junit.runner.RunWith 34import org.junit.runners.JUnit4 35 36@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") 37@RunWith(JUnit4::class) 38class TransactionMethodProcessorTest { 39 40 companion object { 41 const val DAO_PREFIX = """ 42 package foo.bar; 43 import androidx.room.*; 44 import java.util.*; 45 @Dao 46 abstract class MyClass { 47 """ 48 const val DAO_SUFFIX = "}" 49 } 50 51 @Test 52 fun simple() { 53 singleTransactionMethod( 54 """ 55 @Transaction 56 public String doInTransaction(int param) { return null; } 57 """) { transaction, _ -> 58 assertThat(transaction.name, `is`("doInTransaction")) 59 }.compilesWithoutError() 60 } 61 62 @Test 63 fun modifier_private() { 64 singleTransactionMethod( 65 """ 66 @Transaction 67 private String doInTransaction(int param) { return null; } 68 """) { transaction, _ -> 69 assertThat(transaction.name, `is`("doInTransaction")) 70 }.failsToCompile().withErrorContaining(ProcessorErrors.TRANSACTION_METHOD_MODIFIERS) 71 } 72 73 @Test 74 fun modifier_final() { 75 singleTransactionMethod( 76 """ 77 @Transaction 78 public final String doInTransaction(int param) { return null; } 79 """) { transaction, _ -> 80 assertThat(transaction.name, `is`("doInTransaction")) 81 }.failsToCompile().withErrorContaining(ProcessorErrors.TRANSACTION_METHOD_MODIFIERS) 82 } 83 84 private fun singleTransactionMethod(vararg input: String, 85 handler: (TransactionMethod, TestInvocation) -> Unit): 86 CompileTester { 87 return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources()) 88 .that(listOf(JavaFileObjects.forSourceString("foo.bar.MyClass", 89 TransactionMethodProcessorTest.DAO_PREFIX + input.joinToString("\n") + 90 TransactionMethodProcessorTest.DAO_SUFFIX 91 ))) 92 .processedWith(TestProcessor.builder() 93 .forAnnotations(Transaction::class, Dao::class) 94 .nextRunHandler { invocation -> 95 val (owner, methods) = invocation.roundEnv 96 .getElementsAnnotatedWith(Dao::class.java) 97 .map { 98 Pair(it, 99 invocation.processingEnv.elementUtils 100 .getAllMembers(MoreElements.asType(it)) 101 .filter { 102 MoreElements.isAnnotationPresent(it, 103 Transaction::class.java) 104 } 105 ) 106 }.first { it.second.isNotEmpty() } 107 val processor = TransactionMethodProcessor( 108 baseContext = invocation.context, 109 containing = MoreTypes.asDeclared(owner.asType()), 110 executableElement = MoreElements.asExecutable(methods.first())) 111 val processed = processor.process() 112 handler(processed, invocation) 113 true 114 } 115 .build()) 116 } 117} 118