1
package org.postgresql.test.jdbc2.optional;
3
import org.postgresql.jdbc2.optional.ConnectionPool;
4
import org.postgresql.test.TestUtil;
10
* Tests for the ConnectionPoolDataSource and PooledConnection
11
* implementations. They are tested together because the only client
12
* interface to the PooledConnection is through the CPDS.
14
* @author Aaron Mulder (ammulder@chariotsolutions.com)
15
* @version $Revision: 1.6.4.4 $
17
public class ConnectionPoolTest extends BaseDataSourceTest
20
* Constructor required by JUnit
22
public ConnectionPoolTest(String name)
28
* Creates and configures a ConnectionPool
30
protected void initializeDataSource()
34
bds = new ConnectionPool();
35
bds.setServerName(TestUtil.getServer());
36
bds.setPortNumber(TestUtil.getPort());
37
bds.setDatabaseName(TestUtil.getDatabase());
38
bds.setUser(TestUtil.getUser());
39
bds.setPassword(TestUtil.getPassword());
44
* Though the normal client interface is to grab a Connection, in
45
* order to test the middleware/server interface, we need to deal
46
* with PooledConnections. Some tests use each.
48
protected PooledConnection getPooledConnection() throws SQLException
50
initializeDataSource();
51
return ((ConnectionPool)bds).getPooledConnection();
55
* Instead of just fetching a Connection from the ConnectionPool,
56
* get a PooledConnection, add a listener to close it when the
57
* Connection is closed, and then get the Connection. Without
58
* the listener the PooledConnection (and thus the physical connection)
59
* would never by closed. Probably not a disaster during testing, but
62
protected Connection getDataSourceConnection() throws SQLException
64
initializeDataSource();
65
final PooledConnection pc = getPooledConnection();
66
// Since the pooled connection won't be reused in these basic tests, close it when the connection is closed
67
pc.addConnectionEventListener(new ConnectionEventListener()
69
public void connectionClosed(ConnectionEvent event)
75
catch (SQLException e)
77
fail("Unable to close PooledConnection: " + e);
81
public void connectionErrorOccurred(ConnectionEvent event)
85
return pc.getConnection();
89
* Makes sure that if you get a connection from a PooledConnection,
90
* close it, and then get another one, you're really using the same
91
* physical connection. Depends on the implementation of toString
92
* for the connection handle.
94
public void testPoolReuse()
98
PooledConnection pc = getPooledConnection();
99
con = pc.getConnection();
100
String name = con.toString();
102
con = pc.getConnection();
103
String name2 = con.toString();
106
assertTrue("Physical connection doesn't appear to be reused across PooledConnection wrappers", name.equals(name2));
108
catch (SQLException e)
110
fail(e.getMessage());
115
* Makes sure that when you request a connection from the
116
* PooledConnection, and previous connection it might have given
117
* out is closed. See JDBC 2.0 Optional Package spec section
120
public void testPoolCloseOldWrapper()
124
PooledConnection pc = getPooledConnection();
125
con = pc.getConnection();
126
Connection con2 = pc.getConnection();
129
con.createStatement();
130
fail("Original connection wrapper should be closed when new connection wrapper is generated");
132
catch (SQLException e)
137
catch (SQLException e)
139
fail(e.getMessage());
144
* Makes sure that if you get two connection wrappers from the same
145
* PooledConnection, they are different, even though the represent
146
* the same physical connection. See JDBC 2.0 Optional Pacakge spec
149
public void testPoolNewWrapper()
153
PooledConnection pc = getPooledConnection();
154
con = pc.getConnection();
155
Connection con2 = pc.getConnection();
158
assertTrue("Two calls to PooledConnection.getConnection should not return the same connection wrapper", con != con2);
160
catch (SQLException e)
162
fail(e.getMessage());
167
* Makes sure that exactly one close event is fired for each time a
168
* connection handle is closed. Also checks that events are not
169
* fired after a given handle has been closed once.
171
public void testCloseEvent()
175
PooledConnection pc = getPooledConnection();
176
CountClose cc = new CountClose();
177
pc.addConnectionEventListener(cc);
178
con = pc.getConnection();
179
assertTrue(cc.getCount() == 0);
180
assertTrue(cc.getErrorCount() == 0);
182
assertTrue(cc.getCount() == 1);
183
assertTrue(cc.getErrorCount() == 0);
184
con = pc.getConnection();
185
assertTrue(cc.getCount() == 1);
186
assertTrue(cc.getErrorCount() == 0);
188
assertTrue(cc.getCount() == 2);
189
assertTrue(cc.getErrorCount() == 0);
190
// a double close shouldn't fire additional events
192
assertTrue(cc.getCount() == 2);
193
assertTrue(cc.getErrorCount() == 0);
196
catch (SQLException e)
198
fail(e.getMessage());
203
* Makes sure that close events are not fired after a listener has
206
public void testNoCloseEvent()
210
PooledConnection pc = getPooledConnection();
211
CountClose cc = new CountClose();
212
pc.addConnectionEventListener(cc);
213
con = pc.getConnection();
214
assertTrue(cc.getCount() == 0);
215
assertTrue(cc.getErrorCount() == 0);
217
assertTrue(cc.getCount() == 1);
218
assertTrue(cc.getErrorCount() == 0);
219
pc.removeConnectionEventListener(cc);
220
con = pc.getConnection();
221
assertTrue(cc.getCount() == 1);
222
assertTrue(cc.getErrorCount() == 0);
224
assertTrue(cc.getCount() == 1);
225
assertTrue(cc.getErrorCount() == 0);
227
catch (SQLException e)
229
fail(e.getMessage());
234
* Makes sure that a listener can be removed while dispatching
235
* events. Sometimes this causes a ConcurrentModificationException
238
public void testInlineCloseEvent()
242
PooledConnection pc = getPooledConnection();
243
RemoveClose rc1 = new RemoveClose();
244
RemoveClose rc2 = new RemoveClose();
245
RemoveClose rc3 = new RemoveClose();
246
pc.addConnectionEventListener(rc1);
247
pc.addConnectionEventListener(rc2);
248
pc.addConnectionEventListener(rc3);
249
con = pc.getConnection();
251
con = pc.getConnection();
256
fail(e.getMessage());
261
* Tests that a close event is not generated when a connection
262
* handle is closed automatically due to a new connection handle
263
* being opened for the same PooledConnection. See JDBC 2.0
264
* Optional Package spec section 6.3
266
public void testAutomaticCloseEvent()
270
PooledConnection pc = getPooledConnection();
271
CountClose cc = new CountClose();
272
pc.addConnectionEventListener(cc);
273
con = pc.getConnection();
274
assertTrue(cc.getCount() == 0);
275
assertTrue(cc.getErrorCount() == 0);
277
assertTrue(cc.getCount() == 1);
278
assertTrue(cc.getErrorCount() == 0);
279
con = pc.getConnection();
280
assertTrue(cc.getCount() == 1);
281
assertTrue(cc.getErrorCount() == 0);
282
// Open a 2nd connection, causing the first to be closed. No even should be generated.
283
Connection con2 = pc.getConnection();
284
assertTrue("Connection handle was not closed when new handle was opened", con.isClosed());
285
assertTrue(cc.getCount() == 1);
286
assertTrue(cc.getErrorCount() == 0);
288
assertTrue(cc.getCount() == 2);
289
assertTrue(cc.getErrorCount() == 0);
292
catch (SQLException e)
294
fail(e.getMessage());
299
* Makes sure the isClosed method on a connection wrapper does what
300
* you'd expect. Checks the usual case, as well as automatic
301
* closure when a new handle is opened on the same physical connection.
303
public void testIsClosed()
307
PooledConnection pc = getPooledConnection();
308
Connection con = pc.getConnection();
309
assertTrue(!con.isClosed());
311
assertTrue(con.isClosed());
312
con = pc.getConnection();
313
Connection con2 = pc.getConnection();
314
assertTrue(con.isClosed());
315
assertTrue(!con2.isClosed());
317
assertTrue(con.isClosed());
320
catch (SQLException e)
322
fail(e.getMessage());
327
* Ensures that a statement generated by a proxied connection returns the
328
* proxied connection from getConnection() [not the physical connection].
330
public void testStatementConnection() {
332
PooledConnection pc = getPooledConnection();
333
Connection con = pc.getConnection();
334
Statement s = con.createStatement();
335
Connection conRetrieved = s.getConnection();
337
assertTrue(con.getClass().equals(conRetrieved.getClass()));
338
assertTrue(con.equals(conRetrieved));
339
} catch (SQLException e) {
340
fail(e.getMessage());
345
* Ensures that the Statement proxy generated by the Connection handle
346
* throws the correct kind of exception.
348
public void testStatementProxy() {
352
PooledConnection pc = getPooledConnection();
353
Connection con = pc.getConnection();
354
s = con.createStatement();
356
catch (SQLException e)
358
fail(e.getMessage());
362
s.executeQuery("SELECT * FROM THIS_TABLE_SHOULD_NOT_EXIST");
363
fail("An SQL exception was not thrown that should have been");
365
catch (SQLException e)
367
; // This is the expected and correct path
371
fail("bad exception; was expecting SQLException, not" +
372
e.getClass().getName());
377
* Ensures that a prepared statement generated by a proxied connection
378
* returns the proxied connection from getConnection() [not the physical
381
public void testPreparedStatementConnection() {
383
PooledConnection pc = getPooledConnection();
384
Connection con = pc.getConnection();
385
PreparedStatement s = con.prepareStatement("select 'x'");
386
Connection conRetrieved = s.getConnection();
388
assertTrue(con.getClass().equals(conRetrieved.getClass()));
389
assertTrue(con.equals(conRetrieved));
390
} catch (SQLException e) {
391
fail(e.getMessage());
396
* Ensures that a callable statement generated by a proxied connection
397
* returns the proxied connection from getConnection() [not the physical
400
public void testCallableStatementConnection() {
402
PooledConnection pc = getPooledConnection();
403
Connection con = pc.getConnection();
404
CallableStatement s = con.prepareCall("select 'x'");
405
Connection conRetrieved = s.getConnection();
407
assertTrue(con.getClass().equals(conRetrieved.getClass()));
408
assertTrue(con.equals(conRetrieved));
409
} catch (SQLException e) {
410
fail(e.getMessage());
415
* Ensure that a statement created from a pool can be used
416
* like any other statement in regard to pg extensions.
418
public void testStatementsProxyPGStatement() {
420
PooledConnection pc = getPooledConnection();
421
con = pc.getConnection();
423
Statement s = con.createStatement();
424
boolean b = ((org.postgresql.PGStatement)s).isUseServerPrepare();
426
PreparedStatement ps = con.prepareStatement("select 'x'");
427
b = ((org.postgresql.PGStatement)ps).isUseServerPrepare();
429
CallableStatement cs = con.prepareCall("select 'x'");
430
b = ((org.postgresql.PGStatement)cs).isUseServerPrepare();
432
} catch (SQLException e) {
433
fail(e.getMessage());
438
* Helper class to remove a listener during event dispatching.
440
private class RemoveClose implements ConnectionEventListener
442
public void connectionClosed(ConnectionEvent event)
444
((PooledConnection)event.getSource()).removeConnectionEventListener(this);
447
public void connectionErrorOccurred(ConnectionEvent event)
449
((PooledConnection)event.getSource()).removeConnectionEventListener(this);
454
* Helper class that implements the event listener interface, and
455
* counts the number of events it sees.
457
private class CountClose implements ConnectionEventListener
459
private int count = 0, errorCount = 0;
460
public void connectionClosed(ConnectionEvent event)
465
public void connectionErrorOccurred(ConnectionEvent event)
470
public int getCount()
475
public int getErrorCount()
482
count = errorCount = 0;
486
public void testSerializable() throws IOException, ClassNotFoundException
488
ConnectionPool pool = new ConnectionPool();
489
pool.setDefaultAutoCommit(false);
490
pool.setServerName("db.myhost.com");
491
pool.setDatabaseName("mydb");
492
pool.setUser("user");
493
pool.setPassword("pass");
494
pool.setPortNumber(1111);
496
ByteArrayOutputStream baos = new ByteArrayOutputStream();
497
ObjectOutputStream oos = new ObjectOutputStream(baos);
498
oos.writeObject(pool);
500
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
501
ObjectInputStream ois = new ObjectInputStream(bais);
502
ConnectionPool pool2 = (ConnectionPool)ois.readObject();
504
assertEquals(pool.isDefaultAutoCommit(),pool2.isDefaultAutoCommit());
505
assertEquals(pool.getServerName(),pool2.getServerName());
506
assertEquals(pool.getDatabaseName(),pool2.getDatabaseName());
507
assertEquals(pool.getUser(),pool2.getUser());
508
assertEquals(pool.getPassword(),pool2.getPassword());
509
assertEquals(pool.getPortNumber(),pool2.getPortNumber());