001: //CHECKSTYLE_OFF
002: /*
003: * Copyright 1999-2004 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * 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: package com.google.gwt.i18n;
018:
019: import junit.framework.TestCase;
020:
021: import org.apache.commons.collections.DefaultMapEntry;
022: import org.apache.commons.collections.TestCollection;
023: import org.apache.commons.collections.TestSet;
024:
025: import java.util.Collection;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.Map;
029: import java.util.Set;
030:
031: /**
032: * Tests base {@link java.util.Map} methods and contracts.
033: * <p>
034: * The forces at work here are similar to those in {@link TestCollection}. If
035: * your class implements the full Map interface, including optional operations,
036: * simply extend this class, and implement the {@link #makeEmptyMap()} method.
037: * <p>
038: * On the other hand, if your map implementation is weird, you may have to
039: * override one or more of the other protected methods. They're described below.
040: * <P>
041: * <B>Entry Population Methods</B>
042: * <P>
043: * Override these methods if your map requires special entries:
044: * <UL>
045: * <LI>{@link #getSampleKeys()}
046: * <LI>{@link #getSampleValues()}
047: * <LI>{@link #getNewSampleValues()}
048: * <LI>{@link #getOtherKeys()}
049: * <LI>{@link #getOtherValues()}
050: * </UL>
051: * <B>Supported Operation Methods</B>
052: * <P>
053: * Override these methods if your map doesn't support certain operations:
054: * <UL>
055: * <LI> {@link #useDuplicateValues()}
056: * <LI> {@link #useNullKey()}
057: * <LI> {@link #useNullValue()}
058: * <LI> {@link #isRemoveModifiable()}
059: * <LI> {@link #isChangeable()}
060: * </UL>
061: * <B>Fixture Methods</B>
062: * <P>
063: * For tests on modification operations (puts and removes), fixtures are used to
064: * verify that that operation results in correct state for the map and its
065: * collection views. Basically, the modification is performed against your map
066: * implementation, and an identical modification is performed against a
067: * <I>confirmed</I> map implementation. A confirmed map implementation is
068: * something like <Code>java.util.HashMap</Code>, which is known to conform
069: * exactly to the {@link Map} contract. After the modification takes place on
070: * both your map implementation and the confirmed map implementation, the two
071: * maps are compared to see if their state is identical. The comparison also
072: * compares the collection views to make sure they're still the same.
073: * <P>
074: * The upshot of all that is that <I>any</I> test that modifies the map in
075: * <I>any</I> way will verify that <I>all</I> of the map's state is still
076: * correct, including the state of its collection views. So for instance if a
077: * key is removed by the map's key set's iterator, then the entry set is checked
078: * to make sure the key/value pair no longer appears.
079: * <P>
080: * The {@link #map} field holds an instance of your collection implementation.
081: * The {@link #entrySet}, {@link #keySet} and {@link #collectionValues} fields
082: * hold that map's collection views. And the {@link #confirmed} field holds an
083: * instance of the confirmed collection implementation. The
084: * {@link #resetEmpty()} and {@link #resetFull()} methods set these fields to
085: * empty or full maps, so that tests can proceed from a known state.
086: * <P>
087: * After a modification operation to both {@link #map} and {@link #confirmed},
088: * the {@link #verify()} method is invoked to compare the results. The {@link
089: * verify()} method calls separate methods to verify the map and its three
090: * collection views ({@link verifyMap(), {@link verifyEntrySet()}, {@link
091: * verifyKeySet()}, and {@link verifyValues()}). You may want to override one
092: * of the verification methodsto perform additional verifications. For instance,
093: * {@link TestDoubleOrderedMap} would want override its {@link #verifyValues()}
094: * method to verify that the values are unique and in ascending order.
095: * <P>
096: * <B>Other Notes</B>
097: * <P>
098: * If your {@link Map} fails one of these tests by design, you may still use
099: * this base set of cases. Simply override the test case (method) your {@link
100: * Map} fails and/or the methods that define the assumptions used by the test
101: * cases. For example, if your map does not allow duplicate values, override
102: * {@link #useDuplicateValues()} and have it return <code>false</code>
103: *
104: * @author Michael Smith
105: * @author Rodney Waldhoff
106: * @author Paul Jack
107: * @version $Id: TestMap.java,v 1.20.2.1 2004/05/22 12:14:05 scolebourne Exp $
108: */
109: public abstract class MapTestBase extends TestCase {
110:
111: // These instance variables are initialized with the reset method.
112: // Tests for map methods that alter the map (put, putAll, remove)
113: // first call reset() to create the map and its views; then perform
114: // the modification on the map; perform the same modification on the
115: // confirmed; and then call verify() to ensure that the map is equal
116: // to the confirmed, that the already-constructed collection views
117: // are still equal to the confirmed's collection views.
118:
119: /** Map created by reset(). */
120: protected Map map;
121:
122: /** Entry set of map created by reset(). */
123: protected Set entrySet;
124:
125: /** Key set of map created by reset(). */
126: protected Set keySet;
127:
128: /** Values collection of map created by reset(). */
129: protected Collection collectionValues;
130:
131: /** HashMap created by reset(). */
132: protected Map confirmed;
133:
134: /**
135: * Override if your map does not allow a <code>null</code> key. The default
136: * implementation returns <code>true</code>
137: */
138: protected boolean useNullKey() {
139: return true;
140: }
141:
142: /**
143: * Override if your map does not allow <code>null</code> values. The default
144: * implementation returns <code>true</code>.
145: */
146: protected boolean useNullValue() {
147: return true;
148: }
149:
150: /**
151: * Override if your map does not allow duplicate values. The default
152: * implementation returns <code>true</code>.
153: */
154: protected boolean useDuplicateValues() {
155: return true;
156: }
157:
158: /**
159: * Override if your map allows its mappings to be changed to new values. The
160: * default implementation returns <code>true</code>.
161: */
162: protected boolean isChangeable() {
163: return true;
164: }
165:
166: /**
167: * Override if your map does not allow add/remove modifications. The default
168: * implementation returns <code>true</code>.
169: */
170: protected abstract boolean isRemoveModifiable();
171:
172: /**
173: * Returns the set of keys in the mappings used to test the map. This method
174: * must return an array with the same length as {@link #getSampleValues()} and
175: * all array elements must be different. The default implementation constructs
176: * a set of String keys, and includes a single null key if
177: * {@link #useNullKey()} returns <code>true</code>.
178: */
179: protected Object[] getSampleKeys() {
180: Object[] result = new Object[] { "blah", "foo", "bar", "baz",
181: "tmp", "gosh", "golly", "gee", "hello", "goodbye",
182: "we'll", "see", "you", "all", "again", "key", "key2",
183: (useNullKey()) ? null : "nonnullkey" };
184: return result;
185: }
186:
187: protected Object[] getOtherKeys() {
188: return TestCollection.getOtherNonNullStringElements();
189: }
190:
191: protected Object[] getOtherValues() {
192: return TestCollection.getOtherNonNullStringElements();
193: }
194:
195: /**
196: * Returns the set of values in the mappings used to test the map. This method
197: * must return an array with the same length as {@link #getSampleKeys()}. The
198: * default implementation contructs a set of String values and includes a
199: * single null value if {@link #useNullValue()} returns <code>true</code>,
200: * and includes two values that are the same if {@link #useDuplicateValues()}
201: * returns <code>true</code>.
202: */
203: protected Object[] getSampleValues() {
204: Object[] result = new Object[] { "blahv", "foov", "barv",
205: "bazv", "tmpv", "goshv", "gollyv", "geev", "hellov",
206: "goodbyev", "we'llv", "seev", "youv", "allv", "againv",
207: (useNullValue()) ? null : "nonnullvalue", "value",
208: (useDuplicateValues()) ? "value" : "value2", };
209: return result;
210: }
211:
212: /**
213: * Returns a the set of values that can be used to replace the values returned
214: * from {@link #getSampleValues()}. This method must return an array with the
215: * same length as {@link #getSampleValues()}. The values returned from this
216: * method should not be the same as those returned from
217: * {@link #getSampleValues()}. The default implementation constructs a set of
218: * String values and includes a single null value if {@link #useNullValue()}
219: * returns <code>true</code>, and includes two values that are the same if
220: * {@link #useDuplicateValues()} returns <code>true</code>.
221: */
222: protected Object[] getNewSampleValues() {
223: Object[] result = new Object[] {
224: (useNullValue()) ? null : "newnonnullvalue",
225: "newvalue",
226: (useDuplicateValues()) ? "newvalue" : "newvalue2",
227: "newblahv", "newfoov", "newbarv", "newbazv", "newtmpv",
228: "newgoshv", "newgollyv", "newgeev", "newhellov",
229: "newgoodbyev", "newwe'llv", "newseev", "newyouv",
230: "newallv", "newagainv", };
231: return result;
232: }
233:
234: /**
235: * Helper method to add all the mappings described by {@link #getSampleKeys()}
236: * and {@link #getSampleValues()}.
237: */
238: protected void addSampleMappings(Map m) {
239:
240: Object[] keys = getSampleKeys();
241: Object[] values = getSampleValues();
242:
243: for (int i = 0; i < keys.length; i++) {
244: try {
245: m.put(keys[i], values[i]);
246: } catch (NullPointerException exception) {
247: assertTrue(
248: "NullPointerException only allowed to be thrown "
249: + "if either the key or value is null.",
250: keys[i] == null || values[i] == null);
251:
252: assertTrue(
253: "NullPointerException on null key, but "
254: + "useNullKey is not overridden to return false.",
255: keys[i] == null || !useNullKey());
256:
257: assertTrue(
258: "NullPointerException on null value, but "
259: + "useNullValue is not overridden to return false.",
260: values[i] == null || !useNullValue());
261:
262: assertTrue("Unknown reason for NullPointer.", false);
263: }
264: }
265: assertEquals("size must reflect number of mappings added.",
266: keys.length, m.size());
267: }
268:
269: /**
270: * Return a new, empty {@link Map} to be used for testing.
271: */
272: protected abstract Map makeEmptyMap();
273:
274: /**
275: * Return a new, populated map. The mappings in the map should match the keys
276: * and values returned from {@link #getSampleKeys()} and {@link
277: * #getSampleValues()}. The default implementation uses makeEmptyMap() and
278: * calls {@link #addSampleMappings()} to add all the mappings to the map.
279: */
280: protected Map makeFullMap() {
281: Map m = makeEmptyMap();
282: addSampleMappings(m);
283: return m;
284: }
285:
286: public Object makeObject() {
287: return makeEmptyMap();
288: }
289:
290: /**
291: * Test to ensure the test setup is working properly. This method checks to
292: * ensure that the getSampleKeys and getSampleValues methods are returning
293: * results that look appropriate. That is, they both return a non-null array
294: * of equal length. The keys array must not have any duplicate values, and may
295: * only contain a (single) null key if useNullKey() returns true. The values
296: * array must only have a null value if useNullValue() is true and may only
297: * have duplicate values if useDuplicateValues() returns true.
298: */
299: public void testSampleMappings() {
300: Object[] keys = getSampleKeys();
301: Object[] values = getSampleValues();
302: Object[] newValues = getNewSampleValues();
303:
304: assertTrue("failure in test: Must have keys returned from "
305: + "getSampleKeys.", keys != null);
306:
307: assertTrue("failure in test: Must have values returned from "
308: + "getSampleValues.", values != null);
309:
310: // verify keys and values have equivalent lengths (in case getSampleX are
311: // overridden)
312: assertEquals("failure in test: not the same number of sample "
313: + "keys and values.", keys.length, values.length);
314:
315: assertEquals(
316: "failure in test: not the same number of values and new values.",
317: values.length, newValues.length);
318:
319: // verify there aren't duplicate keys, and check values
320: for (int i = 0; i < keys.length - 1; i++) {
321: for (int j = i + 1; j < keys.length; j++) {
322: assertTrue("failure in test: duplicate null keys.",
323: (keys[i] != null || keys[j] != null));
324: assertTrue(
325: "failure in test: duplicate non-null key.",
326: (keys[i] == null || keys[j] == null || (!keys[i]
327: .equals(keys[j]) && !keys[j]
328: .equals(keys[i]))));
329: }
330: assertTrue(
331: "failure in test: found null key, but useNullKey "
332: + "is false.", keys[i] != null
333: || useNullKey());
334: assertTrue(
335: "failure in test: found null value, but useNullValue "
336: + "is false.", values[i] != null
337: || useNullValue());
338: assertTrue(
339: "failure in test: found null new value, but useNullValue "
340: + "is false.", newValues[i] != null
341: || useNullValue());
342: assertTrue(
343: "failure in test: values should not be the same as new value",
344: values[i] != newValues[i]
345: && (values[i] == null || !values[i]
346: .equals(newValues[i])));
347: }
348: }
349:
350: // tests begin here. Each test adds a little bit of tested functionality.
351: // Many methods assume previous methods passed. That is, they do not
352: // exhaustively recheck things that have already been checked in a previous
353: // test methods.
354:
355: /**
356: * Test to ensure that makeEmptyMap and makeFull returns a new non-null map
357: * with each invocation.
358: */
359: public void testMakeMap() {
360: Map em = makeEmptyMap();
361: assertTrue(
362: "failure in test: makeEmptyMap must return a non-null map.",
363: em != null);
364:
365: Map em2 = makeEmptyMap();
366: assertTrue(
367: "failure in test: makeEmptyMap must return a non-null map.",
368: em != null);
369:
370: assertTrue(
371: "failure in test: makeEmptyMap must return a new map "
372: + "with each invocation.", em != em2);
373:
374: Map fm = makeFullMap();
375: assertTrue(
376: "failure in test: makeFullMap must return a non-null map.",
377: fm != null);
378:
379: Map fm2 = makeFullMap();
380: assertTrue(
381: "failure in test: makeFullMap must return a non-null map.",
382: fm != null);
383:
384: assertTrue(
385: "failure in test: makeFullMap must return a new map "
386: + "with each invocation.", fm != fm2);
387: }
388:
389: /**
390: * Tests Map.isEmpty()
391: */
392: public void testMapIsEmpty() {
393:
394: resetEmpty();
395: assertEquals(
396: "Map.isEmpty() should return true with an empty map",
397: true, map.isEmpty());
398: verify();
399:
400: resetFull();
401: assertEquals(
402: "Map.isEmpty() should return false with a non-empty map",
403: false, map.isEmpty());
404: verify();
405: }
406:
407: /**
408: * Tests Map.size()
409: */
410: public void testMapSize() {
411: resetEmpty();
412: assertEquals("Map.size() should be 0 with an empty map", 0, map
413: .size());
414: verify();
415:
416: resetFull();
417: assertEquals("Map.size() should equal the number of entries "
418: + "in the map", getSampleKeys().length, map.size());
419: verify();
420: }
421:
422: /**
423: * Tests {@link Map#clear()}. If the map {@link #isRemoveModifiable() can add
424: * and remove elements}, then {@link Map#size()} and {@link Map#isEmpty()} are
425: * used to ensure that map has no elements after a call to clear. If the map
426: * does not support adding and removing elements, this method checks to ensure
427: * clear throws an UnsupportedOperationException.
428: */
429: public void testMapClear() {
430: if (!isRemoveModifiable())
431: return;
432:
433: resetEmpty();
434: map.clear();
435: confirmed.clear();
436: verify();
437:
438: resetFull();
439: map.clear();
440: confirmed.clear();
441: verify();
442: }
443:
444: /**
445: * Tests Map.containsKey(Object) by verifying it returns false for all sample
446: * keys on a map created using an empty map and returns true for all sample
447: * keys returned on a full map.
448: */
449: public void testMapContainsKey() {
450: Object[] keys = getSampleKeys();
451:
452: resetEmpty();
453: for (int i = 0; i < keys.length; i++) {
454: assertTrue("Map must not contain key when map is empty",
455: !map.containsKey(keys[i]));
456: }
457: verify();
458:
459: resetFull();
460: for (int i = 0; i < keys.length; i++) {
461: assertTrue(
462: "Map must contain key for a mapping in the map. "
463: + "Missing: " + keys[i], map
464: .containsKey(keys[i]));
465: }
466: verify();
467: }
468:
469: /**
470: * Tests Map.containsValue(Object) by verifying it returns false for all
471: * sample values on an empty map and returns true for all sample values on a
472: * full map.
473: */
474: public void testMapContainsValue() {
475: Object[] values = getSampleValues();
476:
477: resetEmpty();
478: for (int i = 0; i < values.length; i++) {
479: assertTrue("Empty map must not contain value", !map
480: .containsValue(values[i]));
481: }
482: verify();
483:
484: resetFull();
485: for (int i = 0; i < values.length; i++) {
486: assertTrue(
487: "Map must contain value for a mapping in the map.",
488: map.containsValue(values[i]));
489: }
490: verify();
491: }
492:
493: /**
494: * Tests Map.equals(Object)
495: */
496: public void testMapEquals() {
497: resetEmpty();
498: assertTrue("Empty maps unequal.", map.equals(confirmed));
499: verify();
500:
501: resetFull();
502: assertTrue("Full maps unequal.", map.equals(confirmed));
503: verify();
504:
505: resetFull();
506: // modify the HashMap created from the full map and make sure this
507: // change results in map.equals() to return false.
508: Iterator iter = confirmed.keySet().iterator();
509: iter.next();
510: iter.remove();
511: assertTrue("Different maps equal.", !map.equals(confirmed));
512:
513: resetFull();
514: assertTrue("equals(null) returned true.", !map.equals(null));
515: assertTrue("equals(new Object()) returned true.", !map
516: .equals(new Object()));
517: verify();
518: }
519:
520: /**
521: * Tests Map.get(Object)
522: */
523: public void testMapGet() {
524: resetEmpty();
525:
526: Object[] keys = getSampleKeys();
527: Object[] values = getSampleValues();
528:
529: for (int i = 0; i < keys.length; i++) {
530: assertTrue("Empty map.get() should return null.", map
531: .get(keys[i]) == null);
532: }
533: verify();
534:
535: resetFull();
536: for (int i = 0; i < keys.length; i++) {
537: assertEquals(
538: "Full map.get() should return value from mapping.",
539: values[i], map.get(keys[i]));
540: }
541: }
542:
543: /**
544: * Tests Map.hashCode()
545: */
546: public void testMapHashCode() {
547: resetEmpty();
548: assertTrue("Empty maps have different hashCodes.", map
549: .hashCode() == confirmed.hashCode());
550:
551: resetFull();
552: // assertTrue("Equal maps have different hashCodes.",
553: // map.hashCode() == confirmed.hashCode());
554: }
555:
556: /**
557: * Tests Map.toString(). Since the format of the string returned by the
558: * toString() method is not defined in the Map interface, there is no common
559: * way to test the results of the toString() method. Thereforce, it is
560: * encouraged that Map implementations override this test with one that checks
561: * the format matches any format defined in its API. This default
562: * implementation just verifies that the toString() method does not return
563: * null.
564: */
565: public void testMapToString() {
566: resetEmpty();
567: assertTrue("Empty map toString() should not return null", map
568: .toString() != null);
569: verify();
570:
571: resetFull();
572: assertTrue("Empty map toString() should not return null", map
573: .toString() != null);
574: verify();
575: }
576:
577: /**
578: * Tests Map.put(Object, Object)
579: */
580: public void testMapPut() {
581: if (!isRemoveModifiable())
582: return;
583:
584: resetEmpty();
585:
586: Object[] keys = getSampleKeys();
587: Object[] values = getSampleValues();
588: Object[] newValues = getNewSampleValues();
589:
590: for (int i = 0; i < keys.length; i++) {
591: Object o = map.put(keys[i], values[i]);
592: confirmed.put(keys[i], values[i]);
593: verify();
594: assertTrue("First map.put should return null", o == null);
595: assertTrue("Map should contain key after put", map
596: .containsKey(keys[i]));
597: assertTrue("Map should contain value after put", map
598: .containsValue(values[i]));
599: }
600:
601: for (int i = 0; i < keys.length; i++) {
602: Object o = map.put(keys[i], newValues[i]);
603: confirmed.put(keys[i], newValues[i]);
604: verify();
605: assertEquals("Second map.put should return previous value",
606: values[i], o);
607: assertTrue("Map should still contain key after put", map
608: .containsKey(keys[i]));
609: assertTrue("Map should contain new value after put", map
610: .containsValue(newValues[i]));
611:
612: // if duplicates are allowed, we're not guarunteed that the value
613: // no longer exists, so don't try checking that.
614: if (!useDuplicateValues()) {
615: assertTrue(
616: "Map should not contain old value after second put",
617: !map.containsValue(values[i]));
618: }
619: }
620: }
621:
622: /**
623: * Tests Map.putAll(Collection)
624: */
625: public void testMapPutAll() {
626: if (!isRemoveModifiable())
627: return;
628:
629: resetEmpty();
630:
631: Map m2 = makeFullMap();
632:
633: map.putAll(m2);
634: confirmed.putAll(m2);
635: verify();
636:
637: resetEmpty();
638:
639: m2 = new HashMap();
640: Object[] keys = getSampleKeys();
641: Object[] values = getSampleValues();
642: for (int i = 0; i < keys.length; i++) {
643: m2.put(keys[i], values[i]);
644: }
645:
646: map.putAll(m2);
647: confirmed.putAll(m2);
648: verify();
649: }
650:
651: /**
652: * Tests Map.remove(Object)
653: */
654: public void testMapRemove() {
655: if (!isRemoveModifiable())
656: return;
657:
658: resetEmpty();
659:
660: Object[] keys = getSampleKeys();
661: Object[] values = getSampleValues();
662: for (int i = 0; i < keys.length; i++) {
663: Object o = map.remove(keys[i]);
664: assertTrue("First map.remove should return null", o == null);
665: }
666: verify();
667:
668: resetFull();
669:
670: for (int i = 0; i < keys.length; i++) {
671: Object o = map.remove(keys[i]);
672: confirmed.remove(keys[i]);
673: verify();
674:
675: assertEquals(
676: "map.remove with valid key should return value",
677: values[i], o);
678: }
679:
680: Object[] other = getOtherKeys();
681:
682: resetFull();
683: int size = map.size();
684: for (int i = 0; i < other.length; i++) {
685: Object o = map.remove(other[i]);
686: assertEquals(
687: "map.remove for nonexistent key should return null",
688: o, null);
689: assertEquals("map.remove for nonexistent key should not "
690: + "shrink map", size, map.size());
691: }
692: verify();
693: }
694:
695: /**
696: * Utility methods to create an array of Map.Entry objects out of the given
697: * key and value arrays.
698: * <P>
699: *
700: * @param keys the array of keys
701: * @param values the array of values
702: * @return an array of Map.Entry of those keys to those values
703: */
704: private Map.Entry[] makeEntryArray(Object[] keys, Object[] values) {
705: Map.Entry[] result = new Map.Entry[keys.length];
706: for (int i = 0; i < keys.length; i++) {
707: result[i] = new DefaultMapEntry(keys[i], values[i]);
708: }
709: return result;
710: }
711:
712: class TestMapEntrySet extends TestSet {
713: public TestMapEntrySet() {
714: super ("");
715: }
716:
717: // Have to implement manually; entrySet doesn't support addAll
718: protected Object[] getFullElements() {
719: Object[] k = getSampleKeys();
720: Object[] v = getSampleValues();
721: return makeEntryArray(k, v);
722: }
723:
724: // Have to implement manually; entrySet doesn't support addAll
725: protected Object[] getOtherElements() {
726: Object[] k = getOtherKeys();
727: Object[] v = getOtherValues();
728: return makeEntryArray(k, v);
729: }
730:
731: protected Set makeEmptySet() {
732: return makeEmptyMap().entrySet();
733: }
734:
735: protected Set makeFullSet() {
736: return makeFullMap().entrySet();
737: }
738:
739: protected boolean isAddSupported() {
740: // Collection views don't support add operations.
741: return false;
742: }
743:
744: protected boolean isRemoveSupported() {
745: // Entry set should only support remove if map does
746: return isRemoveModifiable();
747: }
748:
749: protected void resetFull() {
750: MapTestBase.this .resetFull();
751: collection = map.entrySet();
752: TestMapEntrySet.this .confirmed = MapTestBase.this .confirmed
753: .entrySet();
754: }
755:
756: protected void resetEmpty() {
757: MapTestBase.this .resetEmpty();
758: collection = map.entrySet();
759: TestMapEntrySet.this .confirmed = MapTestBase.this .confirmed
760: .entrySet();
761: }
762:
763: protected void verify() {
764: super .verify();
765: MapTestBase.this .verify();
766: }
767: }
768:
769: class TestMapKeySet extends TestSet {
770: public TestMapKeySet() {
771: super ("");
772: }
773:
774: protected Object[] getFullElements() {
775: return getSampleKeys();
776: }
777:
778: protected Object[] getOtherElements() {
779: return getOtherKeys();
780: }
781:
782: protected Set makeEmptySet() {
783: return makeEmptyMap().keySet();
784: }
785:
786: protected Set makeFullSet() {
787: return makeFullMap().keySet();
788: }
789:
790: protected boolean isAddSupported() {
791: return false;
792: }
793:
794: protected boolean isRemoveSupported() {
795: return isRemoveModifiable();
796: }
797:
798: protected void resetEmpty() {
799: MapTestBase.this .resetEmpty();
800: collection = map.keySet();
801: TestMapKeySet.this .confirmed = MapTestBase.this .confirmed
802: .keySet();
803: }
804:
805: protected void resetFull() {
806: MapTestBase.this .resetFull();
807: collection = map.keySet();
808: TestMapKeySet.this .confirmed = MapTestBase.this .confirmed
809: .keySet();
810: }
811:
812: protected void verify() {
813: super .verify();
814: MapTestBase.this .verify();
815: }
816: }
817:
818: class TestMapValues extends TestCollection {
819: public TestMapValues() {
820:
821: }
822:
823: protected Object[] getFullElements() {
824: return getSampleValues();
825: }
826:
827: protected Object[] getOtherElements() {
828: return getOtherValues();
829: }
830:
831: protected Collection makeCollection() {
832: return makeEmptyMap().values();
833: }
834:
835: protected Collection makeFullCollection() {
836: return makeFullMap().values();
837: }
838:
839: protected boolean isAddSupported() {
840: return false;
841: }
842:
843: protected boolean isRemoveSupported() {
844: return isRemoveModifiable();
845: }
846:
847: protected boolean areEqualElementsDistinguishable() {
848: // equal values are associated with different keys, so they are
849: // distinguishable.
850: return true;
851: }
852:
853: protected Collection makeConfirmedCollection() {
854: // never gets called, reset methods are overridden
855: return null;
856: }
857:
858: protected Collection makeConfirmedFullCollection() {
859: // never gets called, reset methods are overridden
860: return null;
861: }
862:
863: protected void resetFull() {
864: MapTestBase.this .resetFull();
865: collection = map.values();
866: TestMapValues.this .confirmed = MapTestBase.this .confirmed
867: .values();
868: }
869:
870: protected void resetEmpty() {
871: MapTestBase.this .resetEmpty();
872: collection = map.values();
873: TestMapValues.this .confirmed = MapTestBase.this .confirmed
874: .values();
875: }
876:
877: protected void verify() {
878: super .verify();
879: MapTestBase.this .verify();
880: }
881:
882: // TODO: should test that a remove on the values collection view
883: // removes the proper mapping and not just any mapping that may have
884: // the value equal to the value returned from the values iterator.
885: }
886:
887: /**
888: * Resets the {@link #map}, {@link #entrySet}, {@link #keySet},
889: * {@link #collectionValues} and {@link #confirmed} fields to empty.
890: */
891: protected void resetEmpty() {
892: this .map = makeEmptyMap();
893: views();
894: this .confirmed = new HashMap();
895: }
896:
897: /**
898: * Resets the {@link #map}, {@link #entrySet}, {@link #keySet},
899: * {@link #collectionValues} and {@link #confirmed} fields to full.
900: */
901: protected void resetFull() {
902: this .map = makeFullMap();
903: views();
904: this .confirmed = new HashMap();
905: Object[] k = getSampleKeys();
906: Object[] v = getSampleValues();
907: for (int i = 0; i < k.length; i++) {
908: confirmed.put(k[i], v[i]);
909: }
910: }
911:
912: /**
913: * Resets the collection view fields.
914: */
915: private void views() {
916: this .keySet = map.keySet();
917: this .collectionValues = map.values();
918: this .entrySet = map.entrySet();
919: }
920:
921: /**
922: * Verifies that {@link #map} is still equal to {@link #confirmed}. This
923: * method checks that the map is equal to the HashMap, <I>and</I> that the
924: * map's collection views are still equal to the HashMap's collection views.
925: * An <Code>equals</Code> test is done on the maps and their collection
926: * views; their size and <Code>isEmpty</Code> results are compared; their
927: * hashCodes are compared; and <Code>containsAll</Code> tests are run on the
928: * collection views.
929: */
930: protected void verify() {
931: verifyMap();
932: verifyEntrySet();
933: verifyKeySet();
934:
935: }
936:
937: protected void verifyMap() {
938: int size = confirmed.size();
939: boolean empty = confirmed.isEmpty();
940: assertEquals("Map should be same size as HashMap", size, map
941: .size());
942: assertEquals("Map should be empty if HashMap is", empty, map
943: .isEmpty());
944:
945: // assertEquals("hashCodes should be the same",
946: // confirmed.hashCode(), map.hashCode());
947: // this fails for LRUMap because confirmed.equals() somehow modifies
948: // map, causing concurrent modification exceptions.
949: // assertEquals("Map should still equal HashMap", confirmed, map);
950: // this works though and performs the same verification:
951: assertTrue("Map should still equal HashMap", map
952: .equals(confirmed));
953: // TODO: this should really be rexamined to figure out why LRU map
954: // behaves like it does (the equals shouldn't modify since all accesses
955: // by the confirmed collection should be through an iterator, thus not
956: // causing LRUMap to change).
957: }
958:
959: protected void verifyEntrySet() {
960: int size = confirmed.size();
961: boolean empty = confirmed.isEmpty();
962: assertEquals("entrySet should be same size as HashMap's", size,
963: entrySet.size());
964: assertEquals("entrySet should be empty if HashMap is", empty,
965: entrySet.isEmpty());
966: assertTrue("entrySet should contain all HashMap's elements",
967: entrySet.containsAll(confirmed.entrySet()));
968: // Figure out why the hashcodes are not working for constant map
969: // assertEquals("entrySet hashCodes should be the same",
970: // confirmed.entrySet().hashCode(), entrySet.hashCode());
971: assertEquals("Map's entry set should still equal HashMap's",
972: confirmed.entrySet(), entrySet);
973: }
974:
975: protected void verifyKeySet() {
976: int size = confirmed.size();
977: boolean empty = confirmed.isEmpty();
978: assertEquals("keySet should be same size as HashMap's", size,
979: keySet.size());
980: assertEquals("keySet should be empty if HashMap is", empty,
981: keySet.isEmpty());
982: assertTrue("keySet should contain all HashMap's elements",
983: keySet.containsAll(confirmed.keySet()));
984: // assertEquals("keySet hashCodes should be the same",
985: // confirmed.keySet().hashCode(), keySet.hashCode());
986: assertEquals("Map's key set should still equal HashMap's",
987: confirmed.keySet(), keySet);
988: }
989:
990: }
|