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 android.arch.persistence.room.ColumnInfo
18import android.arch.persistence.room.Embedded
19import android.arch.persistence.room.Entity
20import android.arch.persistence.room.PrimaryKey
21import android.arch.persistence.room.Query
22import android.arch.persistence.room.Relation
23import android.arch.persistence.room.ext.LifecyclesTypeNames
24import android.arch.persistence.room.ext.PagingTypeNames
25import android.arch.persistence.room.ext.ReactiveStreamsTypeNames
26import android.arch.persistence.room.ext.RoomRxJava2TypeNames
27import android.arch.persistence.room.ext.RxJava2TypeNames
28import android.arch.persistence.room.processor.EntityProcessor
29import android.arch.persistence.room.solver.CodeGenScope
30import android.arch.persistence.room.testing.TestInvocation
31import android.arch.persistence.room.testing.TestProcessor
32import android.arch.persistence.room.verifier.DatabaseVerifier
33import android.arch.persistence.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 LIVE_PAGED_LIST_PROVIDER by lazy {
90        loadJavaCode("common/input/LivePagedListProvider.java",
91                PagingTypeNames.LIVE_PAGED_LIST_PROVIDER.toString())
92    }
93}
94fun testCodeGenScope(): CodeGenScope {
95    return CodeGenScope(Mockito.mock(ClassWriter::class.java))
96}
97
98fun simpleRun(vararg jfos : JavaFileObject, f: (TestInvocation) -> Unit): CompileTester {
99    return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
100            .that(jfos.toList() + JavaFileObjects.forSourceString("foo.bar.MyClass",
101                    """
102                    package foo.bar;
103                    abstract public class MyClass {
104                    @android.arch.persistence.room.Query("foo")
105                    abstract public void setFoo(String foo);
106                    }
107                    """))
108            .processedWith(TestProcessor.builder()
109                    .nextRunHandler {
110                        f(it)
111                        true
112                    }
113                    .forAnnotations(Query::class, PrimaryKey::class, Embedded::class,
114                            ColumnInfo::class, Relation::class, Entity::class)
115                    .build())
116}
117
118fun loadJavaCode(fileName : String, qName : String) : JavaFileObject {
119    val contents = File("src/test/data/$fileName").readText(Charsets.UTF_8)
120    return JavaFileObjects.forSourceString(qName, contents)
121}
122
123fun createVerifierFromEntities(invocation: TestInvocation) : DatabaseVerifier {
124    val entities = invocation.roundEnv.getElementsAnnotatedWith(Entity::class.java).map {
125        EntityProcessor(invocation.context, MoreElements.asType(it)).process()
126    }
127    return DatabaseVerifier.create(invocation.context, Mockito.mock(Element::class.java),
128            entities)!!
129}
130
131/**
132 * Create mocks of [Element] and [TypeMirror] so that they can be used for instantiating a fake
133 * [android.arch.persistence.room.vo.Field].
134 */
135fun mockElementAndType(): Pair<Element, TypeMirror> {
136    val element = mock(Element::class.java)
137    val type = mock(TypeMirror::class.java)
138    doReturn(TypeKind.DECLARED).`when`(type).kind
139    doReturn(type).`when`(element).asType()
140    return element to type
141}
142