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 package tests.java.sql; 18 19 import java.sql.Connection; 20 import java.sql.DatabaseMetaData; 21 import java.sql.Driver; 22 import java.sql.PreparedStatement; 23 import java.sql.ResultSet; 24 import java.sql.SQLException; 25 import java.sql.Statement; 26 import java.util.Properties; 27 import java.util.Vector; 28 import java.util.logging.Logger; 29 30 import tests.support.DatabaseCreator; 31 import tests.support.Support_SQL; 32 import tests.support.ThreadPool; 33 import junit.framework.TestCase; 34 35 public class StressTest extends TestCase { 36 Vector<Connection> vc = new Vector<Connection>(); 37 38 private static Connection conn; 39 40 private static Statement statement; 41 setUp()42 public void setUp() throws Exception { 43 super.setUp(); 44 Support_SQL.loadDriver(); 45 conn = Support_SQL.getConnection(); 46 statement = conn.createStatement(); 47 createTestTables(); 48 vc.clear(); 49 } 50 tearDown()51 protected void tearDown() throws Exception { 52 closeConnections(); 53 statement.close(); 54 conn.close(); 55 super.tearDown(); 56 } 57 createTestTables()58 private void createTestTables() { 59 try { 60 DatabaseMetaData meta = conn.getMetaData(); 61 ResultSet userTab = meta.getTables(null, null, null, null); 62 63 while (userTab.next()) { 64 String tableName = userTab.getString("TABLE_NAME"); 65 if (tableName.equals(DatabaseCreator.TEST_TABLE2)) { 66 statement.execute(DatabaseCreator.DROP_TABLE2); 67 } 68 } 69 statement.execute(DatabaseCreator.CREATE_TABLE2); 70 } catch (SQLException sql) { 71 fail("Unexpected SQLException " + sql.toString()); 72 } 73 return; 74 } 75 dropTestTables()76 private void dropTestTables() { 77 try { 78 statement.execute(DatabaseCreator.DROP_TABLE2); 79 } catch (SQLException sql) { 80 fail("Unexpected SQLException " + sql.toString()); 81 } 82 return; 83 } 84 85 // /** 86 // * @see junit.framework.TestCase#setUp() 87 // */ 88 // @Override 89 // protected void setUp() throws Exception { 90 // super.setUp(); 91 // vc.clear(); 92 // } 93 // 94 // /** 95 // * @see junit.framework.TestCase#tearDown() 96 // */ 97 // @Override 98 // protected void tearDown() throws Exception { 99 // closeConnections(); 100 // statement.execute("DELETE FROM " + DatabaseCreator.TEST_TABLE2); 101 // super.tearDown(); 102 // } 103 104 /** 105 * StressTest#testManyConnectionsUsingOneThread(). Create many 106 * connections to the DataBase using one thread. 107 */ testManyConnectionsUsingOneThread()108 public void testManyConnectionsUsingOneThread() { 109 try { 110 int maxConnections = getConnectionNum(); 111 openConnections(maxConnections); 112 assertEquals("Incorrect number of created connections", 113 maxConnections, vc.size()); 114 } catch (Exception e) { 115 fail("Unexpected Exception " + e.toString()); 116 } 117 } 118 119 /** 120 * StressTest#testManyConnectionsUsingManyThreads(). Create many 121 * connections to the DataBase using some threads. 122 */ testManyConnectionsUsingManyThreads()123 public void testManyConnectionsUsingManyThreads() { 124 int numTasks = getConnectionNum(); 125 126 ThreadPool threadPool = new ThreadPool(numTasks); 127 128 // run example tasks 129 for (int i = 0; i < numTasks; i++) { 130 threadPool.runTask(createTask(i)); 131 } 132 // close the pool and wait for all tasks to finish. 133 threadPool.join(); 134 assertEquals("Unable to create a connection", numTasks, vc.size()); 135 if (numTasks != Support_SQL.sqlMaxConnections) { 136 try { 137 // try to create connection n + 1 138 Connection c = Support_SQL.getConnection(); 139 c.close(); 140 fail("It is possible to create more than " + numTasks 141 + "connections"); 142 } catch (SQLException sql) { 143 // expected 144 } 145 } 146 } 147 148 /** 149 * StressTest#testInsertOfManyRowsUsingOneThread(). Insert a lot of 150 * records to the Database using a maximum number of connections. 151 */ testInsertOfManyRowsUsingOneThread()152 public void testInsertOfManyRowsUsingOneThread() { 153 154 Logger.global 155 .info("java.sql stress test: single thread and many operations."); 156 int maxConnections = getConnectionNum(); 157 Logger.global.info("Opening " + maxConnections + " to database " 158 + Support_SQL.getFilename()); 159 openConnections(maxConnections); 160 161 int tasksPerConnection = Support_SQL.sqlMaxTasks / maxConnections; 162 Logger.global.info("TasksPerConnection = " + Support_SQL.sqlMaxTasks 163 + " by (maxConnections) " + maxConnections + " = " 164 + tasksPerConnection); 165 int pk = 1; 166 for (int i = 0; i < vc.size(); ++i) { 167 Logger.global.info(" creating " + tasksPerConnection 168 + "tasks for Connection " + i); 169 Connection c = vc.elementAt(i); 170 for (int j = 0; j < tasksPerConnection; ++j) { 171 insertNewRecord(c, pk++); 172 } 173 } 174 try { 175 ResultSet rs = statement 176 .executeQuery("SELECT COUNT(*) as counter FROM " 177 + DatabaseCreator.TEST_TABLE2); 178 assertTrue("RecordSet is empty", rs.next()); 179 assertEquals("Incorrect number of records", tasksPerConnection 180 * maxConnections, rs.getInt("counter")); 181 rs.close(); 182 } catch (SQLException sql) { 183 fail("Unexpected SQLException " + sql.toString()); 184 } 185 186 } 187 188 /** 189 * @tests 190 */ testInsertOfManyRowsUsingManyThreads()191 public void testInsertOfManyRowsUsingManyThreads() { 192 Logger.global.info("java.sql stress test: multiple threads and many operations."); 193 194 int numConnections = getConnectionNum(); 195 int tasksPerConnection = Support_SQL.sqlMaxTasks / numConnections; 196 197 Logger.global.info("Opening "+numConnections+" to database "+Support_SQL.getFilename()); 198 199 ThreadPool threadPool = new ThreadPool(numConnections); 200 201 for (int i = 0; i < numConnections; ++i) { 202 Logger.global.info(" creating "+tasksPerConnection+ " tasks for Connection "+i); 203 threadPool.runTask(insertTask(numConnections, i)); 204 } 205 // close the pool and wait for all tasks to finish. 206 threadPool.join(); 207 assertEquals("Unable to create a connection", numConnections, vc.size()); 208 209 try { 210 ResultSet rs = statement 211 .executeQuery("SELECT COUNT(*) as counter FROM " 212 + DatabaseCreator.TEST_TABLE2); 213 assertTrue("RecordSet is empty", rs.next()); 214 215 216 assertEquals("Incorrect number of records", tasksPerConnection 217 * numConnections, rs.getInt("counter")); 218 rs.close(); 219 } catch (SQLException sql) { 220 fail("Unexpected SQLException " + sql.toString()); 221 222 } 223 224 } 225 getConnectionNum()226 private int getConnectionNum() { 227 int num = Support_SQL.sqlMaxConnections; 228 try { 229 int mc = conn.getMetaData().getMaxConnections(); 230 if (mc != 0) { 231 if (num != mc) { 232 System.err.println("Will be used no more than " + mc 233 + " connections to the DataBase"); 234 } 235 num = mc; 236 } 237 } catch (SQLException sql) { 238 fail("Unexpected SQLException " + sql.toString()); 239 } 240 return num; 241 } 242 openConnections(int maxConnections)243 private void openConnections(int maxConnections) { 244 int i = 0; 245 try { 246 for (; i < maxConnections; ++i) { 247 Connection c = Support_SQL.getConnection(); 248 if (c == null) { 249 assertEquals("Unable to create a connection", 250 maxConnections, i); 251 } 252 vc.add(c); 253 } 254 } catch (SQLException sql) { 255 assertEquals("Unable to create a connection", maxConnections, i); 256 } 257 return; 258 } 259 closeConnections()260 private void closeConnections() { 261 int i = 0; 262 try { 263 for (; i < vc.size(); ++i) { 264 vc.elementAt(i).close(); 265 } 266 } catch (SQLException sql) { 267 assertEquals("Unable to close a connection", vc.size(), i); 268 } 269 return; 270 } 271 createTask(final int taskID)272 private Runnable createTask(final int taskID) { 273 return new Runnable() { 274 public void run() { 275 try { 276 Connection c = Support_SQL.getConnection(); 277 if (c == null) { 278 return; 279 } 280 synchronized (this) { 281 vc.add(c); 282 } 283 } catch (SQLException sql) { 284 // nothing to do 285 } 286 } 287 }; 288 } 289 290 private Runnable insertTask(final int numConnections, final int taskID) { 291 return new Runnable() { 292 public void run() { 293 try { 294 Connection c = Support_SQL.getConnection(); 295 if (c == null) { 296 return; 297 } 298 synchronized (this) { 299 vc.add(c); 300 } 301 int tasksPerConnection = Support_SQL.sqlMaxTasks 302 / numConnections; 303 for (int i = 0; i < tasksPerConnection; ++i) { 304 insertNewRecord(c, (i + 1) + tasksPerConnection 305 * taskID); 306 } 307 } catch (SQLException sql) { 308 // do nothing 309 } 310 } 311 }; 312 } 313 314 private void insertNewRecord(Connection c, int pk) { 315 String query = "INSERT INTO " + DatabaseCreator.TEST_TABLE2 316 + "(finteger, ftext, fcharacter, fdecimal, fnumeric," 317 + " fsmallint, ffloat, freal, fdouble, fdate, ftime)" 318 + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; 319 try { 320 PreparedStatement ps = c.prepareStatement(query); 321 ps.setInt(1, pk); 322 ps.setString(2, "text"); 323 ps.setString(3, "chr"); 324 ps.setFloat(4, 0.1f); 325 ps.setFloat(5, 0.2f); 326 ps.setShort(6, (short) 3); 327 ps.setFloat(7, 0.4f); 328 ps.setDouble(8, 0.5); 329 ps.setDouble(9, 0.6); 330 ps.setDate(10, new java.sql.Date(System.currentTimeMillis())); 331 ps.setTime(11, new java.sql.Time(System.currentTimeMillis())); 332 ps.execute(); 333 ps.close(); 334 } catch (SQLException sql) { 335 fail("Unexpected SQLException " + sql.toString()); 336 } 337 return; 338 } 339 } 340