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;
022:
023: import java.sql.Connection;
024: import java.sql.SQLException;
025: import java.util.concurrent.locks.Lock;
026:
027: import net.sf.hajdbc.DatabaseCluster;
028: import net.sf.hajdbc.LockManager;
029:
030: import org.easymock.EasyMock;
031: import org.testng.annotations.AfterMethod;
032: import org.testng.annotations.DataProvider;
033: import org.testng.annotations.Test;
034:
035: /**
036: * @author Paul Ferraro
037: *
038: */
039: @SuppressWarnings("unchecked")
040: public class TestLocalTransactionContext implements TransactionContext {
041: private Connection connection = EasyMock
042: .createStrictMock(Connection.class);
043: private DatabaseCluster cluster = EasyMock
044: .createStrictMock(DatabaseCluster.class);
045: private InvocationStrategy strategy = EasyMock
046: .createStrictMock(InvocationStrategy.class);
047: private LockManager lockManager = EasyMock
048: .createStrictMock(LockManager.class);
049: private Lock lock = EasyMock.createStrictMock(Lock.class);
050:
051: private Object[] objects() {
052: return new Object[] { this .connection, this .cluster,
053: this .strategy, this .lock, this .lockManager };
054: }
055:
056: void replay() {
057: EasyMock.replay(this .objects());
058: }
059:
060: void verify() {
061: EasyMock.verify(this .objects());
062: }
063:
064: @AfterMethod
065: void reset() {
066: EasyMock.reset(this .objects());
067: }
068:
069: @DataProvider(name="start")
070: Object[][] startParameters() {
071: return new Object[][] { new Object[] { this .strategy,
072: this .connection } };
073: }
074:
075: @Override
076: @Test(dataProvider="start")
077: public InvocationStrategy start(InvocationStrategy strategy,
078: Connection connection) throws SQLException {
079: EasyMock.expect(this .cluster.getLockManager()).andReturn(
080: this .lockManager);
081: EasyMock.expect(this .lockManager.readLock(LockManager.GLOBAL))
082: .andReturn(this .lock);
083:
084: this .replay();
085:
086: TransactionContext context = new LocalTransactionContext(
087: this .cluster);
088:
089: this .verify();
090: this .reset();
091:
092: SQLProxy proxy = EasyMock.createMock(SQLProxy.class);
093: Invoker invoker = EasyMock.createMock(Invoker.class);
094:
095: // Auto-commit on
096: EasyMock.expect(this .connection.getAutoCommit())
097: .andReturn(true);
098:
099: this .replay();
100:
101: InvocationStrategy result = context.start(strategy, connection);
102:
103: this .verify();
104:
105: assert result != null;
106: assert result != strategy;
107: assert LockingInvocationStrategy.class.isInstance(result) : result
108: .getClass().getName();
109:
110: this .reset();
111:
112: try {
113: Object object = new Object();
114:
115: this .lock.lock();
116:
117: EasyMock.expect(strategy.invoke(proxy, invoker)).andReturn(
118: object);
119:
120: this .lock.unlock();
121:
122: this .replay();
123:
124: Object invocationResult = result.invoke(proxy, invoker);
125:
126: this .verify();
127:
128: assert invocationResult == object;
129:
130: this .reset();
131: } catch (Exception e) {
132: assert false : e;
133: }
134:
135: // Auto-commit off
136: EasyMock.expect(this .connection.getAutoCommit()).andReturn(
137: false);
138:
139: this .replay();
140:
141: result = context.start(strategy, connection);
142:
143: this .verify();
144:
145: assert result != null;
146: assert result != strategy;
147: assert !LockingInvocationStrategy.class.isInstance(result);
148:
149: this .reset();
150:
151: try {
152: Object object = new Object();
153:
154: this .lock.lock();
155:
156: EasyMock.expect(strategy.invoke(proxy, invoker)).andReturn(
157: object);
158:
159: this .replay();
160:
161: Object invocationResult = result.invoke(proxy, invoker);
162:
163: this .verify();
164:
165: assert invocationResult == object;
166:
167: this .reset();
168: } catch (Exception e) {
169: assert false : e;
170: }
171:
172: // Already locked
173: this .replay();
174:
175: result = context.start(strategy, connection);
176:
177: this .verify();
178:
179: assert result == strategy;
180:
181: return result;
182: }
183:
184: @DataProvider(name="end")
185: Object[][] endParameters() {
186: return new Object[][] { new Object[] { this .strategy } };
187: }
188:
189: @Override
190: @Test(dataProvider="end")
191: public InvocationStrategy end(InvocationStrategy strategy)
192: throws SQLException {
193: EasyMock.expect(this .cluster.getLockManager()).andReturn(
194: this .lockManager);
195: EasyMock.expect(this .lockManager.readLock(LockManager.GLOBAL))
196: .andReturn(this .lock);
197:
198: this .replay();
199:
200: TransactionContext context = new LocalTransactionContext(
201: this .cluster);
202:
203: this .verify();
204: this .reset();
205:
206: // Not locked
207: this .replay();
208:
209: InvocationStrategy result = context.end(strategy);
210:
211: this .verify();
212:
213: assert result == strategy;
214:
215: this .reset();
216:
217: // Simulate transaction start
218: EasyMock.expect(this .connection.getAutoCommit()).andReturn(
219: false);
220:
221: this .replay();
222:
223: result = context.start(this .strategy, this .connection);
224:
225: this .verify();
226: this .reset();
227:
228: SQLProxy proxy = EasyMock.createMock(SQLProxy.class);
229: Invoker invoker = EasyMock.createMock(Invoker.class);
230:
231: Object object = new Object();
232:
233: try {
234: this .lock.lock();
235:
236: EasyMock.expect(this .strategy.invoke(proxy, invoker))
237: .andReturn(object);
238:
239: this .replay();
240:
241: Object invocationResult = result.invoke(proxy, invoker);
242:
243: this .verify();
244:
245: assert invocationResult == object;
246:
247: this .reset();
248: } catch (Exception e) {
249: assert false : e;
250: }
251:
252: // Locked
253: this .replay();
254:
255: result = context.end(strategy);
256:
257: this .verify();
258:
259: assert result != strategy;
260:
261: this .reset();
262:
263: try {
264: EasyMock.expect(strategy.invoke(proxy, invoker)).andReturn(
265: object);
266:
267: this .lock.unlock();
268:
269: this .replay();
270:
271: Object invocationResult = result.invoke(proxy, invoker);
272:
273: this .verify();
274:
275: assert invocationResult == object;
276: } catch (Exception e) {
277: assert false : e;
278: }
279:
280: return result;
281: }
282:
283: @Override
284: @Test
285: public void close() {
286: EasyMock.expect(this .cluster.getLockManager()).andReturn(
287: this .lockManager);
288: EasyMock.expect(this .lockManager.readLock(LockManager.GLOBAL))
289: .andReturn(this .lock);
290:
291: this .replay();
292:
293: TransactionContext context = new LocalTransactionContext(
294: this .cluster);
295:
296: this .verify();
297: this .reset();
298:
299: // Normally uneventful
300: this .replay();
301:
302: context.close();
303:
304: this .verify();
305: this .reset();
306:
307: // Simulate transaction start
308: try {
309: EasyMock.expect(this .connection.getAutoCommit()).andReturn(
310: false);
311:
312: this .replay();
313:
314: InvocationStrategy result = context.start(this .strategy,
315: this .connection);
316:
317: this .verify();
318: this .reset();
319:
320: SQLProxy proxy = EasyMock.createMock(SQLProxy.class);
321: Invoker invoker = EasyMock.createMock(Invoker.class);
322:
323: Object object = new Object();
324:
325: this .lock.lock();
326:
327: EasyMock.expect(this .strategy.invoke(proxy, invoker))
328: .andReturn(object);
329:
330: this .replay();
331:
332: Object invocationResult = result.invoke(proxy, invoker);
333:
334: this .verify();
335:
336: assert invocationResult == object;
337:
338: this .reset();
339: } catch (Exception e) {
340: assert false : e;
341: }
342:
343: // Closing with uncommitted transaction
344: this.lock.unlock();
345:
346: this.replay();
347:
348: context.close();
349:
350: this.verify();
351: }
352: }
|