Home | History | Annotate | Download | only in SQLite
      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 
     18 package tests.SQLite;
     19 
     20 import SQLite.Callback;
     21 import SQLite.Database;
     22 import SQLite.Exception;
     23 import dalvik.annotation.TestLevel;
     24 import dalvik.annotation.TestTargetClass;
     25 import dalvik.annotation.TestTargetNew;
     26 
     27 import junit.framework.TestCase;
     28 
     29 import java.sql.Connection;
     30 import java.sql.DriverManager;
     31 import java.sql.ResultSet;
     32 import java.sql.SQLException;
     33 import java.sql.Statement;
     34 
     35 
     36 /**
     37  * This class provides SQL unit test, which can be used by subclasses eg. to
     38  * test JDBC drivers.
     39  */
     40 @TestTargetClass(Database.class)
     41 abstract class AbstractSqlTest extends TestCase {
     42 
     43     /**
     44      * The first connection.
     45      */
     46     private Connection firstConnection;
     47 
     48     /**
     49      * The second connection.
     50      */
     51     private Connection secondConnection;
     52 
     53     /**
     54      * The statement from the first connection.
     55      */
     56     private Statement firstStmt;
     57 
     58     /**
     59      * The statement from the second connection.
     60      */
     61     private Statement secondStmt;
     62 
     63     /**
     64      * The values of the first column "one".
     65      */
     66     private final String[] ones = {"hello!", "goodbye"};
     67 
     68     /**
     69      * The values of the second column "two".
     70      */
     71     private final short[] twos = {10, 20};
     72 
     73     /**
     74      * The updated values of the first column "one".
     75      */
     76     private final String[] ones_updated;
     77 
     78     /** Creates a new instance of this class */
     79     public AbstractSqlTest() {
     80         super();
     81         ones_updated = new String[ones.length];
     82         for (int i = 0; i < ones.length; i++) {
     83             ones_updated[i] = ones[i] + twos[i];
     84         }
     85     }
     86 
     87     /**
     88      * Sets up a unit test, by creating two statements from two connections and
     89      * creating a test table.
     90      *
     91      * @exception SQLException if there is a problem accessing the database
     92      * @throws Exception
     93      * @exception Exception may be thrown by subclasses
     94      */
     95     @Override
     96     protected void setUp() throws InstantiationException,
     97             IllegalAccessException, ClassNotFoundException, SQLException, Exception {
     98         Class.forName(getDriverClassName()).newInstance();
     99         firstConnection = DriverManager.getConnection(getConnectionURL());
    100         firstConnection.setTransactionIsolation(getTransactionIsolation());
    101         secondConnection = DriverManager.getConnection(getConnectionURL());
    102         secondConnection.setTransactionIsolation(getTransactionIsolation());
    103         firstStmt = firstConnection.createStatement();
    104         firstStmt.execute("create table tbl1(one varchar(10), two smallint)");
    105         secondStmt = secondConnection.createStatement();
    106     }
    107 
    108     /**
    109      * Tears down a unit test, by setting the auto commit property of the first
    110      * connection back to true, dropping the test table and closing the two
    111      * connections.
    112      */
    113     @Override
    114     protected void tearDown() throws SQLException {
    115         firstStmt.close();
    116         secondStmt.close();
    117         firstConnection.setAutoCommit(true);
    118         firstStmt = firstConnection.createStatement();
    119         firstStmt.execute("drop table tbl1");
    120         firstStmt.close();
    121         firstConnection.close();
    122         secondConnection.close();
    123     }
    124 
    125     /**
    126      * Adds some rows to the test table and asserts that the rows can be
    127      * retrieved again.
    128      *
    129      * @throws SQLException if there is a problem accessing the database
    130      */
    131     private void autoCommitInsertSelect() throws SQLException {
    132         firstStmt.getConnection().setAutoCommit(true);
    133         for (int i = 0; i < ones.length; i++) {
    134             firstStmt.execute("insert into tbl1 values('" + ones[i] + "',"
    135                     + twos[i] + ")");
    136         }
    137         assertAllFromTbl1(firstStmt, ones, twos);
    138     }
    139 
    140     /**
    141      * Asserts that the expected values can be selected from the test table.
    142      *
    143      * @param stmt the statement to be used for the selection of the data
    144      * @param ones the expected values of the column 'one'
    145      * @param twos the expected values of the column 'two'
    146      * @throws SQLException if there is a problem accessing the database
    147      */
    148     private void assertAllFromTbl1(Statement stmt, String[] ones, short[] twos)
    149             throws SQLException {
    150         ResultSet rs = stmt.executeQuery("select * from tbl1");
    151         int i = 0;
    152         for (; rs.next(); i++) {
    153             assertTrue(i < ones.length);
    154             assertEquals(ones[i], rs.getString("one"));
    155             assertEquals(twos[i], rs.getShort("two"));
    156         }
    157         assertTrue(i == ones.length);
    158     }
    159 
    160     @TestTargetNew(
    161       level = TestLevel.PARTIAL_COMPLETE,
    162       notes = "",
    163       clazz = Database.class,
    164       method = "exec",
    165       args = {String.class, Callback.class}
    166     )
    167     public void testAutoCommitInsertSelect() throws SQLException{
    168         autoCommitInsertSelect();
    169     }
    170 
    171     /**
    172      * Tests the following sequence after successful insertion of some test
    173      * data:
    174      * - update data from connection one
    175      * - select data from connection two (-> should have the old values)
    176      * - commit data from connection one
    177      * - select data from connection two (-> should have the new values)
    178      *
    179      * @throws SQLException if there is a problem accessing the database
    180      */
    181     @TestTargetNew(
    182       level = TestLevel.PARTIAL_COMPLETE,
    183       notes = "",
    184       clazz = Database.class,
    185       method = "exec",
    186       args = {String.class, Callback.class}
    187       )
    188     public void testUpdateSelectCommitSelect() throws SQLException {
    189         autoCommitInsertSelect();
    190         firstStmt.getConnection().setAutoCommit(false);
    191         updateOnes(firstStmt, ones_updated, twos);
    192         assertAllFromTbl1(secondStmt, ones, twos);
    193         firstStmt.getConnection().commit();
    194         assertAllFromTbl1(secondStmt, ones_updated, twos);
    195     }
    196 
    197     /**
    198      * Tests the following sequence after successful insertion of some test
    199      * data:
    200      * - update data from connection one
    201      * - select data from connection two (-> should have the old values)
    202      * - rollback data from connection one
    203      * - select data from connection two (-> should still have the old values)
    204      *
    205      * @throws SQLException if there is a problem accessing the database
    206      */
    207     @TestTargetNew(
    208             level = TestLevel.PARTIAL_COMPLETE,
    209             notes = "",
    210             clazz = Database.class,
    211             method = "exec",
    212             args = {String.class, Callback.class}
    213     )
    214     public void testUpdateSelectRollbackSelect() throws SQLException {
    215         autoCommitInsertSelect();
    216         firstStmt.getConnection().setAutoCommit(false);
    217         updateOnes(firstStmt, ones_updated, twos);
    218         assertAllFromTbl1(secondStmt, ones, twos);
    219         firstStmt.getConnection().rollback();
    220         assertAllFromTbl1(secondStmt, ones, twos);
    221     }
    222 
    223     /**
    224      * Updates the values in column 'one'
    225      * @param stmt the statement to be used to update the data
    226      * @param ones_updated the updated valus of column 'one'
    227      * @param twos the reference values of column 'two'
    228      * @throws SQLException if there is a problem accessing the database
    229      */
    230     private void updateOnes(Statement stmt, String[] ones_updated, short[] twos)
    231             throws SQLException {
    232         for (int i = 0; i < ones_updated.length; i++) {
    233             stmt.execute("UPDATE tbl1 SET one = '" + ones_updated[i]
    234                     + "' WHERE two = " + twos[i]);
    235         }
    236     }
    237 
    238     protected abstract String getConnectionURL();
    239 
    240     protected abstract String getDriverClassName();
    241 
    242     protected abstract int getTransactionIsolation();
    243 
    244 }
    245