KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > map > AbstractTestMap


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.collections.map;
17
18 import java.io.Serializable JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Collection JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.Set JavaDoc;
26
27 import org.apache.commons.collections.AbstractTestObject;
28 import org.apache.commons.collections.BulkTest;
29 import org.apache.commons.collections.collection.AbstractTestCollection;
30 import org.apache.commons.collections.set.AbstractTestSet;
31
32 /**
33  * Abstract test class for {@link java.util.Map} methods and contracts.
34  * <p>
35  * The forces at work here are similar to those in {@link AbstractTestCollection}.
36  * If your class implements the full Map interface, including optional
37  * operations, simply extend this class, and implement the
38  * {@link #makeEmptyMap()} method.
39  * <p>
40  * On the other hand, if your map implementation is weird, you may have to
41  * override one or more of the other protected methods. They're described
42  * below.
43  * <p>
44  * <b>Entry Population Methods</b>
45  * <p>
46  * Override these methods if your map requires special entries:
47  *
48  * <ul>
49  * <li>{@link #getSampleKeys()}
50  * <li>{@link #getSampleValues()}
51  * <li>{@link #getNewSampleValues()}
52  * <li>{@link #getOtherKeys()}
53  * <li>{@link #getOtherValues()}
54  * </ul>
55  *
56  * <b>Supported Operation Methods</b>
57  * <p>
58  * Override these methods if your map doesn't support certain operations:
59  *
60  * <ul>
61  * <li> {@link #isPutAddSupported()}
62  * <li> {@link #isPutChangeSupported()}
63  * <li> {@link #isSetValueSupported()}
64  * <li> {@link #isRemoveSupported()}
65  * <li> {@link #isGetStructuralModify()}
66  * <li> {@link #isAllowDuplicateValues()}
67  * <li> {@link #isAllowNullKey()}
68  * <li> {@link #isAllowNullValue()}
69  * </ul>
70  *
71  * <b>Fixture Methods</b>
72  * <p>
73  * For tests on modification operations (puts and removes), fixtures are used
74  * to verify that that operation results in correct state for the map and its
75  * collection views. Basically, the modification is performed against your
76  * map implementation, and an identical modification is performed against
77  * a <I>confirmed</I> map implementation. A confirmed map implementation is
78  * something like <Code>java.util.HashMap</Code>, which is known to conform
79  * exactly to the {@link Map} contract. After the modification takes place
80  * on both your map implementation and the confirmed map implementation, the
81  * two maps are compared to see if their state is identical. The comparison
82  * also compares the collection views to make sure they're still the same.<P>
83  *
84  * The upshot of all that is that <I>any</I> test that modifies the map in
85  * <I>any</I> way will verify that <I>all</I> of the map's state is still
86  * correct, including the state of its collection views. So for instance
87  * if a key is removed by the map's key set's iterator, then the entry set
88  * is checked to make sure the key/value pair no longer appears.<P>
89  *
90  * The {@link #map} field holds an instance of your collection implementation.
91  * The {@link #entrySet}, {@link #keySet} and {@link #values} fields hold
92  * that map's collection views. And the {@link #confirmed} field holds
93  * an instance of the confirmed collection implementation. The
94  * {@link #resetEmpty()} and {@link #resetFull()} methods set these fields to
95  * empty or full maps, so that tests can proceed from a known state.<P>
96  *
97  * After a modification operation to both {@link #map} and {@link #confirmed},
98  * the {@link #verify()} method is invoked to compare the results. The
99  * {@link #verify} method calls separate methods to verify the map and its three
100  * collection views ({@link #verifyMap}, {@link #verifyEntrySet},
101  * {@link #verifyKeySet}, and {@link #verifyValues}). You may want to override
102  * one of the verification methodsto perform additional verifications. For
103  * instance, TestDoubleOrderedMap would want override its
104  * {@link #verifyValues()} method to verify that the values are unique and in
105  * ascending order.<P>
106  *
107  * <b>Other Notes</b>
108  * <p>
109  * If your {@link Map} fails one of these tests by design, you may still use
110  * this base set of cases. Simply override the test case (method) your map
111  * fails and/or the methods that define the assumptions used by the test
112  * cases. For example, if your map does not allow duplicate values, override
113  * {@link #isAllowDuplicateValues()} and have it return <code>false</code>
114  *
115  * @author Michael Smith
116  * @author Rodney Waldhoff
117  * @author Paul Jack
118  * @author Stephen Colebourne
119  * @version $Revision: 1.16 $ $Date: 2004/06/07 23:14:40 $
120  */

121 public abstract class AbstractTestMap extends AbstractTestObject {
122
123     /**
124      * JDK1.2 has bugs in null handling of Maps, especially HashMap.Entry.toString
125      * This avoids nulls for JDK1.2
126      */

127     private static final boolean JDK12;
128     static {
129         String JavaDoc str = System.getProperty("java.version");
130         JDK12 = str.startsWith("1.2");
131     }
132
133     // These instance variables are initialized with the reset method.
134
// Tests for map methods that alter the map (put, putAll, remove)
135
// first call reset() to create the map and its views; then perform
136
// the modification on the map; perform the same modification on the
137
// confirmed; and then call verify() to ensure that the map is equal
138
// to the confirmed, that the already-constructed collection views
139
// are still equal to the confirmed's collection views.
140

141
142     /** Map created by reset(). */
143     protected Map JavaDoc map;
144
145     /** Entry set of map created by reset(). */
146     protected Set JavaDoc entrySet;
147
148     /** Key set of map created by reset(). */
149     protected Set JavaDoc keySet;
150
151     /** Values collection of map created by reset(). */
152     protected Collection JavaDoc values;
153
154     /** HashMap created by reset(). */
155     protected Map JavaDoc confirmed;
156
157     /**
158      * JUnit constructor.
159      *
160      * @param testName the test name
161      */

162     public AbstractTestMap(String JavaDoc testName) {
163         super(testName);
164     }
165
166     /**
167      * Returns true if the maps produced by
168      * {@link #makeEmptyMap()} and {@link #makeFullMap()}
169      * support the <code>put</code> and <code>putAll</code> operations
170      * adding new mappings.
171      * <p>
172      * Default implementation returns true.
173      * Override if your collection class does not support put adding.
174      */

175     public boolean isPutAddSupported() {
176         return true;
177     }
178
179     /**
180      * Returns true if the maps produced by
181      * {@link #makeEmptyMap()} and {@link #makeFullMap()}
182      * support the <code>put</code> and <code>putAll</code> operations
183      * changing existing mappings.
184      * <p>
185      * Default implementation returns true.
186      * Override if your collection class does not support put changing.
187      */

188     public boolean isPutChangeSupported() {
189         return true;
190     }
191
192     /**
193      * Returns true if the maps produced by
194      * {@link #makeEmptyMap()} and {@link #makeFullMap()}
195      * support the <code>setValue</code> operation on entrySet entries.
196      * <p>
197      * Default implementation returns isPutChangeSupported().
198      * Override if your collection class does not support setValue but does
199      * support put changing.
200      */

201     public boolean isSetValueSupported() {
202         return isPutChangeSupported();
203     }
204
205     /**
206      * Returns true if the maps produced by
207      * {@link #makeEmptyMap()} and {@link #makeFullMap()}
208      * support the <code>remove</code> and <code>clear</code> operations.
209      * <p>
210      * Default implementation returns true.
211      * Override if your collection class does not support removal operations.
212      */

213     public boolean isRemoveSupported() {
214         return true;
215     }
216
217     /**
218      * Returns true if the maps produced by
219      * {@link #makeEmptyMap()} and {@link #makeFullMap()}
220      * can cause structural modification on a get(). The example is LRUMap.
221      * <p>
222      * Default implementation returns false.
223      * Override if your map class structurally modifies on get.
224      */

225     public boolean isGetStructuralModify() {
226         return false;
227     }
228
229     /**
230      * Returns whether the sub map views of SortedMap are serializable.
231      * If the class being tested is based around a TreeMap then you should
232      * override and return false as TreeMap has a bug in deserialization.
233      *
234      * @return false
235      */

236     public boolean isSubMapViewsSerializable() {
237         return true;
238     }
239
240     /**
241      * Returns true if the maps produced by
242      * {@link #makeEmptyMap()} and {@link #makeFullMap()}
243      * supports null keys.
244      * <p>
245      * Default implementation returns true.
246      * Override if your collection class does not support null keys.
247      */

248     public boolean isAllowNullKey() {
249         return true;
250     }
251
252     /**
253      * Returns true if the maps produced by
254      * {@link #makeEmptyMap()} and {@link #makeFullMap()}
255      * supports null values.
256      * <p>
257      * Default implementation returns true.
258      * Override if your collection class does not support null values.
259      */

260     public boolean isAllowNullValue() {
261         return true;
262     }
263
264     /**
265      * Returns true if the maps produced by
266      * {@link #makeEmptyMap()} and {@link #makeFullMap()}
267      * supports duplicate values.
268      * <p>
269      * Default implementation returns true.
270      * Override if your collection class does not support duplicate values.
271      */

272     public boolean isAllowDuplicateValues() {
273         return true;
274     }
275
276     /**
277      * Returns the set of keys in the mappings used to test the map. This
278      * method must return an array with the same length as {@link
279      * #getSampleValues()} and all array elements must be different. The
280      * default implementation constructs a set of String keys, and includes a
281      * single null key if {@link #isAllowNullKey()} returns <code>true</code>.
282      */

283     public Object JavaDoc[] getSampleKeys() {
284         Object JavaDoc[] result = new Object JavaDoc[] {
285             "blah", "foo", "bar", "baz", "tmp", "gosh", "golly", "gee",
286             "hello", "goodbye", "we'll", "see", "you", "all", "again",
287             "key",
288             "key2",
289             (isAllowNullKey() && !JDK12) ? null : "nonnullkey"
290         };
291         return result;
292     }
293
294
295     public Object JavaDoc[] getOtherKeys() {
296         return getOtherNonNullStringElements();
297     }
298
299     public Object JavaDoc[] getOtherValues() {
300         return getOtherNonNullStringElements();
301     }
302
303     /**
304      * Returns a list of string elements suitable for return by
305      * {@link #getOtherKeys()} or {@link #getOtherValues}.
306      *
307      * <p>Override getOtherElements to returnthe results of this method if your
308      * collection does not support heterogenous elements or the null element.
309      * </p>
310      */

311     public Object JavaDoc[] getOtherNonNullStringElements() {
312         return new Object JavaDoc[] {
313             "For","then","despite",/* of */"space","I","would","be","brought",
314             "From","limits","far","remote","where","thou","dost","stay"
315         };
316     }
317
318     /**
319      * Returns the set of values in the mappings used to test the map. This
320      * method must return an array with the same length as
321      * {@link #getSampleKeys()}. The default implementation constructs a set of
322      * String values and includes a single null value if
323      * {@link #isAllowNullValue()} returns <code>true</code>, and includes
324      * two values that are the same if {@link #isAllowDuplicateValues()} returns
325      * <code>true</code>.
326      */

327     public Object JavaDoc[] getSampleValues() {
328         Object JavaDoc[] result = new Object JavaDoc[] {
329             "blahv", "foov", "barv", "bazv", "tmpv", "goshv", "gollyv", "geev",
330             "hellov", "goodbyev", "we'llv", "seev", "youv", "allv", "againv",
331             (isAllowNullValue() && !JDK12) ? null : "nonnullvalue",
332             "value",
333             (isAllowDuplicateValues()) ? "value" : "value2",
334         };
335         return result;
336     }
337
338     /**
339      * Returns a the set of values that can be used to replace the values
340      * returned from {@link #getSampleValues()}. This method must return an
341      * array with the same length as {@link #getSampleValues()}. The values
342      * returned from this method should not be the same as those returned from
343      * {@link #getSampleValues()}. The default implementation constructs a
344      * set of String values and includes a single null value if
345      * {@link #isAllowNullValue()} returns <code>true</code>, and includes two values
346      * that are the same if {@link #isAllowDuplicateValues()} returns
347      * <code>true</code>.
348      */

349     public Object JavaDoc[] getNewSampleValues() {
350         Object JavaDoc[] result = new Object JavaDoc[] {
351             (isAllowNullValue() && !JDK12 && isAllowDuplicateValues()) ? null : "newnonnullvalue",
352             "newvalue",
353             (isAllowDuplicateValues()) ? "newvalue" : "newvalue2",
354             "newblahv", "newfoov", "newbarv", "newbazv", "newtmpv", "newgoshv",
355             "newgollyv", "newgeev", "newhellov", "newgoodbyev", "newwe'llv",
356             "newseev", "newyouv", "newallv", "newagainv",
357         };
358         return result;
359     }
360
361     /**
362      * Helper method to add all the mappings described by
363      * {@link #getSampleKeys()} and {@link #getSampleValues()}.
364      */

365     public void addSampleMappings(Map JavaDoc m) {
366
367         Object JavaDoc[] keys = getSampleKeys();
368         Object JavaDoc[] values = getSampleValues();
369         
370         for(int i = 0; i < keys.length; i++) {
371             try {
372                 m.put(keys[i], values[i]);
373             } catch (NullPointerException JavaDoc exception) {
374                 assertTrue("NullPointerException only allowed to be thrown " +
375                            "if either the key or value is null.",
376                            keys[i] == null || values[i] == null);
377                 
378                 assertTrue("NullPointerException on null key, but " +
379                            "isAllowNullKey is not overridden to return false.",
380                            keys[i] == null || !isAllowNullKey());
381                 
382                 assertTrue("NullPointerException on null value, but " +
383                            "isAllowNullValue is not overridden to return false.",
384                            values[i] == null || !isAllowNullValue());
385                 
386                 assertTrue("Unknown reason for NullPointer.", false);
387             }
388         }
389         assertEquals("size must reflect number of mappings added.",
390                      keys.length, m.size());
391     }
392
393     //-----------------------------------------------------------------------
394
/**
395      * Return a new, empty {@link Map} to be used for testing.
396      *
397      * @return the map to be tested
398      */

399     public abstract Map JavaDoc makeEmptyMap();
400
401     /**
402      * Return a new, populated map. The mappings in the map should match the
403      * keys and values returned from {@link #getSampleKeys()} and
404      * {@link #getSampleValues()}. The default implementation uses makeEmptyMap()
405      * and calls {@link #addSampleMappings} to add all the mappings to the
406      * map.
407      *
408      * @return the map to be tested
409      */

410     public Map JavaDoc makeFullMap() {
411         Map JavaDoc m = makeEmptyMap();
412         addSampleMappings(m);
413         return m;
414     }
415
416     /**
417      * Implements the superclass method to return the map to be tested.
418      *
419      * @return the map to be tested
420      */

421     public Object JavaDoc makeObject() {
422         return makeEmptyMap();
423     }
424
425     /**
426      * Override to return a map other than HashMap as the confirmed map.
427      *
428      * @return a map that is known to be valid
429      */

430     public Map JavaDoc makeConfirmedMap() {
431         return new HashMap JavaDoc();
432     }
433
434     /**
435      * Creates a new Map Entry that is independent of the first and the map.
436      */

437     public Map.Entry JavaDoc cloneMapEntry(Map.Entry JavaDoc entry) {
438         HashMap JavaDoc map = new HashMap JavaDoc();
439         map.put(entry.getKey(), entry.getValue());
440         return (Map.Entry JavaDoc) map.entrySet().iterator().next();
441     }
442
443     /**
444      * Gets the compatability version, needed for package access.
445      */

446     public String JavaDoc getCompatibilityVersion() {
447         return super.getCompatibilityVersion();
448     }
449     //-----------------------------------------------------------------------
450
/**
451      * Test to ensure the test setup is working properly. This method checks
452      * to ensure that the getSampleKeys and getSampleValues methods are
453      * returning results that look appropriate. That is, they both return a
454      * non-null array of equal length. The keys array must not have any
455      * duplicate values, and may only contain a (single) null key if
456      * isNullKeySupported() returns true. The values array must only have a null
457      * value if useNullValue() is true and may only have duplicate values if
458      * isAllowDuplicateValues() returns true.
459      */

460     public void testSampleMappings() {
461       Object JavaDoc[] keys = getSampleKeys();
462       Object JavaDoc[] values = getSampleValues();
463       Object JavaDoc[] newValues = getNewSampleValues();
464
465       assertTrue("failure in test: Must have keys returned from " +
466                  "getSampleKeys.", keys != null);
467
468       assertTrue("failure in test: Must have values returned from " +
469                  "getSampleValues.", values != null);
470
471       // verify keys and values have equivalent lengths (in case getSampleX are
472
// overridden)
473
assertEquals("failure in test: not the same number of sample " +
474                    "keys and values.", keys.length, values.length);
475       
476       assertEquals("failure in test: not the same number of values and new values.",
477                    values.length, newValues.length);
478
479       // verify there aren't duplicate keys, and check values
480
for(int i = 0; i < keys.length - 1; i++) {
481           for(int j = i + 1; j < keys.length; j++) {
482               assertTrue("failure in test: duplicate null keys.",
483                          (keys[i] != null || keys[j] != null));
484               assertTrue("failure in test: duplicate non-null key.",
485                          (keys[i] == null || keys[j] == null ||
486                           (!keys[i].equals(keys[j]) &&
487                            !keys[j].equals(keys[i]))));
488           }
489           assertTrue("failure in test: found null key, but isNullKeySupported " +
490                      "is false.", keys[i] != null || isAllowNullKey());
491           assertTrue("failure in test: found null value, but isNullValueSupported " +
492                      "is false.", values[i] != null || isAllowNullValue());
493           assertTrue("failure in test: found null new value, but isNullValueSupported " +
494                      "is false.", newValues[i] != null || isAllowNullValue());
495           assertTrue("failure in test: values should not be the same as new value",
496                      values[i] != newValues[i] &&
497                      (values[i] == null || !values[i].equals(newValues[i])));
498       }
499     }
500     
501     // tests begin here. Each test adds a little bit of tested functionality.
502
// Many methods assume previous methods passed. That is, they do not
503
// exhaustively recheck things that have already been checked in a previous
504
// test methods.
505

506     /**
507      * Test to ensure that makeEmptyMap and makeFull returns a new non-null
508      * map with each invocation.
509      */

510     public void testMakeMap() {
511         Map JavaDoc em = makeEmptyMap();
512         assertTrue("failure in test: makeEmptyMap must return a non-null map.",
513                    em != null);
514         
515         Map JavaDoc em2 = makeEmptyMap();
516         assertTrue("failure in test: makeEmptyMap must return a non-null map.",
517                    em != null);
518
519         assertTrue("failure in test: makeEmptyMap must return a new map " +
520                    "with each invocation.", em != em2);
521
522         Map JavaDoc fm = makeFullMap();
523         assertTrue("failure in test: makeFullMap must return a non-null map.",
524                    fm != null);
525         
526         Map JavaDoc fm2 = makeFullMap();
527         assertTrue("failure in test: makeFullMap must return a non-null map.",
528                    fm != null);
529
530         assertTrue("failure in test: makeFullMap must return a new map " +
531                    "with each invocation.", fm != fm2);
532     }
533
534     /**
535      * Tests Map.isEmpty()
536      */

537     public void testMapIsEmpty() {
538         resetEmpty();
539         assertEquals("Map.isEmpty() should return true with an empty map",
540                      true, map.isEmpty());
541         verify();
542
543         resetFull();
544         assertEquals("Map.isEmpty() should return false with a non-empty map",
545                      false, map.isEmpty());
546         verify();
547     }
548
549     /**
550      * Tests Map.size()
551      */

552     public void testMapSize() {
553         resetEmpty();
554         assertEquals("Map.size() should be 0 with an empty map",
555                      0, map.size());
556         verify();
557
558         resetFull();
559         assertEquals("Map.size() should equal the number of entries " +
560                      "in the map", getSampleKeys().length, map.size());
561         verify();
562     }
563
564     /**
565      * Tests {@link Map#clear()}. If the map {@link #isRemoveSupported()}
566      * can add and remove elements}, then {@link Map#size()} and
567      * {@link Map#isEmpty()} are used to ensure that map has no elements after
568      * a call to clear. If the map does not support adding and removing
569      * elements, this method checks to ensure clear throws an
570      * UnsupportedOperationException.
571      */

572     public void testMapClear() {
573         if (!isRemoveSupported()) {
574             try {
575                 resetFull();
576                 map.clear();
577                 fail("Expected UnsupportedOperationException on clear");
578             } catch (UnsupportedOperationException JavaDoc ex) {}
579             return;
580         }
581
582         resetEmpty();
583         map.clear();
584         confirmed.clear();
585         verify();
586         
587         resetFull();
588         map.clear();
589         confirmed.clear();
590         verify();
591     }
592
593
594     /**
595      * Tests Map.containsKey(Object) by verifying it returns false for all
596      * sample keys on a map created using an empty map and returns true for
597      * all sample keys returned on a full map.
598      */

599     public void testMapContainsKey() {
600         Object JavaDoc[] keys = getSampleKeys();
601
602         resetEmpty();
603         for(int i = 0; i < keys.length; i++) {
604             assertTrue("Map must not contain key when map is empty",
605                        !map.containsKey(keys[i]));
606         }
607         verify();
608
609         resetFull();
610         for(int i = 0; i < keys.length; i++) {
611             assertTrue("Map must contain key for a mapping in the map. " +
612                        "Missing: " + keys[i], map.containsKey(keys[i]));
613         }
614         verify();
615     }
616
617     /**
618      * Tests Map.containsValue(Object) by verifying it returns false for all
619      * sample values on an empty map and returns true for all sample values on
620      * a full map.
621      */

622     public void testMapContainsValue() {
623         Object JavaDoc[] values = getSampleValues();
624
625         resetEmpty();
626         for(int i = 0; i < values.length; i++) {
627             assertTrue("Empty map must not contain value",
628                        !map.containsValue(values[i]));
629         }
630         verify();
631         
632         resetFull();
633         for(int i = 0; i < values.length; i++) {
634             assertTrue("Map must contain value for a mapping in the map.",
635                        map.containsValue(values[i]));
636         }
637         verify();
638     }
639
640
641     /**
642      * Tests Map.equals(Object)
643      */

644     public void testMapEquals() {
645         resetEmpty();
646         assertTrue("Empty maps unequal.", map.equals(confirmed));
647         verify();
648
649         resetFull();
650         assertTrue("Full maps unequal.", map.equals(confirmed));
651         verify();
652
653         resetFull();
654         // modify the HashMap created from the full map and make sure this
655
// change results in map.equals() to return false.
656
Iterator JavaDoc iter = confirmed.keySet().iterator();
657         iter.next();
658         iter.remove();
659         assertTrue("Different maps equal.", !map.equals(confirmed));
660         
661         resetFull();
662         assertTrue("equals(null) returned true.", !map.equals(null));
663         assertTrue("equals(new Object()) returned true.",
664                    !map.equals(new Object JavaDoc()));
665         verify();
666     }
667
668
669     /**
670      * Tests Map.get(Object)
671      */

672     public void testMapGet() {
673         resetEmpty();
674
675         Object JavaDoc[] keys = getSampleKeys();
676         Object JavaDoc[] values = getSampleValues();
677
678         for (int i = 0; i < keys.length; i++) {
679             assertTrue("Empty map.get() should return null.",
680                        map.get(keys[i]) == null);
681         }
682         verify();
683
684         resetFull();
685         for (int i = 0; i < keys.length; i++) {
686             assertEquals("Full map.get() should return value from mapping.",
687                          values[i], map.get(keys[i]));
688         }
689     }
690
691     /**
692      * Tests Map.hashCode()
693      */

694     public void testMapHashCode() {
695         resetEmpty();
696         assertTrue("Empty maps have different hashCodes.",
697                    map.hashCode() == confirmed.hashCode());
698
699         resetFull();
700         assertTrue("Equal maps have different hashCodes.",
701                    map.hashCode() == confirmed.hashCode());
702     }
703
704     /**
705      * Tests Map.toString(). Since the format of the string returned by the
706      * toString() method is not defined in the Map interface, there is no
707      * common way to test the results of the toString() method. Thereforce,
708      * it is encouraged that Map implementations override this test with one
709      * that checks the format matches any format defined in its API. This
710      * default implementation just verifies that the toString() method does
711      * not return null.
712      */

713     public void testMapToString() {
714         resetEmpty();
715         assertTrue("Empty map toString() should not return null",
716                    map.toString() != null);
717         verify();
718
719         resetFull();
720         assertTrue("Empty map toString() should not return null",
721                    map.toString() != null);
722         verify();
723     }
724
725
726     /**
727      * Compare the current serialized form of the Map
728      * against the canonical version in CVS.
729      */

730     public void testEmptyMapCompatibility() throws Exception JavaDoc {
731         /**
732          * Create canonical objects with this code
733         Map map = makeEmptyMap();
734         if (!(map instanceof Serializable)) return;
735         
736         writeExternalFormToDisk((Serializable) map, getCanonicalEmptyCollectionName(map));
737         */

738
739         // test to make sure the canonical form has been preserved
740
Map JavaDoc map = makeEmptyMap();
741         if (map instanceof Serializable JavaDoc && !skipSerializedCanonicalTests() && isTestSerialization()) {
742             Map JavaDoc map2 = (Map JavaDoc) readExternalFormFromDisk(getCanonicalEmptyCollectionName(map));
743             assertEquals("Map is empty", 0, map2.size());
744         }
745     }
746
747     /**
748      * Compare the current serialized form of the Map
749      * against the canonical version in CVS.
750      */

751     public void testFullMapCompatibility() throws Exception JavaDoc {
752         /**
753          * Create canonical objects with this code
754         Map map = makeFullMap();
755         if (!(map instanceof Serializable)) return;
756         
757         writeExternalFormToDisk((Serializable) map, getCanonicalFullCollectionName(map));
758         */

759
760         // test to make sure the canonical form has been preserved
761
Map JavaDoc map = makeFullMap();
762         if (map instanceof Serializable JavaDoc && !skipSerializedCanonicalTests() && isTestSerialization()) {
763             Map JavaDoc map2 = (Map JavaDoc) readExternalFormFromDisk(getCanonicalFullCollectionName(map));
764             assertEquals("Map is the right size", getSampleKeys().length, map2.size());
765         }
766     }
767
768     /**
769      * Tests Map.put(Object, Object)
770      */

771     public void testMapPut() {
772         resetEmpty();
773         Object JavaDoc[] keys = getSampleKeys();
774         Object JavaDoc[] values = getSampleValues();
775         Object JavaDoc[] newValues = getNewSampleValues();
776
777         if (isPutAddSupported()) {
778             for (int i = 0; i < keys.length; i++) {
779                 Object JavaDoc o = map.put(keys[i], values[i]);
780                 confirmed.put(keys[i], values[i]);
781                 verify();
782                 assertTrue("First map.put should return null", o == null);
783                 assertTrue("Map should contain key after put",
784                            map.containsKey(keys[i]));
785                 assertTrue("Map should contain value after put",
786                            map.containsValue(values[i]));
787             }
788             if (isPutChangeSupported()) {
789                 for (int i = 0; i < keys.length; i++) {
790                     Object JavaDoc o = map.put(keys[i], newValues[i]);
791                     confirmed.put(keys[i], newValues[i]);
792                     verify();
793                     assertEquals("Map.put should return previous value when changed",
794                                  values[i], o);
795                     assertTrue("Map should still contain key after put when changed",
796                                map.containsKey(keys[i]));
797                     assertTrue("Map should contain new value after put when changed",
798                                map.containsValue(newValues[i]));
799         
800                     // if duplicates are allowed, we're not guaranteed that the value
801
// no longer exists, so don't try checking that.
802
if (!isAllowDuplicateValues()) {
803                         assertTrue("Map should not contain old value after put when changed",
804                                    !map.containsValue(values[i]));
805                     }
806                 }
807             } else {
808                 try {
809                     // two possible exception here, either valid
810
map.put(keys[0], newValues[0]);
811                     fail("Expected IllegalArgumentException or UnsupportedOperationException on put (change)");
812                 } catch (IllegalArgumentException JavaDoc ex) {
813                 } catch (UnsupportedOperationException JavaDoc ex) {}
814             }
815             
816         } else if (isPutChangeSupported()) {
817             resetEmpty();
818             try {
819                 map.put(keys[0], values[0]);
820                 fail("Expected UnsupportedOperationException or IllegalArgumentException on put (add) when fixed size");
821             } catch (IllegalArgumentException JavaDoc ex) {
822             } catch (UnsupportedOperationException JavaDoc ex) {
823             }
824             
825             resetFull();
826             int i = 0;
827             for (Iterator JavaDoc it = map.keySet().iterator(); it.hasNext() && i < newValues.length; i++) {
828                 Object JavaDoc key = it.next();
829                 Object JavaDoc o = map.put(key, newValues[i]);
830                 Object JavaDoc value = confirmed.put(key, newValues[i]);
831                 verify();
832                 assertEquals("Map.put should return previous value when changed",
833                     value, o);
834                 assertTrue("Map should still contain key after put when changed",
835                     map.containsKey(key));
836                 assertTrue("Map should contain new value after put when changed",
837                     map.containsValue(newValues[i]));
838         
839                 // if duplicates are allowed, we're not guaranteed that the value
840
// no longer exists, so don't try checking that.
841
if (!isAllowDuplicateValues()) {
842                     assertTrue("Map should not contain old value after put when changed",
843                         !map.containsValue(values[i]));
844                 }
845             }
846         } else {
847             try {
848                 map.put(keys[0], values[0]);
849                 fail("Expected UnsupportedOperationException on put (add)");
850             } catch (UnsupportedOperationException JavaDoc ex) {}
851         }
852     }
853
854     /**
855      * Tests Map.put(null, value)
856      */

857     public void testMapPutNullKey() {
858         resetFull();
859         Object JavaDoc[] values = getSampleValues();
860     
861         if (isPutAddSupported()) {
862             if (isAllowNullKey()) {
863                 map.put(null, values[0]);
864             } else {
865                 try {
866                     map.put(null, values[0]);
867                     fail("put(null, value) should throw NPE/IAE");
868                 } catch (NullPointerException JavaDoc ex) {
869                 } catch (IllegalArgumentException JavaDoc ex) {}
870             }
871         }
872     }
873     
874     /**
875      * Tests Map.put(null, value)
876      */

877     public void testMapPutNullValue() {
878         resetFull();
879         Object JavaDoc[] keys = getSampleKeys();
880         
881         if (isPutAddSupported()) {
882             if (isAllowNullValue()) {
883                 map.put(keys[0], null);
884             } else {
885                 try {
886                     map.put(keys[0], null);
887                     fail("put(key, null) should throw NPE/IAE");
888                 } catch (NullPointerException JavaDoc ex) {
889                 } catch (IllegalArgumentException JavaDoc ex) {}
890             }
891         }
892     }
893     
894     /**
895      * Tests Map.putAll(map)
896      */

897     public void testMapPutAll() {
898         if (!isPutAddSupported()) {
899             if (!isPutChangeSupported()) {
900                 Map JavaDoc temp = makeFullMap();
901                 resetEmpty();
902                 try {
903                     map.putAll(temp);
904                     fail("Expected UnsupportedOperationException on putAll");
905                 } catch (UnsupportedOperationException JavaDoc ex) {}
906             }
907             return;
908         }
909
910         resetEmpty();
911
912         Map JavaDoc m2 = makeFullMap();
913
914         map.putAll(m2);
915         confirmed.putAll(m2);
916         verify();
917
918         resetEmpty();
919
920         m2 = makeConfirmedMap();
921         Object JavaDoc[] keys = getSampleKeys();
922         Object JavaDoc[] values = getSampleValues();
923         for(int i = 0; i < keys.length; i++) {
924             m2.put(keys[i], values[i]);
925         }
926
927         map.putAll(m2);
928         confirmed.putAll(m2);
929         verify();
930     }
931
932     /**
933      * Tests Map.remove(Object)
934      */

935     public void testMapRemove() {
936         if (!isRemoveSupported()) {
937             try {
938                 resetFull();
939                 map.remove(map.keySet().iterator().next());
940                 fail("Expected UnsupportedOperationException on remove");
941             } catch (UnsupportedOperationException JavaDoc ex) {}
942             return;
943         }
944
945         resetEmpty();
946
947         Object JavaDoc[] keys = getSampleKeys();
948         Object JavaDoc[] values = getSampleValues();
949         for(int i = 0; i < keys.length; i++) {
950             Object JavaDoc o = map.remove(keys[i]);
951             assertTrue("First map.remove should return null", o == null);
952         }
953         verify();
954
955         resetFull();
956
957         for(int i = 0; i < keys.length; i++) {
958             Object JavaDoc o = map.remove(keys[i]);
959             confirmed.remove(keys[i]);
960             verify();
961
962             assertEquals("map.remove with valid key should return value",
963                          values[i], o);
964         }
965
966         Object JavaDoc[] other = getOtherKeys();
967
968         resetFull();
969         int size = map.size();
970         for (int i = 0; i < other.length; i++) {
971             Object JavaDoc o = map.remove(other[i]);
972             assertEquals("map.remove for nonexistent key should return null",
973                          o, null);
974             assertEquals("map.remove for nonexistent key should not " +
975                          "shrink map", size, map.size());
976         }
977         verify();
978     }
979
980     //-----------------------------------------------------------------------
981
/**
982      * Tests that the {@link Map#values} collection is backed by
983      * the underlying map for clear().
984      */

985     public void testValuesClearChangesMap() {
986         if (!isRemoveSupported()) return;
987         
988         // clear values, reflected in map
989
resetFull();
990         Collection JavaDoc values = map.values();
991         assertTrue(map.size() > 0);
992         assertTrue(values.size() > 0);
993         values.clear();
994         assertTrue(map.size() == 0);
995         assertTrue(values.size() == 0);
996         
997         // clear map, reflected in values
998
resetFull();
999         values = map.values();
1000        assertTrue(map.size() > 0);
1001        assertTrue(values.size() > 0);
1002        map.clear();
1003        assertTrue(map.size() == 0);
1004        assertTrue(values.size() == 0);
1005    }
1006    
1007    /**
1008     * Tests that the {@link Map#keySet} collection is backed by
1009     * the underlying map for clear().
1010     */

1011    public void testKeySetClearChangesMap() {
1012        if (!isRemoveSupported()) return;
1013        
1014        // clear values, reflected in map
1015
resetFull();
1016        Set JavaDoc keySet = map.keySet();
1017        assertTrue(map.size() > 0);
1018        assertTrue(keySet.size() > 0);
1019        keySet.clear();
1020        assertTrue(map.size() == 0);
1021        assertTrue(keySet.size() == 0);
1022        
1023        // clear map, reflected in values
1024
resetFull();
1025        keySet = map.keySet();
1026        assertTrue(map.size() > 0);
1027        assertTrue(keySet.size() > 0);
1028        map.clear();
1029        assertTrue(map.size() == 0);
1030        assertTrue(keySet.size() == 0);
1031    }
1032    
1033    /**
1034     * Tests that the {@link Map#entrySet()} collection is backed by
1035     * the underlying map for clear().
1036     */

1037    public void testEntrySetClearChangesMap() {
1038        if (!isRemoveSupported()) return;
1039        
1040        // clear values, reflected in map
1041
resetFull();
1042        Set JavaDoc entrySet = map.entrySet();
1043        assertTrue(map.size() > 0);
1044        assertTrue(entrySet.size() > 0);
1045        entrySet.clear();
1046        assertTrue(map.size() == 0);
1047        assertTrue(entrySet.size() == 0);
1048        
1049        // clear map, reflected in values
1050
resetFull();
1051        entrySet = map.entrySet();
1052        assertTrue(map.size() > 0);
1053        assertTrue(entrySet.size() > 0);
1054        map.clear();
1055        assertTrue(map.size() == 0);
1056        assertTrue(entrySet.size() == 0);
1057    }
1058
1059    //-----------------------------------------------------------------------
1060
public void testEntrySetContains1() {
1061        resetFull();
1062        Set JavaDoc entrySet = map.entrySet();
1063        Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entrySet.iterator().next();
1064        assertEquals(true, entrySet.contains(entry));
1065    }
1066    public void testEntrySetContains2() {
1067        resetFull();
1068        Set JavaDoc entrySet = map.entrySet();
1069        Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entrySet.iterator().next();
1070        Map.Entry JavaDoc test = cloneMapEntry(entry);
1071        assertEquals(true, entrySet.contains(test));
1072    }
1073    public void testEntrySetContains3() {
1074        resetFull();
1075        Set JavaDoc entrySet = map.entrySet();
1076        Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entrySet.iterator().next();
1077        HashMap JavaDoc temp = new HashMap JavaDoc();
1078        temp.put(entry.getKey(), "A VERY DIFFERENT VALUE");
1079        Map.Entry JavaDoc test = (Map.Entry JavaDoc) temp.entrySet().iterator().next();
1080        assertEquals(false, entrySet.contains(test));
1081    }
1082    
1083    public void testEntrySetRemove1() {
1084        if (!isRemoveSupported()) return;
1085        resetFull();
1086        int size = map.size();
1087        Set JavaDoc entrySet = map.entrySet();
1088        Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entrySet.iterator().next();
1089        Object JavaDoc key = entry.getKey();
1090        
1091        assertEquals(true, entrySet.remove(entry));
1092        assertEquals(false, map.containsKey(key));
1093        assertEquals(size - 1, map.size());
1094    }
1095    public void testEntrySetRemove2() {
1096        if (!isRemoveSupported()) return;
1097        resetFull();
1098        int size = map.size();
1099        Set JavaDoc entrySet = map.entrySet();
1100        Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entrySet.iterator().next();
1101        Object JavaDoc key = entry.getKey();
1102        Map.Entry JavaDoc test = cloneMapEntry(entry);
1103        
1104        assertEquals(true, entrySet.remove(test));
1105        assertEquals(false, map.containsKey(key));
1106        assertEquals(size - 1, map.size());
1107    }
1108    public void testEntrySetRemove3() {
1109        if (!isRemoveSupported()) return;
1110        resetFull();
1111        int size = map.size();
1112        Set JavaDoc entrySet = map.entrySet();
1113        Map.Entry JavaDoc entry = (Map.Entry JavaDoc) entrySet.iterator().next();
1114        Object JavaDoc key = entry.getKey();
1115        HashMap JavaDoc temp = new HashMap JavaDoc();
1116        temp.put(entry.getKey(), "A VERY DIFFERENT VALUE");
1117        Map.Entry JavaDoc test = (Map.Entry JavaDoc) temp.entrySet().iterator().next();
1118        
1119        assertEquals(false, entrySet.remove(test));
1120        assertEquals(true, map.containsKey(key));
1121        assertEquals(size, map.size());
1122    }
1123    
1124    //-----------------------------------------------------------------------
1125
/**
1126     * Tests that the {@link Map#values} collection is backed by
1127     * the underlying map by removing from the values collection
1128     * and testing if the value was removed from the map.
1129     * <p>
1130     * We should really test the "vice versa" case--that values removed
1131     * from the map are removed from the values collection--also,
1132     * but that's a more difficult test to construct (lacking a
1133     * "removeValue" method.)
1134     * </p>
1135     * <p>
1136     * See bug <a HREF="http://issues.apache.org/bugzilla/show_bug.cgi?id=9573">
1137     * 9573</a>.
1138     * </p>
1139     */

1140    public void testValuesRemoveChangesMap() {
1141        resetFull();
1142        Object JavaDoc[] sampleValues = getSampleValues();
1143        Collection JavaDoc values = map.values();
1144        for (int i = 0; i < sampleValues.length; i++) {
1145            if (map.containsValue(sampleValues[i])) {
1146                int j = 0; // loop counter prevents infinite loops when remove is broken
1147
while (values.contains(sampleValues[i]) && j < 10000) {
1148                    try {
1149                        values.remove(sampleValues[i]);
1150                    } catch (UnsupportedOperationException JavaDoc e) {
1151                        // if values.remove is unsupported, just skip this test
1152
return;
1153                    }
1154                    j++;
1155                }
1156                assertTrue("values().remove(obj) is broken", j < 10000);
1157                assertTrue(
1158                    "Value should have been removed from the underlying map.",
1159                    !map.containsValue(sampleValues[i]));
1160            }
1161        }
1162    }
1163
1164    /**
1165     * Tests that the {@link Map#keySet} set is backed by
1166     * the underlying map by removing from the keySet set
1167     * and testing if the key was removed from the map.
1168     */

1169    public void testKeySetRemoveChangesMap() {
1170        resetFull();
1171        Object JavaDoc[] sampleKeys = getSampleKeys();
1172        Set JavaDoc keys = map.keySet();
1173        for (int i = 0; i < sampleKeys.length; i++) {
1174            try {
1175                keys.remove(sampleKeys[i]);
1176            } catch (UnsupportedOperationException JavaDoc e) {
1177                // if key.remove is unsupported, just skip this test
1178
return;
1179            }
1180            assertTrue(
1181                "Key should have been removed from the underlying map.",
1182                !map.containsKey(sampleKeys[i]));
1183        }
1184    }
1185
1186    // TODO: Need:
1187
// testValuesRemovedFromEntrySetAreRemovedFromMap
1188
// same for EntrySet/KeySet/values's
1189
// Iterator.remove, removeAll, retainAll
1190

1191
1192    /**
1193     * Utility methods to create an array of Map.Entry objects
1194     * out of the given key and value arrays.<P>
1195     *
1196     * @param keys the array of keys
1197     * @param values the array of values
1198     * @return an array of Map.Entry of those keys to those values
1199     */

1200    private Map.Entry JavaDoc[] makeEntryArray(Object JavaDoc[] keys, Object JavaDoc[] values) {
1201        Map.Entry JavaDoc[] result = new Map.Entry JavaDoc[keys.length];
1202        for (int i = 0; i < keys.length; i++) {
1203            Map JavaDoc map = makeConfirmedMap();
1204            map.put(keys[i], values[i]);
1205            result[i] = (Map.Entry JavaDoc) map.entrySet().iterator().next();
1206        }
1207        return result;
1208    }
1209
1210
1211    /**
1212     * Bulk test {@link Map#entrySet()}. This method runs through all of
1213     * the tests in {@link AbstractTestSet}.
1214     * After modification operations, {@link #verify()} is invoked to ensure
1215     * that the map and the other collection views are still valid.
1216     *
1217     * @return a {@link AbstractTestSet} instance for testing the map's entry set
1218     */

1219    public BulkTest bulkTestMapEntrySet() {
1220        return new TestMapEntrySet();
1221    }
1222
1223    public class TestMapEntrySet extends AbstractTestSet {
1224        public TestMapEntrySet() {
1225            super("MapEntrySet");
1226        }
1227
1228        // Have to implement manually; entrySet doesn't support addAll
1229
public Object JavaDoc[] getFullElements() {
1230            Object JavaDoc[] k = getSampleKeys();
1231            Object JavaDoc[] v = getSampleValues();
1232            return makeEntryArray(k, v);
1233        }
1234        
1235        // Have to implement manually; entrySet doesn't support addAll
1236
public Object JavaDoc[] getOtherElements() {
1237            Object JavaDoc[] k = getOtherKeys();
1238            Object JavaDoc[] v = getOtherValues();
1239            return makeEntryArray(k, v);
1240        }
1241        
1242        public Set JavaDoc makeEmptySet() {
1243            return makeEmptyMap().entrySet();
1244        }
1245        
1246        public Set JavaDoc makeFullSet() {
1247            return makeFullMap().entrySet();
1248        }
1249        
1250        public boolean isAddSupported() {
1251            // Collection views don't support add operations.
1252
return false;
1253        }
1254        public boolean isRemoveSupported() {
1255            // Entry set should only support remove if map does
1256
return AbstractTestMap.this.isRemoveSupported();
1257        }
1258        public boolean isGetStructuralModify() {
1259            return AbstractTestMap.this.isGetStructuralModify();
1260        }
1261        public boolean isTestSerialization() {
1262            return false;
1263        }
1264
1265        public void resetFull() {
1266            AbstractTestMap.this.resetFull();
1267            collection = map.entrySet();
1268            TestMapEntrySet.this.confirmed = AbstractTestMap.this.confirmed.entrySet();
1269        }
1270        
1271        public void resetEmpty() {
1272            AbstractTestMap.this.resetEmpty();
1273            collection = map.entrySet();
1274            TestMapEntrySet.this.confirmed = AbstractTestMap.this.confirmed.entrySet();
1275        }
1276        
1277        public void testMapEntrySetIteratorEntry() {
1278            resetFull();
1279            Iterator JavaDoc it = collection.iterator();
1280            int count = 0;
1281            while (it.hasNext()) {
1282                Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
1283                assertEquals(true, AbstractTestMap.this.map.containsKey(entry.getKey()));
1284                assertEquals(true, AbstractTestMap.this.map.containsValue(entry.getValue()));
1285                if (isGetStructuralModify() == false) {
1286                    assertEquals(AbstractTestMap.this.map.get(entry.getKey()), entry.getValue());
1287                }
1288                count++;
1289            }
1290            assertEquals(collection.size(), count);
1291        }
1292
1293        public void testMapEntrySetIteratorEntrySetValue() {
1294            Object JavaDoc key1 = getSampleKeys()[0];
1295            Object JavaDoc key2 = (getSampleKeys().length ==1 ? getSampleKeys()[0] : getSampleKeys()[1]);
1296            Object JavaDoc newValue1 = getNewSampleValues()[0];
1297            Object JavaDoc newValue2 = (getNewSampleValues().length ==1 ? getNewSampleValues()[0] : getNewSampleValues()[1]);
1298            
1299            resetFull();
1300            // explicitly get entries as sample values/keys are connected for some maps
1301
// such as BeanMap
1302
Iterator JavaDoc it = TestMapEntrySet.this.collection.iterator();
1303            Map.Entry JavaDoc entry1 = getEntry(it, key1);
1304            it = TestMapEntrySet.this.collection.iterator();
1305            Map.Entry JavaDoc entry2 = getEntry(it, key2);
1306            Iterator JavaDoc itConfirmed = TestMapEntrySet.this.confirmed.iterator();
1307            Map.Entry JavaDoc entryConfirmed1 = getEntry(itConfirmed, key1);
1308            itConfirmed = TestMapEntrySet.this.confirmed.iterator();
1309            Map.Entry JavaDoc entryConfirmed2 = getEntry(itConfirmed, key2);
1310            verify();
1311            
1312            if (isSetValueSupported() == false) {
1313                try {
1314                    entry1.setValue(newValue1);
1315                } catch (UnsupportedOperationException JavaDoc ex) {
1316                }
1317                return;
1318            }
1319            
1320            entry1.setValue(newValue1);
1321            entryConfirmed1.setValue(newValue1);
1322            assertEquals(newValue1, entry1.getValue());
1323            assertEquals(true, AbstractTestMap.this.map.containsKey(entry1.getKey()));
1324            assertEquals(true, AbstractTestMap.this.map.containsValue(newValue1));
1325            assertEquals(newValue1, AbstractTestMap.this.map.get(entry1.getKey()));
1326            verify();
1327            
1328            entry1.setValue(newValue1);
1329            entryConfirmed1.setValue(newValue1);
1330            assertEquals(newValue1, entry1.getValue());
1331            assertEquals(true, AbstractTestMap.this.map.containsKey(entry1.getKey()));
1332            assertEquals(true, AbstractTestMap.this.map.containsValue(newValue1));
1333            assertEquals(newValue1, AbstractTestMap.this.map.get(entry1.getKey()));
1334            verify();
1335            
1336            entry2.setValue(newValue2);
1337            entryConfirmed2.setValue(newValue2);
1338            assertEquals(newValue2, entry2.getValue());
1339            assertEquals(true, AbstractTestMap.this.map.containsKey(entry2.getKey()));
1340            assertEquals(true, AbstractTestMap.this.map.containsValue(newValue2));
1341            assertEquals(newValue2, AbstractTestMap.this.map.get(entry2.getKey()));
1342            verify();
1343        }
1344        
1345        public Map.Entry JavaDoc getEntry(Iterator JavaDoc itConfirmed, Object JavaDoc key) {
1346            Map.Entry JavaDoc entry = null;
1347            while (itConfirmed.hasNext()) {
1348                Map.Entry JavaDoc temp = (Map.Entry JavaDoc) itConfirmed.next();
1349                if (temp.getKey() == null) {
1350                    if (key == null) {
1351                        entry = temp;
1352                        break;
1353                    }
1354                } else if (temp.getKey().equals(key)) {
1355                    entry = temp;
1356                    break;
1357                }
1358            }
1359            assertNotNull("No matching entry in map for key '" + key + "'", entry);
1360            return entry;
1361        }
1362
1363        public void testMapEntrySetRemoveNonMapEntry() {
1364            if (isRemoveSupported() == false) return;
1365            resetFull();
1366            assertEquals(false, getSet().remove(null));
1367            assertEquals(false, getSet().remove(new Object JavaDoc()));
1368        }
1369        
1370        public void verify() {
1371            super.verify();
1372            AbstractTestMap.this.verify();
1373        }
1374    }
1375
1376
1377    /**
1378     * Bulk test {@link Map#keySet()}. This method runs through all of
1379     * the tests in {@link AbstractTestSet}.
1380     * After modification operations, {@link #verify()} is invoked to ensure
1381     * that the map and the other collection views are still valid.
1382     *
1383     * @return a {@link AbstractTestSet} instance for testing the map's key set
1384     */

1385    public BulkTest bulkTestMapKeySet() {
1386        return new TestMapKeySet();
1387    }
1388
1389    public class TestMapKeySet extends AbstractTestSet {
1390        public TestMapKeySet() {
1391            super("");
1392        }
1393        public Object JavaDoc[] getFullElements() {
1394            return getSampleKeys();
1395        }
1396        
1397        public Object JavaDoc[] getOtherElements() {
1398            return getOtherKeys();
1399        }
1400        
1401        public Set JavaDoc makeEmptySet() {
1402            return makeEmptyMap().keySet();
1403        }
1404        
1405        public Set JavaDoc makeFullSet() {
1406            return makeFullMap().keySet();
1407        }
1408        
1409        public boolean isNullSupported() {
1410            return AbstractTestMap.this.isAllowNullKey();
1411        }
1412        public boolean isAddSupported() {
1413            return false;
1414        }
1415        public boolean isRemoveSupported() {
1416            return AbstractTestMap.this.isRemoveSupported();
1417        }
1418        public boolean isTestSerialization() {
1419            return false;
1420        }
1421        
1422        public void resetEmpty() {
1423            AbstractTestMap.this.resetEmpty();
1424            collection = map.keySet();
1425            TestMapKeySet.this.confirmed = AbstractTestMap.this.confirmed.keySet();
1426        }
1427        
1428        public void resetFull() {
1429            AbstractTestMap.this.resetFull();
1430            collection = map.keySet();
1431            TestMapKeySet.this.confirmed = AbstractTestMap.this.confirmed.keySet();
1432        }
1433        
1434        public void verify() {
1435            super.verify();
1436            AbstractTestMap.this.verify();
1437        }
1438    }
1439
1440
1441    /**
1442     * Bulk test {@link Map#values()}. This method runs through all of
1443     * the tests in {@link AbstractTestCollection}.
1444     * After modification operations, {@link #verify()} is invoked to ensure
1445     * that the map and the other collection views are still valid.
1446     *
1447     * @return a {@link AbstractTestCollection} instance for testing the map's
1448     * values collection
1449     */

1450    public BulkTest bulkTestMapValues() {
1451        return new TestMapValues();
1452    }
1453
1454    public class TestMapValues extends AbstractTestCollection {
1455        public TestMapValues() {
1456            super("");
1457        }
1458
1459        public Object JavaDoc[] getFullElements() {
1460            return getSampleValues();
1461        }
1462        
1463        public Object JavaDoc[] getOtherElements() {
1464            return getOtherValues();
1465        }
1466        
1467        public Collection JavaDoc makeCollection() {
1468            return makeEmptyMap().values();
1469        }
1470        
1471        public Collection JavaDoc makeFullCollection() {
1472            return makeFullMap().values();
1473        }
1474        
1475        public boolean isNullSupported() {
1476            return AbstractTestMap.this.isAllowNullKey();
1477        }
1478        public boolean isAddSupported() {
1479            return false;
1480        }
1481        public boolean isRemoveSupported() {
1482            return AbstractTestMap.this.isRemoveSupported();
1483        }
1484        public boolean isTestSerialization() {
1485            return false;
1486        }
1487        
1488        public boolean areEqualElementsDistinguishable() {
1489            // equal values are associated with different keys, so they are
1490
// distinguishable.
1491
return true;
1492        }
1493
1494        public Collection JavaDoc makeConfirmedCollection() {
1495            // never gets called, reset methods are overridden
1496
return null;
1497        }
1498        
1499        public Collection JavaDoc makeConfirmedFullCollection() {
1500            // never gets called, reset methods are overridden
1501
return null;
1502        }
1503        
1504        public void resetFull() {
1505            AbstractTestMap.this.resetFull();
1506            collection = map.values();
1507            TestMapValues.this.confirmed = AbstractTestMap.this.confirmed.values();
1508        }
1509        
1510        public void resetEmpty() {
1511            AbstractTestMap.this.resetEmpty();
1512            collection = map.values();
1513            TestMapValues.this.confirmed = AbstractTestMap.this.confirmed.values();
1514        }
1515
1516        public void verify() {
1517            super.verify();
1518            AbstractTestMap.this.verify();
1519        }
1520
1521        // TODO: should test that a remove on the values collection view
1522
// removes the proper mapping and not just any mapping that may have
1523
// the value equal to the value returned from the values iterator.
1524
}
1525
1526
1527    /**
1528     * Resets the {@link #map}, {@link #entrySet}, {@link #keySet},
1529     * {@link #values} and {@link #confirmed} fields to empty.
1530     */

1531    public void resetEmpty() {
1532        this.map = makeEmptyMap();
1533        views();
1534        this.confirmed = makeConfirmedMap();
1535    }
1536
1537    /**
1538     * Resets the {@link #map}, {@link #entrySet}, {@link #keySet},
1539     * {@link #values} and {@link #confirmed} fields to full.
1540     */

1541    public void resetFull() {
1542        this.map = makeFullMap();
1543        views();
1544        this.confirmed = makeConfirmedMap();
1545        Object JavaDoc[] k = getSampleKeys();
1546        Object JavaDoc[] v = getSampleValues();
1547        for (int i = 0; i < k.length; i++) {
1548            confirmed.put(k[i], v[i]);
1549        }
1550    }
1551
1552
1553    /**
1554     * Resets the collection view fields.
1555     */

1556    private void views() {
1557        this.keySet = map.keySet();
1558        this.values = map.values();
1559        this.entrySet = map.entrySet();
1560    }
1561
1562
1563    /**
1564     * Verifies that {@link #map} is still equal to {@link #confirmed}.
1565     * This method checks that the map is equal to the HashMap,
1566     * <I>and</I> that the map's collection views are still equal to
1567     * the HashMap's collection views. An <Code>equals</Code> test
1568     * is done on the maps and their collection views; their size and
1569     * <Code>isEmpty</Code> results are compared; their hashCodes are
1570     * compared; and <Code>containsAll</Code> tests are run on the
1571     * collection views.
1572     */

1573    public void verify() {
1574        verifyMap();
1575        verifyEntrySet();
1576        verifyKeySet();
1577        verifyValues();
1578    }
1579
1580    public void verifyMap() {
1581        int size = confirmed.size();
1582        boolean empty = confirmed.isEmpty();
1583        assertEquals("Map should be same size as HashMap",
1584                     size, map.size());
1585        assertEquals("Map should be empty if HashMap is",
1586                     empty, map.isEmpty());
1587        assertEquals("hashCodes should be the same",
1588                     confirmed.hashCode(), map.hashCode());
1589        // this fails for LRUMap because confirmed.equals() somehow modifies
1590
// map, causing concurrent modification exceptions.
1591
//assertEquals("Map should still equal HashMap", confirmed, map);
1592
// this works though and performs the same verification:
1593
assertTrue("Map should still equal HashMap", map.equals(confirmed));
1594        // TODO: this should really be reexamined to figure out why LRU map
1595
// behaves like it does (the equals shouldn't modify since all accesses
1596
// by the confirmed collection should be through an iterator, thus not
1597
// causing LRUMap to change).
1598
}
1599
1600    public void verifyEntrySet() {
1601        int size = confirmed.size();
1602        boolean empty = confirmed.isEmpty();
1603        assertEquals("entrySet should be same size as HashMap's" +
1604                     "\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
1605                     size, entrySet.size());
1606        assertEquals("entrySet should be empty if HashMap is" +
1607                     "\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
1608                     empty, entrySet.isEmpty());
1609        assertTrue("entrySet should contain all HashMap's elements" +
1610                   "\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
1611                   entrySet.containsAll(confirmed.entrySet()));
1612        assertEquals("entrySet hashCodes should be the same" +
1613                     "\nTest: " + entrySet + "\nReal: " + confirmed.entrySet(),
1614                     confirmed.entrySet().hashCode(), entrySet.hashCode());
1615        assertEquals("Map's entry set should still equal HashMap's",
1616                     confirmed.entrySet(), entrySet);
1617    }
1618
1619    public void verifyKeySet() {
1620        int size = confirmed.size();
1621        boolean empty = confirmed.isEmpty();
1622        assertEquals("keySet should be same size as HashMap's" +
1623                     "\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
1624                     size, keySet.size());
1625        assertEquals("keySet should be empty if HashMap is" +
1626                     "\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
1627                     empty, keySet.isEmpty());
1628        assertTrue("keySet should contain all HashMap's elements" +
1629                   "\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
1630                   keySet.containsAll(confirmed.keySet()));
1631        assertEquals("keySet hashCodes should be the same" +
1632                     "\nTest: " + keySet + "\nReal: " + confirmed.keySet(),
1633                     confirmed.keySet().hashCode(), keySet.hashCode());
1634        assertEquals("Map's key set should still equal HashMap's",
1635                     confirmed.keySet(), keySet);
1636    }
1637
1638    public void verifyValues() {
1639        List JavaDoc known = new ArrayList JavaDoc(confirmed.values());
1640        List JavaDoc test = new ArrayList JavaDoc(values);
1641
1642        int size = confirmed.size();
1643        boolean empty = confirmed.isEmpty();
1644        assertEquals("values should be same size as HashMap's" +
1645                     "\nTest: " + test + "\nReal: " + known,
1646                     size, values.size());
1647        assertEquals("values should be empty if HashMap is" +
1648                     "\nTest: " + test + "\nReal: " + known,
1649                     empty, values.isEmpty());
1650        assertTrue("values should contain all HashMap's elements" +
1651                   "\nTest: " + test + "\nReal: " + known,
1652                    test.containsAll(known));
1653        assertTrue("values should contain all HashMap's elements" +
1654                   "\nTest: " + test + "\nReal: " + known,
1655                   known.containsAll(test));
1656        // originally coded to use a HashBag, but now separate jar so...
1657
for (Iterator JavaDoc it = known.iterator(); it.hasNext();) {
1658            boolean removed = test.remove(it.next());
1659            assertTrue("Map's values should still equal HashMap's", removed);
1660        }
1661        assertTrue("Map's values should still equal HashMap's", test.isEmpty());
1662    }
1663
1664
1665    /**
1666     * Erases any leftover instance variables by setting them to null.
1667     */

1668    public void tearDown() throws Exception JavaDoc {
1669        map = null;
1670        keySet = null;
1671        entrySet = null;
1672        values = null;
1673        confirmed = null;
1674    }
1675
1676}
1677
Popular Tags