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;
18
19import static org.hamcrest.CoreMatchers.instanceOf;
20import static org.hamcrest.CoreMatchers.is;
21import static org.hamcrest.CoreMatchers.notNullValue;
22import static org.hamcrest.CoreMatchers.nullValue;
23import static org.hamcrest.MatcherAssert.assertThat;
24import static org.mockito.Mockito.mock;
25
26import static java.util.Arrays.asList;
27
28import android.content.Context;
29
30import androidx.annotation.NonNull;
31import androidx.room.migration.Migration;
32import androidx.sqlite.db.SupportSQLiteDatabase;
33import androidx.sqlite.db.SupportSQLiteOpenHelper;
34import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory;
35
36import org.hamcrest.CoreMatchers;
37import org.junit.Test;
38import org.junit.runner.RunWith;
39import org.junit.runners.JUnit4;
40
41import java.util.List;
42
43@SuppressWarnings("ArraysAsListWithZeroOrOneArgument")
44@RunWith(JUnit4.class)
45public class BuilderTest {
46    @Test(expected = IllegalArgumentException.class)
47    public void nullContext() {
48        //noinspection ConstantConditions
49        Room.databaseBuilder(null, RoomDatabase.class, "bla").build();
50    }
51
52    @Test(expected = IllegalArgumentException.class)
53    public void nullContext2() {
54        //noinspection ConstantConditions
55        Room.inMemoryDatabaseBuilder(null, RoomDatabase.class).build();
56    }
57
58    @Test(expected = IllegalArgumentException.class)
59    public void nullName() {
60        //noinspection ConstantConditions
61        Room.databaseBuilder(mock(Context.class), RoomDatabase.class, null).build();
62    }
63
64    @Test(expected = IllegalArgumentException.class)
65    public void emptyName() {
66        Room.databaseBuilder(mock(Context.class), RoomDatabase.class, "  ").build();
67    }
68
69    @Test
70    public void migration() {
71        Migration m1 = new EmptyMigration(0, 1);
72        Migration m2 = new EmptyMigration(1, 2);
73        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
74                .addMigrations(m1, m2).build();
75        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
76        RoomDatabase.MigrationContainer migrations = config.migrationContainer;
77        assertThat(migrations.findMigrationPath(0, 1), is(asList(m1)));
78        assertThat(migrations.findMigrationPath(1, 2), is(asList(m2)));
79        assertThat(migrations.findMigrationPath(0, 2), is(asList(m1, m2)));
80        assertThat(migrations.findMigrationPath(2, 0), CoreMatchers.<List<Migration>>nullValue());
81        assertThat(migrations.findMigrationPath(0, 3), CoreMatchers.<List<Migration>>nullValue());
82    }
83
84    @Test
85    public void migrationOverride() {
86        Migration m1 = new EmptyMigration(0, 1);
87        Migration m2 = new EmptyMigration(1, 2);
88        Migration m3 = new EmptyMigration(0, 1);
89        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
90                .addMigrations(m1, m2, m3).build();
91        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
92        RoomDatabase.MigrationContainer migrations = config.migrationContainer;
93        assertThat(migrations.findMigrationPath(0, 1), is(asList(m3)));
94        assertThat(migrations.findMigrationPath(1, 2), is(asList(m2)));
95        assertThat(migrations.findMigrationPath(0, 3), CoreMatchers.<List<Migration>>nullValue());
96    }
97
98    @Test
99    public void migrationJump() {
100        Migration m1 = new EmptyMigration(0, 1);
101        Migration m2 = new EmptyMigration(1, 2);
102        Migration m3 = new EmptyMigration(2, 3);
103        Migration m4 = new EmptyMigration(0, 3);
104        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
105                .addMigrations(m1, m2, m3, m4).build();
106        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
107        RoomDatabase.MigrationContainer migrations = config.migrationContainer;
108        assertThat(migrations.findMigrationPath(0, 3), is(asList(m4)));
109        assertThat(migrations.findMigrationPath(1, 3), is(asList(m2, m3)));
110    }
111
112    @Test
113    public void migrationDowngrade() {
114        Migration m1_2 = new EmptyMigration(1, 2);
115        Migration m2_3 = new EmptyMigration(2, 3);
116        Migration m3_4 = new EmptyMigration(3, 4);
117        Migration m3_2 = new EmptyMigration(3, 2);
118        Migration m2_1 = new EmptyMigration(2, 1);
119        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
120                .addMigrations(m1_2, m2_3, m3_4, m3_2, m2_1).build();
121        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
122        RoomDatabase.MigrationContainer migrations = config.migrationContainer;
123        assertThat(migrations.findMigrationPath(3, 2), is(asList(m3_2)));
124        assertThat(migrations.findMigrationPath(3, 1), is(asList(m3_2, m2_1)));
125    }
126
127    @Test
128    public void skipMigration() {
129        Context context = mock(Context.class);
130
131        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
132                .fallbackToDestructiveMigration()
133                .build();
134
135        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
136        assertThat(config.requireMigration, is(false));
137    }
138
139    @Test
140    public void fallbackToDestructiveMigrationFrom_calledOnce_migrationsNotRequiredForValues() {
141        Context context = mock(Context.class);
142
143        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
144                .fallbackToDestructiveMigrationFrom(1, 2).build();
145
146        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
147        assertThat(config.isMigrationRequiredFrom(1), is(false));
148        assertThat(config.isMigrationRequiredFrom(2), is(false));
149    }
150
151    @Test
152    public void fallbackToDestructiveMigrationFrom_calledTwice_migrationsNotRequiredForValues() {
153        Context context = mock(Context.class);
154        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
155                .fallbackToDestructiveMigrationFrom(1, 2)
156                .fallbackToDestructiveMigrationFrom(3, 4)
157                .build();
158        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
159
160        assertThat(config.isMigrationRequiredFrom(1), is(false));
161        assertThat(config.isMigrationRequiredFrom(2), is(false));
162        assertThat(config.isMigrationRequiredFrom(3), is(false));
163        assertThat(config.isMigrationRequiredFrom(4), is(false));
164    }
165
166    @Test
167    public void isMigrationRequiredFrom_fallBackToDestructiveCalled_alwaysReturnsFalse() {
168        Context context = mock(Context.class);
169
170        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
171                .fallbackToDestructiveMigration()
172                .build();
173
174        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
175        assertThat(config.isMigrationRequiredFrom(0), is(false));
176        assertThat(config.isMigrationRequiredFrom(1), is(false));
177        assertThat(config.isMigrationRequiredFrom(5), is(false));
178        assertThat(config.isMigrationRequiredFrom(12), is(false));
179        assertThat(config.isMigrationRequiredFrom(132), is(false));
180    }
181
182    @Test
183    public void isMigrationRequiredFrom_byDefault_alwaysReturnsTrue() {
184        Context context = mock(Context.class);
185
186        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
187                .build();
188
189        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
190        assertThat(config.isMigrationRequiredFrom(0), is(true));
191        assertThat(config.isMigrationRequiredFrom(1), is(true));
192        assertThat(config.isMigrationRequiredFrom(5), is(true));
193        assertThat(config.isMigrationRequiredFrom(12), is(true));
194        assertThat(config.isMigrationRequiredFrom(132), is(true));
195    }
196
197    @Test
198    public void isMigrationRequiredFrom_fallBackToDestFromCalled_falseForProvidedValues() {
199        Context context = mock(Context.class);
200
201        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
202                .fallbackToDestructiveMigrationFrom(1, 4, 81)
203                .build();
204
205        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
206        assertThat(config.isMigrationRequiredFrom(1), is(false));
207        assertThat(config.isMigrationRequiredFrom(4), is(false));
208        assertThat(config.isMigrationRequiredFrom(81), is(false));
209    }
210
211    @Test
212    public void isMigrationRequiredFrom_fallBackToDestFromCalled_trueForNonProvidedValues() {
213        Context context = mock(Context.class);
214
215        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
216                .fallbackToDestructiveMigrationFrom(1, 4, 81)
217                .build();
218
219        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
220        assertThat(config.isMigrationRequiredFrom(2), is(true));
221        assertThat(config.isMigrationRequiredFrom(3), is(true));
222        assertThat(config.isMigrationRequiredFrom(73), is(true));
223    }
224
225    @Test
226    public void createBasic() {
227        Context context = mock(Context.class);
228        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class).build();
229        assertThat(db, instanceOf(BuilderTest_TestDatabase_Impl.class));
230        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
231        assertThat(config, notNullValue());
232        assertThat(config.context, is(context));
233        assertThat(config.name, is(nullValue()));
234        assertThat(config.allowMainThreadQueries, is(false));
235        assertThat(config.journalMode, is(RoomDatabase.JournalMode.TRUNCATE));
236        assertThat(config.sqliteOpenHelperFactory,
237                instanceOf(FrameworkSQLiteOpenHelperFactory.class));
238    }
239
240    @Test
241    public void createAllowMainThread() {
242        Context context = mock(Context.class);
243        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
244                .allowMainThreadQueries()
245                .build();
246        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
247        assertThat(config.allowMainThreadQueries, is(true));
248    }
249
250    @Test
251    public void createWriteAheadLogging() {
252        Context context = mock(Context.class);
253        TestDatabase db = Room.databaseBuilder(context, TestDatabase.class, "foo")
254                .setJournalMode(RoomDatabase.JournalMode.WRITE_AHEAD_LOGGING).build();
255        assertThat(db, instanceOf(BuilderTest_TestDatabase_Impl.class));
256        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
257        assertThat(config.journalMode, is(RoomDatabase.JournalMode.WRITE_AHEAD_LOGGING));
258    }
259
260    @Test
261    public void createWithFactoryAndVersion() {
262        Context context = mock(Context.class);
263        SupportSQLiteOpenHelper.Factory factory = mock(SupportSQLiteOpenHelper.Factory.class);
264
265        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
266                .openHelperFactory(factory)
267                .build();
268        assertThat(db, instanceOf(BuilderTest_TestDatabase_Impl.class));
269        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
270        assertThat(config, notNullValue());
271        assertThat(config.sqliteOpenHelperFactory, is(factory));
272    }
273
274    abstract static class TestDatabase extends RoomDatabase {
275    }
276
277    static class EmptyMigration extends Migration {
278        EmptyMigration(int start, int end) {
279            super(start, end);
280        }
281
282        @Override
283        public void migrate(@NonNull SupportSQLiteDatabase database) {
284        }
285    }
286
287}
288