• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 package com.android.providers.contacts;
17 
18 import android.database.Cursor;
19 import android.database.sqlite.SQLiteDatabase;
20 import android.test.AndroidTestCase;
21 
22 import junit.framework.AssertionFailedError;
23 
24 import java.util.HashMap;
25 
26 /**
27  * Unit tests for database create/upgrade operations.
28  *
29  * Run the test like this: <code> runtest -c com.android.providers.contacts.BaseDatabaseHelperUpgradeTest
30  * contactsprov </code>
31  */
32 public abstract class BaseDatabaseHelperUpgradeTest extends AndroidTestCase {
33 
34     protected static final String INTEGER = "INTEGER";
35     protected static final String TEXT = "TEXT";
36     protected static final String STRING = "STRING";
37     protected static final String BLOB = "BLOB";
38 
39     protected SQLiteDatabase mDb;
40 
41     /**
42      * The column info returned by PRAGMA table_info()
43      */
44     protected static class TableColumn {
45 
46         public int cid;
47         public String name;
48         public String type;
49         public boolean notnull;
50         // default value
51         public String dflt_value;
52         // primary key. Not tested.
53         public int pk;
54 
TableColumn()55         public TableColumn() {
56 
57         }
58 
TableColumn(String name, String type, boolean notnull, String defaultValue)59         public TableColumn(String name, String type, boolean notnull, String defaultValue) {
60             this.name = name;
61             this.type = type;
62             this.notnull = notnull;
63             this.dflt_value = defaultValue;
64         }
65     }
66 
67     protected static class TableStructure {
68 
69         private final HashMap<String, TableColumn> mColumns = new HashMap<String, TableColumn>();
70         private final String mName;
71 
TableStructure(SQLiteDatabase db, String tableName)72         public TableStructure(SQLiteDatabase db, String tableName) {
73             mName = tableName;
74             try (final Cursor cursor = db.rawQuery("PRAGMA table_info(" + tableName + ");", null)) {
75                 final int cidIndex = cursor.getColumnIndex("cid");
76                 final int nameIndex = cursor.getColumnIndex("name");
77                 final int typeIndex = cursor.getColumnIndex("type");
78                 final int notNullIndex = cursor.getColumnIndex("notnull");
79                 final int dfltValueIndex = cursor.getColumnIndex("dflt_value");
80                 final int pkIndex = cursor.getColumnIndex("pk");
81                 cursor.moveToPosition(-1);
82                 while (cursor.moveToNext()) {
83                     TableColumn column = new TableColumn();
84                     column.cid = cursor.getInt(cidIndex);
85                     column.name = cursor.getString(nameIndex);
86                     column.type = cursor.getString(typeIndex);
87                     column.notnull = cursor.getInt(notNullIndex) != 0;
88                     column.dflt_value = cursor.getString(dfltValueIndex);
89                     column.pk = cursor.getInt(pkIndex);
90 
91                     addColumn(column);
92                 }
93             }
94         }
95 
TableStructure()96         private TableStructure() {
97             mName = "";
98         }
99 
addColumn(TableColumn column)100         private void addColumn(TableColumn column) {
101             mColumns.put(column.name, column);
102         }
103 
assertHasColumn(String name, String type, boolean notnull, String defaultValue)104         public void assertHasColumn(String name, String type, boolean notnull,
105                 String defaultValue) {
106             final TableColumn column = mColumns.get(name);
107             if (column == null) {
108                 throw new AssertionFailedError("Table " + mName + ": Column missing: " + name);
109             }
110             if (!type.equals(column.type)) {
111                 throw new AssertionFailedError("Table " + mName + ": Column " + name + " type:"
112                         + column.type + ", " + type + " expected");
113             }
114             if (!notnull == column.notnull) {
115                 throw new AssertionFailedError("Table " + mName + ": Column " + name + " notnull:"
116                         + column.notnull + ", " + notnull + " expected");
117             }
118             if (defaultValue == null) {
119                 if (column.dflt_value != null) {
120                     throw new AssertionFailedError("Table " + mName + ": Column " + name
121                             + " defaultValue: " + column.dflt_value + ", null expected");
122                 }
123             } else if (!defaultValue.equals(column.dflt_value)) {
124                 throw new AssertionFailedError("Table " + mName + ": Column " + name
125                         + " defaultValue:" + column.dflt_value + ", " + defaultValue + " expected");
126             }
127         }
128 
129 
assertHasColumns(TableColumn[] columns)130         public void assertHasColumns(TableColumn[] columns) {
131             for (final TableColumn column : columns) {
132                 assertHasColumn(column.name, column.type, column.notnull, column.dflt_value);
133             }
134         }
135 
136         /**
137          * Assert the TableStructure has every column in @param columns, and nothing else.
138          */
assertSame(TableColumn[] columns)139         public void assertSame(TableColumn[] columns) {
140             assertHasColumns(columns);
141             if (columns.length != mColumns.size()) {
142                 throw new RuntimeException("column count mismatch");
143             }
144         }
145 
146     }
147 
148     /**
149      * Used to store a tables' name and its' current structure in a array.
150      */
151     protected static class TableListEntry {
152 
153         public final String name;
154         public final TableColumn[] columns;
155         public final boolean shouldBeInNewDb;
156 
TableListEntry(String name, TableColumn[] columns)157         public TableListEntry(String name, TableColumn[] columns) {
158             this(name, columns, /* shouldBeInNewDb = */ true);
159         }
160 
TableListEntry(String name, TableColumn[] columns, boolean shouldBeInNewDb)161         public TableListEntry(String name, TableColumn[] columns, boolean shouldBeInNewDb) {
162             this.name = name;
163             this.columns = columns;
164             this.shouldBeInNewDb = shouldBeInNewDb;
165         }
166     }
167 
168     @Override
setUp()169     protected void setUp() throws Exception {
170         super.setUp();
171 
172         final String filename = getDatabaseFilename();
173         if (filename == null) {
174             mDb = SQLiteDatabase.create(null);
175         } else {
176             getContext().deleteDatabase(filename);
177             mDb = SQLiteDatabase.openOrCreateDatabase(filename, null);
178         }
179     }
180 
181     @Override
tearDown()182     protected void tearDown() throws Exception {
183         mDb.close();
184         super.tearDown();
185     }
186 
getDatabaseFilename()187     protected abstract String getDatabaseFilename();
188 
assertDatabaseStructureSameAsList(TableListEntry[] list, boolean isNewDatabase)189     protected void assertDatabaseStructureSameAsList(TableListEntry[] list, boolean isNewDatabase) {
190         for (TableListEntry entry : list) {
191             if (!entry.shouldBeInNewDb) {
192                 if (isNewDatabase) {
193                     continue;
194                 }
195             }
196             TableStructure structure = new TableStructure(mDb, entry.name);
197             structure.assertSame(entry.columns);
198         }
199     }
200 
testAssertHasColumn_Match()201     public void testAssertHasColumn_Match() {
202         TableStructure table = createOneColumnTable("foo", INTEGER, false, null);
203         table.assertHasColumn("foo", INTEGER, false, null);
204     }
205 
testAssertHasColumn_Empty()206     public void testAssertHasColumn_Empty() {
207         TableStructure table = new TableStructure();
208 
209         try {
210             table.assertHasColumn("bar", INTEGER, false, null);
211             throw new AssertionError("Assert should fail");
212         } catch (AssertionFailedError e) {
213             // Should fail
214         }
215     }
216 
testAssertHasColumn_ColumnNotExist()217     public void testAssertHasColumn_ColumnNotExist() {
218         TableStructure table = createOneColumnTable("foo", INTEGER, false, null);
219 
220         try {
221             table.assertHasColumn("bar", INTEGER, false, null);
222             throw new AssertionError("Assert should fail");
223         } catch (AssertionFailedError e) {
224             // Should fail
225         }
226     }
227 
testAssertHasColumn_TypeMismatch()228     public void testAssertHasColumn_TypeMismatch() {
229         TableStructure table = createOneColumnTable("foo", INTEGER, false, null);
230 
231         try {
232             table.assertHasColumn("foo", TEXT, false, null);
233             throw new AssertionError("Assert should fail");
234         } catch (AssertionFailedError e) {
235             // Should fail
236         }
237     }
238 
testAssertHasColumn_NotNullMismatch()239     public void testAssertHasColumn_NotNullMismatch() {
240         TableStructure table = createOneColumnTable("foo", INTEGER, false, null);
241 
242         try {
243             table.assertHasColumn("foo", INTEGER, true, null);
244             throw new AssertionError("Assert should fail");
245         } catch (AssertionFailedError e) {
246             // Should fail
247         }
248     }
249 
testAssertHasColumn_DefaultMatch()250     public void testAssertHasColumn_DefaultMatch() {
251         TableStructure table = createOneColumnTable("foo", INTEGER, false, "baz");
252         table.assertHasColumn("foo", INTEGER, false, "baz");
253     }
254 
testAssertHasColumn_DefaultMismatch()255     public void testAssertHasColumn_DefaultMismatch() {
256         TableStructure table = createOneColumnTable("foo", INTEGER, false, "bar");
257 
258         try {
259             table.assertHasColumn("foo", INTEGER, false, "baz");
260             throw new AssertionError("Assert should fail");
261         } catch (AssertionFailedError e) {
262             // Should fail
263         }
264     }
265 
testAssertHasColumn_DefaultMismatch_Null1()266     public void testAssertHasColumn_DefaultMismatch_Null1() {
267         TableStructure table = createOneColumnTable("foo", INTEGER, false, null);
268 
269         try {
270             table.assertHasColumn("foo", INTEGER, false, "baz");
271             throw new AssertionError("Assert should fail");
272         } catch (AssertionFailedError e) {
273             // Should fail
274         }
275     }
276 
testAssertHasColumn_DefaultMismatch_Null2()277     public void testAssertHasColumn_DefaultMismatch_Null2() {
278         TableStructure table = createOneColumnTable("foo", INTEGER, false, "baz");
279 
280         try {
281             table.assertHasColumn("foo", INTEGER, false, null);
282             throw new AssertionError("Assert should fail");
283         } catch (AssertionFailedError e) {
284             // Should fail
285         }
286     }
287 
createOneColumnTable(String name, String type, boolean notnull, String defaultValue)288     private TableStructure createOneColumnTable(String name, String type, boolean notnull,
289             String defaultValue) {
290         TableStructure table = new TableStructure();
291         table.addColumn(new TableColumn(name, type, notnull, defaultValue));
292         return table;
293     }
294 
295 }
296