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