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