blob: 8b80690a67ecf7b26c2efe6bc268a5bf49c7943c [file] [log] [blame]
/*
* 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 dalvik.annotation.BrokenTest;
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetNew;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.Vector;
import java.util.logging.Logger;
import tests.support.DatabaseCreator;
import tests.support.Support_SQL;
import tests.support.ThreadPool;
import junit.framework.TestCase;
@TestTargetClass(Statement.class)
public class StressTest extends TestCase {
Vector<Connection> vc = new Vector<Connection>();
private static Connection conn;
private static Statement statement;
public void setUp() throws Exception {
super.setUp();
Support_SQL.loadDriver();
conn = Support_SQL.getConnection();
statement = conn.createStatement();
createTestTables();
vc.clear();
}
protected void tearDown() throws Exception {
closeConnections();
statement.close();
conn.close();
super.tearDown();
}
private void createTestTables() {
try {
DatabaseMetaData meta = conn.getMetaData();
ResultSet userTab = meta.getTables(null, null, null, null);
while (userTab.next()) {
String tableName = userTab.getString("TABLE_NAME");
if (tableName.equals(DatabaseCreator.TEST_TABLE2)) {
statement.execute(DatabaseCreator.DROP_TABLE2);
}
}
statement.execute(DatabaseCreator.CREATE_TABLE2);
} catch (SQLException sql) {
fail("Unexpected SQLException " + sql.toString());
}
return;
}
private void dropTestTables() {
try {
statement.execute(DatabaseCreator.DROP_TABLE2);
} catch (SQLException sql) {
fail("Unexpected SQLException " + sql.toString());
}
return;
}
// /**
// * @see junit.framework.TestCase#setUp()
// */
// @Override
// protected void setUp() throws Exception {
// super.setUp();
// vc.clear();
// }
//
// /**
// * @see junit.framework.TestCase#tearDown()
// */
// @Override
// protected void tearDown() throws Exception {
// closeConnections();
// statement.execute("DELETE FROM " + DatabaseCreator.TEST_TABLE2);
// super.tearDown();
// }
/**
* @tests StressTest#testManyConnectionsUsingOneThread(). Create many
* connections to the DataBase using one thread.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
method = "connect",
clazz = Driver.class,
args = {String.class, Properties.class}
)
public void testManyConnectionsUsingOneThread() {
try {
int maxConnections = getConnectionNum();
openConnections(maxConnections);
assertEquals("Incorrect number of created connections",
maxConnections, vc.size());
} catch (Exception e) {
fail("Unexpected Exception " + e.toString());
}
}
/**
* @tests StressTest#testManyConnectionsUsingManyThreads(). Create many
* connections to the DataBase using some threads.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "Stress test: Create many connections to the DataBase using some threads",
method = "connect",
clazz = Driver.class,
args = {String.class, Properties.class}
)
public void testManyConnectionsUsingManyThreads() {
int numTasks = getConnectionNum();
ThreadPool threadPool = new ThreadPool(numTasks);
// run example tasks
for (int i = 0; i < numTasks; i++) {
threadPool.runTask(createTask(i));
}
// close the pool and wait for all tasks to finish.
threadPool.join();
assertEquals("Unable to create a connection", numTasks, vc.size());
if (numTasks != Support_SQL.sqlMaxConnections) {
try {
// try to create connection n + 1
Connection c = Support_SQL.getConnection();
c.close();
fail("It is possible to create more than " + numTasks
+ "connections");
} catch (SQLException sql) {
// expected
}
}
}
/**
* @tests StressTest#testInsertOfManyRowsUsingOneThread(). Insert a lot of
* records to the Database using a maximum number of connections.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
method = "connect",
clazz = Driver.class,
args = {String.class, Properties.class}
)
public void testInsertOfManyRowsUsingOneThread() {
Logger.global
.info("java.sql stress test: single thread and many operations.");
int maxConnections = getConnectionNum();
Logger.global.info("Opening " + maxConnections + " to database "
+ Support_SQL.getFilename());
openConnections(maxConnections);
int tasksPerConnection = Support_SQL.sqlMaxTasks / maxConnections;
Logger.global.info("TasksPerConnection = " + Support_SQL.sqlMaxTasks
+ " by (maxConnections) " + maxConnections + " = "
+ tasksPerConnection);
int pk = 1;
for (int i = 0; i < vc.size(); ++i) {
Logger.global.info(" creating " + tasksPerConnection
+ "tasks for Connection " + i);
Connection c = vc.elementAt(i);
for (int j = 0; j < tasksPerConnection; ++j) {
insertNewRecord(c, pk++);
}
}
try {
ResultSet rs = statement
.executeQuery("SELECT COUNT(*) as counter FROM "
+ DatabaseCreator.TEST_TABLE2);
assertTrue("RecordSet is empty", rs.next());
assertEquals("Incorrect number of records", tasksPerConnection
* maxConnections, rs.getInt("counter"));
rs.close();
} catch (SQLException sql) {
fail("Unexpected SQLException " + sql.toString());
}
}
/**
* @tests
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
method = "connect",
clazz = Driver.class,
args = {String.class, Properties.class}
)
@BrokenTest("2191557 ReferenceTable overflow")
public void testInsertOfManyRowsUsingManyThreads() {
Logger.global.info("java.sql stress test: multiple threads and many operations.");
int numConnections = getConnectionNum();
int tasksPerConnection = Support_SQL.sqlMaxTasks / numConnections;
Logger.global.info("Opening "+numConnections+" to database "+Support_SQL.getFilename());
ThreadPool threadPool = new ThreadPool(numConnections);
for (int i = 0; i < numConnections; ++i) {
Logger.global.info(" creating "+tasksPerConnection+ " tasks for Connection "+i);
threadPool.runTask(insertTask(numConnections, i));
}
// close the pool and wait for all tasks to finish.
threadPool.join();
assertEquals("Unable to create a connection", numConnections, vc.size());
try {
ResultSet rs = statement
.executeQuery("SELECT COUNT(*) as counter FROM "
+ DatabaseCreator.TEST_TABLE2);
assertTrue("RecordSet is empty", rs.next());
assertEquals("Incorrect number of records", tasksPerConnection
* numConnections, rs.getInt("counter"));
rs.close();
} catch (SQLException sql) {
fail("Unexpected SQLException " + sql.toString());
}
}
private int getConnectionNum() {
int num = Support_SQL.sqlMaxConnections;
try {
int mc = conn.getMetaData().getMaxConnections();
if (mc != 0) {
if (num != mc) {
System.err.println("Will be used no more than " + mc
+ " connections to the DataBase");
}
num = mc;
}
} catch (SQLException sql) {
fail("Unexpected SQLException " + sql.toString());
}
return num;
}
private void openConnections(int maxConnections) {
int i = 0;
try {
for (; i < maxConnections; ++i) {
Connection c = Support_SQL.getConnection();
if (c == null) {
assertEquals("Unable to create a connection",
maxConnections, i);
}
vc.add(c);
}
} catch (SQLException sql) {
assertEquals("Unable to create a connection", maxConnections, i);
}
return;
}
private void closeConnections() {
int i = 0;
try {
for (; i < vc.size(); ++i) {
vc.elementAt(i).close();
}
} catch (SQLException sql) {
assertEquals("Unable to close a connection", vc.size(), i);
}
return;
}
private Runnable createTask(final int taskID) {
return new Runnable() {
public void run() {
try {
Connection c = Support_SQL.getConnection();
if (c == null) {
return;
}
synchronized (this) {
vc.add(c);
}
} catch (SQLException sql) {
// nothing to do
}
}
};
}
private Runnable insertTask(final int numConnections, final int taskID) {
return new Runnable() {
public void run() {
try {
Connection c = Support_SQL.getConnection();
if (c == null) {
return;
}
synchronized (this) {
vc.add(c);
}
int tasksPerConnection = Support_SQL.sqlMaxTasks
/ numConnections;
for (int i = 0; i < tasksPerConnection; ++i) {
insertNewRecord(c, (i + 1) + tasksPerConnection
* taskID);
}
} catch (SQLException sql) {
// do nothing
}
}
};
}
private void insertNewRecord(Connection c, int pk) {
String query = "INSERT INTO " + DatabaseCreator.TEST_TABLE2
+ "(finteger, ftext, fcharacter, fdecimal, fnumeric,"
+ " fsmallint, ffloat, freal, fdouble, fdate, ftime)"
+ " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
try {
PreparedStatement ps = c.prepareStatement(query);
ps.setInt(1, pk);
ps.setString(2, "text");
ps.setString(3, "chr");
ps.setFloat(4, 0.1f);
ps.setFloat(5, 0.2f);
ps.setShort(6, (short) 3);
ps.setFloat(7, 0.4f);
ps.setDouble(8, 0.5);
ps.setDouble(9, 0.6);
ps.setDate(10, new java.sql.Date(System.currentTimeMillis()));
ps.setTime(11, new java.sql.Time(System.currentTimeMillis()));
ps.execute();
ps.close();
} catch (SQLException sql) {
fail("Unexpected SQLException " + sql.toString());
}
return;
}
}