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