[go: nahoru, domu]

blob: 10e43f728ecbd55aa51ee234e26fef946157be70 [file] [log] [blame]
Alan Viveretteba069d52018-03-08 18:02:39 -05001/*
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
Yigit Boyar91d60562020-07-01 14:34:43 -070019import COMMON
Alan Viveretteba069d52018-03-08 18:02:39 -050020import androidx.room.Dao
21import androidx.room.Transaction
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -040022import androidx.room.compiler.codegen.CodeLanguage
Eli Hart96d8d4d2021-04-06 19:06:18 +000023import androidx.room.compiler.processing.XTypeElement
Yigit Boyarbdffe9a2021-04-05 19:14:06 -070024import androidx.room.compiler.processing.util.Source
25import androidx.room.compiler.processing.util.XTestInvocation
26import androidx.room.compiler.processing.util.runProcessorTest
elifbilgin1f766542022-11-21 17:21:44 -080027import androidx.room.ext.GuavaUtilConcurrentTypeNames.LISTENABLE_FUTURE
28import androidx.room.ext.KotlinTypeNames.FLOW
29import androidx.room.ext.LifecyclesTypeNames.COMPUTABLE_LIVE_DATA
30import androidx.room.ext.LifecyclesTypeNames.LIVE_DATA
31import androidx.room.ext.ReactiveStreamsTypeNames.PUBLISHER
32import androidx.room.ext.RxJava2TypeNames
33import androidx.room.ext.RxJava3TypeNames
Yigit Boyarbdffe9a2021-04-05 19:14:06 -070034import androidx.room.testing.context
Alan Viveretteba069d52018-03-08 18:02:39 -050035import androidx.room.vo.TransactionMethod
Alan Viveretteba069d52018-03-08 18:02:39 -050036import org.hamcrest.CoreMatchers.`is`
37import org.hamcrest.MatcherAssert.assertThat
38import org.junit.Test
39import org.junit.runner.RunWith
40import org.junit.runners.JUnit4
41
42@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
43@RunWith(JUnit4::class)
44class TransactionMethodProcessorTest {
45
46 companion object {
47 const val DAO_PREFIX = """
48 package foo.bar;
49 import androidx.room.*;
50 import java.util.*;
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -080051 import androidx.lifecycle.*;
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -080052 import com.google.common.util.concurrent.*;
mzgreen76c0bb22021-12-08 15:27:37 +010053 import org.reactivestreams.*;
Alan Viveretteba069d52018-03-08 18:02:39 -050054 @Dao
55 abstract class MyClass {
56 """
57 const val DAO_SUFFIX = "}"
58 }
59
60 @Test
61 fun simple() {
62 singleTransactionMethod(
Jeff Gaston63c23102020-09-18 12:53:59 -040063 """
Alan Viveretteba069d52018-03-08 18:02:39 -050064 @Transaction
65 public String doInTransaction(int param) { return null; }
Jeff Gaston63c23102020-09-18 12:53:59 -040066 """
67 ) { transaction, _ ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -080068 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -070069 }
Alan Viveretteba069d52018-03-08 18:02:39 -050070 }
71
72 @Test
73 fun modifier_private() {
74 singleTransactionMethod(
Jeff Gaston63c23102020-09-18 12:53:59 -040075 """
Alan Viveretteba069d52018-03-08 18:02:39 -050076 @Transaction
77 private String doInTransaction(int param) { return null; }
Jeff Gaston63c23102020-09-18 12:53:59 -040078 """
Yigit Boyarbdffe9a2021-04-05 19:14:06 -070079 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -080080 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -070081 invocation.assertCompilationResult {
82 hasErrorContaining(
83 ProcessorErrors.TRANSACTION_METHOD_MODIFIERS
84 )
85 }
86 }
Alan Viveretteba069d52018-03-08 18:02:39 -050087 }
88
89 @Test
90 fun modifier_final() {
91 singleTransactionMethod(
Jeff Gaston63c23102020-09-18 12:53:59 -040092 """
Alan Viveretteba069d52018-03-08 18:02:39 -050093 @Transaction
94 public final String doInTransaction(int param) { return null; }
Jeff Gaston63c23102020-09-18 12:53:59 -040095 """
Yigit Boyarbdffe9a2021-04-05 19:14:06 -070096 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -080097 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -070098 invocation.assertCompilationResult {
99 hasErrorContaining(ProcessorErrors.TRANSACTION_METHOD_MODIFIERS)
100 }
101 }
Alan Viveretteba069d52018-03-08 18:02:39 -0500102 }
103
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800104 @Test
Elif Bilgin5f3b4742021-06-07 11:49:20 -0700105 fun deferredReturnType_flow() {
106 singleTransactionMethod(
107 """
108 @Transaction
109 public kotlinx.coroutines.flow.Flow<String> doInTransaction(int param) {
110 return null;
111 }
112 """
113 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -0800114 assertThat(transaction.jvmName, `is`("doInTransaction"))
Elif Bilgin5f3b4742021-06-07 11:49:20 -0700115 invocation.assertCompilationResult {
116 hasErrorContaining(
117 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400118 FLOW.rawTypeName.toString(CodeLanguage.JAVA)
Elif Bilgin5f3b4742021-06-07 11:49:20 -0700119 )
120 )
121 }
122 }
123 }
124
125 @Test
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800126 fun deferredReturnType_liveData() {
127 singleTransactionMethod(
128 """
129 @Transaction
130 public LiveData<String> doInTransaction(int param) { return null; }
Jeff Gaston63c23102020-09-18 12:53:59 -0400131 """
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700132 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -0800133 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700134 invocation.assertCompilationResult {
135 hasErrorContaining(
136 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400137 LIVE_DATA.rawTypeName.toString(CodeLanguage.JAVA)
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700138 )
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800139 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700140 }
141 }
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800142 }
143
144 @Test
mzgreen76c0bb22021-12-08 15:27:37 +0100145 fun deferredReturnType_computableLiveData() {
146 singleTransactionMethod(
147 """
148 @Transaction
149 public ComputableLiveData<String> doInTransaction(int param) { return null; }
150 """
151 ) { transaction, invocation ->
152 assertThat(transaction.jvmName, `is`("doInTransaction"))
153 invocation.assertCompilationResult {
154 hasErrorContaining(
155 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400156 COMPUTABLE_LIVE_DATA.rawTypeName.toString(CodeLanguage.JAVA)
mzgreen76c0bb22021-12-08 15:27:37 +0100157 )
158 )
159 }
160 }
161 }
162
163 @Test
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700164 fun deferredReturnType_rx2_flowable() {
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800165 singleTransactionMethod(
166 """
167 @Transaction
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700168 public io.reactivex.Flowable<String> doInTransaction(int param) { return null; }
Jeff Gaston63c23102020-09-18 12:53:59 -0400169 """
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700170 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -0800171 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700172 invocation.assertCompilationResult {
173 hasErrorContaining(
174 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400175 RxJava2TypeNames.FLOWABLE.rawTypeName.toString(CodeLanguage.JAVA)
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700176 )
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800177 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700178 }
179 }
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800180 }
181
182 @Test
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700183 fun deferredReturnType_rx3_flowable() {
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800184 singleTransactionMethod(
185 """
186 @Transaction
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700187 public io.reactivex.rxjava3.core.Flowable<String> doInTransaction(int param) {
188 return null;
189 }
Jeff Gaston63c23102020-09-18 12:53:59 -0400190 """
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700191 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -0800192 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700193 invocation.assertCompilationResult {
194 hasErrorContaining(
195 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400196 RxJava3TypeNames.FLOWABLE.rawTypeName.toString(CodeLanguage.JAVA)
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700197 )
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700198 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700199 }
200 }
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700201 }
202
203 @Test
204 fun deferredReturnType_rx2_completable() {
205 singleTransactionMethod(
206 """
207 @Transaction
208 public io.reactivex.Completable doInTransaction(int param) { return null; }
Jeff Gaston63c23102020-09-18 12:53:59 -0400209 """
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700210 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -0800211 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700212 invocation.assertCompilationResult {
213 hasErrorContaining(
214 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400215 RxJava2TypeNames.COMPLETABLE.rawTypeName.toString(CodeLanguage.JAVA)
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700216 )
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800217 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700218 }
219 }
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800220 }
221
222 @Test
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700223 fun deferredReturnType_rx3_completable() {
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800224 singleTransactionMethod(
225 """
226 @Transaction
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700227 public io.reactivex.rxjava3.core.Completable doInTransaction(int param) {
228 return null;
229 }
Jeff Gaston63c23102020-09-18 12:53:59 -0400230 """
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700231 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -0800232 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700233 invocation.assertCompilationResult {
234 hasErrorContaining(
235 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400236 RxJava3TypeNames.COMPLETABLE.rawTypeName.toString(CodeLanguage.JAVA)
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700237 )
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700238 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700239 }
240 }
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700241 }
242
243 @Test
244 fun deferredReturnType_rx2_single() {
245 singleTransactionMethod(
246 """
247 @Transaction
248 public io.reactivex.Single<String> doInTransaction(int param) { return null; }
Jeff Gaston63c23102020-09-18 12:53:59 -0400249 """
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700250 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -0800251 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700252 invocation.assertCompilationResult {
253 hasErrorContaining(
254 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400255 RxJava2TypeNames.SINGLE.rawTypeName.toString(CodeLanguage.JAVA)
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700256 )
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800257 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700258 }
259 }
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800260 }
261
262 @Test
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700263 fun deferredReturnType_rx3_single() {
264 singleTransactionMethod(
265 """
266 @Transaction
267 public io.reactivex.rxjava3.core.Single<String> doInTransaction(int param) {
268 return null;
269 }
Jeff Gaston63c23102020-09-18 12:53:59 -0400270 """
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700271 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -0800272 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700273 invocation.assertCompilationResult {
274 hasErrorContaining(
275 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400276 RxJava3TypeNames.SINGLE.rawTypeName.toString(CodeLanguage.JAVA)
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700277 )
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700278 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700279 }
280 }
Daniel Santiago Rivera2056c162020-06-03 17:12:43 -0700281 }
282
283 @Test
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800284 fun deferredReturnType_listenableFuture() {
285 singleTransactionMethod(
286 """
287 @Transaction
288 public ListenableFuture<String> doInTransaction(int param) { return null; }
Jeff Gaston63c23102020-09-18 12:53:59 -0400289 """
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700290 ) { transaction, invocation ->
Yigit Boyardd1f1d02021-11-12 23:19:09 -0800291 assertThat(transaction.jvmName, `is`("doInTransaction"))
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700292 invocation.assertCompilationResult {
293 hasErrorContaining(
294 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400295 LISTENABLE_FUTURE.rawTypeName.toString(CodeLanguage.JAVA)
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700296 )
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800297 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700298 }
299 }
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800300 }
301
mzgreen76c0bb22021-12-08 15:27:37 +0100302 @Test
303 fun deferredReturnType_publisher() {
304 singleTransactionMethod(
305 """
306 @Transaction
307 public Publisher<String> doInTransaction(int param) { return null; }
308 """
309 ) { transaction, invocation ->
310 assertThat(transaction.jvmName, `is`("doInTransaction"))
311 invocation.assertCompilationResult {
312 hasErrorContaining(
313 ProcessorErrors.transactionMethodAsync(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400314 PUBLISHER.rawTypeName.toString(CodeLanguage.JAVA)
mzgreen76c0bb22021-12-08 15:27:37 +0100315 )
316 )
317 }
318 }
319 }
320
Yigit Boyardd1f1d02021-11-12 23:19:09 -0800321 private val TransactionMethod.jvmName: String
322 get() = element.jvmName
Daniel Santiago Rivera633c84b2019-02-11 17:13:04 -0800323
Daniel Santiago Rivera9b78b582019-01-15 13:10:58 -0800324 private fun singleTransactionMethod(
325 vararg input: String,
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700326 handler: (TransactionMethod, XTestInvocation) -> Unit
327 ) {
328 val inputSource = listOf(
329 Source.java(
330 "foo.bar.MyClass",
331 DAO_PREFIX + input.joinToString("\n") + DAO_SUFFIX
Jeff Gaston63c23102020-09-18 12:53:59 -0400332 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700333 )
334 val otherSources = listOf(
mzgreen76c0bb22021-12-08 15:27:37 +0100335 COMMON.LIVE_DATA, COMMON.COMPUTABLE_LIVE_DATA, COMMON.RX2_FLOWABLE, COMMON.PUBLISHER,
336 COMMON.RX2_COMPLETABLE, COMMON.RX2_SINGLE, COMMON.RX3_FLOWABLE, COMMON.RX3_COMPLETABLE,
Elif Bilgin5f3b4742021-06-07 11:49:20 -0700337 COMMON.RX3_SINGLE, COMMON.LISTENABLE_FUTURE, COMMON.FLOW
Yigit Boyarccdf4232021-04-08 18:13:35 -0700338 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700339 runProcessorTest(
Daniel Santiago Rivera2514b022024-04-15 17:30:42 -0400340 sources = inputSource + otherSources,
341 options = mapOf(Context.BooleanProcessorOptions.GENERATE_KOTLIN.argName to "false")
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700342 ) { invocation ->
343 val (owner, methods) = invocation.roundEnv
344 .getElementsAnnotatedWith(Dao::class.qualifiedName!!)
345 .filterIsInstance<XTypeElement>()
346 .map {
347 Pair(
348 it,
349 it.getAllMethods().filter {
350 it.hasAnnotation(Transaction::class)
Yigit Boyarad311f12021-06-28 11:14:26 -0700351 }.toList()
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700352 )
353 }.first { it.second.isNotEmpty() }
354 val processor = TransactionMethodProcessor(
355 baseContext = invocation.context,
Yigit Boyar577a3a62021-09-13 18:40:16 -0700356 containingElement = owner,
357 containingType = owner.type,
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700358 executableElement = methods.first()
Jeff Gaston63c23102020-09-18 12:53:59 -0400359 )
Yigit Boyarbdffe9a2021-04-05 19:14:06 -0700360 val processed = processor.process()
361 handler(processed, invocation)
362 }
Alan Viveretteba069d52018-03-08 18:02:39 -0500363 }
364}