1/* 2 * Copyright (C) 2016 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 17import androidx.room.ColumnInfo 18import androidx.room.Embedded 19import androidx.room.Entity 20import androidx.room.PrimaryKey 21import androidx.room.Query 22import androidx.room.Relation 23import androidx.room.ext.LifecyclesTypeNames 24import androidx.room.ext.PagingTypeNames 25import androidx.room.ext.ReactiveStreamsTypeNames 26import androidx.room.ext.RoomRxJava2TypeNames 27import androidx.room.ext.RxJava2TypeNames 28import androidx.room.processor.EntityProcessor 29import androidx.room.solver.CodeGenScope 30import androidx.room.testing.TestInvocation 31import androidx.room.testing.TestProcessor 32import androidx.room.verifier.DatabaseVerifier 33import androidx.room.writer.ClassWriter 34import com.google.auto.common.MoreElements 35import com.google.common.truth.Truth 36import com.google.testing.compile.CompileTester 37import com.google.testing.compile.JavaFileObjects 38import com.google.testing.compile.JavaSourcesSubjectFactory 39import com.squareup.javapoet.ClassName 40import org.mockito.Mockito 41import org.mockito.Mockito.doReturn 42import org.mockito.Mockito.mock 43import java.io.File 44import javax.lang.model.element.Element 45import javax.lang.model.type.TypeKind 46import javax.lang.model.type.TypeMirror 47import javax.tools.JavaFileObject 48 49object COMMON { 50 val USER by lazy { 51 loadJavaCode("common/input/User.java", "foo.bar.User") 52 } 53 val USER_TYPE_NAME by lazy { 54 ClassName.get("foo.bar", "User") 55 } 56 val BOOK by lazy { 57 loadJavaCode("common/input/Book.java", "foo.bar.Book") 58 } 59 val NOT_AN_ENTITY by lazy { 60 loadJavaCode("common/input/NotAnEntity.java", "foo.bar.NotAnEntity") 61 } 62 63 val NOT_AN_ENTITY_TYPE_NAME by lazy { 64 ClassName.get("foo.bar", "NotAnEntity") 65 } 66 67 val MULTI_PKEY_ENTITY by lazy { 68 loadJavaCode("common/input/MultiPKeyEntity.java", "MultiPKeyEntity") 69 } 70 val LIVE_DATA by lazy { 71 loadJavaCode("common/input/LiveData.java", LifecyclesTypeNames.LIVE_DATA.toString()) 72 } 73 val COMPUTABLE_LIVE_DATA by lazy { 74 loadJavaCode("common/input/ComputableLiveData.java", 75 LifecyclesTypeNames.COMPUTABLE_LIVE_DATA.toString()) 76 } 77 val PUBLISHER by lazy { 78 loadJavaCode("common/input/reactivestreams/Publisher.java", 79 ReactiveStreamsTypeNames.PUBLISHER.toString()) 80 } 81 val FLOWABLE by lazy { 82 loadJavaCode("common/input/rxjava2/Flowable.java", RxJava2TypeNames.FLOWABLE.toString()) 83 } 84 85 val RX2_ROOM by lazy { 86 loadJavaCode("common/input/Rx2Room.java", RoomRxJava2TypeNames.RX_ROOM.toString()) 87 } 88 89 val DATA_SOURCE_FACTORY by lazy { 90 loadJavaCode("common/input/DataSource.java", "androidx.paging.DataSource") 91 } 92 93 val POSITIONAL_DATA_SOURCE by lazy { 94 loadJavaCode("common/input/PositionalDataSource.java", 95 PagingTypeNames.POSITIONAL_DATA_SOURCE.toString()) 96 } 97} 98fun testCodeGenScope(): CodeGenScope { 99 return CodeGenScope(Mockito.mock(ClassWriter::class.java)) 100} 101 102fun simpleRun(vararg jfos: JavaFileObject, f: (TestInvocation) -> Unit): CompileTester { 103 return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources()) 104 .that(jfos.toList() + JavaFileObjects.forSourceString("foo.bar.MyClass", 105 """ 106 package foo.bar; 107 abstract public class MyClass { 108 @androidx.room.Query("foo") 109 abstract public void setFoo(String foo); 110 } 111 """)) 112 .processedWith(TestProcessor.builder() 113 .nextRunHandler { 114 f(it) 115 true 116 } 117 .forAnnotations(Query::class, PrimaryKey::class, Embedded::class, 118 ColumnInfo::class, Relation::class, Entity::class) 119 .build()) 120} 121 122fun loadJavaCode(fileName: String, qName: String): JavaFileObject { 123 val contents = File("src/test/data/$fileName").readText(Charsets.UTF_8) 124 return JavaFileObjects.forSourceString(qName, contents) 125} 126 127fun createVerifierFromEntities(invocation: TestInvocation): DatabaseVerifier { 128 val entities = invocation.roundEnv.getElementsAnnotatedWith(Entity::class.java).map { 129 EntityProcessor(invocation.context, MoreElements.asType(it)).process() 130 } 131 return DatabaseVerifier.create(invocation.context, Mockito.mock(Element::class.java), 132 entities)!! 133} 134 135/** 136 * Create mocks of [Element] and [TypeMirror] so that they can be used for instantiating a fake 137 * [androidx.room.vo.Field]. 138 */ 139fun mockElementAndType(): Pair<Element, TypeMirror> { 140 val element = mock(Element::class.java) 141 val type = mock(TypeMirror::class.java) 142 doReturn(TypeKind.DECLARED).`when`(type).kind 143 doReturn(type).`when`(element).asType() 144 return element to type 145} 146