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 17package androidx.room.writer 18 19import androidx.annotation.NonNull 20import androidx.room.processor.DatabaseProcessor 21import androidx.room.testing.TestInvocation 22import androidx.room.testing.TestProcessor 23import androidx.room.vo.Database 24import com.google.auto.common.MoreElements 25import com.google.common.truth.Truth 26import com.google.testing.compile.CompileTester 27import com.google.testing.compile.JavaFileObjects 28import com.google.testing.compile.JavaSourcesSubjectFactory 29import org.hamcrest.CoreMatchers.`is` 30import org.hamcrest.MatcherAssert.assertThat 31import org.junit.Test 32import org.junit.runner.RunWith 33import org.junit.runners.JUnit4 34 35@RunWith(JUnit4::class) 36class SQLiteOpenHelperWriterTest { 37 companion object { 38 const val ENTITY_PREFIX = """ 39 package foo.bar; 40 import androidx.annotation.NonNull; 41 import androidx.room.*; 42 @Entity%s 43 public class MyEntity { 44 """ 45 const val ENTITY_SUFFIX = "}" 46 const val DATABASE_CODE = """ 47 package foo.bar; 48 import androidx.room.*; 49 @Database(entities = {MyEntity.class}, version = 3) 50 abstract public class MyDatabase extends RoomDatabase { 51 } 52 """ 53 } 54 55 @Test 56 fun createSimpleEntity() { 57 singleEntity( 58 """ 59 @PrimaryKey 60 @NonNull 61 String uuid; 62 String name; 63 int age; 64 """.trimIndent() 65 ) { database, _ -> 66 val query = SQLiteOpenHelperWriter(database) 67 .createQuery(database.entities.first()) 68 assertThat(query, `is`("CREATE TABLE IF NOT EXISTS" + 69 " `MyEntity` (`uuid` TEXT NOT NULL, `name` TEXT, `age` INTEGER NOT NULL," + 70 " PRIMARY KEY(`uuid`))")) 71 }.compilesWithoutError() 72 } 73 74 @Test 75 fun multiplePrimaryKeys() { 76 singleEntity( 77 """ 78 @NonNull 79 String uuid; 80 @NonNull 81 String name; 82 int age; 83 """.trimIndent(), attributes = mapOf("primaryKeys" to "{\"uuid\", \"name\"}") 84 ) { database, _ -> 85 val query = SQLiteOpenHelperWriter(database) 86 .createQuery(database.entities.first()) 87 assertThat(query, `is`("CREATE TABLE IF NOT EXISTS" + 88 " `MyEntity` (`uuid` TEXT NOT NULL, `name` TEXT NOT NULL, " + 89 "`age` INTEGER NOT NULL, PRIMARY KEY(`uuid`, `name`))")) 90 }.compilesWithoutError() 91 } 92 93 @Test 94 fun autoIncrementObject() { 95 listOf("Long", "Integer").forEach { type -> 96 singleEntity( 97 """ 98 @PrimaryKey(autoGenerate = true) 99 $type uuid; 100 String name; 101 int age; 102 """.trimIndent() 103 ) { database, _ -> 104 val query = SQLiteOpenHelperWriter(database) 105 .createQuery(database.entities.first()) 106 assertThat(query, `is`("CREATE TABLE IF NOT EXISTS" + 107 " `MyEntity` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT," + 108 " `name` TEXT, `age` INTEGER NOT NULL)")) 109 }.compilesWithoutError() 110 } 111 } 112 113 @Test 114 fun autoIncrementPrimitives() { 115 listOf("long", "int").forEach { type -> 116 singleEntity( 117 """ 118 @PrimaryKey(autoGenerate = true) 119 $type uuid; 120 String name; 121 int age; 122 """.trimIndent() 123 ) { database, _ -> 124 val query = SQLiteOpenHelperWriter(database) 125 .createQuery(database.entities.first()) 126 assertThat(query, `is`("CREATE TABLE IF NOT EXISTS" + 127 " `MyEntity` (`uuid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," + 128 " `name` TEXT, `age` INTEGER NOT NULL)")) 129 }.compilesWithoutError() 130 } 131 } 132 133 fun singleEntity(input: String, attributes: Map<String, String> = mapOf(), 134 handler: (Database, TestInvocation) -> Unit): CompileTester { 135 val attributesReplacement: String 136 if (attributes.isEmpty()) { 137 attributesReplacement = "" 138 } else { 139 attributesReplacement = "(" + 140 attributes.entries.joinToString(",") { "${it.key} = ${it.value}" } + 141 ")".trimIndent() 142 } 143 return Truth.assertAbout(JavaSourcesSubjectFactory.javaSources()) 144 .that(listOf(JavaFileObjects.forSourceString("foo.bar.MyEntity", 145 ENTITY_PREFIX.format(attributesReplacement) + input + ENTITY_SUFFIX 146 ), JavaFileObjects.forSourceString("foo.bar.MyDatabase", 147 DATABASE_CODE))) 148 .processedWith(TestProcessor.builder() 149 .forAnnotations(androidx.room.Database::class, 150 NonNull::class) 151 .nextRunHandler { invocation -> 152 val db = MoreElements.asType(invocation.roundEnv 153 .getElementsAnnotatedWith( 154 androidx.room.Database::class.java) 155 .first()) 156 handler(DatabaseProcessor(invocation.context, db).process(), invocation) 157 true 158 } 159 .build()) 160 } 161} 162