00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 package com.sleepycat.collections.test;
00011
00012 import java.util.Iterator;
00013 import java.util.List;
00014 import java.util.SortedSet;
00015
00016 import junit.framework.Test;
00017 import junit.framework.TestCase;
00018 import junit.framework.TestSuite;
00019
00020 import com.sleepycat.collections.CurrentTransaction;
00021 import com.sleepycat.collections.StoredCollections;
00022 import com.sleepycat.collections.StoredContainer;
00023 import com.sleepycat.collections.StoredIterator;
00024 import com.sleepycat.collections.StoredList;
00025 import com.sleepycat.collections.StoredSortedMap;
00026 import com.sleepycat.collections.TransactionRunner;
00027 import com.sleepycat.collections.TransactionWorker;
00028 import com.sleepycat.compat.DbCompat;
00029 import com.sleepycat.db.CursorConfig;
00030 import com.sleepycat.db.Database;
00031 import com.sleepycat.db.DatabaseConfig;
00032 import com.sleepycat.db.DatabaseEntry;
00033 import com.sleepycat.db.Environment;
00034 import com.sleepycat.db.Transaction;
00035 import com.sleepycat.db.TransactionConfig;
00036 import com.sleepycat.util.RuntimeExceptionWrapper;
00037
00041 public class TransactionTest extends TestCase {
00042
00043 private static final Long ONE = new Long(1);
00044 private static final Long TWO = new Long(2);
00045 private static final Long THREE = new Long(3);
00046
00051 public static void main(String[] args)
00052 throws Exception {
00053
00054 if (args.length == 1 &&
00055 (args[0].equals("-h") || args[0].equals("-help"))) {
00056 usage();
00057 } else {
00058 junit.framework.TestResult tr =
00059 junit.textui.TestRunner.run(suite());
00060 if (tr.errorCount() > 0 ||
00061 tr.failureCount() > 0) {
00062 System.exit(1);
00063 } else {
00064 System.exit(0);
00065 }
00066 }
00067 }
00068
00069 private static void usage() {
00070
00071 System.out.println(
00072 "Usage: java com.sleepycat.collections.test.TransactionTest"
00073 + " [-h | -help]\n");
00074 System.exit(2);
00075 }
00076
00077 public static Test suite()
00078 throws Exception {
00079
00080 TestSuite suite = new TestSuite(TransactionTest.class);
00081 return suite;
00082 }
00083
00084 private Environment env;
00085 private CurrentTransaction currentTxn;
00086 private Database store;
00087 private StoredSortedMap map;
00088 private TestStore testStore = TestStore.BTREE_UNIQ;
00089
00090 public TransactionTest(String name) {
00091
00092 super(name);
00093 }
00094
00095 public void setUp()
00096 throws Exception {
00097
00098 DbTestUtil.printTestName(DbTestUtil.qualifiedTestName(this));
00099 env = TestEnv.TXN.open("TransactionTests");
00100 currentTxn = CurrentTransaction.getInstance(env);
00101 store = testStore.open(env, dbName(0));
00102 map = new StoredSortedMap(store, testStore.getKeyBinding(),
00103 testStore.getValueBinding(), true);
00104 }
00105
00106 public void tearDown() {
00107
00108 try {
00109 if (store != null) {
00110 store.close();
00111 }
00112 if (env != null) {
00113 env.close();
00114 }
00115 } catch (Exception e) {
00116 System.out.println("Ignored exception during tearDown: " + e);
00117 } finally {
00118
00119 store = null;
00120 env = null;
00121 currentTxn = null;
00122 map = null;
00123 testStore = null;
00124 }
00125 }
00126
00127 private String dbName(int i) {
00128
00129 return "txn-test-" + getName() + '-' + i;
00130 }
00131
00132 public void testGetters()
00133 throws Exception {
00134
00135 assertNotNull(env);
00136 assertNotNull(currentTxn);
00137 assertNull(currentTxn.getTransaction());
00138
00139 currentTxn.beginTransaction(null);
00140 assertNotNull(currentTxn.getTransaction());
00141 currentTxn.commitTransaction();
00142 assertNull(currentTxn.getTransaction());
00143
00144 currentTxn.beginTransaction(null);
00145 assertNotNull(currentTxn.getTransaction());
00146 currentTxn.abortTransaction();
00147 assertNull(currentTxn.getTransaction());
00148
00149
00150
00151 assertTrue(!isReadUncommitted(map));
00152 assertTrue(!isReadUncommitted(map.values()));
00153 assertTrue(!isReadUncommitted(map.keySet()));
00154 assertTrue(!isReadUncommitted(map.entrySet()));
00155
00156 StoredSortedMap other = (StoredSortedMap)
00157 StoredCollections.configuredMap
00158 (map, CursorConfig.READ_UNCOMMITTED);
00159 assertTrue(isReadUncommitted(other));
00160 assertTrue(isReadUncommitted(other.values()));
00161 assertTrue(isReadUncommitted(other.keySet()));
00162 assertTrue(isReadUncommitted(other.entrySet()));
00163 assertTrue(!isReadUncommitted(map));
00164 assertTrue(!isReadUncommitted(map.values()));
00165 assertTrue(!isReadUncommitted(map.keySet()));
00166 assertTrue(!isReadUncommitted(map.entrySet()));
00167
00168
00169
00170 assertTrue(!isReadCommitted(map));
00171 assertTrue(!isReadCommitted(map.values()));
00172 assertTrue(!isReadCommitted(map.keySet()));
00173 assertTrue(!isReadCommitted(map.entrySet()));
00174
00175 other = (StoredSortedMap)
00176 StoredCollections.configuredMap
00177 (map, CursorConfig.READ_COMMITTED);
00178 assertTrue(isReadCommitted(other));
00179 assertTrue(isReadCommitted(other.values()));
00180 assertTrue(isReadCommitted(other.keySet()));
00181 assertTrue(isReadCommitted(other.entrySet()));
00182 assertTrue(!isReadCommitted(map));
00183 assertTrue(!isReadCommitted(map.values()));
00184 assertTrue(!isReadCommitted(map.keySet()));
00185 assertTrue(!isReadCommitted(map.entrySet()));
00186 }
00187
00188 public void testTransactional()
00189 throws Exception {
00190
00191
00192
00193
00194 assertTrue(map.isTransactional());
00195 store.close();
00196 store = null;
00197
00198
00199
00200 DatabaseConfig dbConfig = new DatabaseConfig();
00201 DbCompat.setTypeBtree(dbConfig);
00202 dbConfig.setAllowCreate(true);
00203 Database db = DbCompat.openDatabase(env, null,
00204 dbName(1), null,
00205 dbConfig);
00206 map = new StoredSortedMap(db, testStore.getKeyBinding(),
00207 testStore.getValueBinding(), true);
00208 assertTrue(!map.isTransactional());
00209 map.put(ONE, ONE);
00210 readCheck(map, ONE, ONE);
00211 db.close();
00212
00213
00214
00215 dbConfig.setTransactional(true);
00216 currentTxn.beginTransaction(null);
00217 db = DbCompat.openDatabase(env, currentTxn.getTransaction(),
00218 dbName(2), null, dbConfig);
00219 currentTxn.commitTransaction();
00220 map = new StoredSortedMap(db, testStore.getKeyBinding(),
00221 testStore.getValueBinding(), true);
00222 assertTrue(map.isTransactional());
00223 currentTxn.beginTransaction(null);
00224 map.put(ONE, ONE);
00225 readCheck(map, ONE, ONE);
00226 currentTxn.commitTransaction();
00227 db.close();
00228 }
00229
00230 public void testExceptions()
00231 throws Exception {
00232
00233 try {
00234 currentTxn.commitTransaction();
00235 fail();
00236 } catch (IllegalStateException expected) {}
00237
00238 try {
00239 currentTxn.abortTransaction();
00240 fail();
00241 } catch (IllegalStateException expected) {}
00242 }
00243
00244 public void testNested()
00245 throws Exception {
00246
00247 if (!DbCompat.NESTED_TRANSACTIONS) {
00248 return;
00249 }
00250 assertNull(currentTxn.getTransaction());
00251
00252 Transaction txn1 = currentTxn.beginTransaction(null);
00253 assertNotNull(txn1);
00254 assertTrue(txn1 == currentTxn.getTransaction());
00255
00256 assertNull(map.get(ONE));
00257 assertNull(map.put(ONE, ONE));
00258 assertEquals(ONE, map.get(ONE));
00259
00260 Transaction txn2 = currentTxn.beginTransaction(null);
00261 assertNotNull(txn2);
00262 assertTrue(txn2 == currentTxn.getTransaction());
00263 assertTrue(txn1 != txn2);
00264
00265 assertNull(map.put(TWO, TWO));
00266 assertEquals(TWO, map.get(TWO));
00267
00268 Transaction txn3 = currentTxn.beginTransaction(null);
00269 assertNotNull(txn3);
00270 assertTrue(txn3 == currentTxn.getTransaction());
00271 assertTrue(txn1 != txn2);
00272 assertTrue(txn1 != txn3);
00273 assertTrue(txn2 != txn3);
00274
00275 assertNull(map.put(THREE, THREE));
00276 assertEquals(THREE, map.get(THREE));
00277
00278 Transaction txn = currentTxn.abortTransaction();
00279 assertTrue(txn == txn2);
00280 assertTrue(txn == currentTxn.getTransaction());
00281 assertNull(map.get(THREE));
00282 assertEquals(TWO, map.get(TWO));
00283
00284 txn3 = currentTxn.beginTransaction(null);
00285 assertNotNull(txn3);
00286 assertTrue(txn3 == currentTxn.getTransaction());
00287 assertTrue(txn1 != txn2);
00288 assertTrue(txn1 != txn3);
00289 assertTrue(txn2 != txn3);
00290
00291 assertNull(map.put(THREE, THREE));
00292 assertEquals(THREE, map.get(THREE));
00293
00294 txn = currentTxn.commitTransaction();
00295 assertTrue(txn == txn2);
00296 assertTrue(txn == currentTxn.getTransaction());
00297 assertEquals(THREE, map.get(THREE));
00298 assertEquals(TWO, map.get(TWO));
00299
00300 txn = currentTxn.commitTransaction();
00301 assertTrue(txn == txn1);
00302 assertTrue(txn == currentTxn.getTransaction());
00303 assertEquals(THREE, map.get(THREE));
00304 assertEquals(TWO, map.get(TWO));
00305 assertEquals(ONE, map.get(ONE));
00306
00307 txn = currentTxn.commitTransaction();
00308 assertNull(txn);
00309 assertNull(currentTxn.getTransaction());
00310 assertEquals(THREE, map.get(THREE));
00311 assertEquals(TWO, map.get(TWO));
00312 assertEquals(ONE, map.get(ONE));
00313 }
00314
00315 public void testRunnerCommit()
00316 throws Exception {
00317
00318 commitTest(false);
00319 }
00320
00321 public void testExplicitCommit()
00322 throws Exception {
00323
00324 commitTest(true);
00325 }
00326
00327 private void commitTest(final boolean explicit)
00328 throws Exception {
00329
00330 final TransactionRunner runner = new TransactionRunner(env);
00331 runner.setAllowNestedTransactions(DbCompat.NESTED_TRANSACTIONS);
00332
00333 assertNull(currentTxn.getTransaction());
00334
00335 runner.run(new TransactionWorker() {
00336 public void doWork() throws Exception {
00337 final Transaction txn1 = currentTxn.getTransaction();
00338 assertNotNull(txn1);
00339 assertNull(map.put(ONE, ONE));
00340 assertEquals(ONE, map.get(ONE));
00341
00342 runner.run(new TransactionWorker() {
00343 public void doWork() throws Exception {
00344 final Transaction txn2 = currentTxn.getTransaction();
00345 assertNotNull(txn2);
00346 if (DbCompat.NESTED_TRANSACTIONS) {
00347 assertTrue(txn1 != txn2);
00348 } else {
00349 assertTrue(txn1 == txn2);
00350 }
00351 assertNull(map.put(TWO, TWO));
00352 assertEquals(TWO, map.get(TWO));
00353 assertEquals(ONE, map.get(ONE));
00354 if (DbCompat.NESTED_TRANSACTIONS && explicit) {
00355 currentTxn.commitTransaction();
00356 }
00357 }
00358 });
00359
00360 Transaction txn3 = currentTxn.getTransaction();
00361 assertSame(txn1, txn3);
00362
00363 assertEquals(TWO, map.get(TWO));
00364 assertEquals(ONE, map.get(ONE));
00365 }
00366 });
00367
00368 assertNull(currentTxn.getTransaction());
00369 }
00370
00371 public void testRunnerAbort()
00372 throws Exception {
00373
00374 abortTest(false);
00375 }
00376
00377 public void testExplicitAbort()
00378 throws Exception {
00379
00380 abortTest(true);
00381 }
00382
00383 private void abortTest(final boolean explicit)
00384 throws Exception {
00385
00386 final TransactionRunner runner = new TransactionRunner(env);
00387 runner.setAllowNestedTransactions(DbCompat.NESTED_TRANSACTIONS);
00388
00389 assertNull(currentTxn.getTransaction());
00390
00391 runner.run(new TransactionWorker() {
00392 public void doWork() throws Exception {
00393 final Transaction txn1 = currentTxn.getTransaction();
00394 assertNotNull(txn1);
00395 assertNull(map.put(ONE, ONE));
00396 assertEquals(ONE, map.get(ONE));
00397
00398 if (DbCompat.NESTED_TRANSACTIONS) {
00399 try {
00400 runner.run(new TransactionWorker() {
00401 public void doWork() throws Exception {
00402 final Transaction txn2 =
00403 currentTxn.getTransaction();
00404 assertNotNull(txn2);
00405 assertTrue(txn1 != txn2);
00406 assertNull(map.put(TWO, TWO));
00407 assertEquals(TWO, map.get(TWO));
00408 if (explicit) {
00409 currentTxn.abortTransaction();
00410 } else {
00411 throw new IllegalArgumentException(
00412 "test-abort");
00413 }
00414 }
00415 });
00416 assertTrue(explicit);
00417 } catch (IllegalArgumentException e) {
00418 assertTrue(!explicit);
00419 assertEquals("test-abort", e.getMessage());
00420 }
00421 }
00422
00423 Transaction txn3 = currentTxn.getTransaction();
00424 assertSame(txn1, txn3);
00425
00426 assertEquals(ONE, map.get(ONE));
00427 assertNull(map.get(TWO));
00428 }
00429 });
00430
00431 assertNull(currentTxn.getTransaction());
00432 }
00433
00434 public void testReadCommittedCollection()
00435 throws Exception {
00436
00437 StoredSortedMap degree2Map = (StoredSortedMap)
00438 StoredCollections.configuredSortedMap
00439 (map, CursorConfig.READ_COMMITTED);
00440
00441
00442 assertTrue(!isReadCommitted(map));
00443
00444
00445 assertTrue(isReadCommitted(degree2Map));
00446 assertTrue(isReadCommitted
00447 (StoredCollections.configuredMap
00448 (map, CursorConfig.READ_COMMITTED)));
00449 assertTrue(isReadCommitted
00450 (StoredCollections.configuredCollection
00451 (map.values(), CursorConfig.READ_COMMITTED)));
00452 assertTrue(isReadCommitted
00453 (StoredCollections.configuredSet
00454 (map.keySet(), CursorConfig.READ_COMMITTED)));
00455 assertTrue(isReadCommitted
00456 (StoredCollections.configuredSortedSet
00457 ((SortedSet) map.keySet(),
00458 CursorConfig.READ_COMMITTED)));
00459
00460 if (DbCompat.RECNO_METHOD) {
00461
00462 Database listStore = TestStore.RECNO_RENUM.open(env, null);
00463 List list = new StoredList(listStore, TestStore.VALUE_BINDING,
00464 true);
00465 assertTrue(isReadCommitted
00466 (StoredCollections.configuredList
00467 (list, CursorConfig.READ_COMMITTED)));
00468 listStore.close();
00469 }
00470
00471 map.put(ONE, ONE);
00472 doReadCommitted(degree2Map, null);
00473 }
00474
00475 private static boolean isReadCommitted(Object container) {
00476 StoredContainer storedContainer = (StoredContainer) container;
00477
00478 return storedContainer.getCursorConfig() != null &&
00479 storedContainer.getCursorConfig().getReadCommitted();
00480 }
00481
00482 public void testReadCommittedTransaction()
00483 throws Exception {
00484
00485 TransactionConfig config = new TransactionConfig();
00486 config.setReadCommitted(true);
00487 doReadCommitted(map, config);
00488 }
00489
00490 private void doReadCommitted(final StoredSortedMap degree2Map,
00491 TransactionConfig txnConfig)
00492 throws Exception {
00493
00494 map.put(ONE, ONE);
00495 TransactionRunner runner = new TransactionRunner(env);
00496 runner.setTransactionConfig(txnConfig);
00497 assertNull(currentTxn.getTransaction());
00498 runner.run(new TransactionWorker() {
00499 public void doWork() throws Exception {
00500 assertNotNull(currentTxn.getTransaction());
00501
00502
00503 assertEquals(ONE, degree2Map.get(ONE));
00504
00505
00506
00507
00508
00509
00510
00511
00512 DatabaseEntry key = new DatabaseEntry();
00513 DatabaseEntry value = new DatabaseEntry();
00514 testStore.getKeyBinding().objectToEntry(ONE, key);
00515 testStore.getValueBinding().objectToEntry(TWO, value);
00516 store.put(null, key, value);
00517 }
00518 });
00519 assertNull(currentTxn.getTransaction());
00520 }
00521
00522 public void testReadUncommittedCollection()
00523 throws Exception {
00524
00525 StoredSortedMap dirtyMap = (StoredSortedMap)
00526 StoredCollections.configuredSortedMap
00527 (map, CursorConfig.READ_UNCOMMITTED);
00528
00529
00530 assertTrue(!isReadUncommitted(map));
00531
00532
00533 assertTrue(isReadUncommitted(dirtyMap));
00534 assertTrue(isReadUncommitted
00535 (StoredCollections.configuredMap
00536 (map, CursorConfig.READ_UNCOMMITTED)));
00537 assertTrue(isReadUncommitted
00538 (StoredCollections.configuredCollection
00539 (map.values(), CursorConfig.READ_UNCOMMITTED)));
00540 assertTrue(isReadUncommitted
00541 (StoredCollections.configuredSet
00542 (map.keySet(), CursorConfig.READ_UNCOMMITTED)));
00543 assertTrue(isReadUncommitted
00544 (StoredCollections.configuredSortedSet
00545 ((SortedSet) map.keySet(), CursorConfig.READ_UNCOMMITTED)));
00546
00547 if (DbCompat.RECNO_METHOD) {
00548
00549 Database listStore = TestStore.RECNO_RENUM.open(env, null);
00550 List list = new StoredList(listStore, TestStore.VALUE_BINDING,
00551 true);
00552 assertTrue(isReadUncommitted
00553 (StoredCollections.configuredList
00554 (list, CursorConfig.READ_UNCOMMITTED)));
00555 listStore.close();
00556 }
00557
00558 doReadUncommitted(dirtyMap);
00559 }
00560
00561 private static boolean isReadUncommitted(Object container) {
00562 StoredContainer storedContainer = (StoredContainer) container;
00563 return storedContainer.getCursorConfig() != null &&
00564 storedContainer.getCursorConfig().getReadUncommitted();
00565 }
00566
00567 public void testReadUncommittedTransaction()
00568 throws Exception {
00569
00570 TransactionRunner runner = new TransactionRunner(env);
00571 TransactionConfig config = new TransactionConfig();
00572 config.setReadUncommitted(true);
00573 runner.setTransactionConfig(config);
00574 assertNull(currentTxn.getTransaction());
00575 runner.run(new TransactionWorker() {
00576 public void doWork() throws Exception {
00577 assertNotNull(currentTxn.getTransaction());
00578 doReadUncommitted(map);
00579 }
00580 });
00581 assertNull(currentTxn.getTransaction());
00582 }
00583
00584 private synchronized void doReadUncommitted(StoredSortedMap dirtyMap)
00585 throws Exception {
00586
00587
00588 ReadUncommittedThreadOne t1 = new ReadUncommittedThreadOne(env, this);
00589 t1.start();
00590 wait();
00591
00592
00593 synchronized (t1) { t1.notify(); }
00594 wait();
00595 readCheck(dirtyMap, ONE, ONE);
00596 assertTrue(!dirtyMap.isEmpty());
00597
00598
00599 synchronized (t1) { t1.notify(); }
00600 t1.join();
00601 readCheck(dirtyMap, ONE, null);
00602 assertTrue(dirtyMap.isEmpty());
00603
00604
00605 ReadUncommittedThreadTwo t2 = new ReadUncommittedThreadTwo(env, this);
00606 t2.start();
00607 wait();
00608
00609
00610 synchronized (t2) { t2.notify(); }
00611 wait();
00612 readCheck(dirtyMap, TWO, TWO);
00613 assertTrue(!dirtyMap.isEmpty());
00614
00615
00616 synchronized (t2) { t2.notify(); }
00617 t2.join();
00618 readCheck(dirtyMap, TWO, TWO);
00619 assertTrue(!dirtyMap.isEmpty());
00620 }
00621
00622 private static class ReadUncommittedThreadOne extends Thread {
00623
00624 private Environment env;
00625 private CurrentTransaction currentTxn;
00626 private TransactionTest parent;
00627 private StoredSortedMap map;
00628
00629 private ReadUncommittedThreadOne(Environment env,
00630 TransactionTest parent) {
00631
00632 this.env = env;
00633 this.currentTxn = CurrentTransaction.getInstance(env);
00634 this.parent = parent;
00635 this.map = parent.map;
00636 }
00637
00638 public synchronized void run() {
00639
00640 try {
00641 assertNull(currentTxn.getTransaction());
00642 assertNotNull(currentTxn.beginTransaction(null));
00643 assertNotNull(currentTxn.getTransaction());
00644 readCheck(map, ONE, null);
00645 synchronized (parent) { parent.notify(); }
00646 wait();
00647
00648
00649 assertNull(map.put(ONE, ONE));
00650 readCheck(map, ONE, ONE);
00651 synchronized (parent) { parent.notify(); }
00652 wait();
00653
00654
00655 assertNull(currentTxn.abortTransaction());
00656 assertNull(currentTxn.getTransaction());
00657 } catch (Exception e) {
00658 throw new RuntimeExceptionWrapper(e);
00659 }
00660 }
00661 }
00662
00663 private static class ReadUncommittedThreadTwo extends Thread {
00664
00665 private Environment env;
00666 private CurrentTransaction currentTxn;
00667 private TransactionTest parent;
00668 private StoredSortedMap map;
00669
00670 private ReadUncommittedThreadTwo(Environment env,
00671 TransactionTest parent) {
00672
00673 this.env = env;
00674 this.currentTxn = CurrentTransaction.getInstance(env);
00675 this.parent = parent;
00676 this.map = parent.map;
00677 }
00678
00679 public synchronized void run() {
00680
00681 try {
00682 final TransactionRunner runner = new TransactionRunner(env);
00683 final Object thread = this;
00684 assertNull(currentTxn.getTransaction());
00685
00686 runner.run(new TransactionWorker() {
00687 public void doWork() throws Exception {
00688 assertNotNull(currentTxn.getTransaction());
00689 readCheck(map, TWO, null);
00690 synchronized (parent) { parent.notify(); }
00691 thread.wait();
00692
00693
00694 assertNull(map.put(TWO, TWO));
00695 readCheck(map, TWO, TWO);
00696 synchronized (parent) { parent.notify(); }
00697 thread.wait();
00698
00699
00700 }
00701 });
00702 assertNull(currentTxn.getTransaction());
00703 } catch (Exception e) {
00704 throw new RuntimeExceptionWrapper(e);
00705 }
00706 }
00707 }
00708
00709 private static void readCheck(StoredSortedMap checkMap, Object key,
00710 Object expect) {
00711 if (expect == null) {
00712 assertNull(checkMap.get(key));
00713 assertTrue(checkMap.tailMap(key).isEmpty());
00714 assertTrue(!checkMap.tailMap(key).containsKey(key));
00715 assertTrue(!checkMap.keySet().contains(key));
00716 assertTrue(checkMap.duplicates(key).isEmpty());
00717 Iterator i = checkMap.keySet().iterator();
00718 try {
00719 while (i.hasNext()) {
00720 assertTrue(!key.equals(i.next()));
00721 }
00722 } finally { StoredIterator.close(i); }
00723 } else {
00724 assertEquals(expect, checkMap.get(key));
00725 assertEquals(expect, checkMap.tailMap(key).get(key));
00726 assertTrue(!checkMap.tailMap(key).isEmpty());
00727 assertTrue(checkMap.tailMap(key).containsKey(key));
00728 assertTrue(checkMap.keySet().contains(key));
00729 assertTrue(checkMap.values().contains(expect));
00730 assertTrue(!checkMap.duplicates(key).isEmpty());
00731 assertTrue(checkMap.duplicates(key).contains(expect));
00732 Iterator i = checkMap.keySet().iterator();
00733 try {
00734 boolean found = false;
00735 while (i.hasNext()) {
00736 if (expect.equals(i.next())) {
00737 found = true;
00738 }
00739 }
00740 assertTrue(found);
00741 }
00742 finally { StoredIterator.close(i); }
00743 }
00744 }
00745 }