ForeignKeyTest.java revision 36023a6ffdcc24a64c3f86efd4e754cfc3493761
10045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar/*
20045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * Copyright (C) 2017 The Android Open Source Project
30045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar *
40045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
50045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * you may not use this file except in compliance with the License.
60045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * You may obtain a copy of the License at
70045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar *
80045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
90045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar *
100045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * Unless required by applicable law or agreed to in writing, software
110045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
120045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * See the License for the specific language governing permissions and
140045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar * limitations under the License.
150045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar */
160045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
170045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarpackage com.android.support.room.integration.testapp.test;
180045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
190045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.CoreMatchers.containsString;
200045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.CoreMatchers.equalTo;
210045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.CoreMatchers.instanceOf;
220045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.CoreMatchers.notNullValue;
230045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.CoreMatchers.nullValue;
240045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport static org.hamcrest.MatcherAssert.assertThat;
250045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
260045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport android.database.sqlite.SQLiteException;
270045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport android.support.test.InstrumentationRegistry;
280045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport android.support.test.filters.SmallTest;
290045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport android.support.test.runner.AndroidJUnit4;
300045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
310045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.Dao;
320045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.Database;
330045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.Delete;
340045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.Entity;
350045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.ForeignKey;
360045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.Index;
370045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.Insert;
380045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.PrimaryKey;
390045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.Query;
400045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.Room;
410045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport com.android.support.room.RoomDatabase;
420045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
430045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport org.junit.Before;
440045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport org.junit.Test;
450045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarimport org.junit.runner.RunWith;
460045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
4736023a6ffdcc24a64c3f86efd4e754cfc3493761Yigit Boyarimport java.util.Locale;
4836023a6ffdcc24a64c3f86efd4e754cfc3493761Yigit Boyar
490045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar@RunWith(AndroidJUnit4.class)
500045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar@SmallTest
510045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyarpublic class ForeignKeyTest {
520045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Database(version = 1, entities = {A.class, B.class, C.class, D.class, E.class},
530045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            exportSchema = false)
540045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    abstract static class ForeignKeyDb extends RoomDatabase {
550045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        abstract FkDao dao();
560045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
570045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
580045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @SuppressWarnings({"SqlNoDataSourceInspection", "SameParameterValue"})
590045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Dao
600045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    interface FkDao {
610045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Insert
620045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        void insert(A... a);
630045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
640045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Insert
650045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        void insert(B... b);
660045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
670045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Insert
680045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        void insert(C... c);
690045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
700045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Insert
710045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        void insert(D... d);
720045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
730045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Query("SELECT * FROM A WHERE id = ?")
740045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        A loadA(int id);
750045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
760045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Query("SELECT * FROM B WHERE id = ?")
770045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        B loadB(int id);
780045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
790045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Query("SELECT * FROM C WHERE id = ?")
800045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        C loadC(int id);
810045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
820045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Query("SELECT * FROM D WHERE id = ?")
830045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        D loadD(int id);
840045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
850045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Query("SELECT * FROM E WHERE id = ?")
860045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        E loadE(int id);
870045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
880045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Delete
890045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        void delete(A... a);
900045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
910045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Delete
920045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        void delete(B... b);
930045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
940045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Delete
950045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        void delete(C... c);
960045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
970045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Query("UPDATE A SET name = :newName WHERE id = :id")
980045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        void changeNameA(int id, String newName);
990045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1000045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @Insert
1010045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        void insert(E... e);
1020045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1030045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1040045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
1050045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1060045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Entity(indices = {@Index(value = "name", unique = true),
1070045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @Index(value = {"name", "lastName"}, unique = true)})
1080045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    static class A {
1090045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @PrimaryKey(autoGenerate = true)
1100045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public int id;
1110045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public String name;
1120045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public String lastName;
1130045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1140045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        A() {
1150045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
1160045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1170045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        A(String name) {
1180045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            this.name = name;
1190045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
1200045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1210045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        A(String name, String lastName) {
1220045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            this.name = name;
1230045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            this.lastName = lastName;
1240045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
1250045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
1260045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1270045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @SuppressWarnings("WeakerAccess")
1280045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Entity(foreignKeys = {
1290045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @ForeignKey(entity = A.class,
1300045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    parentColumns = "name",
1310045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    childColumns = "aName")})
1320045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1330045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    static class B {
1340045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @PrimaryKey(autoGenerate = true)
1350045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public int id;
1360045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public String aName;
1370045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1380045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        B() {
1390045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
1400045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1410045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        B(String aName) {
1420045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            this.aName = aName;
1430045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
1440045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
1450045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1460045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @SuppressWarnings("WeakerAccess")
1470045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Entity(foreignKeys = {
1480045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @ForeignKey(entity = A.class,
1490045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    parentColumns = "name",
1500045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    childColumns = "aName",
1510045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    deferred = true)})
1520045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    static class C {
1530045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @PrimaryKey(autoGenerate = true)
1540045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public int id;
1550045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public String aName;
1560045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1570045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        C() {
1580045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
1590045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1600045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        C(String aName) {
1610045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            this.aName = aName;
1620045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
1630045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
1640045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1650045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @SuppressWarnings("WeakerAccess")
1660045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Entity(foreignKeys = {
1670045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @ForeignKey(entity = A.class,
1680045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    parentColumns = "name",
1690045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    childColumns = "aName",
1700045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    onDelete = ForeignKey.CASCADE,
1710045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    onUpdate = ForeignKey.CASCADE)})
1720045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    static class D {
1730045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @PrimaryKey(autoGenerate = true)
1740045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public int id;
1750045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public String aName;
1760045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1770045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        D() {
1780045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
1790045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1800045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        D(String aName) {
1810045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            this.aName = aName;
1820045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
1830045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
1840045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1850045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @SuppressWarnings("WeakerAccess")
1860045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Entity(foreignKeys = {
1870045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @ForeignKey(entity = A.class,
1880045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    parentColumns = {"name", "lastName"},
1890045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    childColumns = {"aName", "aLastName"},
1900045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    onDelete = ForeignKey.SET_NULL,
1910045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    onUpdate = ForeignKey.CASCADE)})
1920045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    static class E {
1930045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        @PrimaryKey(autoGenerate = true)
1940045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public int id;
1950045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public String aName;
1960045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        public String aLastName;
1970045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
1980045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        E() {
1990045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
2000045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
2010045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        E(String aName, String aLastName) {
2020045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            this.aName = aName;
2030045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            this.aLastName = aLastName;
2040045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
2050045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
2060045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
2070045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
2080045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    private ForeignKeyDb mDb;
2090045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    private FkDao mDao;
2100045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
2110045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Before
2120045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void openDb() {
2130045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDb = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext(),
2140045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                ForeignKeyDb.class).build();
2150045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao = mDb.dao();
2160045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
2170045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
2180045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
2190045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void simpleForeignKeyFailure() {
2200045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        Throwable t = catchException(new ThrowingRunnable() {
2210045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @Override
2220045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            public void run() throws Exception {
2230045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                mDao.insert(new B("foo"));
2240045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            }
2250045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        });
2260045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(t, instanceOf(SQLiteException.class));
22736023a6ffdcc24a64c3f86efd4e754cfc3493761Yigit Boyar        assertThat(t.getMessage().toUpperCase(Locale.US), containsString("FOREIGN KEY"));
2280045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
2290045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
2300045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
2310045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void simpleForeignKeyDeferredFailure() {
2320045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        Throwable t = catchException(new ThrowingRunnable() {
2330045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @Override
2340045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            public void run() throws Exception {
2350045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                mDao.insert(new C("foo"));
2360045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            }
2370045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        });
2380045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(t, instanceOf(SQLiteException.class));
23936023a6ffdcc24a64c3f86efd4e754cfc3493761Yigit Boyar        assertThat(t.getMessage().toUpperCase(Locale.US), containsString("FOREIGN KEY"));
2400045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
2410045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
2420045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
2430045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void immediateForeignKeyFailure() {
2440045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        Throwable t = catchException(new ThrowingRunnable() {
2450045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @Override
2460045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            public void run() throws Exception {
2470045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                try {
2480045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    mDb.beginTransaction();
2490045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    mDao.insert(new B("foo"));
2500045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    mDao.insert(new A("foo"));
2510045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    mDb.setTransactionSuccessful();
2520045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                } finally {
2530045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                    mDb.endTransaction();
2540045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                }
2550045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            }
2560045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        });
2570045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(t, instanceOf(SQLiteException.class));
2580045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
2590045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
2600045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
2610045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void deferredForeignKeySuccess() {
2620045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        try {
2630045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDb.beginTransaction();
2640045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDao.insert(new C("foo"));
2650045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDao.insert(new A("foo"));
2660045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDb.setTransactionSuccessful();
2670045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        } finally {
2680045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDb.endTransaction();
2690045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
2700045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(mDao.loadA(1), notNullValue());
2710045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(mDao.loadC(1), notNullValue());
2720045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
2730045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
2740045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
2750045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void onDelete_noAction() {
2760045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new A("a1"));
2770045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final A a = mDao.loadA(1);
2780045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new B("a1"));
2790045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        Throwable t = catchException(new ThrowingRunnable() {
2800045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @Override
2810045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            public void run() throws Exception {
2820045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                mDao.delete(a);
2830045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            }
2840045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        });
2850045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(t, instanceOf(SQLiteException.class));
28636023a6ffdcc24a64c3f86efd4e754cfc3493761Yigit Boyar        assertThat(t.getMessage().toUpperCase(Locale.US), containsString("FOREIGN KEY"));
2870045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
2880045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
2890045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
2900045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void onDelete_noAction_withTransaction() {
2910045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new A("a1"));
2920045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final A a = mDao.loadA(1);
2930045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new B("a1"));
2940045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final B b = mDao.loadB(1);
2950045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        Throwable t = catchException(new ThrowingRunnable() {
2960045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @Override
2970045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            public void run() throws Exception {
2980045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                deleteInTransaction(a, b);
2990045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            }
3000045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        });
3010045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(t, instanceOf(SQLiteException.class));
30236023a6ffdcc24a64c3f86efd4e754cfc3493761Yigit Boyar        assertThat(t.getMessage().toUpperCase(Locale.US), containsString("FOREIGN KEY"));
3030045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
3040045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
3050045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
3060045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void onDelete_noAction_deferred() {
3070045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new A("a1"));
3080045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final A a = mDao.loadA(1);
3090045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new C("a1"));
3100045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        Throwable t = catchException(new ThrowingRunnable() {
3110045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @Override
3120045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            public void run() throws Exception {
3130045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                mDao.delete(a);
3140045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            }
3150045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        });
3160045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(t, instanceOf(SQLiteException.class));
31736023a6ffdcc24a64c3f86efd4e754cfc3493761Yigit Boyar        assertThat(t.getMessage().toUpperCase(Locale.US), containsString("FOREIGN KEY"));
3180045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
3190045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
3200045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
3210045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void onDelete_noAction__deferredWithTransaction() {
3220045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new A("a1"));
3230045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final A a = mDao.loadA(1);
3240045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new C("a1"));
3250045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final C c = mDao.loadC(1);
3260045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        deleteInTransaction(a, c);
3270045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
3280045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
3290045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
3300045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void onDelete_cascade() {
3310045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new A("a1"));
3320045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final A a = mDao.loadA(1);
3330045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new D("a1"));
3340045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final D d = mDao.loadD(1);
3350045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat("test sanity", d, notNullValue());
3360045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.delete(a);
3370045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(mDao.loadD(1), nullValue());
3380045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
3390045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
3400045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
3410045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void onUpdate_cascade() {
3420045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new A("a1"));
3430045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new D("a1"));
3440045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final D d = mDao.loadD(1);
3450045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat("test sanity", d, notNullValue());
3460045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.changeNameA(1, "bla");
3470045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(mDao.loadD(1).aName, equalTo("bla"));
3480045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(mDao.loadA(1).name, equalTo("bla"));
3490045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
3500045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
3510045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
3520045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void multipleReferences() {
3530045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new A("a1", "a2"));
3540045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final A a = mDao.loadA(1);
3550045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat("test sanity", a, notNullValue());
3560045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        Throwable t = catchException(new ThrowingRunnable() {
3570045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            @Override
3580045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            public void run() throws Exception {
3590045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar                mDao.insert(new E("a1", "dsa"));
3600045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            }
3610045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        });
36236023a6ffdcc24a64c3f86efd4e754cfc3493761Yigit Boyar        assertThat(t.getMessage().toUpperCase(Locale.US), containsString("FOREIGN KEY"));
3630045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
3640045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
3650045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
3660045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void onDelete_setNull_multipleReferences() {
3670045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new A("a1", "a2"));
3680045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final A a = mDao.loadA(1);
3690045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new E("a1", "a2"));
3700045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(mDao.loadE(1), notNullValue());
3710045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.delete(a);
3720045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        E e = mDao.loadE(1);
3730045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(e, notNullValue());
3740045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(e.aName, nullValue());
3750045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(e.aLastName, nullValue());
3760045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
3770045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
3780045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @Test
3790045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    public void onUpdate_cascade_multipleReferences() {
3800045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new A("a1", "a2"));
3810045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        final A a = mDao.loadA(1);
3820045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.insert(new E("a1", "a2"));
3830045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(mDao.loadE(1), notNullValue());
3840045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDao.changeNameA(1, "foo");
3850045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(mDao.loadE(1), notNullValue());
3860045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(mDao.loadE(1).aName, equalTo("foo"));
3870045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        assertThat(mDao.loadE(1).aLastName, equalTo("a2"));
3880045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
3890045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
3900045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @SuppressWarnings("Duplicates")
3910045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    private void deleteInTransaction(A a, B b) {
3920045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDb.beginTransaction();
3930045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        try {
3940045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDao.delete(a);
3950045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDao.delete(b);
3960045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDb.setTransactionSuccessful();
3970045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        } finally {
3980045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDb.endTransaction();
3990045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
4000045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
4010045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
4020045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    @SuppressWarnings("Duplicates")
4030045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    private void deleteInTransaction(A a, C c) {
4040045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        mDb.beginTransaction();
4050045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        try {
4060045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDao.delete(a);
4070045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDao.delete(c);
4080045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDb.setTransactionSuccessful();
4090045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        } finally {
4100045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            mDb.endTransaction();
4110045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
4120045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
4130045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
4140045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    private static Throwable catchException(ThrowingRunnable throwingRunnable) {
4150045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        try {
4160045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            throwingRunnable.run();
4170045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        } catch (Throwable t) {
4180045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar            return t;
4190045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        }
4200045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        throw new RuntimeException("didn't throw an exception");
4210045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
4220045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar
4230045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    private interface ThrowingRunnable {
4240045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar        void run() throws Exception;
4250045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar    }
4260045a1c980b44c882f4ece571a0a113d36bbf0fbYigit Boyar}
427