Home | History | Annotate | Download | only in sqlite
      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 
     17 package android.database.sqlite;
     18 
     19 import android.content.Context;
     20 import android.test.AndroidTestCase;
     21 import android.test.FlakyTest;
     22 import android.test.suitebuilder.annotation.LargeTest;
     23 
     24 import java.io.File;
     25 
     26 public 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