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