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 import java.util.concurrent.atomic.AtomicReference;
29
30 import org.apache.commons.collections4.MapIterator;
31 import org.apache.commons.collections4.keyvalue.MultiKey;
32 import org.junit.jupiter.api.Test;
33
34
35
36
37
38
39
40 public class MultiKeyMapTest<K, V> extends AbstractIterableMapTest<MultiKey<? extends K>, V> {
41
42 static final Integer I1 = Integer.valueOf(1);
43 static final Integer I2 = Integer.valueOf(2);
44 static final Integer I3 = Integer.valueOf(3);
45 static final Integer I4 = Integer.valueOf(4);
46 static final Integer I5 = Integer.valueOf(5);
47 static final Integer I6 = Integer.valueOf(6);
48 static final Integer I7 = Integer.valueOf(7);
49 static final Integer I8 = Integer.valueOf(8);
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154 @Test
155 public void testCompress872() {
156 final AtomicReference<String> k1 = new AtomicReference<>("K1v1");
157 final AtomicReference<String> k2 = new AtomicReference<>("K2v1");
158 final MultiKeyMap<AtomicReference<String>, String> map = (MultiKeyMap<AtomicReference<String>, String>) makeObject();
159 assertNull(map.put(k1, k2, "V"));
160 assertEquals("V", map.get(k1, k2));
161 k1.set("K1v2");
162 assertEquals("V", map.get(k1, k2));
163 assertEquals("V", map.get(k1, k2));
164 }
165
166 @Test
167 @SuppressWarnings("unchecked")
168 public void testLRUMultiKeyMap() {
169 final MultiKeyMap<K, V> map = MultiKeyMap.multiKeyMap(new LRUMap<>(2));
170 map.put((K) I1, (K) I2, (V) "1-2");
171 map.put((K) I1, (K) I3, (V) "1-1");
172 assertEquals(2, map.size());
173 map.put((K) I1, (K) I4, (V) "1-4");
174 assertEquals(2, map.size());
175 assertTrue(map.containsKey(I1, I3));
176 assertTrue(map.containsKey(I1, I4));
177 assertFalse(map.containsKey(I1, I2));
178
179 final MultiKeyMap<K, V> cloned = map.clone();
180 assertEquals(2, map.size());
181 assertTrue(cloned.containsKey(I1, I3));
182 assertTrue(cloned.containsKey(I1, I4));
183 assertFalse(cloned.containsKey(I1, I2));
184 cloned.put((K) I1, (K) I5, (V) "1-5");
185 assertEquals(2, cloned.size());
186 assertTrue(cloned.containsKey(I1, I4));
187 assertTrue(cloned.containsKey(I1, I5));
188 }
189
190 @Test
191 public void testMultiKeyContainsKey() {
192 resetFull();
193 final MultiKeyMap<K, V> multimap = getMap();
194 final MultiKey<K>[] keys = getMultiKeyKeys();
195
196 for (final MultiKey<K> key : keys) {
197 switch (key.size()) {
198 case 2:
199 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
200 assertFalse(multimap.containsKey(null, key.getKey(1)));
201 assertFalse(multimap.containsKey(key.getKey(0), null));
202 assertFalse(multimap.containsKey(null, null));
203 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null));
204 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, null));
205 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, null, null));
206 break;
207 case 3:
208 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
209 assertFalse(multimap.containsKey(null, key.getKey(1), key.getKey(2)));
210 assertFalse(multimap.containsKey(key.getKey(0), null, key.getKey(2)));
211 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null));
212 assertFalse(multimap.containsKey(null, null, null));
213 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null));
214 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null, null));
215 break;
216 case 4:
217 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
218 assertFalse(multimap.containsKey(null, key.getKey(1), key.getKey(2), key.getKey(3)));
219 assertFalse(multimap.containsKey(key.getKey(0), null, key.getKey(2), key.getKey(3)));
220 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, key.getKey(3)));
221 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null));
222 assertFalse(multimap.containsKey(null, null, null, null));
223 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
224 break;
225 case 5:
226 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
227 assertFalse(multimap.containsKey(null, key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
228 assertFalse(multimap.containsKey(key.getKey(0), null, key.getKey(2), key.getKey(3), key.getKey(4)));
229 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), null, key.getKey(3), key.getKey(4)));
230 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), null, key.getKey(4)));
231 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
232 assertFalse(multimap.containsKey(null, null, null, null, null));
233 break;
234 default:
235 fail("Invalid key size");
236 }
237 }
238 }
239
240 @Test
241 public void testMultiKeyGet() {
242 resetFull();
243 final MultiKeyMap<K, V> multimap = getMap();
244 final MultiKey<K>[] keys = getMultiKeyKeys();
245 final V[] values = getSampleValues();
246
247 for (int i = 0; i < keys.length; i++) {
248 final MultiKey<K> key = keys[i];
249 final V value = values[i];
250
251 switch (key.size()) {
252 case 2:
253 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1)));
254 assertNull(multimap.get(null, key.getKey(1)));
255 assertNull(multimap.get(key.getKey(0), null));
256 assertNull(multimap.get(null, null));
257 assertNull(multimap.get(key.getKey(0), key.getKey(1), null));
258 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, null));
259 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, null, null));
260 break;
261 case 3:
262 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2)));
263 assertNull(multimap.get(null, key.getKey(1), key.getKey(2)));
264 assertNull(multimap.get(key.getKey(0), null, key.getKey(2)));
265 assertNull(multimap.get(key.getKey(0), key.getKey(1), null));
266 assertNull(multimap.get(null, null, null));
267 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null));
268 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null, null));
269 break;
270 case 4:
271 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
272 assertNull(multimap.get(null, key.getKey(1), key.getKey(2), key.getKey(3)));
273 assertNull(multimap.get(key.getKey(0), null, key.getKey(2), key.getKey(3)));
274 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, key.getKey(3)));
275 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null));
276 assertNull(multimap.get(null, null, null, null));
277 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
278 break;
279 case 5:
280 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
281 assertNull(multimap.get(null, key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
282 assertNull(multimap.get(key.getKey(0), null, key.getKey(2), key.getKey(3), key.getKey(4)));
283 assertNull(multimap.get(key.getKey(0), key.getKey(1), null, key.getKey(3), key.getKey(4)));
284 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), null, key.getKey(4)));
285 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
286 assertNull(multimap.get(null, null, null, null, null));
287 break;
288 default:
289 fail("Invalid key size");
290 }
291 }
292 }
293
294 @Test
295 public void testMultiKeyPut() {
296 final MultiKey<K>[] keys = getMultiKeyKeys();
297 final V[] values = getSampleValues();
298
299 for (int i = 0; i < keys.length; i++) {
300 final MultiKeyMap<K, V> multimap = new MultiKeyMap<>();
301
302 final MultiKey<K> key = keys[i];
303 final V value = values[i];
304
305 switch (key.size()) {
306 case 2:
307 assertNull(multimap.put(key.getKey(0), key.getKey(1), value));
308 assertEquals(1, multimap.size());
309 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1)));
310 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
311 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1))));
312 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), null));
313 assertEquals(1, multimap.size());
314 assertNull(multimap.get(key.getKey(0), key.getKey(1)));
315 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
316 break;
317 case 3:
318 assertNull(multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), value));
319 assertEquals(1, multimap.size());
320 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2)));
321 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
322 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1), key.getKey(2))));
323 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), null));
324 assertEquals(1, multimap.size());
325 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2)));
326 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
327 break;
328 case 4:
329 assertNull(multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), value));
330 assertEquals(1, multimap.size());
331 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
332 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
333 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3))));
334 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), null));
335 assertEquals(1, multimap.size());
336 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
337 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
338 break;
339 case 5:
340 assertNull(multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4), value));
341 assertEquals(1, multimap.size());
342 assertEquals(value, multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
343 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
344 assertTrue(multimap.containsKey(new MultiKey<>(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4))));
345 assertEquals(value, multimap.put(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4), null));
346 assertEquals(1, multimap.size());
347 assertNull(multimap.get(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
348 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
349 break;
350 default:
351 fail("Invalid key size");
352 }
353 }
354 }
355
356 @Test
357 public void testMultiKeyPutWithNullKey() {
358 final MultiKeyMap<String, String> map = new MultiKeyMap<>();
359 map.put("a", null, "value1");
360 map.put("b", null, "value2");
361 map.put("c", null, "value3");
362 map.put("a", "z", "value4");
363 map.put("a", null, "value5");
364 map.put(null, "a", "value6");
365 map.put(null, null, "value7");
366
367 assertEquals(6, map.size());
368 assertEquals("value5", map.get("a", null));
369 assertEquals("value4", map.get("a", "z"));
370 assertEquals("value6", map.get(null, "a"));
371 }
372
373 @Test
374 public void testMultiKeyRemove() {
375 final MultiKey<K>[] keys = getMultiKeyKeys();
376 final V[] values = getSampleValues();
377
378 for (int i = 0; i < keys.length; i++) {
379 resetFull();
380 final MultiKeyMap<K, V> multimap = getMap();
381 final int size = multimap.size();
382
383 final MultiKey<K> key = keys[i];
384 final V value = values[i];
385
386 switch (key.size()) {
387 case 2:
388 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1)));
389 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1)));
390 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1)));
391 assertEquals(size - 1, multimap.size());
392 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1)));
393 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1)));
394 break;
395 case 3:
396 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
397 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2)));
398 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
399 assertEquals(size - 1, multimap.size());
400 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2)));
401 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2)));
402 break;
403 case 4:
404 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
405 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
406 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
407 assertEquals(size - 1, multimap.size());
408 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
409 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3)));
410 break;
411 case 5:
412 assertTrue(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
413 assertEquals(value, multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
414 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
415 assertEquals(size - 1, multimap.size());
416 assertNull(multimap.removeMultiKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
417 assertFalse(multimap.containsKey(key.getKey(0), key.getKey(1), key.getKey(2), key.getKey(3), key.getKey(4)));
418 break;
419 default:
420 fail("Invalid key size");
421 }
422 }
423 }
424
425 @Test
426 public void testMultiKeyRemoveAll1() {
427 resetFull();
428 final MultiKeyMap<K, V> multimap = getMap();
429 assertEquals(12, multimap.size());
430
431 multimap.removeAll(I1);
432 assertEquals(8, multimap.size());
433 for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
434 final MultiKey<? extends K> key = it.next();
435 assertFalse(I1.equals(key.getKey(0)));
436 }
437 }
438
439 @Test
440 public void testMultiKeyRemoveAll2() {
441 resetFull();
442 final MultiKeyMap<K, V> multimap = getMap();
443 assertEquals(12, multimap.size());
444
445 multimap.removeAll(I2, I3);
446 assertEquals(9, multimap.size());
447 for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
448 final MultiKey<? extends K> key = it.next();
449 assertFalse(I2.equals(key.getKey(0)) && I3.equals(key.getKey(1)));
450 }
451 }
452
453 @Test
454 public void testMultiKeyRemoveAll3() {
455 resetFull();
456 final MultiKeyMap<K, V> multimap = getMap();
457 assertEquals(12, multimap.size());
458
459 multimap.removeAll(I1, I1, I2);
460 assertEquals(9, multimap.size());
461 for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
462 final MultiKey<? extends K> key = it.next();
463 assertFalse(I1.equals(key.getKey(0)) && I1.equals(key.getKey(1)) && I2.equals(key.getKey(2)));
464 }
465 }
466
467
468
469
470
471
472
473
474
475
476
477
478 @Test
479 public void testMultiKeyRemoveAll4() {
480 resetFull();
481 final MultiKeyMap<K, V> multimap = getMap();
482 assertEquals(12, multimap.size());
483
484 multimap.removeAll(I1, I1, I2, I3);
485 assertEquals(10, multimap.size());
486 for (final MapIterator<MultiKey<? extends K>, V> it = multimap.mapIterator(); it.hasNext();) {
487 final MultiKey<? extends K> key = it.next();
488 assertFalse(I1.equals(key.getKey(0)) && I1.equals(key.getKey(1)) && I2.equals(key.getKey(2)) && key.size() >= 4 && I3.equals(key.getKey(3)));
489 }
490 }
491
492 @Test
493 @SuppressWarnings("unchecked")
494 public void testNullHandling() {
495 resetFull();
496 assertNull(map.get(null));
497 assertFalse(map.containsKey(null));
498 assertFalse(map.containsValue(null));
499 assertNull(map.remove(null));
500 assertFalse(map.entrySet().contains(null));
501 assertFalse(map.containsKey(null));
502 assertFalse(map.containsValue(null));
503
504 assertThrows(NullPointerException.class, () -> map.put(null, null));
505
506 assertNull(map.put(new MultiKey<>(null, null), null));
507
508 assertThrows(NullPointerException.class, () -> map.put(null, (V) new Object()));
509 }
510
511 }