~ubuntu-branches/ubuntu/wily/libpgjava/wily

« back to all changes in this revision

Viewing changes to src/interfaces/jdbc/org/postgresql/test/jdbc2/optional/ConnectionPoolTest.java

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Vandyck
  • Date: 2005-04-21 14:25:11 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050421142511-wibh5vc31fkrorx7
Tags: 7.4.7-3
Built with sources...

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.postgresql.test.jdbc2.optional;
 
2
 
 
3
import org.postgresql.jdbc2.optional.ConnectionPool;
 
4
import org.postgresql.test.TestUtil;
 
5
import javax.sql.*;
 
6
import java.sql.*;
 
7
import java.io.*;
 
8
 
 
9
/**
 
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.
 
13
 *
 
14
 * @author Aaron Mulder (ammulder@chariotsolutions.com)
 
15
 * @version $Revision: 1.6.4.4 $
 
16
 */
 
17
public class ConnectionPoolTest extends BaseDataSourceTest
 
18
{
 
19
        /**
 
20
         * Constructor required by JUnit
 
21
         */
 
22
        public ConnectionPoolTest(String name)
 
23
        {
 
24
                super(name);
 
25
        }
 
26
 
 
27
        /**
 
28
         * Creates and configures a ConnectionPool
 
29
         */
 
30
        protected void initializeDataSource()
 
31
        {
 
32
                if (bds == null)
 
33
                {
 
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());
 
40
                }
 
41
        }
 
42
 
 
43
        /**
 
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.
 
47
         */
 
48
        protected PooledConnection getPooledConnection() throws SQLException
 
49
        {
 
50
                initializeDataSource();
 
51
                return ((ConnectionPool)bds).getPooledConnection();
 
52
        }
 
53
 
 
54
        /**
 
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
 
60
         * you never know.
 
61
         */
 
62
        protected Connection getDataSourceConnection() throws SQLException
 
63
        {
 
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()
 
68
                                                                          {
 
69
                                                                                  public void connectionClosed(ConnectionEvent event)
 
70
                                                                                  {
 
71
                                                                                          try
 
72
                                                                                          {
 
73
                                                                                                  pc.close();
 
74
                                                                                          }
 
75
                                                                                          catch (SQLException e)
 
76
                                                                                          {
 
77
                                                                                                  fail("Unable to close PooledConnection: " + e);
 
78
                                                                                          }
 
79
                                                                                  }
 
80
 
 
81
                                                                                  public void connectionErrorOccurred(ConnectionEvent event)
 
82
                                                                                  {}
 
83
                                                                          }
 
84
                                                                         );
 
85
                return pc.getConnection();
 
86
        }
 
87
 
 
88
        /**
 
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.
 
93
         */
 
94
        public void testPoolReuse()
 
95
        {
 
96
                try
 
97
                {
 
98
                        PooledConnection pc = getPooledConnection();
 
99
                        con = pc.getConnection();
 
100
                        String name = con.toString();
 
101
                        con.close();
 
102
                        con = pc.getConnection();
 
103
                        String name2 = con.toString();
 
104
                        con.close();
 
105
                        pc.close();
 
106
                        assertTrue("Physical connection doesn't appear to be reused across PooledConnection wrappers", name.equals(name2));
 
107
                }
 
108
                catch (SQLException e)
 
109
                {
 
110
                        fail(e.getMessage());
 
111
                }
 
112
        }
 
113
 
 
114
        /**
 
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
 
118
         * 6.2.3
 
119
         */
 
120
        public void testPoolCloseOldWrapper()
 
121
        {
 
122
                try
 
123
                {
 
124
                        PooledConnection pc = getPooledConnection();
 
125
                        con = pc.getConnection();
 
126
                        Connection con2 = pc.getConnection();
 
127
                        try
 
128
                        {
 
129
                                con.createStatement();
 
130
                                fail("Original connection wrapper should be closed when new connection wrapper is generated");
 
131
                        }
 
132
                        catch (SQLException e)
 
133
                        {}
 
134
                        con2.close();
 
135
                        pc.close();
 
136
                }
 
137
                catch (SQLException e)
 
138
                {
 
139
                        fail(e.getMessage());
 
140
                }
 
141
        }
 
142
 
 
143
        /**
 
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
 
147
         * section 6.2.2
 
148
         */
 
149
        public void testPoolNewWrapper()
 
150
        {
 
151
                try
 
152
                {
 
153
                        PooledConnection pc = getPooledConnection();
 
154
                        con = pc.getConnection();
 
155
                        Connection con2 = pc.getConnection();
 
156
                        con2.close();
 
157
                        pc.close();
 
158
                        assertTrue("Two calls to PooledConnection.getConnection should not return the same connection wrapper", con != con2);
 
159
                }
 
160
                catch (SQLException e)
 
161
                {
 
162
                        fail(e.getMessage());
 
163
                }
 
164
        }
 
165
 
 
166
        /**
 
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.
 
170
         */
 
171
        public void testCloseEvent()
 
172
        {
 
173
                try
 
174
                {
 
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);
 
181
                        con.close();
 
182
                        assertTrue(cc.getCount() == 1);
 
183
                        assertTrue(cc.getErrorCount() == 0);
 
184
                        con = pc.getConnection();
 
185
                        assertTrue(cc.getCount() == 1);
 
186
                        assertTrue(cc.getErrorCount() == 0);
 
187
                        con.close();
 
188
                        assertTrue(cc.getCount() == 2);
 
189
                        assertTrue(cc.getErrorCount() == 0);
 
190
                        // a double close shouldn't fire additional events
 
191
                                con.close();
 
192
                        assertTrue(cc.getCount() == 2);
 
193
                        assertTrue(cc.getErrorCount() == 0);
 
194
                        pc.close();
 
195
                }
 
196
                catch (SQLException e)
 
197
                {
 
198
                        fail(e.getMessage());
 
199
                }
 
200
        }
 
201
 
 
202
        /**
 
203
         * Makes sure that close events are not fired after a listener has
 
204
         * been removed.
 
205
         */
 
206
        public void testNoCloseEvent()
 
207
        {
 
208
                try
 
209
                {
 
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);
 
216
                        con.close();
 
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);
 
223
                        con.close();
 
224
                        assertTrue(cc.getCount() == 1);
 
225
                        assertTrue(cc.getErrorCount() == 0);
 
226
                }
 
227
                catch (SQLException e)
 
228
                {
 
229
                        fail(e.getMessage());
 
230
                }
 
231
        }
 
232
 
 
233
        /**
 
234
         * Makes sure that a listener can be removed while dispatching
 
235
         * events.      Sometimes this causes a ConcurrentModificationException
 
236
         * or something.
 
237
         */
 
238
        public void testInlineCloseEvent()
 
239
        {
 
240
                try
 
241
                {
 
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();
 
250
                        con.close();
 
251
                        con = pc.getConnection();
 
252
                        con.close();
 
253
                }
 
254
                catch (Exception e)
 
255
                {
 
256
                        fail(e.getMessage());
 
257
                }
 
258
        }
 
259
 
 
260
        /**
 
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
 
265
         */
 
266
        public void testAutomaticCloseEvent()
 
267
        {
 
268
                try
 
269
                {
 
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);
 
276
                        con.close();
 
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);
 
287
                        con2.close();
 
288
                        assertTrue(cc.getCount() == 2);
 
289
                        assertTrue(cc.getErrorCount() == 0);
 
290
                        pc.close();
 
291
                }
 
292
                catch (SQLException e)
 
293
                {
 
294
                        fail(e.getMessage());
 
295
                }
 
296
        }
 
297
 
 
298
        /**
 
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.
 
302
         */
 
303
        public void testIsClosed()
 
304
        {
 
305
                try
 
306
                {
 
307
                        PooledConnection pc = getPooledConnection();
 
308
                        Connection con = pc.getConnection();
 
309
                        assertTrue(!con.isClosed());
 
310
                        con.close();
 
311
                        assertTrue(con.isClosed());
 
312
                        con = pc.getConnection();
 
313
                        Connection con2 = pc.getConnection();
 
314
                        assertTrue(con.isClosed());
 
315
                        assertTrue(!con2.isClosed());
 
316
                        con2.close();
 
317
                        assertTrue(con.isClosed());
 
318
                        pc.close();
 
319
                }
 
320
                catch (SQLException e)
 
321
                {
 
322
                        fail(e.getMessage());
 
323
                }
 
324
        }
 
325
 
 
326
    /**
 
327
     * Ensures that a statement generated by a proxied connection returns the
 
328
     * proxied connection from getConnection() [not the physical connection].
 
329
     */
 
330
    public void testStatementConnection() {
 
331
        try {
 
332
            PooledConnection pc = getPooledConnection();
 
333
            Connection con = pc.getConnection();
 
334
            Statement s = con.createStatement();
 
335
            Connection conRetrieved = s.getConnection();
 
336
 
 
337
            assertTrue(con.getClass().equals(conRetrieved.getClass()));
 
338
            assertTrue(con.equals(conRetrieved));
 
339
        } catch (SQLException e) {
 
340
            fail(e.getMessage());
 
341
        }
 
342
    }
 
343
 
 
344
    /**
 
345
     * Ensures that the Statement proxy generated by the Connection handle
 
346
     * throws the correct kind of exception.
 
347
     */
 
348
    public void testStatementProxy() {
 
349
            Statement s = null;
 
350
            try 
 
351
            {
 
352
                    PooledConnection pc = getPooledConnection();
 
353
                    Connection con = pc.getConnection();
 
354
                    s = con.createStatement();
 
355
            } 
 
356
            catch (SQLException e) 
 
357
            {
 
358
                    fail(e.getMessage());
 
359
            }
 
360
            try 
 
361
            {
 
362
                    s.executeQuery("SELECT * FROM THIS_TABLE_SHOULD_NOT_EXIST");
 
363
                    fail("An SQL exception was not thrown that should have been");
 
364
            } 
 
365
            catch (SQLException e) 
 
366
            {
 
367
                    ; // This is the expected and correct path
 
368
            }
 
369
            catch (Exception e) 
 
370
            {
 
371
                    fail("bad exception; was expecting SQLException, not" +
 
372
                         e.getClass().getName());
 
373
            }
 
374
    }
 
375
 
 
376
    /**
 
377
     * Ensures that a prepared statement generated by a proxied connection
 
378
     * returns the proxied connection from getConnection() [not the physical
 
379
     * connection].
 
380
     */
 
381
    public void testPreparedStatementConnection() {
 
382
        try {
 
383
            PooledConnection pc = getPooledConnection();
 
384
            Connection con = pc.getConnection();
 
385
            PreparedStatement s = con.prepareStatement("select 'x'");
 
386
            Connection conRetrieved = s.getConnection();
 
387
 
 
388
            assertTrue(con.getClass().equals(conRetrieved.getClass()));
 
389
            assertTrue(con.equals(conRetrieved));
 
390
        } catch (SQLException e) {
 
391
            fail(e.getMessage());
 
392
        }
 
393
    }
 
394
 
 
395
    /**
 
396
     * Ensures that a callable statement generated by a proxied connection
 
397
     * returns the proxied connection from getConnection() [not the physical
 
398
     * connection].
 
399
     */
 
400
    public void testCallableStatementConnection() {
 
401
        try {
 
402
            PooledConnection pc = getPooledConnection();
 
403
            Connection con = pc.getConnection();
 
404
            CallableStatement s = con.prepareCall("select 'x'");
 
405
            Connection conRetrieved = s.getConnection();
 
406
 
 
407
            assertTrue(con.getClass().equals(conRetrieved.getClass()));
 
408
            assertTrue(con.equals(conRetrieved));
 
409
        } catch (SQLException e) {
 
410
            fail(e.getMessage());
 
411
        }
 
412
    }
 
413
 
 
414
    /**
 
415
     * Ensure that a statement created from a pool can be used
 
416
     * like any other statement in regard to pg extensions.
 
417
     */
 
418
    public void testStatementsProxyPGStatement() {
 
419
        try {
 
420
            PooledConnection pc = getPooledConnection();
 
421
            con = pc.getConnection();
 
422
            
 
423
            Statement s = con.createStatement();
 
424
            boolean b = ((org.postgresql.PGStatement)s).isUseServerPrepare();
 
425
 
 
426
            PreparedStatement ps = con.prepareStatement("select 'x'");
 
427
            b = ((org.postgresql.PGStatement)ps).isUseServerPrepare();
 
428
 
 
429
            CallableStatement cs = con.prepareCall("select 'x'");
 
430
            b = ((org.postgresql.PGStatement)cs).isUseServerPrepare();
 
431
 
 
432
        } catch (SQLException e) {
 
433
            fail(e.getMessage());
 
434
        }
 
435
    }
 
436
 
 
437
    /**
 
438
         * Helper class to remove a listener during event dispatching.
 
439
         */
 
440
        private class RemoveClose implements ConnectionEventListener
 
441
        {
 
442
                public void connectionClosed(ConnectionEvent event)
 
443
                {
 
444
                        ((PooledConnection)event.getSource()).removeConnectionEventListener(this);
 
445
                }
 
446
 
 
447
                public void connectionErrorOccurred(ConnectionEvent event)
 
448
                {
 
449
                        ((PooledConnection)event.getSource()).removeConnectionEventListener(this);
 
450
                }
 
451
        }
 
452
 
 
453
        /**
 
454
         * Helper class that implements the event listener interface, and
 
455
         * counts the number of events it sees.
 
456
         */
 
457
        private class CountClose implements ConnectionEventListener
 
458
        {
 
459
                private int count = 0, errorCount = 0;
 
460
                public void connectionClosed(ConnectionEvent event)
 
461
                {
 
462
                        count++;
 
463
                }
 
464
 
 
465
                public void connectionErrorOccurred(ConnectionEvent event)
 
466
                {
 
467
                        errorCount++;
 
468
                }
 
469
 
 
470
                public int getCount()
 
471
                {
 
472
                        return count;
 
473
                }
 
474
 
 
475
                public int getErrorCount()
 
476
                {
 
477
                        return errorCount;
 
478
                }
 
479
 
 
480
                public void clear()
 
481
                {
 
482
                        count = errorCount = 0;
 
483
                }
 
484
        }
 
485
 
 
486
        public void testSerializable() throws IOException, ClassNotFoundException
 
487
        {
 
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);
 
495
 
 
496
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
 
497
                ObjectOutputStream oos = new ObjectOutputStream(baos);
 
498
                oos.writeObject(pool);
 
499
 
 
500
                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
 
501
                ObjectInputStream ois = new ObjectInputStream(bais);
 
502
                ConnectionPool pool2 = (ConnectionPool)ois.readObject();
 
503
 
 
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());
 
510
        }
 
511
 
 
512
}