18bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar/*
28bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar * Copyright (C) 2016 The Android Open Source Project
38bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar *
48bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
58bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar * you may not use this file except in compliance with the License.
68bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar * You may obtain a copy of the License at
78bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar *
88bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
98bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar *
108bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar * Unless required by applicable law or agreed to in writing, software
118bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
128bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar * See the License for the specific language governing permissions and
148bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar * limitations under the License.
158bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar */
168bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar
17bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverettepackage androidx.room.processor
18bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette
19bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport COMMON
20bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.RoomProcessor
21bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.solver.query.result.EntityRowAdapter
22bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.solver.query.result.PojoRowAdapter
23bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.testing.TestInvocation
24bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.testing.TestProcessor
25bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.vo.Database
26bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viveretteimport androidx.room.vo.Warning
278bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport com.google.auto.common.MoreElements
288bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport com.google.common.truth.Truth
298bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport com.google.testing.compile.CompileTester
308bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport com.google.testing.compile.JavaFileObjects
318bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport com.google.testing.compile.JavaSourcesSubjectFactory
3288865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyarimport com.squareup.javapoet.ClassName
338bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport org.hamcrest.CoreMatchers.`is`
345124503104860e68981cc3e3092b95932586f66fYigit Boyarimport org.hamcrest.CoreMatchers.instanceOf
355124503104860e68981cc3e3092b95932586f66fYigit Boyarimport org.hamcrest.CoreMatchers.not
365124503104860e68981cc3e3092b95932586f66fYigit Boyarimport org.hamcrest.CoreMatchers.notNullValue
375124503104860e68981cc3e3092b95932586f66fYigit Boyarimport org.hamcrest.CoreMatchers.sameInstance
388bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport org.hamcrest.MatcherAssert.assertThat
398bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport org.junit.Test
408bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport org.junit.runner.RunWith
418bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport org.junit.runners.JUnit4
428bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarimport javax.tools.JavaFileObject
4388865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyarimport javax.tools.StandardLocation
448bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar
458bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar@RunWith(JUnit4::class)
468bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyarclass DatabaseProcessorTest {
478bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar    companion object {
488bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar        const val DATABASE_PREFIX = """
498bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar            package foo.bar;
50bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette            import androidx.room.*;
518bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar            """
5217caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        val DB1: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.Db1",
5317caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """
5417caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                $DATABASE_PREFIX
5517caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                @Database(entities = {Book.class}, version = 42)
5617caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                public abstract class Db1 extends RoomDatabase {
5717caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                    abstract BookDao bookDao();
5817caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                }
5917caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """)
6017caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        val DB2: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.Db2",
6117caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """
6217caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                $DATABASE_PREFIX
6317caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                @Database(entities = {Book.class}, version = 42)
6417caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                public abstract class Db2 extends RoomDatabase {
6517caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                    abstract BookDao bookDao();
6617caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                }
6717caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """)
6817caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        val DB3: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.Db3",
6917caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """
7017caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                $DATABASE_PREFIX
7117caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                @Database(entities = {Book.class}, version = 42)
7217caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                public abstract class Db3 extends RoomDatabase {
7317caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                }
7417caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """)
758bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar        val USER: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.User",
768bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                """
778bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                package foo.bar;
78bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
798bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                @Entity
808bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                public class User {
818bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                    @PrimaryKey
828bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                    int uid;
838bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                }
848bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                """)
858bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar        val USER_DAO: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.UserDao",
868bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                """
878bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                package foo.bar;
88bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
898bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                @Dao
908bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                public interface UserDao {
918bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                    @Query("SELECT * FROM user")
928bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                    public java.util.List<User> loadAll();
935124503104860e68981cc3e3092b95932586f66fYigit Boyar
945124503104860e68981cc3e3092b95932586f66fYigit Boyar                    @Insert
955124503104860e68981cc3e3092b95932586f66fYigit Boyar                    public void insert(User... users);
965124503104860e68981cc3e3092b95932586f66fYigit Boyar
973542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar                    @Query("SELECT * FROM user where uid = :uid")
985124503104860e68981cc3e3092b95932586f66fYigit Boyar                    public User loadOne(int uid);
995124503104860e68981cc3e3092b95932586f66fYigit Boyar
1005124503104860e68981cc3e3092b95932586f66fYigit Boyar                    @TypeConverters(Converter.class)
1013542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar                    @Query("SELECT * FROM user where uid = :uid")
1025124503104860e68981cc3e3092b95932586f66fYigit Boyar                    public User loadWithConverter(int uid);
1035124503104860e68981cc3e3092b95932586f66fYigit Boyar
1043542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar                    @Query("SELECT * FROM user where uid = :uid")
1055124503104860e68981cc3e3092b95932586f66fYigit Boyar                    public Pojo loadOnePojo(int uid);
1065124503104860e68981cc3e3092b95932586f66fYigit Boyar
1075124503104860e68981cc3e3092b95932586f66fYigit Boyar                    @Query("SELECT * FROM user")
1085124503104860e68981cc3e3092b95932586f66fYigit Boyar                    public java.util.List<Pojo> loadAllPojos();
1095124503104860e68981cc3e3092b95932586f66fYigit Boyar
1105124503104860e68981cc3e3092b95932586f66fYigit Boyar                    @TypeConverters(Converter.class)
1113542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar                    @Query("SELECT * FROM user where uid = :uid")
1125124503104860e68981cc3e3092b95932586f66fYigit Boyar                    public Pojo loadPojoWithConverter(int uid);
1135124503104860e68981cc3e3092b95932586f66fYigit Boyar
1145124503104860e68981cc3e3092b95932586f66fYigit Boyar                    public static class Converter {
1155124503104860e68981cc3e3092b95932586f66fYigit Boyar                        @TypeConverter
1165124503104860e68981cc3e3092b95932586f66fYigit Boyar                        public static java.util.Date foo(Long input) {return null;}
1175124503104860e68981cc3e3092b95932586f66fYigit Boyar                    }
1185124503104860e68981cc3e3092b95932586f66fYigit Boyar
1195124503104860e68981cc3e3092b95932586f66fYigit Boyar                    public static class Pojo {
1205124503104860e68981cc3e3092b95932586f66fYigit Boyar                        public int uid;
1215124503104860e68981cc3e3092b95932586f66fYigit Boyar                    }
1228bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                }
1238bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                """)
1248bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar        val BOOK: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.Book",
1258bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                """
1268bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                package foo.bar;
127bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
1288bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                @Entity
1298bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                public class Book {
1308bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                    @PrimaryKey
1318bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                    int bookId;
1328bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                }
1338bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                """)
1348bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar        val BOOK_DAO: JavaFileObject = JavaFileObjects.forSourceString("foo.bar.BookDao",
1358bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                """
1368bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                package foo.bar;
137bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
1388bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                @Dao
1398bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                public interface BookDao {
140af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                    @Query("SELECT * FROM book")
1418bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                    public java.util.List<Book> loadAllBooks();
14208ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                    @Insert
14308ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                    public void insert(Book book);
1448bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                }
1458bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                """)
1468bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar    }
1478bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar
1488bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar    @Test
1498bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar    fun simple() {
1508bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar        singleDb("""
151a64756a18111a7312b3fa03b76d13381a8907176Yigit Boyar            @Database(entities = {User.class}, version = 42)
152291985054e698c918df1c735d1042b63b9e97219Yigit Boyar            public abstract class MyDb extends RoomDatabase {
153291985054e698c918df1c735d1042b63b9e97219Yigit Boyar                abstract UserDao userDao();
1548bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar            }
155d2649c45a34db46fb03a24dcb2a443a92298b5adSergey Vasilinets            """, USER, USER_DAO) { db, _ ->
1568bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar            assertThat(db.daoMethods.size, `is`(1))
1578bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar            assertThat(db.entities.size, `is`(1))
1588bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar        }.compilesWithoutError()
1598bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar    }
1608bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar
1618bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar    @Test
1628bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar    fun multiple() {
1638bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar        singleDb("""
164a64756a18111a7312b3fa03b76d13381a8907176Yigit Boyar            @Database(entities = {User.class, Book.class}, version = 42)
165291985054e698c918df1c735d1042b63b9e97219Yigit Boyar            public abstract class MyDb extends RoomDatabase {
1668bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                abstract UserDao userDao();
1678bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                abstract BookDao bookDao();
1688bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar            }
169d2649c45a34db46fb03a24dcb2a443a92298b5adSergey Vasilinets            """, USER, USER_DAO, BOOK, BOOK_DAO) { db, _ ->
1708bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar            assertThat(db.daoMethods.size, `is`(2))
1718bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar            assertThat(db.entities.size, `is`(2))
1728bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar            assertThat(db.daoMethods.map { it.name }, `is`(listOf("userDao", "bookDao")))
1738bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar            assertThat(db.entities.map { it.type.toString() },
1748bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                    `is`(listOf("foo.bar.User", "foo.bar.Book")))
1758bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar        }.compilesWithoutError()
1768bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar    }
1778bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar
178291985054e698c918df1c735d1042b63b9e97219Yigit Boyar    @Test
179291985054e698c918df1c735d1042b63b9e97219Yigit Boyar    fun detectMissingBaseClass() {
180291985054e698c918df1c735d1042b63b9e97219Yigit Boyar        singleDb("""
181a64756a18111a7312b3fa03b76d13381a8907176Yigit Boyar            @Database(entities = {User.class, Book.class}, version = 42)
182291985054e698c918df1c735d1042b63b9e97219Yigit Boyar            public abstract class MyDb {
183291985054e698c918df1c735d1042b63b9e97219Yigit Boyar            }
184d2649c45a34db46fb03a24dcb2a443a92298b5adSergey Vasilinets            """, USER, BOOK) { _, _ ->
185291985054e698c918df1c735d1042b63b9e97219Yigit Boyar        }.failsToCompile().withErrorContaining(ProcessorErrors.DB_MUST_EXTEND_ROOM_DB)
186291985054e698c918df1c735d1042b63b9e97219Yigit Boyar    }
187291985054e698c918df1c735d1042b63b9e97219Yigit Boyar
188af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar    @Test
189af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar    fun detectMissingTable() {
190af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar        singleDb(
191af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                """
192a64756a18111a7312b3fa03b76d13381a8907176Yigit Boyar                @Database(entities = {Book.class}, version = 42)
193af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                public abstract class MyDb extends RoomDatabase {
194af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                    abstract BookDao bookDao();
195af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                }
196af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                """, BOOK, JavaFileObjects.forSourceString("foo.bar.BookDao",
197af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                """
198af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                package foo.bar;
199bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
200af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                @Dao
201af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                public interface BookDao {
202af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                    @Query("SELECT * FROM nonExistentTable")
203af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                    public java.util.List<Book> loadAllBooks();
204af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                }
2056f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """)) { _, _ ->
20688865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar        }.failsToCompile().withErrorContaining("no such table: nonExistentTable")
207af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar    }
208af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar
209af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar    @Test
210af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar    fun detectDuplicateTableNames() {
211af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar        singleDb("""
212a64756a18111a7312b3fa03b76d13381a8907176Yigit Boyar                @Database(entities = {User.class, AnotherClass.class}, version = 42)
213af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                public abstract class MyDb extends RoomDatabase {
214af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                    abstract UserDao userDao();
215af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                }
216af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                """, USER, USER_DAO, JavaFileObjects.forSourceString("foo.bar.AnotherClass",
217af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                """
218af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                package foo.bar;
219bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
220af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                @Entity(tableName="user")
221af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                public class AnotherClass {
222af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                    @PrimaryKey
223af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                    int uid;
224af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                }
225d2649c45a34db46fb03a24dcb2a443a92298b5adSergey Vasilinets                """)) { _, _ ->
226af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar        }.failsToCompile().withErrorContaining(
227af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                ProcessorErrors.duplicateTableNames("user",
228af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar                        listOf("foo.bar.User", "foo.bar.AnotherClass"))
229af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar        )
230af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar    }
231af2292b2f53204a3004f53201f51908d70d8090eYigit Boyar
23288865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar    @Test
23388865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar    fun skipBadQueryVerification() {
23488865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar        singleDb(
23588865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                """
23688865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                @SkipQueryVerification
237a64756a18111a7312b3fa03b76d13381a8907176Yigit Boyar                @Database(entities = {Book.class}, version = 42)
23888865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                public abstract class MyDb extends RoomDatabase {
23988865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                    abstract BookDao bookDao();
24088865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                }
24188865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                """, BOOK, JavaFileObjects.forSourceString("foo.bar.BookDao",
24288865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                """
24388865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                package foo.bar;
244bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
24588865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                @Dao
24688865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                public interface BookDao {
24788865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                    @Query("SELECT nonExistingField FROM Book")
24888865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                    public java.util.List<Book> loadAllBooks();
24988865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                }
2506f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """)) { _, _ ->
25188865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar        }.compilesWithoutError()
25288865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar    }
25388865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar
25488865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar    @Test
25588865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar    fun multipleDatabases() {
25688865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar        val db1_2 = JavaFileObjects.forSourceString("foo.barx.Db1",
25788865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                """
25888865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                package foo.barx;
259bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
26088865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                import foo.bar.*;
261a64756a18111a7312b3fa03b76d13381a8907176Yigit Boyar                @Database(entities = {Book.class}, version = 42)
26288865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                public abstract class Db1 extends RoomDatabase {
26388865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                    abstract BookDao bookDao();
26488865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                }
26588865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                """)
26688865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar        Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
26717caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .that(listOf(BOOK, BOOK_DAO, DB1, DB2, db1_2))
26888865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .processedWith(RoomProcessor())
26988865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .compilesWithoutError()
27088865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .and()
27188865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar", "Db1_Impl.class")
27288865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .and()
27388865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar", "Db2_Impl.class")
27488865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .and()
27588865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.barx", "Db1_Impl.class")
27688865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .and()
27788865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar",
27888865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                        "BookDao_Db1_0_Impl.class")
27988865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .and()
28088865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar",
28188865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                        "BookDao_Db1_1_Impl.class")
28288865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .and()
28388865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .generatesFileNamed(StandardLocation.CLASS_OUTPUT, "foo.bar",
28488865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                        "BookDao_Db2_Impl.class")
28588865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar    }
28688865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar
28788865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar    @Test
28888865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar    fun twoDaoMethodsForTheSameDao() {
28988865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar        singleDb(
29088865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                """
291a64756a18111a7312b3fa03b76d13381a8907176Yigit Boyar                @Database(entities = {User.class}, version = 42)
29288865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                public abstract class MyDb extends RoomDatabase {
29388865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                    abstract UserDao userDao();
29488865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                    abstract UserDao userDao2();
29588865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                }
2966f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, USER, USER_DAO) { _, _ -> }
29788865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .failsToCompile()
29888865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .withErrorContaining(ProcessorErrors.DAO_METHOD_CONFLICTS_WITH_OTHERS)
29988865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .and()
30088865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                .withErrorContaining(ProcessorErrors.duplicateDao(
30188865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                        ClassName.get("foo.bar", "UserDao"), listOf("userDao", "userDao2")
30288865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar                ))
30388865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar    }
30488865f77c35657a2bc545a718ca16a648fc8b62eYigit Boyar
30513a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar    @Test
30613a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar    fun suppressedWarnings() {
30713a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar        singleDb(
30813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar                """
30913a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar                @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
310a64756a18111a7312b3fa03b76d13381a8907176Yigit Boyar                @Database(entities = {User.class}, version = 42)
31113a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar                public abstract class MyDb extends RoomDatabase {
31213a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar                    abstract UserDao userDao();
31313a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar                }
3146f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, USER, USER_DAO) { db, invocation ->
315aa82fce1d73394bdc7f4c2510cf94a3572032b24Yigit Boyar            assertThat(DatabaseProcessor(invocation.context, db.element)
316aa82fce1d73394bdc7f4c2510cf94a3572032b24Yigit Boyar                    .context.logger.suppressedWarnings, `is`(setOf(Warning.CURSOR_MISMATCH)))
31713a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar        }.compilesWithoutError()
31813a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar    }
31913a2048db98b1cc2dbd1692b73b794527975a446Yigit Boyar
320dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar    @Test
321dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar    fun duplicateIndexNames() {
322dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar        val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
323dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                """
324dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                package foo.bar;
325bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
326dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                @Entity(indices = {@Index(name ="index_name", value = {"name"})})
327dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                public class Entity1 {
328dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                    @PrimaryKey
329dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                    int uid;
330dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                    String name;
331dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                }
332dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                """)
333dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar
334dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar        val entity2 = JavaFileObjects.forSourceString("foo.bar.Entity2",
335dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                """
336dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                package foo.bar;
337bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
338dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                @Entity(indices = {@Index(name ="index_name", value = {"anotherName"})})
339dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                public class Entity2 {
340dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                    @PrimaryKey
341dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                    int uid;
342dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                    String anotherName;
343dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                }
344dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                """)
345dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar        singleDb("""
346a64756a18111a7312b3fa03b76d13381a8907176Yigit Boyar                @Database(entities = {Entity1.class, Entity2.class}, version = 42)
347dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                public abstract class MyDb extends RoomDatabase {
348dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                }
3496f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, entity1, entity2) { _, _ ->
350dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar        }.failsToCompile().withErrorContaining(
351dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                ProcessorErrors.duplicateIndexInDatabase("index_name",
352dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar                        listOf("foo.bar.Entity1 > index_name", "foo.bar.Entity2 > index_name"))
353dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar        )
354dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar    }
355dc18ce63fe07921b1080e48d3e597e2b5240d17aYigit Boyar
356875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    @Test
357875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    fun foreignKey_missingParent() {
358875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
359875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """
360875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                package foo.bar;
361bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
362875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Entity(foreignKeys = @ForeignKey(entity = ${COMMON.USER_TYPE_NAME}.class,
363875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                        parentColumns = "lastName",
364875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                        childColumns = "name"))
365875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public class Entity1 {
366875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    @PrimaryKey
367875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    int uid;
368875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String name;
369875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
370875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """)
371875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        singleDb("""
372875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Database(entities = {Entity1.class}, version = 42)
373875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public abstract class MyDb extends RoomDatabase {
374875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
3756f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, entity1, COMMON.USER) { _, _ ->
376875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        }.failsToCompile().withErrorContaining(
377875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                ProcessorErrors.foreignKeyMissingParentEntityInDatabase("User", "foo.bar.Entity1")
378875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        )
379875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    }
380875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar
381875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    @Test
382875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    fun foreignKey_missingParentIndex() {
383875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
384875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """
385875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                package foo.bar;
386bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
387875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Entity(foreignKeys = @ForeignKey(entity = ${COMMON.USER_TYPE_NAME}.class,
388875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                        parentColumns = "lastName",
389875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                        childColumns = "name"))
390875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public class Entity1 {
391875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    @PrimaryKey
392875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    int uid;
393875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String name;
394875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
395875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """)
396875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        singleDb("""
397875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Database(entities = {Entity1.class, User.class}, version = 42)
398875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public abstract class MyDb extends RoomDatabase {
399875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
4006f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, entity1, COMMON.USER) { _, _ ->
401875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        }.failsToCompile().withErrorContaining(
402875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                ProcessorErrors.foreignKeyMissingIndexInParent(
403875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                        parentEntity = COMMON.USER_TYPE_NAME.toString(),
404875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                        parentColumns = listOf("lastName"),
405875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                        childEntity = "foo.bar.Entity1",
406875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                        childColumns = listOf("name")
407875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                )
408875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        )
409875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    }
410875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar
411875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    @Test
412875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    fun foreignKey_goodWithPrimaryKey() {
413875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
414875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """
415875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                package foo.bar;
416bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
417875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Entity(foreignKeys = @ForeignKey(entity = Entity2.class,
418875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    parentColumns = "uid",
419875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    childColumns = "parentId"))
420875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public class Entity1 {
421875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    @PrimaryKey
422875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    int uid;
423875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    int parentId;
424875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String name;
425875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
426875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """)
427875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar
428875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        val entity2 = JavaFileObjects.forSourceString("foo.bar.Entity2",
429875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """
430875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                package foo.bar;
431bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
432875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Entity
433875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public class Entity2 {
434875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    @PrimaryKey
435875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    int uid;
436875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String anotherName;
437875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
438875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """)
439875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        singleDb("""
440875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Database(entities = {Entity1.class, Entity2.class}, version = 42)
441875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public abstract class MyDb extends RoomDatabase {
442875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
4436f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, entity1, entity2) { _, _ ->
444875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        }.compilesWithoutError()
445875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    }
446875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar
447875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    @Test
448875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    fun foreignKey_missingParentColumn() {
449875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
450875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """
451875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                package foo.bar;
452bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
453875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Entity(foreignKeys = @ForeignKey(entity = Entity2.class,
454875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    parentColumns = {"anotherName", "anotherName2"},
455875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    childColumns = {"name", "name2"}))
456875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public class Entity1 {
457875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    @PrimaryKey
458875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    int uid;
459875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String name;
460875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String name2;
461875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
462875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """)
463875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar
464875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        val entity2 = JavaFileObjects.forSourceString("foo.bar.Entity2",
465875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """
466875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                package foo.bar;
467bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
468875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Entity
469875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public class Entity2 {
470875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    @PrimaryKey
471875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    int uid;
472875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String anotherName;
473875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
474875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """)
475875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        singleDb("""
476875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Database(entities = {Entity1.class, Entity2.class}, version = 42)
477875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public abstract class MyDb extends RoomDatabase {
478875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
4796f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, entity1, entity2) { _, _ ->
480875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        }.failsToCompile().withErrorContaining(
481875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                ProcessorErrors.foreignKeyParentColumnDoesNotExist("foo.bar.Entity2",
482875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                        "anotherName2", listOf("uid", "anotherName"))
483875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        )
484875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    }
485875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar
486875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    @Test
487875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    fun foreignKey_goodWithIndex() {
488875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        val entity1 = JavaFileObjects.forSourceString("foo.bar.Entity1",
489875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """
490875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                package foo.bar;
491bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
492875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Entity(foreignKeys = @ForeignKey(entity = Entity2.class,
493875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    parentColumns = {"anotherName", "anotherName2"},
494875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    childColumns = {"name", "name2"}))
495875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public class Entity1 {
496875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    @PrimaryKey
497875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    int uid;
498875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String name;
499875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String name2;
500875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
501875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """)
502875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar
503875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        val entity2 = JavaFileObjects.forSourceString("foo.bar.Entity2",
504875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """
505875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                package foo.bar;
506bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
507875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Entity(indices = @Index(value = {"anotherName2", "anotherName"}, unique = true))
508875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public class Entity2 {
509875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    @PrimaryKey
510875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    int uid;
511875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String anotherName;
512875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                    String anotherName2;
513875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
514875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                """)
515875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        singleDb("""
516875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                @Database(entities = {Entity1.class, Entity2.class}, version = 42)
517875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                public abstract class MyDb extends RoomDatabase {
518875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar                }
5196f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, entity1, entity2) { _, _ ->
520875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar        }.compilesWithoutError()
521875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar    }
522875203d39f95be2367dec3ee70be4e2169b4e0f0Yigit Boyar
52308ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar    @Test
52408ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar    fun insertNotAReferencedEntity() {
52508ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar        singleDb("""
52608ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                @Database(entities = {User.class}, version = 42)
52708ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                public abstract class MyDb extends RoomDatabase {
52808ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                    abstract BookDao bookDao();
52908ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                }
5306f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, USER, USER_DAO, BOOK, BOOK_DAO) { _, _ ->
53108ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar        }.failsToCompile().withErrorContaining(
53208ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                ProcessorErrors.shortcutEntityIsNotInDatabase(
53308ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                        database = "foo.bar.MyDb",
53408ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                        dao = "foo.bar.BookDao",
53508ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                        entity = "foo.bar.Book"
53608ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar                )
53708ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar        )
53808ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar    }
53908ddf77b7cc743f85b23e83de8b22b69fe4bf6d2Yigit Boyar
5405124503104860e68981cc3e3092b95932586f66fYigit Boyar    @Test
5415124503104860e68981cc3e3092b95932586f66fYigit Boyar    fun cache_entity() {
5425124503104860e68981cc3e3092b95932586f66fYigit Boyar        singleDb("""
5435124503104860e68981cc3e3092b95932586f66fYigit Boyar                @Database(entities = {User.class}, version = 42)
544f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                @SkipQueryVerification
5455124503104860e68981cc3e3092b95932586f66fYigit Boyar                public abstract class MyDb extends RoomDatabase {
546f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                    public abstract MyUserDao userDao();
547f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                    @Dao
548f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                    interface MyUserDao {
549f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                        @Insert
550f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                        public void insert(User... users);
551f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar
5523542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar                        @Query("SELECT * FROM user where uid = :uid")
553f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                        public User loadOne(int uid);
554f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar
555f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                        @TypeConverters(Converter.class)
5563542101509120586bbae17b1f748f302e1fb82a3Yigit Boyar                        @Query("SELECT * FROM user where uid = :uid")
557f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                        public User loadWithConverter(int uid);
558f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                    }
559f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                    public static class Converter {
560f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                        @TypeConverter
561f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                        public static java.util.Date foo(Long input) {return null;}
562f8c3624579d5761a2d34a7199932492d267f5f85Yigit Boyar                    }
5635124503104860e68981cc3e3092b95932586f66fYigit Boyar                }
5646f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, USER, USER_DAO) { db, _ ->
5655124503104860e68981cc3e3092b95932586f66fYigit Boyar            val userDao = db.daoMethods.first().dao
5665124503104860e68981cc3e3092b95932586f66fYigit Boyar            val insertionMethod = userDao.insertionMethods.find { it.name == "insert" }
5675124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(insertionMethod, notNullValue())
5685124503104860e68981cc3e3092b95932586f66fYigit Boyar            val loadOne = userDao.queryMethods.find { it.name == "loadOne" }
5695124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(loadOne, notNullValue())
5705124503104860e68981cc3e3092b95932586f66fYigit Boyar            val adapter = loadOne?.queryResultBinder?.adapter?.rowAdapter
5715124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat("test sanity", adapter, instanceOf(EntityRowAdapter::class.java))
5725124503104860e68981cc3e3092b95932586f66fYigit Boyar            val adapterEntity = (adapter as EntityRowAdapter).entity
57386b3f8d9bd637749668174e0736fe9fbecbcfb09Yuichi Araki            assertThat(insertionMethod?.entities?.values?.first(), sameInstance(adapterEntity))
5745124503104860e68981cc3e3092b95932586f66fYigit Boyar
5755124503104860e68981cc3e3092b95932586f66fYigit Boyar            val withConverter = userDao.queryMethods.find { it.name == "loadWithConverter" }
5765124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(withConverter, notNullValue())
5775124503104860e68981cc3e3092b95932586f66fYigit Boyar            val convAdapter = withConverter?.queryResultBinder?.adapter?.rowAdapter
5785124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat("test sanity", adapter, instanceOf(EntityRowAdapter::class.java))
5795124503104860e68981cc3e3092b95932586f66fYigit Boyar            val convAdapterEntity = (convAdapter as EntityRowAdapter).entity
58086b3f8d9bd637749668174e0736fe9fbecbcfb09Yuichi Araki            assertThat(insertionMethod?.entities?.values?.first(),
58186b3f8d9bd637749668174e0736fe9fbecbcfb09Yuichi Araki                    not(sameInstance(convAdapterEntity)))
5825124503104860e68981cc3e3092b95932586f66fYigit Boyar
5835124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(convAdapterEntity, notNullValue())
5845124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(adapterEntity, notNullValue())
5855124503104860e68981cc3e3092b95932586f66fYigit Boyar        }.compilesWithoutError()
5865124503104860e68981cc3e3092b95932586f66fYigit Boyar    }
5875124503104860e68981cc3e3092b95932586f66fYigit Boyar
5885124503104860e68981cc3e3092b95932586f66fYigit Boyar    @Test
5895124503104860e68981cc3e3092b95932586f66fYigit Boyar    fun cache_pojo() {
5905124503104860e68981cc3e3092b95932586f66fYigit Boyar        singleDb("""
5915124503104860e68981cc3e3092b95932586f66fYigit Boyar                @Database(entities = {User.class}, version = 42)
5925124503104860e68981cc3e3092b95932586f66fYigit Boyar                public abstract class MyDb extends RoomDatabase {
5935124503104860e68981cc3e3092b95932586f66fYigit Boyar                    public abstract UserDao userDao();
5945124503104860e68981cc3e3092b95932586f66fYigit Boyar                }
5956f1f5567abe765d30fda9c8fedce5617ecdeda9cAurimas Liutikas                """, USER, USER_DAO) { db, _ ->
5965124503104860e68981cc3e3092b95932586f66fYigit Boyar            val userDao = db.daoMethods.first().dao
5975124503104860e68981cc3e3092b95932586f66fYigit Boyar            val loadOne = userDao.queryMethods.find { it.name == "loadOnePojo" }
5985124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(loadOne, notNullValue())
5995124503104860e68981cc3e3092b95932586f66fYigit Boyar            val adapter = loadOne?.queryResultBinder?.adapter?.rowAdapter
6005124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat("test sanity", adapter, instanceOf(PojoRowAdapter::class.java))
6015124503104860e68981cc3e3092b95932586f66fYigit Boyar            val adapterPojo = (adapter as PojoRowAdapter).pojo
6025124503104860e68981cc3e3092b95932586f66fYigit Boyar
6035124503104860e68981cc3e3092b95932586f66fYigit Boyar            val loadAll = userDao.queryMethods.find { it.name == "loadAllPojos" }
6045124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(loadAll, notNullValue())
6055124503104860e68981cc3e3092b95932586f66fYigit Boyar            val loadAllAdapter = loadAll?.queryResultBinder?.adapter?.rowAdapter
6065124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat("test sanity", loadAllAdapter, instanceOf(PojoRowAdapter::class.java))
6075124503104860e68981cc3e3092b95932586f66fYigit Boyar            val loadAllPojo = (loadAllAdapter as PojoRowAdapter).pojo
6085124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(adapter, not(sameInstance(loadAllAdapter)))
6095124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(adapterPojo, sameInstance(loadAllPojo))
6105124503104860e68981cc3e3092b95932586f66fYigit Boyar
6115124503104860e68981cc3e3092b95932586f66fYigit Boyar            val withConverter = userDao.queryMethods.find { it.name == "loadPojoWithConverter" }
6125124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(withConverter, notNullValue())
6135124503104860e68981cc3e3092b95932586f66fYigit Boyar            val convAdapter = withConverter?.queryResultBinder?.adapter?.rowAdapter
6145124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat("test sanity", adapter, instanceOf(PojoRowAdapter::class.java))
6155124503104860e68981cc3e3092b95932586f66fYigit Boyar            val convAdapterPojo = (convAdapter as PojoRowAdapter).pojo
6165124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(convAdapterPojo, notNullValue())
6175124503104860e68981cc3e3092b95932586f66fYigit Boyar            assertThat(convAdapterPojo, not(sameInstance(adapterPojo)))
6185124503104860e68981cc3e3092b95932586f66fYigit Boyar        }.compilesWithoutError()
6195124503104860e68981cc3e3092b95932586f66fYigit Boyar    }
6205124503104860e68981cc3e3092b95932586f66fYigit Boyar
62117caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    @Test
62217caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    fun daoConstructor_RoomDatabase() {
62317caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        assertConstructor(listOf(DB1), "BookDao(RoomDatabase db) {}")
62417caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .compilesWithoutError()
62517caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    }
62617caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki
62717caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    @Test
62817caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    fun daoConstructor_specificDatabase() {
62917caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        assertConstructor(listOf(DB1), "BookDao(Db1 db) {}")
63017caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .compilesWithoutError()
63117caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    }
63217caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki
63317caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    @Test
63417caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    fun daoConstructor_wrongDatabase() {
63517caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        assertConstructor(listOf(DB1, DB3), "BookDao(Db3 db) {}")
63617caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .failsToCompile()
63717caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .withErrorContaining(ProcessorErrors
63817caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                        .daoMustHaveMatchingConstructor("foo.bar.BookDao", "foo.bar.Db1"))
63917caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    }
64017caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki
64117caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    @Test
64217caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    fun daoConstructor_multipleDatabases_RoomDatabase() {
64317caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        assertConstructor(listOf(DB1, DB2), "BookDao(RoomDatabase db) {}")
64417caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .compilesWithoutError()
64517caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    }
64617caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki
64717caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    @Test
64817caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    fun daoConstructor_multipleDatabases_specificDatabases() {
64917caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        assertConstructor(listOf(DB1, DB2), """
65017caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                    BookDao(Db1 db) {}
65117caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                    BookDao(Db2 db) {}
65217caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """)
65317caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .compilesWithoutError()
65417caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    }
65517caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki
65617caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    @Test
65717caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    fun daoConstructor_multipleDatabases_empty() {
65817caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        assertConstructor(listOf(DB1, DB2), """
65917caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                    BookDao(Db1 db) {}
66017caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                    BookDao() {} // Db2 uses this
66117caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """)
66217caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .compilesWithoutError()
66317caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    }
66417caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki
66517caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    @Test
66617caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    fun daoConstructor_multipleDatabases_noMatch() {
66717caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        assertConstructor(listOf(DB1, DB2), """
66817caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                    BookDao(Db1 db) {}
66917caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """)
67017caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .failsToCompile()
67117caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .withErrorContaining(ProcessorErrors
67217caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                        .daoMustHaveMatchingConstructor("foo.bar.BookDao", "foo.bar.Db2"))
67317caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    }
67417caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki
67517caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    fun assertConstructor(dbs: List<JavaFileObject>, constructor: String): CompileTester {
67617caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        val bookDao = JavaFileObjects.forSourceString("foo.bar.BookDao",
67717caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """
67817caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                package foo.bar;
679bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                import androidx.room.*;
68017caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                @Dao
68117caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                public abstract class BookDao {
68217caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                    $constructor
68317caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                }
68417caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                """)
68517caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki        return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
68617caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .that(listOf(BOOK, bookDao) + dbs)
68717caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki                .processedWith(RoomProcessor())
68817caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki    }
68917caba59e1fd850fe1381d7311d23afc4e07cdfbYuichi Araki
6908bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar    fun singleDb(input: String, vararg otherFiles: JavaFileObject,
6918bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                 handler: (Database, TestInvocation) -> Unit): CompileTester {
6928bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar        return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources())
6938bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                .that(otherFiles.toMutableList()
6948bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                        + JavaFileObjects.forSourceString("foo.bar.MyDb",
6958bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                        DATABASE_PREFIX + input
6968bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                ))
6978bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                .processedWith(TestProcessor.builder()
698bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                        .forAnnotations(androidx.room.Database::class)
6998bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                        .nextRunHandler { invocation ->
7008bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                            val entity = invocation.roundEnv
7018bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                                    .getElementsAnnotatedWith(
702bdc4c86d3dff74f6634a38e2f7b316b0e823a2c8Alan Viverette                                            androidx.room.Database::class.java)
7038bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                                    .first()
704aa82fce1d73394bdc7f4c2510cf94a3572032b24Yigit Boyar                            val parser = DatabaseProcessor(invocation.context,
705aa82fce1d73394bdc7f4c2510cf94a3572032b24Yigit Boyar                                    MoreElements.asType(entity))
706aa82fce1d73394bdc7f4c2510cf94a3572032b24Yigit Boyar                            val parsedDb = parser.process()
7078bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                            handler(parsedDb, invocation)
7088bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                            true
7098bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                        }
7108bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar                        .build())
7118bad027c789d3fb3da8e68fa0154f2a24ccc2865Yigit Boyar    }
712ddde363d8028917a4cb0167552b24f7e5b2907d1Yigit Boyar}
713