1 /* 2 * Copyright (C) 2007 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 17 package com.android.unit_tests; 18 19 import android.database.Cursor; 20 import android.database.sqlite.SQLiteConstraintException; 21 import android.database.sqlite.SQLiteDatabase; 22 import android.database.sqlite.SQLiteDoneException; 23 import android.database.sqlite.SQLiteStatement; 24 import android.test.PerformanceTestCase; 25 import android.test.suitebuilder.annotation.MediumTest; 26 import android.test.suitebuilder.annotation.SmallTest; 27 import junit.framework.TestCase; 28 29 import java.io.File; 30 31 public class DatabaseStatementTest extends TestCase implements PerformanceTestCase { 32 33 private static final String sString1 = "this is a test"; 34 private static final String sString2 = "and yet another test"; 35 private static final String sString3 = "this string is a little longer, but still a test"; 36 37 private static final int CURRENT_DATABASE_VERSION = 42; 38 private SQLiteDatabase mDatabase; 39 private File mDatabaseFile; 40 41 @Override setUp()42 protected void setUp() throws Exception { 43 super.setUp(); 44 mDatabaseFile = new File("/sqlite_stmt_journals", "database_test.db"); 45 if (mDatabaseFile.exists()) { 46 mDatabaseFile.delete(); 47 } 48 mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null); 49 assertNotNull(mDatabase); 50 mDatabase.setVersion(CURRENT_DATABASE_VERSION); 51 } 52 53 @Override tearDown()54 protected void tearDown() throws Exception { 55 mDatabase.close(); 56 mDatabaseFile.delete(); 57 super.tearDown(); 58 } 59 isPerformanceOnly()60 public boolean isPerformanceOnly() { 61 return false; 62 } 63 64 // These test can only be run once. startPerformance(Intermediates intermediates)65 public int startPerformance(Intermediates intermediates) { 66 return 1; 67 } 68 populateDefaultTable()69 private void populateDefaultTable() { 70 mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); 71 72 mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString1 + "');"); 73 mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString2 + "');"); 74 mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString3 + "');"); 75 } 76 77 @MediumTest testExecuteStatement()78 public void testExecuteStatement() throws Exception { 79 populateDefaultTable(); 80 SQLiteStatement statement = mDatabase.compileStatement("DELETE FROM test"); 81 statement.execute(); 82 83 Cursor c = mDatabase.query("test", null, null, null, null, null, null); 84 assertEquals(0, c.getCount()); 85 c.deactivate(); 86 statement.close(); 87 } 88 89 @MediumTest testSimpleQuery()90 public void testSimpleQuery() throws Exception { 91 mDatabase.execSQL("CREATE TABLE test (num INTEGER NOT NULL, str TEXT NOT NULL);"); 92 mDatabase.execSQL("INSERT INTO test VALUES (1234, 'hello');"); 93 SQLiteStatement statement1 = 94 mDatabase.compileStatement("SELECT num FROM test WHERE str = ?"); 95 SQLiteStatement statement2 = 96 mDatabase.compileStatement("SELECT str FROM test WHERE num = ?"); 97 98 try { 99 statement1.bindString(1, "hello"); 100 long value = statement1.simpleQueryForLong(); 101 assertEquals(1234, value); 102 103 statement1.bindString(1, "world"); 104 statement1.simpleQueryForLong(); 105 fail("shouldn't get here"); 106 } catch (SQLiteDoneException e) { 107 // expected 108 } 109 110 try { 111 statement2.bindLong(1, 1234); 112 String value = statement1.simpleQueryForString(); 113 assertEquals("hello", value); 114 115 statement2.bindLong(1, 5678); 116 statement1.simpleQueryForString(); 117 fail("shouldn't get here"); 118 } catch (SQLiteDoneException e) { 119 // expected 120 } 121 122 statement1.close(); 123 statement2.close(); 124 } 125 126 @MediumTest testStatementLongBinding()127 public void testStatementLongBinding() throws Exception { 128 mDatabase.execSQL("CREATE TABLE test (num INTEGER);"); 129 SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)"); 130 131 for (int i = 0; i < 10; i++) { 132 statement.bindLong(1, i); 133 statement.execute(); 134 } 135 statement.close(); 136 137 Cursor c = mDatabase.query("test", null, null, null, null, null, null); 138 int numCol = c.getColumnIndexOrThrow("num"); 139 c.moveToFirst(); 140 for (long i = 0; i < 10; i++) { 141 long num = c.getLong(numCol); 142 assertEquals(i, num); 143 c.moveToNext(); 144 } 145 c.close(); 146 } 147 148 @MediumTest testStatementStringBinding()149 public void testStatementStringBinding() throws Exception { 150 mDatabase.execSQL("CREATE TABLE test (num TEXT);"); 151 SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)"); 152 153 for (long i = 0; i < 10; i++) { 154 statement.bindString(1, Long.toHexString(i)); 155 statement.execute(); 156 } 157 statement.close(); 158 159 Cursor c = mDatabase.query("test", null, null, null, null, null, null); 160 int numCol = c.getColumnIndexOrThrow("num"); 161 c.moveToFirst(); 162 for (long i = 0; i < 10; i++) { 163 String num = c.getString(numCol); 164 assertEquals(Long.toHexString(i), num); 165 c.moveToNext(); 166 } 167 c.close(); 168 } 169 170 @MediumTest testStatementClearBindings()171 public void testStatementClearBindings() throws Exception { 172 mDatabase.execSQL("CREATE TABLE test (num INTEGER);"); 173 SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)"); 174 175 for (long i = 0; i < 10; i++) { 176 statement.bindLong(1, i); 177 statement.clearBindings(); 178 statement.execute(); 179 } 180 statement.close(); 181 182 Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID"); 183 int numCol = c.getColumnIndexOrThrow("num"); 184 assertTrue(c.moveToFirst()); 185 for (long i = 0; i < 10; i++) { 186 assertTrue(c.isNull(numCol)); 187 c.moveToNext(); 188 } 189 c.close(); 190 } 191 192 @MediumTest testSimpleStringBinding()193 public void testSimpleStringBinding() throws Exception { 194 mDatabase.execSQL("CREATE TABLE test (num TEXT, value TEXT);"); 195 String statement = "INSERT INTO test (num, value) VALUES (?,?)"; 196 197 String[] args = new String[2]; 198 for (int i = 0; i < 2; i++) { 199 args[i] = Integer.toHexString(i); 200 } 201 202 mDatabase.execSQL(statement, args); 203 204 Cursor c = mDatabase.query("test", null, null, null, null, null, null); 205 int numCol = c.getColumnIndexOrThrow("num"); 206 int valCol = c.getColumnIndexOrThrow("value"); 207 c.moveToFirst(); 208 String num = c.getString(numCol); 209 assertEquals(Integer.toHexString(0), num); 210 211 String val = c.getString(valCol); 212 assertEquals(Integer.toHexString(1), val); 213 c.close(); 214 } 215 216 @MediumTest testStatementMultipleBindings()217 public void testStatementMultipleBindings() throws Exception { 218 mDatabase.execSQL("CREATE TABLE test (num INTEGER, str TEXT);"); 219 SQLiteStatement statement = 220 mDatabase.compileStatement("INSERT INTO test (num, str) VALUES (?, ?)"); 221 222 for (long i = 0; i < 10; i++) { 223 statement.bindLong(1, i); 224 statement.bindString(2, Long.toHexString(i)); 225 statement.execute(); 226 } 227 statement.close(); 228 229 Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID"); 230 int numCol = c.getColumnIndexOrThrow("num"); 231 int strCol = c.getColumnIndexOrThrow("str"); 232 assertTrue(c.moveToFirst()); 233 for (long i = 0; i < 10; i++) { 234 long num = c.getLong(numCol); 235 String str = c.getString(strCol); 236 assertEquals(i, num); 237 assertEquals(Long.toHexString(i), str); 238 c.moveToNext(); 239 } 240 c.close(); 241 } 242 243 private static class StatementTestThread extends Thread { 244 private SQLiteDatabase mDatabase; 245 private SQLiteStatement mStatement; 246 StatementTestThread(SQLiteDatabase db, SQLiteStatement statement)247 public StatementTestThread(SQLiteDatabase db, SQLiteStatement statement) { 248 super(); 249 mDatabase = db; 250 mStatement = statement; 251 } 252 253 @Override run()254 public void run() { 255 mDatabase.beginTransaction(); 256 for (long i = 0; i < 10; i++) { 257 mStatement.bindLong(1, i); 258 mStatement.bindString(2, Long.toHexString(i)); 259 mStatement.execute(); 260 } 261 mDatabase.setTransactionSuccessful(); 262 mDatabase.endTransaction(); 263 264 Cursor c = mDatabase.query("test", null, null, null, null, null, "ROWID"); 265 int numCol = c.getColumnIndexOrThrow("num"); 266 int strCol = c.getColumnIndexOrThrow("str"); 267 assertTrue(c.moveToFirst()); 268 for (long i = 0; i < 10; i++) { 269 long num = c.getLong(numCol); 270 String str = c.getString(strCol); 271 assertEquals(i, num); 272 assertEquals(Long.toHexString(i), str); 273 c.moveToNext(); 274 } 275 c.close(); 276 } 277 } 278 279 @MediumTest testStatementMultiThreaded()280 public void testStatementMultiThreaded() throws Exception { 281 mDatabase.execSQL("CREATE TABLE test (num INTEGER, str TEXT);"); 282 SQLiteStatement statement = 283 mDatabase.compileStatement("INSERT INTO test (num, str) VALUES (?, ?)"); 284 285 StatementTestThread thread = new StatementTestThread(mDatabase, statement); 286 thread.start(); 287 try { 288 thread.join(); 289 } finally { 290 statement.close(); 291 } 292 } 293 294 @MediumTest testStatementConstraint()295 public void testStatementConstraint() throws Exception { 296 mDatabase.execSQL("CREATE TABLE test (num INTEGER NOT NULL);"); 297 SQLiteStatement statement = mDatabase.compileStatement("INSERT INTO test (num) VALUES (?)"); 298 299 // Try to insert NULL, which violates the constraint 300 try { 301 statement.clearBindings(); 302 statement.execute(); 303 fail("expected exception not thrown"); 304 } catch (SQLiteConstraintException e) { 305 // expected 306 } 307 308 // Make sure the statement can still be used 309 statement.bindLong(1, 1); 310 statement.execute(); 311 statement.close(); 312 313 Cursor c = mDatabase.query("test", null, null, null, null, null, null); 314 int numCol = c.getColumnIndexOrThrow("num"); 315 c.moveToFirst(); 316 long num = c.getLong(numCol); 317 assertEquals(1, num); 318 c.close(); 319 } 320 } 321