View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.map;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertFalse;
21  import static org.junit.jupiter.api.Assertions.assertNull;
22  import static org.junit.jupiter.api.Assertions.assertSame;
23  import static org.junit.jupiter.api.Assertions.assertThrows;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  
26  import java.io.ByteArrayInputStream;
27  import java.io.ByteArrayOutputStream;
28  import java.io.IOException;
29  import java.io.ObjectInputStream;
30  import java.io.ObjectOutputStream;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.Collection;
34  import java.util.HashMap;
35  import java.util.HashSet;
36  import java.util.Iterator;
37  import java.util.LinkedList;
38  import java.util.Map;
39  
40  import org.apache.commons.collections4.AbstractObjectTest;
41  import org.apache.commons.collections4.IteratorUtils;
42  import org.apache.commons.collections4.MultiMap;
43  import org.junit.jupiter.api.Test;
44  
45  /**
46   * TestMultiValueMap.
47   */
48  @Deprecated
49  public class MultiValueMapTest<K, V> extends AbstractObjectTest {
50  
51      public MultiValueMapTest() {
52          super(MultiValueMapTest.class.getSimpleName());
53      }
54  
55      @SuppressWarnings("unchecked")
56      private MultiValueMap<K, V> createTestMap() {
57          return createTestMap(ArrayList.class);
58      }
59  
60      @SuppressWarnings("unchecked")
61      private <C extends Collection<V>> MultiValueMap<K, V> createTestMap(final Class<C> collectionClass) {
62          final MultiValueMap<K, V> map = MultiValueMap.multiValueMap(new HashMap<>(), collectionClass);
63          map.put((K) "one", (V) "uno");
64          map.put((K) "one", (V) "un");
65          map.put((K) "two", (V) "dos");
66          map.put((K) "two", (V) "deux");
67          map.put((K) "three", (V) "tres");
68          map.put((K) "three", (V) "trois");
69          return map;
70      }
71  
72      private Object deserialize(final byte[] data) throws IOException, ClassNotFoundException {
73          final ByteArrayInputStream bais = new ByteArrayInputStream(data);
74          final ObjectInputStream iis = new ObjectInputStream(bais);
75  
76          return iis.readObject();
77      }
78  
79      @Override
80      public String getCompatibilityVersion() {
81          return "4";
82      }
83  
84      @SuppressWarnings("rawtypes")
85      private Map makeEmptyMap() {
86          return new MultiValueMap();
87      }
88  
89      @Override
90      public Object makeObject() {
91          @SuppressWarnings("unchecked")
92          final Map<String, String> m = makeEmptyMap();
93          m.put("a", "1");
94          m.put("a", "1b");
95          m.put("b", "2");
96          m.put("c", "3");
97          m.put("c", "3b");
98          m.put("d", "4");
99          return m;
100     }
101 
102     private byte[] serialize(final Object object) throws IOException {
103         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
104         final ObjectOutputStream oos = new ObjectOutputStream(baos);
105 
106         oos.writeObject(object);
107         oos.close();
108 
109         return baos.toByteArray();
110     }
111 
112     @Test
113     @SuppressWarnings("unchecked")
114     public void testContainsValue() {
115         final MultiValueMap<K, V> map = createTestMap(HashSet.class);
116         assertTrue(map.containsValue("uno"));
117         assertTrue(map.containsValue("un"));
118         assertTrue(map.containsValue("dos"));
119         assertTrue(map.containsValue("deux"));
120         assertTrue(map.containsValue("tres"));
121         assertTrue(map.containsValue("trois"));
122         assertFalse(map.containsValue("quatro"));
123     }
124 
125     @Test
126     @SuppressWarnings("unchecked")
127     public void testContainsValue_Key() {
128         final MultiValueMap<K, V> map = new MultiValueMap<>();
129         assertFalse(map.containsValue("A", "AA"));
130         assertFalse(map.containsValue("B", "BB"));
131         map.put((K) "A", "AA");
132         assertTrue(map.containsValue("A", "AA"));
133         assertFalse(map.containsValue("A", "AB"));
134     }
135 
136     @Test
137     public void testEmptyMapCompatibility() throws Exception {
138         final Map<?, ?> map = makeEmptyMap();
139         final Map<?, ?> map2 = (Map<?, ?>) readExternalFormFromDisk(getCanonicalEmptyCollectionName(map));
140         assertEquals(0, map2.size(), "Map is empty");
141     }
142 
143     @Test
144     public void testFullMapCompatibility() throws Exception {
145         final Map<?, ?> map = (Map<?, ?>) makeObject();
146         final Map<?, ?> map2 = (Map<?, ?>) readExternalFormFromDisk(getCanonicalFullCollectionName(map));
147         assertEquals(map.size(), map2.size(), "Map is the right size");
148         for (final Object key : map.keySet()) {
149             assertEquals(map.get(key), map2.get(key), "Map had unequal elements");
150             map2.remove(key);
151         }
152         assertEquals(0, map2.size(), "Map had extra values");
153     }
154 
155     @Test
156     @SuppressWarnings("unchecked")
157     public void testGetCollection() {
158         final MultiValueMap<K, V> map = new MultiValueMap<>();
159         map.put((K) "A", "AA");
160         assertSame(map.get("A"), map.getCollection("A"));
161     }
162 
163     @Test
164     public void testIterator() {
165         final MultiValueMap<K, V> map = createTestMap();
166         @SuppressWarnings("unchecked")
167         final Collection<V> values = new ArrayList<>((Collection<V>) map.values());
168         final Iterator<Map.Entry<K, V>> iterator = map.iterator();
169         while (iterator.hasNext()) {
170             final Map.Entry<K, V> entry = iterator.next();
171             assertTrue(map.containsValue(entry.getKey(), entry.getValue()));
172             assertTrue(values.contains(entry.getValue()));
173             assertTrue(values.remove(entry.getValue()));
174         }
175         assertTrue(values.isEmpty());
176     }
177 
178     @Test
179     @SuppressWarnings("unchecked")
180     public void testIterator_Key() {
181         final MultiValueMap<K, V> map = new MultiValueMap<>();
182         assertFalse(map.iterator("A").hasNext());
183         map.put((K) "A", "AA");
184         final Iterator<?> it = map.iterator("A");
185         assertTrue(it.hasNext());
186         it.next();
187         assertFalse(it.hasNext());
188     }
189 
190     @Test
191     @SuppressWarnings("unchecked")
192     public void testKeyContainsValue() {
193         final MultiValueMap<K, V> map = createTestMap(HashSet.class);
194         assertTrue(map.containsValue("one", "uno"));
195         assertTrue(map.containsValue("one", "un"));
196         assertTrue(map.containsValue("two", "dos"));
197         assertTrue(map.containsValue("two", "deux"));
198         assertTrue(map.containsValue("three", "tres"));
199         assertTrue(map.containsValue("three", "trois"));
200         assertFalse(map.containsValue("four", "quatro"));
201     }
202 
203     @Test
204     public void testKeyedIterator() {
205         final MultiValueMap<K, V> map = createTestMap();
206         final ArrayList<Object> actual = new ArrayList<>(IteratorUtils.toList(map.iterator("one")));
207         final ArrayList<Object> expected = new ArrayList<>(Arrays.asList("uno", "un"));
208         assertEquals(expected, actual);
209     }
210 
211     @Test
212     @SuppressWarnings("unchecked")
213     public void testMapEquals() {
214         final MultiValueMap<K, V> one = new MultiValueMap<>();
215         final Integer value = Integer.valueOf(1);
216         one.put((K) "One", value);
217         one.removeMapping("One", value);
218 
219         final MultiValueMap<K, V> two = new MultiValueMap<>();
220         assertEquals(two, one);
221     }
222 
223     @Test
224     @SuppressWarnings("unchecked")
225     public void testMultipleValues() {
226         final MultiValueMap<K, V> map = createTestMap(HashSet.class);
227         final HashSet<V> expected = new HashSet<>();
228         expected.add((V) "uno");
229         expected.add((V) "un");
230         assertEquals(expected, map.get("one"));
231     }
232 
233     @Test
234     public void testNoMappingReturnsNull() {
235         final MultiValueMap<K, V> map = createTestMap();
236         assertNull(map.get("whatever"));
237     }
238 
239     @Test
240     @SuppressWarnings("unchecked")
241     public void testPutAll_KeyCollection() {
242         final MultiValueMap<K, V> map = new MultiValueMap<>();
243         Collection<V> coll = (Collection<V>) Arrays.asList("X", "Y", "Z");
244 
245         assertTrue(map.putAll((K) "A", coll));
246         assertEquals(3, map.size("A"));
247         assertTrue(map.containsValue("A", "X"));
248         assertTrue(map.containsValue("A", "Y"));
249         assertTrue(map.containsValue("A", "Z"));
250 
251         assertFalse(map.putAll((K) "A", null));
252         assertEquals(3, map.size("A"));
253         assertTrue(map.containsValue("A", "X"));
254         assertTrue(map.containsValue("A", "Y"));
255         assertTrue(map.containsValue("A", "Z"));
256 
257         assertFalse(map.putAll((K) "A", new ArrayList<>()));
258         assertEquals(3, map.size("A"));
259         assertTrue(map.containsValue("A", "X"));
260         assertTrue(map.containsValue("A", "Y"));
261         assertTrue(map.containsValue("A", "Z"));
262 
263         coll = (Collection<V>) Arrays.asList("M");
264         assertTrue(map.putAll((K) "A", coll));
265         assertEquals(4, map.size("A"));
266         assertTrue(map.containsValue("A", "X"));
267         assertTrue(map.containsValue("A", "Y"));
268         assertTrue(map.containsValue("A", "Z"));
269         assertTrue(map.containsValue("A", "M"));
270     }
271 
272     @Test
273     @SuppressWarnings("unchecked")
274     public void testPutAll_Map1() {
275         final MultiMap<K, V> original = new MultiValueMap<>();
276         original.put((K) "key", "object1");
277         original.put((K) "key", "object2");
278 
279         final MultiValueMap<K, V> test = new MultiValueMap<>();
280         test.put((K) "keyA", "objectA");
281         test.put((K) "key", "object0");
282         test.putAll(original);
283 
284         assertEquals(2, test.size());
285         assertEquals(4, test.totalSize());
286         assertEquals(1, test.getCollection("keyA").size());
287         assertEquals(3, test.getCollection("key").size());
288         assertTrue(test.containsValue("objectA"));
289         assertTrue(test.containsValue("object0"));
290         assertTrue(test.containsValue("object1"));
291         assertTrue(test.containsValue("object2"));
292     }
293 
294     @Test
295     @SuppressWarnings("unchecked")
296     public void testPutAll_Map2() {
297         final Map<K, V> original = new HashMap<>();
298         original.put((K) "keyX", (V) "object1");
299         original.put((K) "keyY", (V) "object2");
300 
301         final MultiValueMap<K, V> test = new MultiValueMap<>();
302         test.put((K) "keyA", "objectA");
303         test.put((K) "keyX", "object0");
304         test.putAll(original);
305 
306         assertEquals(3, test.size());
307         assertEquals(4, test.totalSize());
308         assertEquals(1, test.getCollection("keyA").size());
309         assertEquals(2, test.getCollection("keyX").size());
310         assertEquals(1, test.getCollection("keyY").size());
311         assertTrue(test.containsValue("objectA"));
312         assertTrue(test.containsValue("object0"));
313         assertTrue(test.containsValue("object1"));
314         assertTrue(test.containsValue("object2"));
315     }
316 
317     @Test
318     @SuppressWarnings("unchecked")
319     public void testPutWithList() {
320         @SuppressWarnings("rawtypes")
321         final MultiValueMap<K, V> test = MultiValueMap.multiValueMap(new HashMap<>(), ArrayList.class);
322         assertEquals("a", test.put((K) "A", "a"));
323         assertEquals("b", test.put((K) "A", "b"));
324         assertEquals(1, test.size());
325         assertEquals(2, test.size("A"));
326         assertEquals(2, test.totalSize());
327     }
328 
329     @Test
330     @SuppressWarnings("unchecked")
331     public void testPutWithSet() {
332         @SuppressWarnings("rawtypes")
333         final MultiValueMap<K, V> test = MultiValueMap.multiValueMap(new HashMap<>(), HashSet.class);
334         assertEquals("a", test.put((K) "A", "a"));
335         assertEquals("b", test.put((K) "A", "b"));
336         assertNull(test.put((K) "A", "a"));
337         assertEquals(1, test.size());
338         assertEquals(2, test.size("A"));
339         assertEquals(2, test.totalSize());
340     }
341 
342     @Test
343     @SuppressWarnings("unchecked")
344     public void testRemove_KeyItem() {
345         final MultiValueMap<K, V> map = new MultiValueMap<>();
346         map.put((K) "A", "AA");
347         map.put((K) "A", "AB");
348         map.put((K) "A", "AC");
349         assertFalse(map.removeMapping("C", "CA"));
350         assertFalse(map.removeMapping("A", "AD"));
351         assertTrue(map.removeMapping("A", "AC"));
352         assertTrue(map.removeMapping("A", "AB"));
353         assertTrue(map.removeMapping("A", "AA"));
354         assertEquals(new MultiValueMap<>(), map);
355     }
356 
357     @Test
358     public void testRemoveAllViaEntryIterator() {
359         final MultiValueMap<K, V> map = createTestMap();
360         for (final Iterator<?> i = map.iterator(); i.hasNext();) {
361             i.next();
362             i.remove();
363         }
364         assertNull(map.get("one"));
365         assertEquals(0, map.totalSize());
366     }
367 
368     @Test
369     public void testRemoveAllViaIterator() {
370         final MultiValueMap<K, V> map = createTestMap();
371         for (final Iterator<?> i = map.values().iterator(); i.hasNext();) {
372             i.next();
373             i.remove();
374         }
375         assertNull(map.get("one"));
376         assertTrue(map.isEmpty());
377     }
378 
379     @Test
380     public void testRemoveAllViaKeyedIterator() {
381         final MultiValueMap<K, V> map = createTestMap();
382         for (final Iterator<?> i = map.iterator("one"); i.hasNext();) {
383             i.next();
384             i.remove();
385         }
386         assertNull(map.get("one"));
387         assertEquals(4, map.totalSize());
388     }
389 
390     @Test
391     @SuppressWarnings("unchecked")
392     public void testSize() {
393         final MultiValueMap<K, V> map = new MultiValueMap<>();
394         assertEquals(0, map.size());
395         map.put((K) "A", "AA");
396         assertEquals(1, map.size());
397         map.put((K) "B", "BA");
398         assertEquals(2, map.size());
399         map.put((K) "B", "BB");
400         assertEquals(2, map.size());
401         map.put((K) "B", "BC");
402         assertEquals(2, map.size());
403         map.remove("A");
404         assertEquals(1, map.size());
405         map.removeMapping("B", "BC");
406         assertEquals(1, map.size());
407     }
408 
409     @Test
410     @SuppressWarnings("unchecked")
411     public void testSize_Key() {
412         final MultiValueMap<K, V> map = new MultiValueMap<>();
413         assertEquals(0, map.size("A"));
414         assertEquals(0, map.size("B"));
415         map.put((K) "A", "AA");
416         assertEquals(1, map.size("A"));
417         assertEquals(0, map.size("B"));
418         map.put((K) "B", "BA");
419         assertEquals(1, map.size("A"));
420         assertEquals(1, map.size("B"));
421         map.put((K) "B", "BB");
422         assertEquals(1, map.size("A"));
423         assertEquals(2, map.size("B"));
424         map.put((K) "B", "BC");
425         assertEquals(1, map.size("A"));
426         assertEquals(3, map.size("B"));
427         map.remove("A");
428         assertEquals(0, map.size("A"));
429         assertEquals(3, map.size("B"));
430         map.removeMapping("B", "BC");
431         assertEquals(0, map.size("A"));
432         assertEquals(2, map.size("B"));
433     }
434 
435     // Manual serialization testing as this class cannot easily
436     // extend the AbstractTestMap
437 
438     @Test
439     @SuppressWarnings("unchecked")
440     public void testTotalSize() {
441         final MultiValueMap<K, V> map = new MultiValueMap<>();
442         assertEquals(0, map.totalSize());
443         map.put((K) "A", "AA");
444         assertEquals(1, map.totalSize());
445         map.put((K) "B", "BA");
446         assertEquals(2, map.totalSize());
447         map.put((K) "B", "BB");
448         assertEquals(3, map.totalSize());
449         map.put((K) "B", "BC");
450         assertEquals(4, map.totalSize());
451         map.remove("A");
452         assertEquals(3, map.totalSize());
453         map.removeMapping("B", "BC");
454         assertEquals(2, map.totalSize());
455     }
456 
457     @Test
458     public void testTotalSizeA() {
459         assertEquals(6, createTestMap().totalSize());
460     }
461 
462     @Test
463     public void testUnsafeDeSerialization() throws Exception {
464         final MultiValueMap map1 = MultiValueMap.multiValueMap(new HashMap(), ArrayList.class);
465         byte[] bytes = serialize(map1);
466         final Object result = deserialize(bytes);
467         assertEquals(map1, result);
468 
469         final MultiValueMap map2 = MultiValueMap.multiValueMap(new HashMap(), (Class) String.class);
470         bytes = serialize(map2);
471 
472         final byte[] finalBytes = bytes;
473         assertThrows(UnsupportedOperationException.class, () -> deserialize(finalBytes));
474     }
475 
476     @Test
477     @SuppressWarnings("unchecked")
478     public void testValueCollectionType() {
479         final MultiValueMap<K, V> map = createTestMap(LinkedList.class);
480         assertTrue(map.get("one") instanceof LinkedList);
481     }
482 
483     @Test
484     @SuppressWarnings("unchecked")
485     public void testValues() {
486         final MultiValueMap<K, V> map = createTestMap(HashSet.class);
487         final HashSet<V> expected = new HashSet<>();
488         expected.add((V) "uno");
489         expected.add((V) "dos");
490         expected.add((V) "tres");
491         expected.add((V) "un");
492         expected.add((V) "deux");
493         expected.add((V) "trois");
494         final Collection<Object> c = map.values();
495         assertEquals(6, c.size());
496         assertEquals(expected, new HashSet<>(c));
497     }
498 
499 //    public void testCreate() throws Exception {
500 //        writeExternalFormToDisk(
501 //            (java.io.Serializable) makeEmptyMap(),
502 //            "src/test/resources/data/test/MultiValueMap.emptyCollection.version4.obj");
503 //
504 //        writeExternalFormToDisk(
505 //            (java.io.Serializable) makeObject(),
506 //            "src/test/resources/data/test/MultiValueMap.fullCollection.version4.obj");
507 //    }
508 
509 }