001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.commons.dbcp.datasources;
019:
020: import java.sql.Connection;
021: import java.sql.PreparedStatement;
022: import java.sql.ResultSet;
023: import java.sql.SQLException;
024:
025: import javax.sql.DataSource;
026:
027: import junit.framework.Test;
028: import junit.framework.TestSuite;
029:
030: import org.apache.commons.dbcp.TestConnectionPool;
031: import org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS;
032:
033: /**
034: * @author John McNally
035: * @author Dirk Verbeeck
036: * @version $Revision: 479137 $ $Date: 2006-11-25 08:51:48 -0700 (Sat, 25 Nov 2006) $
037: */
038: public class TestSharedPoolDataSource extends TestConnectionPool {
039: public TestSharedPoolDataSource(String testName) {
040: super (testName);
041: }
042:
043: public static Test suite() {
044: return new TestSuite(TestSharedPoolDataSource.class);
045: }
046:
047: protected Connection getConnection() throws Exception {
048: return ds.getConnection("foo", "bar");
049: }
050:
051: private DriverAdapterCPDS pcds;
052: private DataSource ds;
053:
054: public void setUp() throws Exception {
055: pcds = new DriverAdapterCPDS();
056: pcds.setDriver("org.apache.commons.dbcp.TesterDriver");
057: pcds.setUrl("jdbc:apache:commons:testdriver");
058: pcds.setUser("foo");
059: pcds.setPassword("bar");
060: pcds.setPoolPreparedStatements(false);
061:
062: SharedPoolDataSource tds = new SharedPoolDataSource();
063: tds.setConnectionPoolDataSource(pcds);
064: tds.setMaxActive(getMaxActive());
065: tds.setMaxWait((int) (getMaxWait()));
066: tds
067: .setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
068:
069: ds = tds;
070: }
071:
072: /**
073: * Switching 'u1 -> 'u2' and 'p1' -> 'p2' will
074: * exhibit the bug detailed in
075: * http://issues.apache.org/bugzilla/show_bug.cgi?id=18905
076: */
077: public void testIncorrectPassword() throws Exception {
078: try {
079: // Use bad password
080: ds.getConnection("u1", "zlsafjk").close();
081: fail("Able to retrieve connection with incorrect password");
082: } catch (SQLException e1) {
083: // should fail
084:
085: }
086:
087: // Use good password
088: ds.getConnection("u1", "p1").close();
089: try {
090: ds.getConnection("u1", "x").close();
091: fail("Able to retrieve connection with incorrect password");
092: } catch (SQLException e) {
093: if (!e.getMessage().startsWith(
094: "Given password did not match")) {
095: throw e;
096: }
097: // else the exception was expected
098: }
099:
100: // Make sure we can still use our good password.
101: ds.getConnection("u1", "p1").close();
102: }
103:
104: public void testSimple() throws Exception {
105: Connection conn = ds.getConnection();
106: assertTrue(null != conn);
107: PreparedStatement stmt = conn
108: .prepareStatement("select * from dual");
109: assertTrue(null != stmt);
110: ResultSet rset = stmt.executeQuery();
111: assertTrue(null != rset);
112: assertTrue(rset.next());
113: rset.close();
114: stmt.close();
115: conn.close();
116: }
117:
118: public void testSimpleWithUsername() throws Exception {
119: Connection conn = ds.getConnection("u1", "p1");
120: assertTrue(null != conn);
121: PreparedStatement stmt = conn
122: .prepareStatement("select * from dual");
123: assertTrue(null != stmt);
124: ResultSet rset = stmt.executeQuery();
125: assertTrue(null != rset);
126: assertTrue(rset.next());
127: rset.close();
128: stmt.close();
129: conn.close();
130: }
131:
132: public void testClosingWithUserName() throws Exception {
133: Connection[] c = new Connection[getMaxActive()];
134: // open the maximum connections
135: for (int i = 0; i < c.length; i++) {
136: c[i] = ds.getConnection("u1", "p1");
137: }
138:
139: // close one of the connections
140: c[0].close();
141: assertTrue(c[0].isClosed());
142: // get a new connection
143: c[0] = ds.getConnection("u1", "p1");
144:
145: for (int i = 0; i < c.length; i++) {
146: c[i].close();
147: }
148:
149: // open the maximum connections
150: for (int i = 0; i < c.length; i++) {
151: c[i] = ds.getConnection("u1", "p1");
152: }
153: for (int i = 0; i < c.length; i++) {
154: c[i].close();
155: }
156: }
157:
158: public void testSimple2() throws Exception {
159: Connection conn = ds.getConnection();
160: assertTrue(null != conn);
161:
162: PreparedStatement stmt = conn
163: .prepareStatement("select * from dual");
164: assertTrue(null != stmt);
165: ResultSet rset = stmt.executeQuery();
166: assertTrue(null != rset);
167: assertTrue(rset.next());
168: rset.close();
169: stmt.close();
170:
171: stmt = conn.prepareStatement("select * from dual");
172: assertTrue(null != stmt);
173: rset = stmt.executeQuery();
174: assertTrue(null != rset);
175: assertTrue(rset.next());
176: rset.close();
177: stmt.close();
178:
179: conn.close();
180: try {
181: conn.createStatement();
182: fail("Can't use closed connections");
183: } catch (SQLException e) {
184: // expected
185: }
186:
187: conn = ds.getConnection();
188: assertTrue(null != conn);
189:
190: stmt = conn.prepareStatement("select * from dual");
191: assertTrue(null != stmt);
192: rset = stmt.executeQuery();
193: assertTrue(null != rset);
194: assertTrue(rset.next());
195: rset.close();
196: stmt.close();
197:
198: stmt = conn.prepareStatement("select * from dual");
199: assertTrue(null != stmt);
200: rset = stmt.executeQuery();
201: assertTrue(null != rset);
202: assertTrue(rset.next());
203: rset.close();
204: stmt.close();
205:
206: conn.close();
207: conn = null;
208: }
209:
210: public void testOpening() throws Exception {
211: Connection[] c = new Connection[getMaxActive()];
212: // test that opening new connections is not closing previous
213: for (int i = 0; i < c.length; i++) {
214: c[i] = ds.getConnection();
215: assertTrue(c[i] != null);
216: for (int j = 0; j <= i; j++) {
217: assertTrue(!c[j].isClosed());
218: }
219: }
220:
221: for (int i = 0; i < c.length; i++) {
222: c[i].close();
223: }
224: }
225:
226: public void testClosing() throws Exception {
227: Connection[] c = new Connection[getMaxActive()];
228: // open the maximum connections
229: for (int i = 0; i < c.length; i++) {
230: c[i] = ds.getConnection();
231: }
232:
233: // close one of the connections
234: c[0].close();
235: assertTrue(c[0].isClosed());
236:
237: // get a new connection
238: c[0] = ds.getConnection();
239:
240: for (int i = 0; i < c.length; i++) {
241: c[i].close();
242: }
243: }
244:
245: /**
246: * Test pool close. Illustrates BZ 37359.
247: *
248: * @throws Exception
249: */
250: public void testClosePool() throws Exception {
251: ((SharedPoolDataSource) ds).close();
252: SharedPoolDataSource tds = new SharedPoolDataSource();
253: // NPE before BZ 37359 fix
254: tds.close();
255: }
256:
257: public void testMaxActive() throws Exception {
258: Connection[] c = new Connection[getMaxActive()];
259: for (int i = 0; i < c.length; i++) {
260: c[i] = ds.getConnection();
261: assertTrue(c[i] != null);
262: }
263:
264: try {
265: ds.getConnection();
266: fail("Allowed to open more than DefaultMaxActive connections.");
267: } catch (java.sql.SQLException e) {
268: // should only be able to open 10 connections, so this test should
269: // throw an exception
270: }
271:
272: for (int i = 0; i < c.length; i++) {
273: c[i].close();
274: }
275: }
276:
277: public void testMultipleThreads() throws Exception {
278: assertTrue(multipleThreads(1));
279: assertTrue(!multipleThreads(2 * (int) (getMaxWait())));
280: }
281:
282: private boolean multipleThreads(int holdTime) throws Exception {
283: long startTime = System.currentTimeMillis();
284: final boolean[] success = new boolean[1];
285: success[0] = true;
286: final PoolTest[] pts = new PoolTest[2 * getMaxActive()];
287: ThreadGroup threadGroup = new ThreadGroup("foo") {
288: public void uncaughtException(Thread t, Throwable e) {
289: /*
290: for (int i = 0; i < pts.length; i++)
291: {
292: System.out.println(i + ": " + pts[i].reportState());
293: }
294: */
295: for (int i = 0; i < pts.length; i++) {
296: pts[i].stop();
297: }
298:
299: //e.printStackTrace();
300: success[0] = false;
301: }
302: };
303:
304: for (int i = 0; i < pts.length; i++) {
305: pts[i] = new PoolTest(threadGroup, holdTime);
306: }
307: Thread.sleep(10 * holdTime);
308: for (int i = 0; i < pts.length; i++) {
309: pts[i].stop();
310: }
311: long time = System.currentTimeMillis() - startTime;
312: // - (pts.length*10*holdTime);
313: System.out.println("Multithread test time = " + time + " ms");
314:
315: Thread.sleep(holdTime);
316: return success[0];
317: }
318:
319: private static int currentThreadCount = 0;
320:
321: private class PoolTest implements Runnable {
322: /**
323: * The number of milliseconds to hold onto a database connection
324: */
325: private int connHoldTime;
326:
327: private boolean isRun;
328:
329: private String state;
330:
331: protected PoolTest(ThreadGroup threadGroup, int connHoldTime) {
332: this .connHoldTime = connHoldTime;
333: Thread thread = new Thread(threadGroup, this , "Thread+"
334: + currentThreadCount++);
335: thread.setDaemon(false);
336: thread.start();
337: }
338:
339: public void run() {
340: isRun = true;
341: while (isRun) {
342: try {
343: Connection conn = null;
344: state = "Getting Connection";
345: conn = getConnection();
346: state = "Using Connection";
347: assertTrue(null != conn);
348: PreparedStatement stmt = conn
349: .prepareStatement("select * from dual");
350: assertTrue(null != stmt);
351: ResultSet rset = stmt.executeQuery();
352: assertTrue(null != rset);
353: assertTrue(rset.next());
354: state = "Holding Connection";
355: Thread.sleep(connHoldTime);
356: state = "Returning Connection";
357: rset.close();
358: stmt.close();
359: conn.close();
360: } catch (RuntimeException e) {
361: throw e;
362: } catch (Exception e) {
363: throw new RuntimeException(e.toString());
364: }
365: }
366: }
367:
368: public void stop() {
369: isRun = false;
370: }
371:
372: public String reportState() {
373: return state;
374: }
375: }
376:
377: public void testTransactionIsolationBehavior() throws Exception {
378: Connection conn = getConnection();
379: assertTrue(conn != null);
380: assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn
381: .getTransactionIsolation());
382: conn
383: .setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
384: conn.close();
385:
386: Connection conn2 = getConnection();
387: assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn2
388: .getTransactionIsolation());
389:
390: Connection conn3 = getConnection();
391: assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn3
392: .getTransactionIsolation());
393: conn2.close();
394: conn3.close();
395: }
396:
397: // Bugzilla Bug 24136 ClassCastException in DriverAdapterCPDS
398: // when setPoolPreparedStatements(true)
399: public void testPoolPrepareStatement() throws Exception {
400: pcds.setPoolPreparedStatements(true);
401:
402: Connection conn = ds.getConnection();
403: assertTrue(null != conn);
404: PreparedStatement stmt = conn
405: .prepareStatement("select * from dual");
406: assertTrue(null != stmt);
407: ResultSet rset = stmt.executeQuery();
408: assertTrue(null != rset);
409: assertTrue(rset.next());
410: rset.close();
411: stmt.close();
412: conn.close();
413: }
414:
415: public void testPoolPreparedStatements() throws Exception {
416: DriverAdapterCPDS mypcds = new DriverAdapterCPDS();
417: DataSource myds = null;
418: mypcds.setDriver("org.apache.commons.dbcp.TesterDriver");
419: mypcds.setUrl("jdbc:apache:commons:testdriver");
420: mypcds.setUser("foo");
421: mypcds.setPassword("bar");
422: mypcds.setPoolPreparedStatements(true);
423: mypcds.setMaxPreparedStatements(10);
424:
425: SharedPoolDataSource tds = new SharedPoolDataSource();
426: tds.setConnectionPoolDataSource(mypcds);
427: tds.setMaxActive(getMaxActive());
428: tds.setMaxWait((int) (getMaxWait()));
429: tds
430: .setDefaultTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
431:
432: myds = tds;
433:
434: Connection conn = ds.getConnection();
435: PreparedStatement stmt = null;
436: ResultSet rset = null;
437:
438: assertTrue(null != conn);
439:
440: stmt = conn.prepareStatement("select * from dual");
441: assertTrue(null != stmt);
442: long l1HashCode = stmt.hashCode();
443: rset = stmt.executeQuery();
444: assertTrue(null != rset);
445: assertTrue(rset.next());
446: rset.close();
447: stmt.close();
448:
449: stmt = conn.prepareStatement("select * from dual");
450: assertTrue(null != stmt);
451: long l2HashCode = stmt.hashCode();
452: rset = stmt.executeQuery();
453: assertTrue(null != rset);
454: assertTrue(rset.next());
455: rset.close();
456: stmt.close();
457:
458: // statement pooling is not enabled, we should get different statements
459: assertTrue(l1HashCode != l2HashCode);
460: conn.close();
461: conn = null;
462:
463: conn = myds.getConnection();
464:
465: stmt = conn.prepareStatement("select * from dual");
466: assertTrue(null != stmt);
467: long l3HashCode = stmt.hashCode();
468: rset = stmt.executeQuery();
469: assertTrue(null != rset);
470: assertTrue(rset.next());
471: rset.close();
472: stmt.close();
473:
474: stmt = conn.prepareStatement("select * from dual");
475: assertTrue(null != stmt);
476: long l4HashCode = stmt.hashCode();
477: rset = stmt.executeQuery();
478: assertTrue(null != rset);
479: assertTrue(rset.next());
480: rset.close();
481: stmt.close();
482:
483: // prepared statement pooling is working
484: assertTrue(l3HashCode == l4HashCode);
485: conn.close();
486: conn = null;
487:
488: }
489: }
|