KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > testsuite > regression > PooledConnectionRegressionTest


1 /*
2  Copyright (C) 2002-2004 MySQL AB
3
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of version 2 of the GNU General Public License as
6  published by the Free Software Foundation.
7
8  There are special exceptions to the terms and conditions of the GPL
9  as it is applied to this software. View the full text of the
10  exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
11  software distribution.
12
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22
23  
24  */

25 package testsuite.regression;
26
27 import java.sql.Connection JavaDoc;
28 import java.sql.PreparedStatement JavaDoc;
29 import java.sql.SQLException JavaDoc;
30
31 import javax.sql.ConnectionEvent JavaDoc;
32 import javax.sql.ConnectionEventListener JavaDoc;
33 import javax.sql.ConnectionPoolDataSource JavaDoc;
34 import javax.sql.PooledConnection JavaDoc;
35
36 import junit.framework.Test;
37 import junit.framework.TestSuite;
38 import junit.textui.TestRunner;
39 import testsuite.BaseTestCase;
40 import testsuite.simple.BlobTest;
41
42 import com.mysql.jdbc.PacketTooBigException;
43 import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;
44
45 /**
46  * Tests a PooledConnection implementation provided by a JDBC driver. Test case
47  * provided by Johnny Macchione from bug database record BUG#884. According to
48  * the JDBC 2.0 specification:
49  *
50  * <p>
51  * "Each call to PooledConnection.getConnection() must return a newly
52  * constructed Connection object that exhibits the default Connection behavior.
53  * Only the most recent Connection object produced from a particular
54  * PooledConnection is open. An existing Connection object is automatically
55  * closed, if the getConnection() method of its associated Pooled-Connection is
56  * called again, before it has been explicitly closed by the application. This
57  * gives the application server a way to �take away� a Connection from the
58  * application if it wishes, and give it out to someone else. This capability
59  * will not likely be used frequently in practice."
60  * </p>
61  *
62  * <p>
63  * "When the application calls Connection.close(), an event is triggered that
64  * tells the connection pool it can recycle the physical database connection. In
65  * other words, the event signals the connection pool that the PooledConnection
66  * object which originally produced the Connection object generating the event
67  * can be put back in the connection pool."
68  * </p>
69  *
70  * <p>
71  * "A Connection-EventListener will also be notified when a fatal error occurs,
72  * so that it can make a note not to put a bad PooledConnection object back in
73  * the cache when the application finishes using it. When an error occurs, the
74  * ConnectionEventListener is notified by the JDBC driver, just before the
75  * driver throws an SQLException to the application to notify it of the same
76  * error. Note that automatic closing of a Connection object as discussed in the
77  * previous section does not generate a connection close event."
78  * </p>
79  * The JDBC 3.0 specification states the same in other words:
80  *
81  * <p>
82  * "The Connection.close method closes the logical handle, but the physical
83  * connection is maintained. The connection pool manager is notified that the
84  * underlying PooledConnection object is now available for reuse. If the
85  * application attempts to reuse the logical handle, the Connection
86  * implementation throws an SQLException."
87  * </p>
88  *
89  * <p>
90  * "For a given PooledConnection object, only the most recently produced logical
91  * Connection object will be valid. Any previously existing Connection object is
92  * automatically closed when the associated PooledConnection.getConnection
93  * method is called. Listeners (connection pool managers) are not notified in
94  * this case. This gives the application server a way to take a connection away
95  * from a client. This is an unlikely scenario but may be useful if the
96  * application server is trying to force an orderly shutdown."
97  * </p>
98  *
99  * <p>
100  * "A connection pool manager shuts down a physical connection by calling the
101  * method PooledConnection.close. This method is typically called only in
102  * certain circumstances: when the application server is undergoing an orderly
103  * shutdown, when the connection cache is being reinitialized, or when the
104  * application server receives an event indicating that an unrecoverable error
105  * has occurred on the connection."
106  * </p>
107  * Even though the specification isn't clear about it, I think it is no use
108  * generating a close event when calling the method PooledConnection.close(),
109  * even if a logical Connection is open for this PooledConnection, bc the
110  * PooledConnection will obviously not be returned to the pool.
111  *
112  * @author fcr
113  */

114 public final class PooledConnectionRegressionTest extends BaseTestCase {
115     private ConnectionPoolDataSource JavaDoc cpds;
116
117     // Count nb of closeEvent.
118
private int closeEventCount;
119
120     // Count nb of connectionErrorEvent
121
private int connectionErrorEventCount;
122
123     /**
124      * Creates a new instance of ProgressPooledConnectionTest
125      *
126      * @param testname
127      * DOCUMENT ME!
128      */

129     public PooledConnectionRegressionTest(String JavaDoc testname) {
130         super(testname);
131     }
132
133     /**
134      * Set up test case before a test is run.
135      *
136      * @throws Exception
137      * DOCUMENT ME!
138      */

139     public void setUp() throws Exception JavaDoc {
140         super.setUp();
141
142         // Reset event count.
143
this.closeEventCount = 0;
144         this.connectionErrorEventCount = 0;
145
146         MysqlConnectionPoolDataSource ds = new MysqlConnectionPoolDataSource();
147
148         ds.setURL(BaseTestCase.dbUrl);
149
150         cpds = ds;
151     }
152
153     /**
154      * Runs all test cases in this test suite
155      *
156      * @param args
157      */

158     public static void main(String JavaDoc[] args) {
159         junit.textui.TestRunner.run(PooledConnectionRegressionTest.class);
160     }
161
162     /**
163      * DOCUMENT ME!
164      *
165      * @return a test suite composed of this test case.
166      */

167     public static Test suite() {
168         TestSuite suite = new TestSuite(PooledConnectionRegressionTest.class);
169
170         return suite;
171     }
172
173     /**
174      * After the test is run.
175      */

176     public void tearDown() {
177         cpds = null;
178     }
179
180     /**
181      * Tests fix for BUG#7136 ... Statement.getConnection() returning physical
182      * connection instead of logical connection.
183      */

184     public void testBug7136() {
185         final ConnectionEventListener JavaDoc conListener = new ConnectionListener();
186         PooledConnection JavaDoc pc = null;
187         this.closeEventCount = 0;
188
189         try {
190             pc = cpds.getPooledConnection();
191
192             pc.addConnectionEventListener(conListener);
193
194             Connection JavaDoc conn = pc.getConnection();
195
196             Connection JavaDoc connFromStatement = conn.createStatement()
197                     .getConnection();
198
199             // This should generate a close event.
200

201             connFromStatement.close();
202
203             assertEquals("One close event should've been registered", 1,
204                     this.closeEventCount);
205
206             this.closeEventCount = 0;
207
208             conn = pc.getConnection();
209
210             Connection JavaDoc connFromPreparedStatement = conn.prepareStatement(
211                     "SELECT 1").getConnection();
212
213             // This should generate a close event.
214

215             connFromPreparedStatement.close();
216
217             assertEquals("One close event should've been registered", 1,
218                     this.closeEventCount);
219
220         } catch (SQLException JavaDoc ex) {
221             fail(ex.toString());
222         } finally {
223             if (pc != null) {
224                 try {
225                     pc.close();
226                 } catch (SQLException JavaDoc ex) {
227                     ex.printStackTrace();
228                 }
229             }
230         }
231     }
232
233     /**
234      * Test the nb of closeEvents generated when a Connection is reclaimed. No
235      * event should be generated in that case.
236      */

237     public void testConnectionReclaim() {
238         final ConnectionEventListener JavaDoc conListener = new ConnectionListener();
239         PooledConnection JavaDoc pc = null;
240         final int NB_TESTS = 5;
241
242         try {
243             pc = cpds.getPooledConnection();
244
245             pc.addConnectionEventListener(conListener);
246
247             for (int i = 0; i < NB_TESTS; i++) {
248                 Connection JavaDoc conn = pc.getConnection();
249
250                 try {
251                     // Try to reclaim connection.
252
System.out.println("Before connection reclaim.");
253
254                     conn = pc.getConnection();
255
256                     System.out.println("After connection reclaim.");
257                 } finally {
258                     if (conn != null) {
259                         System.out.println("Before connection.close().");
260
261                         // This should generate a close event.
262
conn.close();
263
264                         System.out.println("After connection.close().");
265                     }
266                 }
267             }
268         } catch (SQLException JavaDoc ex) {
269             ex.printStackTrace();
270             fail(ex.toString());
271         } finally {
272             if (pc != null) {
273                 try {
274                     System.out.println("Before pooledConnection.close().");
275
276                     // This should not generate a close event.
277
pc.close();
278
279                     System.out.println("After pooledConnection.close().");
280                 } catch (SQLException JavaDoc ex) {
281                     ex.printStackTrace();
282                     fail(ex.toString());
283                 }
284             }
285         }
286
287         assertEquals("Wrong nb of CloseEvents: ", NB_TESTS, closeEventCount);
288     }
289
290     /**
291      * Tests that PacketTooLargeException doesn't clober the connection.
292      *
293      * @throws Exception
294      * if the test fails.
295      */

296     public void testPacketTooLargeException() throws Exception JavaDoc {
297         final ConnectionEventListener JavaDoc conListener = new ConnectionListener();
298         PooledConnection JavaDoc pc = null;
299
300         pc = cpds.getPooledConnection();
301
302         pc.addConnectionEventListener(conListener);
303
304         try {
305             this.stmt.executeUpdate("DROP TABLE IF EXISTS testPacketTooLarge");
306             this.stmt
307                     .executeUpdate("CREATE TABLE testPacketTooLarge(field1 LONGBLOB)");
308
309             Connection JavaDoc connFromPool = pc.getConnection();
310             PreparedStatement JavaDoc pStmtFromPool = connFromPool
311                     .prepareStatement("INSERT INTO testPacketTooLarge VALUES (?)");
312             this.rs = this.stmt
313                     .executeQuery("SHOW VARIABLES LIKE 'max_allowed_packet'");
314             this.rs.next();
315
316             int maxAllowedPacket = this.rs.getInt(2);
317
318             byte[] bigBytes = new byte[(int) (maxAllowedPacket * 1.2)];
319
320             try {
321                 pStmtFromPool.setBytes(1, bigBytes);
322                 pStmtFromPool.executeUpdate();
323                 fail("Expecting PacketTooLargeException");
324             } catch (PacketTooBigException ptbe) {
325                 // We're expecting this one...
326
}
327
328             // This should still work okay, even though the last query on the
329
// same
330
// connection didn't...
331
connFromPool.createStatement().executeQuery("SELECT 1");
332
333             assertTrue(this.connectionErrorEventCount == 0);
334             assertTrue(this.closeEventCount == 0);
335         } finally {
336             this.stmt.executeUpdate("DROP TABLE IF EXISTS testPacketTooLarge");
337         }
338     }
339
340     /**
341      * Test the nb of closeEvents generated by a PooledConnection. A
342      * JDBC-compliant driver should only generate 1 closeEvent each time
343      * connection.close() is called.
344      */

345     public void testCloseEvent() {
346         final ConnectionEventListener JavaDoc conListener = new ConnectionListener();
347         PooledConnection JavaDoc pc = null;
348         final int NB_TESTS = 5;
349
350         try {
351             pc = this.cpds.getPooledConnection();
352
353             pc.addConnectionEventListener(conListener);
354
355             for (int i = 0; i < NB_TESTS; i++) {
356                 Connection JavaDoc pConn = pc.getConnection();
357
358                 System.out.println("Before connection.close().");
359
360                 // This should generate a close event.
361
pConn.close();
362
363                 System.out.println("After connection.close().");
364             }
365         } catch (SQLException JavaDoc ex) {
366             fail(ex.toString());
367         } finally {
368             if (pc != null) {
369                 try {
370                     System.out.println("Before pooledConnection.close().");
371
372                     // This should not generate a close event.
373
pc.close();
374
375                     System.out.println("After pooledConnection.close().");
376                 } catch (SQLException JavaDoc ex) {
377                     ex.printStackTrace();
378                 }
379             }
380         }
381         assertEquals("Wrong nb of CloseEvents: ", NB_TESTS,
382                 this.closeEventCount);
383     }
384
385     /**
386      * Listener for PooledConnection events.
387      */

388     private final class ConnectionListener implements ConnectionEventListener JavaDoc {
389         /** */
390         public void connectionClosed(ConnectionEvent JavaDoc event) {
391             closeEventCount++;
392             System.out.println(closeEventCount + " - Connection closed.");
393         }
394
395         /** */
396         public void connectionErrorOccurred(ConnectionEvent JavaDoc event) {
397             connectionErrorEventCount++;
398             System.out.println("Connection error: " + event.getSQLException());
399         }
400     }
401 }
402
Popular Tags