Home | History | Annotate | Download | only in sql
      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 
     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 
     51     protected void tearDown() throws Exception {
     52         closeConnections();
     53         statement.close();
     54         conn.close();
     55         super.tearDown();
     56     }
     57 
     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 
     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      */
    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      */
    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      */
    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      */
    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 
    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 
    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 
    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 
    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