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