1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 import static org.junit.jupiter.api.Assertions.fail;
26
27 import java.util.Map;
28
29 import org.apache.commons.collections4.MapIterator;
30 import org.apache.commons.collections4.keyvalue.MultiKey;
31 import org.junit.jupiter.api.Test;
32
33
34
35
36 public class MultiKeyMapTest<K, V> extends AbstractIterableMapTest<MultiKey<? extends K>, V> {
37
38 static final Integer I1 = Integer.valueOf(1);
39 static final Integer I2 = Integer.valueOf(2);
40 static final Integer I3 = Integer.valueOf(3);
41 static final Integer I4 = Integer.valueOf(4);
42 static final Integer I5 = Integer.valueOf(5);
43 static final Integer I6 = Integer.valueOf(6);
44 static final Integer I7 = Integer.valueOf(7);
45 static final Integer I8 = Integer.valueOf(8);
46
47 public MultiKeyMapTest() {
48 super(MultiKeyMapTest.class.getSimpleName());
49 }
50
51 @Override
52 public String getCompatibilityVersion() {
53 return "4";
54 }
55
56
57
58
59 @Override
60 public MultiKeyMap<K, V> getMap() {
61 return (MultiKeyMap<K, V>) super.getMap();
62 }
63
64 @SuppressWarnings("unchecked")
65 private MultiKey<K>[] getMultiKeyKeys() {
66 return new MultiKey[] {
67 new MultiKey<>(I1, I2),
68 new MultiKey<>(I2, I3),
69 new MultiKey<>(I3, I4),
70 new MultiKey<>(I1, I1, I2),
71 new MultiKey<>(I2, I3, I4),
72 new MultiKey<>(I3, I7, I6),
73 new MultiKey<>(I1, I1, I2, I3),
74 new MultiKey<>(I2, I4, I5, I6),
75 new MultiKey<>(I3, I6, I7, I8),
76 new MultiKey<>(I1, I1, I2, I3, I4),
77 new MultiKey<>(I2, I3, I4, I5, I6),
78 new MultiKey<>(I3, I5, I6, I7, I8),
79 };
80 }
81
82 @Override
83 @SuppressWarnings("unchecked")
84 public V[] getNewSampleValues() {
85 return (V[]) new Object[] {
86 "1a", "1b", "1c",
87 "2d", "2e", "2f",
88 "3g", "3h", "3i",
89 "4j", "4k", "4l",
90 };
91 }
92
93 @Override
94 @SuppressWarnings("unchecked")
95 public MultiKey<K>[] getOtherKeys() {
96 return new MultiKey[] {
97 new MultiKey<>(I1, I7),
98 new MultiKey<>(I1, I8),
99 new MultiKey<>(I2, I4),
100 new MultiKey<>(I2, I5),
101 };
102 }
103
104 @Override
105 public MultiKey<K>[] getSampleKeys() {
106 return getMultiKeyKeys();
107 }
108
109 @Override
110 @SuppressWarnings("unchecked")
111 public V[] getSampleValues() {
112 return (V[]) new Object[] {
113 "2A", "2B", "2C",
114 "3D", "3E", "3F",
115 "4G", "4H", "4I",
116 "5J", "5K", "5L",
117 };
118 }
119
120 @Override
121 public boolean isAllowNullKey() {
122 return false;
123 }
124
125 @Override
126 public MultiKeyMap<K, V> makeObject() {
127 return new MultiKeyMap<>();
128 }
129
130 @Test
131 @SuppressWarnings("unchecked")
132 public void testClone() {
133 final MultiKeyMap<K, V> map = new MultiKeyMap<>();
134 map.put(new MultiKey<>((K) I1, (K) I2), (V) "1-2");
135 final Map<MultiKey<? extends K>, V> cloned = map.clone();
136 assertEquals(map.size(), cloned.size());
137 assertSame(map.get(new MultiKey<>((K) I1, (K) I2)), cloned.get(new MultiKey<>((K) I1, (K) I2)));
138 }
139
140 @Test
141 @SuppressWarnings("unchecked")
142 public void testLRUMultiKeyMap() {
143 final MultiKeyMap<K, V> map = MultiKeyMap.multiKeyMap(new LRUMap<>(2));
144 map.put((K) I1, (K) I2, (V) "1-2");
145 map.put((K) I1, (K) I3, (V) "1-1");
146 assertEquals(2, map.size());
147 map.put((K) I1, (K) I4, (V) "1-4");
148 assertEquals(2, map.size());
149 assertTrue(map.containsKey(I1, I3));
150 assertTrue(map.containsKey(I1, I4));
151 assertFalse(map.containsKey(I1, I2));
152
153 final MultiKeyMap<K, V> cloned = map.clone();
154 assertEquals(2, map.size());
155 assertTrue(cloned.containsKey(I1, I3));
156 assertTrue(cloned.containsKey(I1, I4));
157 assertFalse(cloned.containsKey(I1, I2));
158 cloned.put((K) I1, (K) I5, (V) "1-5");
159 assertEquals(2, cloned.size());
160 assertTrue(cloned.containsKey(I1, I4));
161 assertTrue(cloned.containsKey(I1, I5));
162 }
163
164 @Test
165 public void testMultiKeyContainsKey() {
166 resetFull();
167 final MultiKeyMap<K, V> multimap = getMap();
168 final MultiKey<K>[] keys = getMultiKeyKeys();
169
170 for (final MultiKey<K> key : keys) {
171 switch (key.size()) {
172 case 2:
173 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
174 assertFalse(multimap.containsKey(null, key.getKey(1)));
175 assertFalse(multimap.containsKey(key.getKey(0), null));
176 assertFalse(multimap.containsKey(null, null));
177 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null));
178 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, null));
179 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, null, null));
180 break;
181 case 3:
182 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
183 assertFalse(multimap.containsKey(null, key.getKey(1), key.getKey(2)));
184 assertFalse(multimap.containsKey(key.getKey(0), null, key.getKey(2)));
185 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null));
186 assertFalse(multimap.containsKey(null, null, null));
187 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null));
188 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null, null));
189 break;
190 case 4:
191 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
192 assertFalse(multimap.containsKey(null, key.getKey(1), key.getKey(2), key.getKey(3)));
193 assertFalse(multimap.containsKey(key.getKey(0), null, key.getKey(2), key.getKey(3)));
194 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, key.getKey(3)));
195 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null));
196 assertFalse(multimap.containsKey(null, null, null, null));
197 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
198 break;
199 case 5:
200 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
201 assertFalse(multimap.containsKey(null, key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
202 assertFalse(multimap.containsKey(key.getKey(0), null, key.getKey(2), key.getKey(3), key.getKey(4)));
203 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, key.getKey(3), key.getKey(4)));
204 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null, key.getKey(4)));
205 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
206 assertFalse(multimap.containsKey(null, null, null, null, null));
207 break;
208 default:
209 fail("Invalid key size");
210 }
211 }
212 }
213
214 @Test
215 public void testMultiKeyGet() {
216 resetFull();
217 final MultiKeyMap<K, V> multimap = getMap();
218 final MultiKey<K>[] keys = getMultiKeyKeys();
219 final V[] values = getSampleValues();
220
221 for (int i = 0; i < keys.length; i++) {
222 final MultiKey<K> key = keys[i];
223 final V value = values[i];
224
225 switch (key.size()) {
226 case 2:
227 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1)));
228 assertNull(multimap.get(null, key.getKey(1)));
229 assertNull(multimap.get(key.getKey(0), null));
230 assertNull(multimap.get(null, null));
231 assertNull(multimap.get(key.getKey(0), key.getKey(1), null));
232 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, null));
233 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, null, null));
234 break;
235 case 3:
236 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2)));
237 assertNull(multimap.get(null, key.getKey(1), key.getKey(2)));
238 assertNull(multimap.get(key.getKey(0), null, key.getKey(2)));
239 assertNull(multimap.get(key.getKey(0), key.getKey(1), null));
240 assertNull(multimap.get(null, null, null));
241 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null));
242 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null, null));
243 break;
244 case 4:
245 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
246 assertNull(multimap.get(null, key.getKey(1), key.getKey(2), key.getKey(3)));
247 assertNull(multimap.get(key.getKey(0), null, key.getKey(2), key.getKey(3)));
248 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, key.getKey(3)));
249 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null));
250 assertNull(multimap.get(null, null, null, null));
251 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
252 break;
253 case 5:
254 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
255 assertNull(multimap.get(null, key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
256 assertNull(multimap.get(key.getKey(0), null, key.getKey(2), key.getKey(3), key.getKey(4)));
257 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, key.getKey(3), key.getKey(4)));
258 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null, key.getKey(4)));
259 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
260 assertNull(multimap.get(null, null, null, null, null));
261 break;
262 default:
263 fail("Invalid key size");
264 }
265 }
266 }
267
268 @Test
269 public void testMultiKeyPut() {
270 final MultiKey<K>[] keys = getMultiKeyKeys();
271 final V[] values = getSampleValues();
272
273 for (int i = 0; i < keys.length; i++) {
274 final MultiKeyMap<K, V> multimap = new MultiKeyMap<>();
275
276 final MultiKey<K> key = keys[i];
277 final V value = values[i];
278
279 switch (key.size()) {
280 case 2:
281 assertNull(multimap.put(key.getKey(0), key.getKey(1), value));
282 assertEquals(1, multimap.size());
283 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1)));
284 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
285 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1))));
286 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), null));
287 assertEquals(1, multimap.size());
288 assertNull(multimap.get(key.getKey(0), key.getKey(1)));
289 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
290 break;
291 case 3:
292 assertNull(multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), value));
293 assertEquals(1, multimap.size());
294 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2)));
295 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
296 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1), key.getKey(2))));
297 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), null));
298 assertEquals(1, multimap.size());
299 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2)));
300 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
301 break;
302 case 4:
303 assertNull(multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), value));
304 assertEquals(1, multimap.size());
305 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
306 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
307 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3))));
308 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
309 assertEquals(1, multimap.size());
310 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
311 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
312 break;
313 case 5:
314 assertNull(multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4), value));
315 assertEquals(1, multimap.size());
316 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
317 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
318 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4))));
319 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4), null));
320 assertEquals(1, multimap.size());
321 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
322 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
323 break;
324 default:
325 fail("Invalid key size");
326 }
327 }
328 }
329
330 @Test
331 public void testMultiKeyPutWithNullKey() {
332 final MultiKeyMap<String, String> map = new MultiKeyMap<>();
333 map.put("a", null, "value1");
334 map.put("b", null, "value2");
335 map.put("c", null, "value3");
336 map.put("a", "z", "value4");
337 map.put("a", null, "value5");
338 map.put(null, "a", "value6");
339 map.put(null, null, "value7");
340
341 assertEquals(6, map.size());
342 assertEquals("value5", map.get("a", null));
343 assertEquals("value4", map.get("a", "z"));
344 assertEquals("value6", map.get(null, "a"));
345 }
346
347 @Test
348 public void testMultiKeyRemove() {
349 final MultiKey<K>[] keys = getMultiKeyKeys();
350 final V[] values = getSampleValues();
351
352 for (int i = 0; i < keys.length; i++) {
353 resetFull();
354 final MultiKeyMap<K, V> multimap = getMap();
355 final int size = multimap.size();
356
357 final MultiKey<K> key = keys[i];
358 final V value = values[i];
359
360 switch (key.size()) {
361 case 2:
362 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
363 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1)));
364 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1)));
365 assertEquals(size - 1, multimap.size());
366 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1)));
367 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1)));
368 break;
369 case 3:
370 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
371 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2)));
372 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
373 assertEquals(size - 1, multimap.size());
374 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2)));
375 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
376 break;
377 case 4:
378 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
379 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
380 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
381 assertEquals(size - 1, multimap.size());
382 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
383 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
384 break;
385 case 5:
386 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
387 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
388 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
389 assertEquals(size - 1, multimap.size());
390 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
391 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
392 break;
393 default:
394 fail("Invalid key size");
395 }
396 }
397 }
398
399 @Test
400 public void testMultiKeyRemoveAll1() {
401 resetFull();
402 final MultiKeyMap<K, V> multimap = getMap();
403 assertEquals(12, multimap.size());
404
405 multimap.removeAll(I1);
406 assertEquals(8, multimap.size());
407 for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
408 final MultiKey<? extends K> key = it.next();
409 assertFalse(I1.equals(key.getKey(0)));
410 }
411 }
412
413 @Test
414 public void testMultiKeyRemoveAll2() {
415 resetFull();
416 final MultiKeyMap<K, V> multimap = getMap();
417 assertEquals(12, multimap.size());
418
419 multimap.removeAll(I2, I3);
420 assertEquals(9, multimap.size());
421 for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
422 final MultiKey<? extends K> key = it.next();
423 assertFalse(I2.equals(key.getKey(0)) && I3.equals(key.getKey(1)));
424 }
425 }
426
427 @Test
428 public void testMultiKeyRemoveAll3() {
429 resetFull();
430 final MultiKeyMap<K, V> multimap = getMap();
431 assertEquals(12, multimap.size());
432
433 multimap.removeAll(I1, I1, I2);
434 assertEquals(9, multimap.size());
435 for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
436 final MultiKey<? extends K> key = it.next();
437 assertFalse(I1.equals(key.getKey(0)) && I1.equals(key.getKey(1)) && I2.equals(key.getKey(2)));
438 }
439 }
440
441 @Test
442 public void testMultiKeyRemoveAll4() {
443 resetFull();
444 final MultiKeyMap<K, V> multimap = getMap();
445 assertEquals(12, multimap.size());
446
447 multimap.removeAll(I1, I1, I2, I3);
448 assertEquals(10, multimap.size());
449 for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
450 final MultiKey<? extends K> key = it.next();
451 assertFalse(I1.equals(key.getKey(0)) && I1.equals(key.getKey(1)) && I2.equals(key.getKey(2)) && key.size() >= 4 && I3.equals(key.getKey(3)));
452 }
453 }
454
455
456
457
458
459
460
461
462
463
464
465
466 @Test
467 @SuppressWarnings("unchecked")
468 public void testNullHandling() {
469 resetFull();
470 assertNull(map.get(null));
471 assertFalse(map.containsKey(null));
472 assertFalse(map.containsValue(null));
473 assertNull(map.remove(null));
474 assertFalse(map.entrySet().contains(null));
475 assertFalse(map.containsKey(null));
476 assertFalse(map.containsValue(null));
477
478 assertThrows(NullPointerException.class, () -> map.put(null, null));
479
480 assertNull(map.put(new MultiKey<>(null, null), null));
481
482 assertThrows(NullPointerException.class, () -> map.put(null, (V) new Object()));
483 }
484 }