001: /*
002: * HA-JDBC: High-Availability JDBC
003: * Copyright (c) 2004-2007 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.io.ByteArrayInputStream;
024: import java.io.ByteArrayOutputStream;
025: import java.io.InputStream;
026: import java.io.OutputStream;
027: import java.io.Reader;
028: import java.io.StringReader;
029: import java.io.StringWriter;
030: import java.io.Writer;
031: import java.sql.Clob;
032: import java.sql.NClob;
033: import java.sql.SQLException;
034: import java.util.Map;
035: import java.util.Set;
036: import java.util.TreeMap;
037: import java.util.concurrent.ExecutorService;
038: import java.util.concurrent.Executors;
039: import java.util.concurrent.locks.Lock;
040:
041: import net.sf.hajdbc.Balancer;
042: import net.sf.hajdbc.Database;
043: import net.sf.hajdbc.DatabaseCluster;
044: import net.sf.hajdbc.LockManager;
045: import net.sf.hajdbc.MockDatabase;
046: import net.sf.hajdbc.util.reflect.ProxyFactory;
047:
048: import org.easymock.EasyMock;
049: import org.testng.annotations.AfterMethod;
050: import org.testng.annotations.BeforeClass;
051: import org.testng.annotations.DataProvider;
052: import org.testng.annotations.Test;
053:
054: /**
055: * @author Paul Ferraro
056: *
057: */
058: @SuppressWarnings({"unchecked","nls"})
059: public class TestClob implements NClob {
060: private Balancer balancer = EasyMock
061: .createStrictMock(Balancer.class);
062: private DatabaseCluster cluster = EasyMock
063: .createStrictMock(DatabaseCluster.class);
064: private Lock readLock = EasyMock.createStrictMock(Lock.class);
065: private Lock writeLock1 = EasyMock.createStrictMock(Lock.class);
066: private Lock writeLock2 = EasyMock.createStrictMock(Lock.class);
067: private LockManager lockManager = EasyMock
068: .createStrictMock(LockManager.class);
069: private NClob clob1 = EasyMock.createStrictMock(NClob.class);
070: private NClob clob2 = EasyMock.createStrictMock(NClob.class);
071: private SQLProxy parent = EasyMock.createStrictMock(SQLProxy.class);
072: private SQLProxy root = EasyMock.createStrictMock(SQLProxy.class);
073:
074: private Database database1 = new MockDatabase("1");
075: private Database database2 = new MockDatabase("2");
076: private Set<Database> databaseSet;
077: private ExecutorService executor = Executors
078: .newSingleThreadExecutor();
079: private NClob clob;
080: private ClobInvocationHandler handler;
081:
082: @BeforeClass
083: void init() throws Exception {
084: Map<Database, NClob> map = new TreeMap<Database, NClob>();
085: map.put(this .database1, this .clob1);
086: map.put(this .database2, this .clob2);
087:
088: this .databaseSet = map.keySet();
089:
090: EasyMock.expect(this .parent.getDatabaseCluster()).andReturn(
091: this .cluster);
092: this .parent.addChild(EasyMock.isA(ClobInvocationHandler.class));
093:
094: this .replay();
095:
096: this .handler = new ClobInvocationHandler(new Object(),
097: this .parent, EasyMock.createMock(Invoker.class), map);
098: this .clob = ProxyFactory.createProxy(NClob.class, this .handler);
099:
100: this .verify();
101: this .reset();
102: }
103:
104: private Object[] objects() {
105: return new Object[] { this .cluster, this .balancer, this .clob1,
106: this .clob2, this .readLock, this .writeLock1,
107: this .writeLock2, this .lockManager, this .parent,
108: this .root };
109: }
110:
111: void replay() {
112: EasyMock.replay(this .objects());
113: }
114:
115: void verify() {
116: EasyMock.verify(this .objects());
117: }
118:
119: @AfterMethod
120: void reset() {
121: EasyMock.reset(this .objects());
122: }
123:
124: /**
125: * @see java.sql.Clob#free()
126: */
127: @Test
128: public void free() throws SQLException {
129: EasyMock.expect(this .cluster.isActive()).andReturn(true);
130:
131: EasyMock.expect(this .cluster.getNonTransactionalExecutor())
132: .andReturn(this .executor);
133:
134: EasyMock.expect(this .cluster.getBalancer()).andReturn(
135: this .balancer);
136: EasyMock.expect(this .balancer.all())
137: .andReturn(this .databaseSet);
138:
139: EasyMock.expect(this .parent.getRoot()).andReturn(this .root);
140:
141: this .root.retain(this .databaseSet);
142:
143: this .parent.removeChild(this .handler);
144:
145: this .clob1.free();
146: this .clob2.free();
147:
148: this .replay();
149:
150: this .clob.free();
151:
152: this .verify();
153: }
154:
155: /**
156: * @see java.sql.Clob#getAsciiStream()
157: */
158: @Test
159: public InputStream getAsciiStream() throws SQLException {
160: InputStream input = new ByteArrayInputStream(new byte[0]);
161:
162: EasyMock.expect(this .cluster.isActive()).andReturn(true);
163:
164: EasyMock.expect(this .cluster.getBalancer()).andReturn(
165: this .balancer);
166: EasyMock.expect(this .balancer.next()).andReturn(this .database2);
167:
168: this .balancer.beforeInvocation(this .database2);
169:
170: EasyMock.expect(this .clob2.getAsciiStream()).andReturn(input);
171:
172: this .balancer.afterInvocation(this .database2);
173:
174: this .replay();
175:
176: InputStream result = this .clob.getAsciiStream();
177:
178: this .verify();
179:
180: assert result == input;
181:
182: return result;
183: }
184:
185: /**
186: * @see java.sql.Clob#getCharacterStream()
187: */
188: @Test
189: public Reader getCharacterStream() throws SQLException {
190: Reader reader = new StringReader("");
191:
192: EasyMock.expect(this .cluster.isActive()).andReturn(true);
193:
194: EasyMock.expect(this .cluster.getBalancer()).andReturn(
195: this .balancer);
196: EasyMock.expect(this .balancer.next()).andReturn(this .database2);
197:
198: this .balancer.beforeInvocation(this .database2);
199:
200: EasyMock.expect(this .clob2.getCharacterStream()).andReturn(
201: reader);
202:
203: this .balancer.afterInvocation(this .database2);
204:
205: this .replay();
206:
207: Reader result = this .clob.getCharacterStream();
208:
209: this .verify();
210:
211: assert result == reader;
212:
213: return result;
214: }
215:
216: @DataProvider(name="long-long")
217: Object[][] longLongProvider() {
218: return new Object[][] { new Object[] { 1L, 1L } };
219: }
220:
221: /**
222: * @see java.sql.Clob#getCharacterStream(long, long)
223: */
224: @Test(dataProvider="long-long")
225: public Reader getCharacterStream(long position, long length)
226: throws SQLException {
227: Reader reader = new StringReader("");
228:
229: EasyMock.expect(this .cluster.isActive()).andReturn(true);
230:
231: EasyMock.expect(this .cluster.getBalancer()).andReturn(
232: this .balancer);
233: EasyMock.expect(this .balancer.next()).andReturn(this .database2);
234:
235: this .balancer.beforeInvocation(this .database2);
236:
237: EasyMock
238: .expect(this .clob2.getCharacterStream(position, length))
239: .andReturn(reader);
240:
241: this .balancer.afterInvocation(this .database2);
242:
243: this .replay();
244:
245: Reader result = this .clob.getCharacterStream(position, length);
246:
247: this .verify();
248:
249: assert result == reader;
250:
251: return result;
252: }
253:
254: @DataProvider(name="long-int")
255: Object[][] longIntProvider() {
256: return new Object[][] { new Object[] { 1L, 1 } };
257: }
258:
259: /**
260: * @see java.sql.Clob#getSubString(long, int)
261: */
262: @Test(dataProvider="long-int")
263: public String getSubString(long position, int length)
264: throws SQLException {
265: EasyMock.expect(this .cluster.isActive()).andReturn(true);
266:
267: EasyMock.expect(this .cluster.getBalancer()).andReturn(
268: this .balancer);
269: EasyMock.expect(this .balancer.next()).andReturn(this .database2);
270:
271: this .balancer.beforeInvocation(this .database2);
272:
273: EasyMock.expect(this .clob2.getSubString(position, length))
274: .andReturn("");
275:
276: this .balancer.afterInvocation(this .database2);
277:
278: this .replay();
279:
280: String result = this .clob.getSubString(position, length);
281:
282: this .verify();
283:
284: assert result.equals("");
285:
286: return result;
287: }
288:
289: /**
290: * @see java.sql.Clob#length()
291: */
292: @Test
293: public long length() throws SQLException {
294: EasyMock.expect(this .cluster.isActive()).andReturn(true);
295:
296: EasyMock.expect(this .cluster.getBalancer()).andReturn(
297: this .balancer);
298: EasyMock.expect(this .balancer.next()).andReturn(this .database2);
299:
300: this .balancer.beforeInvocation(this .database2);
301:
302: EasyMock.expect(this .clob2.length()).andReturn(1L);
303:
304: this .balancer.afterInvocation(this .database2);
305:
306: this .replay();
307:
308: long result = this .clob.length();
309:
310: this .verify();
311:
312: assert result == 1L;
313:
314: return result;
315: }
316:
317: @DataProvider(name="string-long")
318: Object[][] stringLongProvider() {
319: return new Object[][] { new Object[] { "", 1L } };
320: }
321:
322: /**
323: * @see java.sql.Clob#position(java.lang.String, long)
324: */
325: @Test(dataProvider="string-long")
326: public long position(String pattern, long start)
327: throws SQLException {
328: EasyMock.expect(this .cluster.isActive()).andReturn(true);
329:
330: EasyMock.expect(this .cluster.getBalancer()).andReturn(
331: this .balancer);
332: EasyMock.expect(this .balancer.next()).andReturn(this .database2);
333:
334: this .balancer.beforeInvocation(this .database2);
335:
336: EasyMock.expect(this .clob2.position(pattern, start)).andReturn(
337: 1L);
338:
339: this .balancer.afterInvocation(this .database2);
340:
341: this .replay();
342:
343: long result = this .clob.position(pattern, start);
344:
345: this .verify();
346:
347: assert result == 1L;
348:
349: return result;
350: }
351:
352: @DataProvider(name="clob-long")
353: Object[][] clobLongProvider() {
354: return new Object[][] { new Object[] {
355: EasyMock.createMock(Clob.class), 1L } };
356: }
357:
358: /**
359: * @see java.sql.Clob#position(java.sql.Clob, long)
360: */
361: @Test(dataProvider="clob-long")
362: public long position(Clob pattern, long start) throws SQLException {
363: EasyMock.expect(this .cluster.isActive()).andReturn(true);
364:
365: EasyMock.expect(this .cluster.getBalancer()).andReturn(
366: this .balancer);
367: EasyMock.expect(this .balancer.next()).andReturn(this .database2);
368:
369: this .balancer.beforeInvocation(this .database2);
370:
371: EasyMock.expect(this .clob2.position(pattern, start)).andReturn(
372: 1L);
373:
374: this .balancer.afterInvocation(this .database2);
375:
376: this .replay();
377:
378: long result = this .clob.position(pattern, start);
379:
380: this .verify();
381:
382: assert result == 1L;
383:
384: return result;
385: }
386:
387: @DataProvider(name="long")
388: Object[][] longProvider() {
389: return new Object[][] { new Object[] { 1L } };
390: }
391:
392: /**
393: * @see java.sql.Clob#setAsciiStream(long)
394: */
395: @Test(dataProvider="long")
396: public OutputStream setAsciiStream(long position)
397: throws SQLException {
398: OutputStream output1 = new ByteArrayOutputStream();
399: OutputStream output2 = new ByteArrayOutputStream();
400:
401: EasyMock.expect(this .cluster.isActive()).andReturn(true);
402:
403: EasyMock.expect(this .cluster.getNonTransactionalExecutor())
404: .andReturn(this .executor);
405:
406: EasyMock.expect(this .cluster.getBalancer()).andReturn(
407: this .balancer);
408: EasyMock.expect(this .balancer.all())
409: .andReturn(this .databaseSet);
410:
411: EasyMock.expect(this .parent.getRoot()).andReturn(this .root);
412:
413: this .root.retain(this .databaseSet);
414:
415: EasyMock.expect(this .clob1.setAsciiStream(position)).andReturn(
416: output1);
417: EasyMock.expect(this .clob2.setAsciiStream(position)).andReturn(
418: output2);
419:
420: this .replay();
421:
422: OutputStream result = this .clob.setAsciiStream(position);
423:
424: this .verify();
425:
426: assert result == output1;
427:
428: return result;
429: }
430:
431: /**
432: * @see java.sql.Clob#setCharacterStream(long)
433: */
434: @Test(dataProvider="long")
435: public Writer setCharacterStream(long position) throws SQLException {
436: Writer writer1 = new StringWriter();
437: Writer writer2 = new StringWriter();
438:
439: EasyMock.expect(this .cluster.isActive()).andReturn(true);
440:
441: EasyMock.expect(this .cluster.getNonTransactionalExecutor())
442: .andReturn(this .executor);
443:
444: EasyMock.expect(this .cluster.getBalancer()).andReturn(
445: this .balancer);
446: EasyMock.expect(this .balancer.all())
447: .andReturn(this .databaseSet);
448:
449: EasyMock.expect(this .parent.getRoot()).andReturn(this .root);
450:
451: this .root.retain(this .databaseSet);
452:
453: EasyMock.expect(this .clob1.setCharacterStream(position))
454: .andReturn(writer1);
455: EasyMock.expect(this .clob2.setCharacterStream(position))
456: .andReturn(writer2);
457:
458: this .replay();
459:
460: Writer result = this .clob.setCharacterStream(position);
461:
462: this .verify();
463:
464: assert result == writer1;
465:
466: return result;
467: }
468:
469: @DataProvider(name="long-string")
470: Object[][] longBytesProvider() {
471: return new Object[][] { new Object[] { 1L, "" } };
472: }
473:
474: /**
475: * @see java.sql.Clob#setString(long, java.lang.String)
476: */
477: @Test(dataProvider="long-string")
478: public int setString(long position, String string)
479: throws SQLException {
480: EasyMock.expect(this .cluster.isActive()).andReturn(true);
481:
482: EasyMock.expect(this .cluster.getNonTransactionalExecutor())
483: .andReturn(this .executor);
484:
485: EasyMock.expect(this .cluster.getBalancer()).andReturn(
486: this .balancer);
487: EasyMock.expect(this .balancer.all())
488: .andReturn(this .databaseSet);
489:
490: EasyMock.expect(this .parent.getRoot()).andReturn(this .root);
491:
492: this .root.retain(this .databaseSet);
493:
494: EasyMock.expect(this .clob1.setString(position, string))
495: .andReturn(1);
496: EasyMock.expect(this .clob2.setString(position, string))
497: .andReturn(1);
498:
499: this .replay();
500:
501: int result = this .clob.setString(position, string);
502:
503: this .verify();
504:
505: assert result == 1;
506:
507: return result;
508: }
509:
510: @DataProvider(name="long-string-int-int")
511: Object[][] longBytesIntIntProvider() {
512: return new Object[][] { new Object[] { 1L, "", 1, 1 } };
513: }
514:
515: /**
516: * @see java.sql.Clob#setString(long, java.lang.String, int, int)
517: */
518: @Test(dataProvider="long-string-int-int")
519: public int setString(long position, String string, int offset,
520: int length) throws SQLException {
521: EasyMock.expect(this .cluster.isActive()).andReturn(true);
522:
523: EasyMock.expect(this .cluster.getNonTransactionalExecutor())
524: .andReturn(this .executor);
525:
526: EasyMock.expect(this .cluster.getBalancer()).andReturn(
527: this .balancer);
528: EasyMock.expect(this .balancer.all())
529: .andReturn(this .databaseSet);
530:
531: EasyMock.expect(this .parent.getRoot()).andReturn(this .root);
532:
533: this .root.retain(this .databaseSet);
534:
535: EasyMock.expect(
536: this .clob1.setString(position, string, offset, length))
537: .andReturn(1);
538: EasyMock.expect(
539: this .clob2.setString(position, string, offset, length))
540: .andReturn(1);
541:
542: this .replay();
543:
544: int result = this .clob.setString(position, string, offset,
545: length);
546:
547: this .verify();
548:
549: assert result == 1;
550:
551: return result;
552: }
553:
554: /**
555: * @see java.sql.Clob#truncate(long)
556: */
557: @Test(dataProvider="long")
558: public void truncate(long position) throws SQLException {
559: EasyMock.expect(this .cluster.isActive()).andReturn(true);
560:
561: EasyMock.expect(this.cluster.getNonTransactionalExecutor())
562: .andReturn(this.executor);
563:
564: EasyMock.expect(this.cluster.getBalancer()).andReturn(
565: this.balancer);
566: EasyMock.expect(this.balancer.all())
567: .andReturn(this.databaseSet);
568:
569: EasyMock.expect(this.parent.getRoot()).andReturn(this.root);
570:
571: this.root.retain(this.databaseSet);
572:
573: this.clob1.truncate(position);
574: this.clob2.truncate(position);
575:
576: this.replay();
577:
578: this.clob.truncate(position);
579:
580: this.verify();
581: }
582: }
|