1/* 2 * Copyright (C) 2006 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 android.database.sqlite; 18 19import android.content.Context; 20import android.test.AndroidTestCase; 21import android.test.FlakyTest; 22import android.test.suitebuilder.annotation.LargeTest; 23 24import java.io.File; 25 26public class SQLiteGeneralTest extends AndroidTestCase { 27 28 private SQLiteDatabase mDatabase; 29 private File mDatabaseFile; 30 Boolean exceptionRecvd = false; 31 32 @Override 33 protected void setUp() throws Exception { 34 super.setUp(); 35 exceptionRecvd = false; 36 File dbDir = getContext().getDir(this.getClass().getName(), Context.MODE_PRIVATE); 37 mDatabaseFile = new File(dbDir, "database_test.db"); 38 if (mDatabaseFile.exists()) { 39 mDatabaseFile.delete(); 40 } 41 mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null); 42 assertNotNull(mDatabase); 43 } 44 45 @Override 46 protected void tearDown() throws Exception { 47 mDatabase.close(); 48 mDatabaseFile.delete(); 49 super.tearDown(); 50 } 51 52 @LargeTest 53 public void testUseOfSameSqlStatementBy2Threads() throws Exception { 54 mDatabase.execSQL("CREATE TABLE test_pstmt (i INTEGER PRIMARY KEY, j text);"); 55 56 // thread 1 creates a prepared statement 57 final String stmt = "SELECT * FROM test_pstmt WHERE i = ?"; 58 59 // start 2 threads to do repeatedly execute "stmt" 60 // since these 2 threads are executing the same sql, they each should get 61 // their own copy and 62 // there SHOULD NOT be an error from sqlite: "prepared statement is busy" 63 class RunStmtThread extends Thread { 64 private static final int N = 1000; 65 @Override public void run() { 66 int i = 0; 67 try { 68 // execute many times 69 for (i = 0; i < N; i++) { 70 SQLiteStatement s1 = mDatabase.compileStatement(stmt); 71 s1.bindLong(1, i); 72 s1.execute(); 73 s1.close(); 74 } 75 } catch (SQLiteException e) { 76 fail("SQLiteException: " + e.getMessage()); 77 return; 78 } catch (Exception e) { 79 e.printStackTrace(); 80 fail("random unexpected exception: " + e.getMessage()); 81 return; 82 } 83 } 84 } 85 RunStmtThread t1 = new RunStmtThread(); 86 t1.start(); 87 RunStmtThread t2 = new RunStmtThread(); 88 t2.start(); 89 while (t1.isAlive() || t2.isAlive()) { 90 Thread.sleep(1000); 91 } 92 } 93 94 @FlakyTest 95 public void testUseOfSamePreparedStatementBy2Threads() throws Exception { 96 mDatabase.execSQL("CREATE TABLE test_pstmt (i INTEGER PRIMARY KEY, j text);"); 97 98 // thread 1 creates a prepared statement 99 final String stmt = "SELECT * FROM test_pstmt WHERE i = ?"; 100 final SQLiteStatement s1 = mDatabase.compileStatement(stmt); 101 102 // start 2 threads to do repeatedly execute "stmt" 103 // since these 2 threads are executing the same prepared statement, 104 // should see an error from sqlite: "prepared statement is busy" 105 class RunStmtThread extends Thread { 106 private static final int N = 1000; 107 @Override public void run() { 108 int i = 0; 109 try { 110 // execute many times 111 for (i = 0; i < N; i++) { 112 s1.bindLong(1, i); 113 s1.execute(); 114 } 115 } catch (SQLiteException e) { 116 // expect it 117 assertTrue(e.getMessage().contains("library routine called out of sequence:")); 118 exceptionRecvd = true; 119 return; 120 } catch (Exception e) { 121 e.printStackTrace(); 122 fail("random unexpected exception: " + e.getMessage()); 123 return; 124 } 125 } 126 } 127 RunStmtThread t1 = new RunStmtThread(); 128 t1.start(); 129 RunStmtThread t2 = new RunStmtThread(); 130 t2.start(); 131 while (t1.isAlive() || t2.isAlive()) { 132 Thread.sleep(1000); 133 } 134 assertTrue(exceptionRecvd); 135 } 136} 137