001: /*
002: * HA-JDBC: High-Availability JDBC
003: * Copyright (c) 2004-2008 Paul Ferraro
004: *
005: * This library is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU Lesser General Public License as published by the
007: * Free Software Foundation; either version 2.1 of the License, or (at your
008: * option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
013: * for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public License
016: * along with this library; if not, write to the Free Software Foundation,
017: * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *
019: * Contact: ferraro@users.sourceforge.net
020: */
021: package net.sf.hajdbc.sql.pool;
022:
023: import java.lang.reflect.Proxy;
024: import java.sql.Connection;
025: import java.sql.SQLException;
026: import java.util.Map;
027: import java.util.Set;
028: import java.util.TreeMap;
029: import java.util.concurrent.ExecutorService;
030: import java.util.concurrent.Executors;
031: import java.util.concurrent.locks.Lock;
032:
033: import javax.sql.ConnectionEventListener;
034: import javax.sql.ConnectionPoolDataSource;
035: import javax.sql.PooledConnection;
036: import javax.sql.StatementEventListener;
037:
038: import net.sf.hajdbc.Balancer;
039: import net.sf.hajdbc.Database;
040: import net.sf.hajdbc.DatabaseCluster;
041: import net.sf.hajdbc.LockManager;
042: import net.sf.hajdbc.MockDatabase;
043: import net.sf.hajdbc.sql.Invoker;
044: import net.sf.hajdbc.sql.SQLProxy;
045: import net.sf.hajdbc.util.reflect.ProxyFactory;
046:
047: import org.easymock.EasyMock;
048: import org.testng.annotations.AfterMethod;
049: import org.testng.annotations.BeforeClass;
050: import org.testng.annotations.DataProvider;
051: import org.testng.annotations.Test;
052:
053: /**
054: * @author Paul Ferraro
055: *
056: */
057: @SuppressWarnings({"unchecked","nls"})
058: public class TestPooledConnection implements PooledConnection {
059: protected Balancer balancer = EasyMock
060: .createStrictMock(Balancer.class);
061: protected DatabaseCluster cluster = EasyMock
062: .createStrictMock(DatabaseCluster.class);
063: protected PooledConnection connection1 = EasyMock
064: .createStrictMock(PooledConnection.class);
065: protected PooledConnection connection2 = EasyMock
066: .createStrictMock(PooledConnection.class);
067: protected SQLProxy parent = EasyMock
068: .createStrictMock(SQLProxy.class);
069: private SQLProxy root = EasyMock.createStrictMock(SQLProxy.class);
070: private LockManager lockManager = EasyMock
071: .createStrictMock(LockManager.class);
072: private Lock lock = EasyMock.createStrictMock(Lock.class);
073:
074: protected Database database1 = new MockDatabase("1");
075: protected Database database2 = new MockDatabase("2");
076: protected Set<Database> databaseSet;
077: protected ExecutorService executor = Executors
078: .newSingleThreadExecutor();
079: private AbstractPooledConnectionInvocationHandler handler;
080: protected PooledConnection connection;
081:
082: protected Class<? extends PooledConnection> getConnectionClass() {
083: return PooledConnection.class;
084: }
085:
086: protected AbstractPooledConnectionInvocationHandler getInvocationHandler(
087: Map map) throws Exception {
088: return new PooledConnectionInvocationHandler(EasyMock
089: .createStrictMock(ConnectionPoolDataSource.class),
090: this .parent, EasyMock.createMock(Invoker.class), map);
091: }
092:
093: @BeforeClass
094: protected void init() throws Exception {
095: Map map = new TreeMap();
096: map.put(this .database1, this .connection1);
097: map.put(this .database2, this .connection2);
098:
099: this .databaseSet = map.keySet();
100:
101: EasyMock.expect(this .parent.getDatabaseCluster()).andReturn(
102: this .cluster);
103:
104: this .parent.addChild(EasyMock
105: .isA(AbstractPooledConnectionInvocationHandler.class));
106:
107: this .replay();
108:
109: this .handler = this .getInvocationHandler(map);
110: this .connection = ProxyFactory.createProxy(this
111: .getConnectionClass(), this .handler);
112:
113: this .verify();
114: this .reset();
115: }
116:
117: private Object[] objects() {
118: return new Object[] { this .cluster, this .balancer,
119: this .connection1, this .connection2, this .parent,
120: this .root, this .lock, this .lockManager };
121: }
122:
123: protected void replay() {
124: EasyMock.replay(this .objects());
125: }
126:
127: protected void verify() {
128: EasyMock.verify(this .objects());
129: }
130:
131: @AfterMethod
132: protected void reset() {
133: EasyMock.reset(this .objects());
134: }
135:
136: @DataProvider(name="connection-listener")
137: protected Object[][] connectionListenerParameters() {
138: return new Object[][] { new Object[] { EasyMock
139: .createMock(ConnectionEventListener.class) } };
140: }
141:
142: /**
143: * @see javax.sql.PooledConnection#addConnectionEventListener(javax.sql.ConnectionEventListener)
144: */
145: @Override
146: @Test(dataProvider="connection-listener")
147: public void addConnectionEventListener(
148: ConnectionEventListener listener) {
149: EasyMock.expect(this .cluster.isActive()).andReturn(true);
150:
151: this .connection1.addConnectionEventListener(listener);
152: this .connection2.addConnectionEventListener(listener);
153:
154: this .replay();
155:
156: this .connection.addConnectionEventListener(listener);
157:
158: this .verify();
159: }
160:
161: @DataProvider(name="statement-listener")
162: protected Object[][] statementListenerParameters() {
163: return new Object[][] { new Object[] { EasyMock
164: .createMock(StatementEventListener.class) } };
165: }
166:
167: /**
168: * @see javax.sql.PooledConnection#addStatementEventListener(javax.sql.StatementEventListener)
169: */
170: @Override
171: @Test(dataProvider="statement-listener")
172: public void addStatementEventListener(
173: StatementEventListener listener) {
174: EasyMock.expect(this .cluster.isActive()).andReturn(true);
175:
176: this .connection1.addStatementEventListener(listener);
177: this .connection2.addStatementEventListener(listener);
178:
179: this .replay();
180:
181: this .connection.addStatementEventListener(listener);
182:
183: this .verify();
184: }
185:
186: /**
187: * @see javax.sql.PooledConnection#close()
188: */
189: @Override
190: public void close() throws SQLException {
191: EasyMock.expect(this .cluster.isActive()).andReturn(true);
192:
193: EasyMock.expect(this .cluster.getNonTransactionalExecutor())
194: .andReturn(this .executor);
195:
196: EasyMock.expect(this .cluster.getBalancer()).andReturn(
197: this .balancer);
198: EasyMock.expect(this .balancer.all())
199: .andReturn(this .databaseSet);
200:
201: EasyMock.expect(this .parent.getRoot()).andReturn(this .root);
202:
203: this .root.retain(this .databaseSet);
204:
205: this .connection1.close();
206: this .connection2.close();
207:
208: this .parent.removeChild(this .handler);
209:
210: this .replay();
211:
212: this .connection.close();
213:
214: this .verify();
215: }
216:
217: /**
218: * @see javax.sql.PooledConnection#getConnection()
219: */
220: @Override
221: public Connection getConnection() throws SQLException {
222: Connection connection1 = EasyMock
223: .createStrictMock(Connection.class);
224: Connection connection2 = EasyMock
225: .createStrictMock(Connection.class);
226:
227: EasyMock.expect(this .cluster.isActive()).andReturn(true);
228:
229: EasyMock.expect(this .cluster.getLockManager()).andReturn(
230: this .lockManager);
231: EasyMock.expect(this .lockManager.readLock(LockManager.GLOBAL))
232: .andReturn(this .lock);
233:
234: EasyMock.expect(this .cluster.getNonTransactionalExecutor())
235: .andReturn(this .executor);
236:
237: EasyMock.expect(this .cluster.getBalancer()).andReturn(
238: this .balancer);
239: EasyMock.expect(this .balancer.all())
240: .andReturn(this .databaseSet);
241:
242: EasyMock.expect(this .connection1.getConnection()).andReturn(
243: connection1);
244: EasyMock.expect(this .connection2.getConnection()).andReturn(
245: connection2);
246:
247: this .replay();
248:
249: Connection result = this .connection.getConnection();
250:
251: this .verify();
252:
253: assert Proxy.isProxyClass(result.getClass());
254:
255: SQLProxy proxy = SQLProxy.class.cast(Proxy
256: .getInvocationHandler(result));
257:
258: assert proxy.getObject(this .database1) == connection1;
259: assert proxy.getObject(this .database2) == connection2;
260:
261: return result;
262: }
263:
264: /**
265: * @see javax.sql.PooledConnection#removeConnectionEventListener(javax.sql.ConnectionEventListener)
266: */
267: @Override
268: @Test(dataProvider="connection-listener")
269: public void removeConnectionEventListener(
270: ConnectionEventListener listener) {
271: EasyMock.expect(this .cluster.isActive()).andReturn(true);
272:
273: this .connection1.removeConnectionEventListener(listener);
274: this .connection2.removeConnectionEventListener(listener);
275:
276: this .replay();
277:
278: this .connection.removeConnectionEventListener(listener);
279:
280: this .verify();
281: }
282:
283: /**
284: * @see javax.sql.PooledConnection#removeStatementEventListener(javax.sql.StatementEventListener)
285: */
286: @Override
287: @Test(dataProvider="statement-listener")
288: public void removeStatementEventListener(
289: StatementEventListener listener) {
290: EasyMock.expect(this .cluster.isActive()).andReturn(true);
291:
292: this.connection1.removeStatementEventListener(listener);
293: this.connection2.removeStatementEventListener(listener);
294:
295: this.replay();
296:
297: this.connection.removeStatementEventListener(listener);
298:
299: this.verify();
300: }
301: }
|