/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package tests.java.sql; import java.math.BigDecimal; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import tests.support.DatabaseCreator; import tests.support.Support_SQL; import junit.extensions.TestSetup; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import tests.support.ThreadPool; public class MultiThreadAccessTest extends TestCase { private static Connection conn; private static Statement statement; private static final int numThreads = 10; private static final int numOfRecords = 20; private ThreadPool threadPool; public void setUp() throws Exception { super.setUp(); Support_SQL.loadDriver(); try { conn = Support_SQL.getConnection(); statement = conn.createStatement(); createTestTables(); } catch (SQLException e) { fail("Unexpected SQLException " + e.toString()); } threadPool = new ThreadPool(numThreads); } public void tearDown() throws Exception { threadPool.join(); deleteTestTables(); conn.close(); statement.close(); super.tearDown(); } public void createTestTables() { try { ResultSet userTab = conn.getMetaData().getTables(null, null, null, null); while (userTab.next()) { String tableName = userTab.getString("TABLE_NAME"); if (tableName.equals(DatabaseCreator.TEST_TABLE1)) { statement.execute(DatabaseCreator.DROP_TABLE1); } else if (tableName .equals(DatabaseCreator.TEST_TABLE2)) { statement.execute(DatabaseCreator.DROP_TABLE2); } else if (tableName .equals(DatabaseCreator.TEST_TABLE4)) { statement.execute(DatabaseCreator.DROP_TABLE4); } else if (tableName .equals(DatabaseCreator.TEST_TABLE3)) { statement.execute(DatabaseCreator.DROP_TABLE3); } } userTab.close(); statement.execute(DatabaseCreator.CREATE_TABLE3); statement.execute(DatabaseCreator.CREATE_TABLE4); statement.execute(DatabaseCreator.CREATE_TABLE1); statement.execute(DatabaseCreator.CREATE_TABLE2); DatabaseCreator.fillTestTable1(conn, numOfRecords); DatabaseCreator.fillTestTable2(conn, numOfRecords); DatabaseCreator.fillTestTable4(conn, numOfRecords); } catch (SQLException e) { fail("Unexpected SQLException " + e.toString()); } } public void deleteTestTables() { try { statement.execute(DatabaseCreator.DROP_TABLE1); statement.execute(DatabaseCreator.DROP_TABLE2); statement.execute(DatabaseCreator.DROP_TABLE3); statement.execute(DatabaseCreator.DROP_TABLE4); } catch (SQLException e) { fail("Unexpected SQLException " + e.toString()); } } /** * A few threads execute select operation in the same time for one table in * the database. Number of threads is defined by numThreads variable * * @throws SQLException */ public void test_MultipleAccessToOneTable() throws SQLException { for (int i = 0; i < numThreads; i++) { threadPool.runTask(createTask1(i)); } } /** * A few threads execute select operation in the same time for different * tables in the database. Number of threads is defined by numThreads * variable * * @throws SQLException */ public void test_MultipleAccessToSeveralTables() throws SQLException { threadPool.runTask(createTask1(1)); threadPool.runTask(createTask2(2)); threadPool.runTask(createTask3(3)); } /** * A few threads execute update, insert and delete operations in the same * time for one table in the database. Number of threads is defined by * numThreads variable * * @throws SQLException */ public void test_MultipleOperationsInSeveralTables() throws SQLException { int id1 = numOfRecords - 1; threadPool.runTask(createTask4(id1)); int id2 = numOfRecords + 1; threadPool.runTask(createTask5(id2)); int oldID = 5; int newID = 100; threadPool.runTask(createTask6(oldID, newID)); threadPool.join(); Statement statement = conn.createStatement(); String selectQuery = "SELECT * FROM " + DatabaseCreator.TEST_TABLE1 + " WHERE id="; ResultSet result = statement.executeQuery(selectQuery + id1); assertFalse("The record was not deleted", result.next()); result = statement.executeQuery(selectQuery + id2); assertTrue("The record was not inserted", result.next()); assertEquals("Wrong value of field1", DatabaseCreator.defaultString + id2, result.getString("field1")); // TODO getBigDecimal is not supported assertEquals("Wrong value of field2", Integer.valueOf(id2).intValue(), result .getInt("field2")); assertEquals("Wrong value of field3", Integer.valueOf(id2).intValue(), result .getInt("field3")); result.close(); result = statement.executeQuery(selectQuery + oldID); assertFalse("The record was not deleted", result.next()); result.close(); result = statement.executeQuery(selectQuery + newID); assertTrue("The record was not updated", result.next()); assertEquals("Wrong value of field1", DatabaseCreator.defaultString + newID, result.getString("field1")); // TODO getBigDecimal is not supported assertEquals("Wrong value of field2", Integer.valueOf(newID).intValue(), result .getInt("field2")); assertEquals("Wrong value of field3", Integer.valueOf(newID).intValue(), result .getInt("field3")); result.close(); } /** * A few threads execute update operation in the same time for one tables in * the database. Number of threads is defined by numThreads variable * * @throws SQLException */ public void test_MultipleUpdatesInOneTables() throws SQLException { int id = 1; String field = "field3"; String selectQuery = "SELECT * FROM " + DatabaseCreator.TEST_TABLE1 + " WHERE id=" + id; Statement statement = conn.createStatement(); ResultSet result = statement.executeQuery(selectQuery); assertTrue("There is no records with id = " + id, result.next()); // TODO getBigDecimal is not supported // assertEquals("Wrong value of field " + field, BigDecimal.valueOf(id), // result.getBigDecimal(field)); result.close(); for (int i = 0; i < numThreads; i++) { threadPool.runTask(createTask7(id, field)); } threadPool.join(); double expectedVal = id + numThreads; result = statement.executeQuery(selectQuery); assertTrue("There is no records with id = " + id, result.next()); // TODO getBigDecimal is not supported -> // assertEquals("Wrong value of field " + field, expectedVal, result // .getBigDecimal(field).doubleValue()); result.close(); } /** * This method creates a Runnable that executes select operation for the * first table * * @param taskID * @return */ private static Runnable createTask1(final int taskID) { return new Runnable() { public void run() { try { Statement statement = conn.createStatement(); ResultSet result = statement.executeQuery("SELECT * FROM " + DatabaseCreator.TEST_TABLE1); while (result.next()) { assertEquals("Wrong value of id ", DatabaseCreator.defaultString + result.getInt("id"), result .getString("field1")); assertEquals("Wrong value of field2 ", result.getInt("id"), result .getInt("field2")); assertEquals("Wrong value of field3 ",result.getInt("id"), result .getInt("field3")); } result.close(); } catch (Exception e) { System.err.println("Task 1 "+e.getMessage()); } } }; } /** * This method creates a Runnable that execute select operation for the * second table * * @param taskID */ private static Runnable createTask2(final int taskID) { return new Runnable() { public void run() { try { Statement statement = conn.createStatement(); ResultSet result = statement.executeQuery("SELECT * FROM " + DatabaseCreator.TEST_TABLE2); while (result.next()) { while (result.next()) { int id = result.getInt("finteger"); assertEquals("Wrong value of ftext", DatabaseCreator.defaultString + id, result .getString("ftext")); assertEquals("Wrong value of fcharacter", DatabaseCreator.defaultCharacter + id, result.getString("fcharacter")); assertEquals("Wrong value of fdecimal", DatabaseCreator.defaultDouble + id, result .getDouble("fdecimal")); assertEquals("Wrong value of fnumeric", DatabaseCreator.defaultDouble + id, result .getDouble("fnumeric")); assertEquals("Wrong value of fsmallint", result .getInt("finteger"), result .getShort("fsmallint")); assertEquals("Wrong value of ffloat", (float) DatabaseCreator.defaultDouble + id, result.getFloat("ffloat")); assertEquals("Wrong value of freal", (float) DatabaseCreator.defaultDouble + id, result.getFloat("freal")); assertEquals("Wrong value of fdouble", DatabaseCreator.defaultDouble + id, result .getDouble("fdouble")); } } result.close(); } catch (Exception e) { System.err.println("Task2 "+e.getMessage()); } } }; } /** * This method creates a Runnable that execute select operation for the * third table * * @param taskID */ private static Runnable createTask3(final int taskID) { return new Runnable() { public void run() { try { Statement statement = conn.createStatement(); ResultSet result = statement.executeQuery("SELECT * FROM " + DatabaseCreator.TEST_TABLE4); while (result.next()) { assertEquals("Wrong value of field1", DatabaseCreator.defaultString + result.getInt("fk"), result .getString("field1")); } result.close(); } catch (Exception e) { System.err.println("Task 3 "+e.getMessage()); } } }; } /** * This method creates a Runnable that executes delete operation for the * first table * * @param taskID */ private static Runnable createTask4(final int id) { return new Runnable() { public void run() { try { Statement statement = conn.createStatement(); statement.execute("DELETE FROM " + DatabaseCreator.TEST_TABLE1 + " WHERE id=" + id); } catch (Exception e) { System.err.println("Task 4 "+e.getMessage()); } } }; } /** * This method creates a Runnable that executes insert operation for the * first table * * @param taskID */ private static Runnable createTask5(final int id) { return new Runnable() { public void run() { try { Statement statement = conn.createStatement(); String value = DatabaseCreator.defaultString + id; String insertQuery = "INSERT INTO " + DatabaseCreator.TEST_TABLE1 + " (id, field1, field2, field3) VALUES(" + id + ", '" + value + "', " + id + ", " + id + ")"; statement.execute(insertQuery); } catch (Exception e) { System.err.println("Task 5 "+e.getMessage()); } } }; } /** * This method creates a Runnable that executes update operation for the one * record of the first table * * @param taskID */ private static Runnable createTask6(final int oldID, final int newID) { return new Runnable() { public void run() { try { Statement statement = conn.createStatement(); String value = DatabaseCreator.defaultString + newID; String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1 + " SET id=" + newID + ", field1='" + value + "', field2=" + newID + ", field3=" + newID + " WHERE id=" + oldID; statement.execute(updateQuery); } catch (Exception e) { System.err.println("Task 6 "+e.getMessage()); } } }; } /** * This method creates a Runnable that executes update operation for the one * field of one record with identifier id in the first table * * @param taskID */ private static Runnable createTask7(final int id, final String field) { return new Runnable() { public void run() { try { Statement statement = conn.createStatement(); String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1 + " SET " + field + "= " + field + "+ 1 WHERE id=" + id; statement.execute(updateQuery); } catch (Exception e) { System.err.println("Task 7 "+e.getMessage()); } } }; } }