1 /*
2  * Copyright (C) 2011 The Guava Authors
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 
17 package com.google.common.util.concurrent;
18 
19 import com.google.common.annotations.GwtCompatible;
20 import com.google.common.annotations.GwtIncompatible;
21 import com.google.common.collect.ImmutableMap;
22 import com.google.common.collect.Sets;
23 import com.google.common.testing.NullPointerTester;
24 import com.google.common.testing.SerializableTester;
25 import java.util.Map;
26 import java.util.Random;
27 import java.util.Set;
28 import junit.framework.TestCase;
29 
30 /**
31  * Tests for {@link AtomicLongMap}.
32  *
33  * @author mike nonemacher
34  */
35 @GwtCompatible(emulated = true)
36 public class AtomicLongMapTest extends TestCase {
37   private static final int ITERATIONS = 100;
38   private static final int MAX_ADDEND = 100;
39 
40   private final Random random = new Random(301);
41 
42   @GwtIncompatible // NullPointerTester
testNulls()43   public void testNulls() {
44     NullPointerTester tester = new NullPointerTester();
45     tester.testAllPublicConstructors(AtomicLongMap.class);
46     tester.testAllPublicStaticMethods(AtomicLongMap.class);
47     AtomicLongMap<Object> map = AtomicLongMap.create();
48     tester.testAllPublicInstanceMethods(map);
49   }
50 
testCreate_map()51   public void testCreate_map() {
52     Map<String, Long> in = ImmutableMap.of("1", 1L, "2", 2L, "3", 3L);
53     AtomicLongMap<String> map = AtomicLongMap.create(in);
54     assertFalse(map.isEmpty());
55     assertSame(3, map.size());
56     assertTrue(map.containsKey("1"));
57     assertTrue(map.containsKey("2"));
58     assertTrue(map.containsKey("3"));
59     assertEquals(1L, map.get("1"));
60     assertEquals(2L, map.get("2"));
61     assertEquals(3L, map.get("3"));
62   }
63 
testIncrementAndGet()64   public void testIncrementAndGet() {
65     AtomicLongMap<String> map = AtomicLongMap.create();
66     String key = "key";
67     for (int i = 0; i < ITERATIONS; i++) {
68       long before = map.get(key);
69       long result = map.incrementAndGet(key);
70       long after = map.get(key);
71       assertEquals(before + 1, after);
72       assertEquals(after, result);
73     }
74     assertEquals(1, map.size());
75     assertTrue(!map.isEmpty());
76     assertTrue(map.containsKey(key));
77     assertEquals(ITERATIONS, (int) map.get(key));
78   }
79 
testIncrementAndGet_zero()80   public void testIncrementAndGet_zero() {
81     AtomicLongMap<String> map = AtomicLongMap.create();
82     String key = "key";
83     assertEquals(0L, map.get(key));
84     assertFalse(map.containsKey(key));
85 
86     assertEquals(1L, map.incrementAndGet(key));
87     assertEquals(1L, map.get(key));
88 
89     assertEquals(0L, map.decrementAndGet(key));
90     assertEquals(0L, map.get(key));
91     assertTrue(map.containsKey(key));
92 
93     assertEquals(1L, map.incrementAndGet(key));
94     assertEquals(1L, map.get(key));
95   }
96 
testGetAndIncrement()97   public void testGetAndIncrement() {
98     AtomicLongMap<String> map = AtomicLongMap.create();
99     String key = "key";
100     for (int i = 0; i < ITERATIONS; i++) {
101       long before = map.get(key);
102       long result = map.getAndIncrement(key);
103       long after = map.get(key);
104       assertEquals(before + 1, after);
105       assertEquals(before, result);
106     }
107     assertEquals(1, map.size());
108     assertTrue(!map.isEmpty());
109     assertTrue(map.containsKey(key));
110     assertEquals(ITERATIONS, (int) map.get(key));
111   }
112 
testGetAndIncrement_zero()113   public void testGetAndIncrement_zero() {
114     AtomicLongMap<String> map = AtomicLongMap.create();
115     String key = "key";
116     assertEquals(0L, map.get(key));
117     assertFalse(map.containsKey(key));
118 
119     assertEquals(0L, map.getAndIncrement(key));
120     assertEquals(1L, map.get(key));
121 
122     assertEquals(1L, map.getAndDecrement(key));
123     assertEquals(0L, map.get(key));
124     assertTrue(map.containsKey(key));
125 
126     assertEquals(0L, map.getAndIncrement(key));
127     assertEquals(1L, map.get(key));
128   }
129 
testDecrementAndGet()130   public void testDecrementAndGet() {
131     AtomicLongMap<String> map = AtomicLongMap.create();
132     String key = "key";
133     for (int i = 0; i < ITERATIONS; i++) {
134       long before = map.get(key);
135       long result = map.decrementAndGet(key);
136       long after = map.get(key);
137       assertEquals(before - 1, after);
138       assertEquals(after, result);
139     }
140     assertEquals(1, map.size());
141     assertTrue(!map.isEmpty());
142     assertTrue(map.containsKey(key));
143     assertEquals(-1 * ITERATIONS, (int) map.get(key));
144   }
145 
testDecrementAndGet_zero()146   public void testDecrementAndGet_zero() {
147     AtomicLongMap<String> map = AtomicLongMap.create();
148     String key = "key";
149     assertEquals(0L, map.get(key));
150     assertFalse(map.containsKey(key));
151 
152     assertEquals(-1L, map.decrementAndGet(key));
153     assertEquals(-1L, map.get(key));
154 
155     assertEquals(0L, map.incrementAndGet(key));
156     assertEquals(0L, map.get(key));
157     assertTrue(map.containsKey(key));
158 
159     assertEquals(-1L, map.decrementAndGet(key));
160     assertEquals(-1L, map.get(key));
161   }
162 
testGetAndDecrement()163   public void testGetAndDecrement() {
164     AtomicLongMap<String> map = AtomicLongMap.create();
165     String key = "key";
166     for (int i = 0; i < ITERATIONS; i++) {
167       long before = map.get(key);
168       long result = map.getAndDecrement(key);
169       long after = map.get(key);
170       assertEquals(before - 1, after);
171       assertEquals(before, result);
172     }
173     assertEquals(1, map.size());
174     assertTrue(!map.isEmpty());
175     assertTrue(map.containsKey(key));
176     assertEquals(-1 * ITERATIONS, (int) map.get(key));
177   }
178 
testGetAndDecrement_zero()179   public void testGetAndDecrement_zero() {
180     AtomicLongMap<String> map = AtomicLongMap.create();
181     String key = "key";
182     assertEquals(0L, map.get(key));
183     assertFalse(map.containsKey(key));
184 
185     assertEquals(0L, map.getAndDecrement(key));
186     assertEquals(-1L, map.get(key));
187 
188     assertEquals(-1L, map.getAndIncrement(key));
189     assertEquals(0L, map.get(key));
190     assertTrue(map.containsKey(key));
191 
192     assertEquals(0L, map.getAndDecrement(key));
193     assertEquals(-1L, map.get(key));
194   }
195 
testAddAndGet()196   public void testAddAndGet() {
197     AtomicLongMap<String> map = AtomicLongMap.create();
198     String key = "key";
199     long addend = random.nextInt(MAX_ADDEND);
200     for (int i = 0; i < ITERATIONS; i++) {
201       long before = map.get(key);
202       long result = map.addAndGet(key, addend);
203       long after = map.get(key);
204       assertEquals(before + addend, after);
205       assertEquals(after, result);
206       addend = after;
207     }
208     assertEquals(1, map.size());
209     assertTrue(!map.isEmpty());
210     assertTrue(map.containsKey(key));
211   }
212 
testAddAndGet_zero()213   public void testAddAndGet_zero() {
214     AtomicLongMap<String> map = AtomicLongMap.create();
215     String key = "key";
216     long value = random.nextInt(MAX_ADDEND);
217     assertEquals(0L, map.get(key));
218     assertFalse(map.containsKey(key));
219 
220     assertEquals(value, map.addAndGet(key, value));
221     assertEquals(value, map.get(key));
222 
223     assertEquals(0L, map.addAndGet(key, -1 * value));
224     assertEquals(0L, map.get(key));
225     assertTrue(map.containsKey(key));
226 
227     assertEquals(value, map.addAndGet(key, value));
228     assertEquals(value, map.get(key));
229   }
230 
testGetAndAdd()231   public void testGetAndAdd() {
232     AtomicLongMap<String> map = AtomicLongMap.create();
233     String key = "key";
234     long addend = random.nextInt(MAX_ADDEND);
235     for (int i = 0; i < ITERATIONS; i++) {
236       long before = map.get(key);
237       long result = map.getAndAdd(key, addend);
238       long after = map.get(key);
239       assertEquals(before + addend, after);
240       assertEquals(before, result);
241       addend = after;
242     }
243     assertEquals(1, map.size());
244     assertTrue(!map.isEmpty());
245     assertTrue(map.containsKey(key));
246   }
247 
testGetAndAdd_zero()248   public void testGetAndAdd_zero() {
249     AtomicLongMap<String> map = AtomicLongMap.create();
250     String key = "key";
251     long value = random.nextInt(MAX_ADDEND);
252     assertEquals(0L, map.get(key));
253     assertFalse(map.containsKey(key));
254 
255     assertEquals(0L, map.getAndAdd(key, value));
256     assertEquals(value, map.get(key));
257 
258     assertEquals(value, map.getAndAdd(key, -1 * value));
259     assertEquals(0L, map.get(key));
260     assertTrue(map.containsKey(key));
261 
262     assertEquals(0L, map.getAndAdd(key, value));
263     assertEquals(value, map.get(key));
264   }
265 
testPut()266   public void testPut() {
267     AtomicLongMap<String> map = AtomicLongMap.create();
268     String key = "key";
269     long newValue = random.nextInt(MAX_ADDEND);
270     for (int i = 0; i < ITERATIONS; i++) {
271       long before = map.get(key);
272       long result = map.put(key, newValue);
273       long after = map.get(key);
274       assertEquals(newValue, after);
275       assertEquals(before, result);
276       newValue += newValue;
277     }
278     assertEquals(1, map.size());
279     assertTrue(!map.isEmpty());
280     assertTrue(map.containsKey(key));
281   }
282 
testPut_zero()283   public void testPut_zero() {
284     AtomicLongMap<String> map = AtomicLongMap.create();
285     String key = "key";
286     long value = random.nextInt(MAX_ADDEND);
287     assertEquals(0L, map.get(key));
288     assertFalse(map.containsKey(key));
289 
290     assertEquals(0L, map.put(key, value));
291     assertEquals(value, map.get(key));
292 
293     assertEquals(value, map.put(key, 0L));
294     assertEquals(0L, map.get(key));
295     assertTrue(map.containsKey(key));
296 
297     assertEquals(0L, map.put(key, value));
298     assertEquals(value, map.get(key));
299   }
300 
testPutAll()301   public void testPutAll() {
302     Map<String, Long> in = ImmutableMap.of("1", 1L, "2", 2L, "3", 3L);
303     AtomicLongMap<String> map = AtomicLongMap.create();
304     assertTrue(map.isEmpty());
305     assertSame(0, map.size());
306     assertFalse(map.containsKey("1"));
307     assertFalse(map.containsKey("2"));
308     assertFalse(map.containsKey("3"));
309     assertEquals(0L, map.get("1"));
310     assertEquals(0L, map.get("2"));
311     assertEquals(0L, map.get("3"));
312 
313     map.putAll(in);
314     assertFalse(map.isEmpty());
315     assertSame(3, map.size());
316     assertTrue(map.containsKey("1"));
317     assertTrue(map.containsKey("2"));
318     assertTrue(map.containsKey("3"));
319     assertEquals(1L, map.get("1"));
320     assertEquals(2L, map.get("2"));
321     assertEquals(3L, map.get("3"));
322   }
323 
testPutIfAbsent()324   public void testPutIfAbsent() {
325     AtomicLongMap<String> map = AtomicLongMap.create();
326     String key = "key";
327     long newValue = random.nextInt(MAX_ADDEND);
328     for (int i = 0; i < ITERATIONS; i++) {
329       long before = map.get(key);
330       long result = map.putIfAbsent(key, newValue);
331       long after = map.get(key);
332       assertEquals(before, result);
333       assertEquals(before == 0 ? newValue : before, after);
334 
335       map.remove(key);
336       before = map.get(key);
337       result = map.putIfAbsent(key, newValue);
338       after = map.get(key);
339       assertEquals(0, before);
340       assertEquals(before, result);
341       assertEquals(newValue, after);
342 
343       map.put(key, 0L);
344       before = map.get(key);
345       result = map.putIfAbsent(key, newValue);
346       after = map.get(key);
347       assertEquals(0, before);
348       assertEquals(before, result);
349       assertEquals(newValue, after);
350 
351       newValue += newValue;
352     }
353     assertEquals(1, map.size());
354     assertTrue(!map.isEmpty());
355     assertTrue(map.containsKey(key));
356   }
357 
testPutIfAbsent_zero()358   public void testPutIfAbsent_zero() {
359     AtomicLongMap<String> map = AtomicLongMap.create();
360     String key = "key";
361     long value = random.nextInt(MAX_ADDEND);
362     assertEquals(0L, map.get(key));
363     assertFalse(map.containsKey(key));
364 
365     assertEquals(0L, map.putIfAbsent(key, value));
366     assertEquals(value, map.get(key));
367 
368     assertEquals(value, map.put(key, 0L));
369     assertEquals(0L, map.get(key));
370     assertTrue(map.containsKey(key));
371 
372     assertEquals(0L, map.putIfAbsent(key, value));
373     assertEquals(value, map.get(key));
374   }
375 
testReplace()376   public void testReplace() {
377     AtomicLongMap<String> map = AtomicLongMap.create();
378     String key = "key";
379     long newValue = random.nextInt(MAX_ADDEND);
380     for (int i = 0; i < ITERATIONS; i++) {
381       long before = map.get(key);
382       assertFalse(map.replace(key, before + 1, newValue + 1));
383       assertFalse(map.replace(key, before - 1, newValue - 1));
384       assertTrue(map.replace(key, before, newValue));
385       long after = map.get(key);
386       assertEquals(newValue, after);
387       newValue += newValue;
388     }
389     assertEquals(1, map.size());
390     assertTrue(!map.isEmpty());
391     assertTrue(map.containsKey(key));
392   }
393 
testReplace_zero()394   public void testReplace_zero() {
395     AtomicLongMap<String> map = AtomicLongMap.create();
396     String key = "key";
397     long value = random.nextInt(MAX_ADDEND);
398     assertEquals(0L, map.get(key));
399     assertFalse(map.containsKey(key));
400 
401     assertTrue(map.replace(key, 0L, value));
402     assertEquals(value, map.get(key));
403 
404     assertTrue(map.replace(key, value, 0L));
405     assertEquals(0L, map.get(key));
406     assertTrue(map.containsKey(key));
407 
408     assertTrue(map.replace(key, 0L, value));
409     assertEquals(value, map.get(key));
410   }
411 
testRemove()412   public void testRemove() {
413     AtomicLongMap<String> map = AtomicLongMap.create();
414     String key = "key";
415     assertEquals(0, map.size());
416     assertTrue(map.isEmpty());
417     assertEquals(0L, map.remove(key));
418 
419     long newValue = random.nextInt(MAX_ADDEND);
420     for (int i = 0; i < ITERATIONS; i++) {
421       map.put(key, newValue);
422       assertTrue(map.containsKey(key));
423 
424       long before = map.get(key);
425       long result = map.remove(key);
426       long after = map.get(key);
427       assertFalse(map.containsKey(key));
428       assertEquals(before, result);
429       assertEquals(0L, after);
430       newValue += newValue;
431     }
432     assertEquals(0, map.size());
433     assertTrue(map.isEmpty());
434   }
435 
testRemove_zero()436   public void testRemove_zero() {
437     AtomicLongMap<String> map = AtomicLongMap.create();
438     String key = "key";
439     assertEquals(0L, map.get(key));
440     assertFalse(map.containsKey(key));
441 
442     assertEquals(0L, map.remove(key));
443     assertEquals(0L, map.get(key));
444     assertFalse(map.containsKey(key));
445 
446     assertEquals(0L, map.put(key, 0L));
447     assertEquals(0L, map.get(key));
448     assertTrue(map.containsKey(key));
449 
450     assertEquals(0L, map.remove(key));
451     assertEquals(0L, map.get(key));
452     assertFalse(map.containsKey(key));
453   }
454 
testRemoveIfZero()455   public void testRemoveIfZero() {
456     AtomicLongMap<String> map = AtomicLongMap.create();
457     String key = "key";
458     assertEquals(0, map.size());
459     assertTrue(map.isEmpty());
460     assertFalse(map.removeIfZero(key));
461 
462     assertEquals(1, map.incrementAndGet(key));
463     assertFalse(map.removeIfZero(key));
464     assertEquals(2, map.incrementAndGet(key));
465     assertFalse(map.removeIfZero(key));
466     assertEquals(1, map.decrementAndGet(key));
467     assertFalse(map.removeIfZero(key));
468     assertEquals(0, map.decrementAndGet(key));
469     assertTrue(map.removeIfZero(key));
470     assertFalse(map.containsKey(key));
471   }
472 
testRemoveValue()473   public void testRemoveValue() {
474     AtomicLongMap<String> map = AtomicLongMap.create();
475     String key = "key";
476     assertEquals(0, map.size());
477     assertTrue(map.isEmpty());
478     assertFalse(map.remove(key, 0L));
479 
480     long newValue = random.nextInt(MAX_ADDEND);
481     for (int i = 0; i < ITERATIONS; i++) {
482       map.put(key, newValue);
483       assertTrue(map.containsKey(key));
484 
485       long before = map.get(key);
486       assertFalse(map.remove(key, newValue + 1));
487       assertFalse(map.remove(key, newValue - 1));
488       assertTrue(map.remove(key, newValue));
489       long after = map.get(key);
490       assertFalse(map.containsKey(key));
491       assertEquals(0L, after);
492       newValue += newValue;
493     }
494     assertEquals(0, map.size());
495     assertTrue(map.isEmpty());
496   }
497 
testRemoveValue_zero()498   public void testRemoveValue_zero() {
499     AtomicLongMap<String> map = AtomicLongMap.create();
500     String key = "key";
501     assertEquals(0L, map.get(key));
502     assertFalse(map.containsKey(key));
503 
504     assertFalse(map.remove(key, 0L));
505     assertEquals(0L, map.get(key));
506     assertFalse(map.containsKey(key));
507 
508     assertEquals(0L, map.put(key, 0L));
509     assertEquals(0L, map.get(key));
510     assertTrue(map.containsKey(key));
511 
512     assertTrue(map.remove(key, 0L));
513     assertEquals(0L, map.get(key));
514     assertFalse(map.containsKey(key));
515   }
516 
testRemoveZeros()517   public void testRemoveZeros() {
518     AtomicLongMap<Object> map = AtomicLongMap.create();
519     Set<Object> nonZeroKeys = Sets.newHashSet();
520     for (int i = 0; i < ITERATIONS; i++) {
521       Object key = new Object();
522       long value = i % 2;
523       map.put(key, value);
524       if (value != 0L) {
525         nonZeroKeys.add(key);
526       }
527     }
528     assertEquals(ITERATIONS, map.size());
529     assertTrue(map.asMap().containsValue(0L));
530 
531     map.removeAllZeros();
532     assertFalse(map.asMap().containsValue(0L));
533     assertEquals(ITERATIONS / 2, map.size());
534     assertEquals(nonZeroKeys, map.asMap().keySet());
535   }
536 
testClear()537   public void testClear() {
538     AtomicLongMap<Object> map = AtomicLongMap.create();
539     for (int i = 0; i < ITERATIONS; i++) {
540       map.put(new Object(), i);
541     }
542     assertEquals(ITERATIONS, map.size());
543 
544     map.clear();
545     assertEquals(0, map.size());
546     assertTrue(map.isEmpty());
547   }
548 
testSum()549   public void testSum() {
550     AtomicLongMap<Object> map = AtomicLongMap.create();
551     long sum = 0;
552     for (int i = 0; i < ITERATIONS; i++) {
553       map.put(new Object(), i);
554       sum += i;
555     }
556     assertEquals(ITERATIONS, map.size());
557     assertEquals(sum, map.sum());
558   }
559 
testEmpty()560   public void testEmpty() {
561     AtomicLongMap<String> map = AtomicLongMap.create();
562     assertEquals(0L, map.get("a"));
563     assertEquals(0, map.size());
564     assertTrue(map.isEmpty());
565     assertFalse(map.remove("a", 1L));
566     assertFalse(map.remove("a", 0L));
567     assertFalse(map.replace("a", 1L, 0L));
568   }
569 
testSerialization()570   public void testSerialization() {
571     AtomicLongMap<String> map = AtomicLongMap.create();
572     map.put("key", 1L);
573     AtomicLongMap<String> reserialized = SerializableTester.reserialize(map);
574     assertEquals(map.asMap(), reserialized.asMap());
575   }
576 }
577