• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Written by Doug Lea and Martin Buchholz with assistance from
3  * members of JCP JSR-166 Expert Group and released to the public
4  * domain, as explained at
5  * http://creativecommons.org/publicdomain/zero/1.0/
6  */
7 
8 /*
9  * Source:
10  * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/test/tck-jsr166e/AtomicDoubleTest.java?revision=1.8
11  * (Modified to adapt to guava coding conventions)
12  */
13 
14 package com.google.common.util.concurrent;
15 
16 import static java.lang.Math.max;
17 
18 /** Unit test for {@link AtomicDouble}. */
19 public class AtomicDoubleTest extends JSR166TestCase {
20 
21   private static final double[] VALUES = {
22     Double.NEGATIVE_INFINITY,
23     -Double.MAX_VALUE,
24     (double) Long.MIN_VALUE,
25     (double) Integer.MIN_VALUE,
26     -Math.PI,
27     -1.0,
28     -Double.MIN_VALUE,
29     -0.0,
30     +0.0,
31     Double.MIN_VALUE,
32     1.0,
33     Math.PI,
34     (double) Integer.MAX_VALUE,
35     (double) Long.MAX_VALUE,
36     Double.MAX_VALUE,
37     Double.POSITIVE_INFINITY,
38     Double.NaN,
39     Float.MAX_VALUE,
40   };
41 
42   /** The notion of equality used by AtomicDouble */
bitEquals(double x, double y)43   static boolean bitEquals(double x, double y) {
44     return Double.doubleToRawLongBits(x) == Double.doubleToRawLongBits(y);
45   }
46 
assertBitEquals(double x, double y)47   static void assertBitEquals(double x, double y) {
48     assertEquals(Double.doubleToRawLongBits(x), Double.doubleToRawLongBits(y));
49   }
50 
51   /** constructor initializes to given value */
testConstructor()52   public void testConstructor() {
53     for (double x : VALUES) {
54       AtomicDouble a = new AtomicDouble(x);
55       assertBitEquals(x, a.get());
56     }
57   }
58 
59   /** default constructed initializes to zero */
testConstructor2()60   public void testConstructor2() {
61     AtomicDouble a = new AtomicDouble();
62     assertBitEquals(0.0, a.get());
63   }
64 
65   /** get returns the last value set */
testGetSet()66   public void testGetSet() {
67     AtomicDouble at = new AtomicDouble(1.0);
68     assertBitEquals(1.0, at.get());
69     for (double x : VALUES) {
70       at.set(x);
71       assertBitEquals(x, at.get());
72     }
73   }
74 
75   /** get returns the last value lazySet in same thread */
testGetLazySet()76   public void testGetLazySet() {
77     AtomicDouble at = new AtomicDouble(1.0);
78     assertBitEquals(1.0, at.get());
79     for (double x : VALUES) {
80       at.lazySet(x);
81       assertBitEquals(x, at.get());
82     }
83   }
84 
85   /** compareAndSet succeeds in changing value if equal to expected else fails */
testCompareAndSet()86   public void testCompareAndSet() {
87     double prev = Math.E;
88     double unused = Math.E + Math.PI;
89     AtomicDouble at = new AtomicDouble(prev);
90     for (double x : VALUES) {
91       assertBitEquals(prev, at.get());
92       assertFalse(at.compareAndSet(unused, x));
93       assertBitEquals(prev, at.get());
94       assertTrue(at.compareAndSet(prev, x));
95       assertBitEquals(x, at.get());
96       prev = x;
97     }
98   }
99 
100   /** compareAndSet in one thread enables another waiting for value to succeed */
testCompareAndSetInMultipleThreads()101   public void testCompareAndSetInMultipleThreads() throws Exception {
102     final AtomicDouble at = new AtomicDouble(1.0);
103     Thread t =
104         newStartedThread(
105             new CheckedRunnable() {
106               @Override
107               public void realRun() {
108                 while (!at.compareAndSet(2.0, 3.0)) {
109                   Thread.yield();
110                 }
111               }
112             });
113 
114     assertTrue(at.compareAndSet(1.0, 2.0));
115     awaitTermination(t);
116     assertBitEquals(3.0, at.get());
117   }
118 
119   /** repeated weakCompareAndSet succeeds in changing value when equal to expected */
testWeakCompareAndSet()120   public void testWeakCompareAndSet() {
121     double prev = Math.E;
122     double unused = Math.E + Math.PI;
123     AtomicDouble at = new AtomicDouble(prev);
124     for (double x : VALUES) {
125       assertBitEquals(prev, at.get());
126       assertFalse(at.weakCompareAndSet(unused, x));
127       assertBitEquals(prev, at.get());
128       while (!at.weakCompareAndSet(prev, x)) {
129         ;
130       }
131       assertBitEquals(x, at.get());
132       prev = x;
133     }
134   }
135 
136   /** getAndSet returns previous value and sets to given value */
testGetAndSet()137   public void testGetAndSet() {
138     double prev = Math.E;
139     AtomicDouble at = new AtomicDouble(prev);
140     for (double x : VALUES) {
141       assertBitEquals(prev, at.getAndSet(x));
142       prev = x;
143     }
144   }
145 
146   /** getAndAdd returns previous value and adds given value */
testGetAndAdd()147   public void testGetAndAdd() {
148     for (double x : VALUES) {
149       for (double y : VALUES) {
150         AtomicDouble a = new AtomicDouble(x);
151         double z = a.getAndAdd(y);
152         assertBitEquals(x, z);
153         assertBitEquals(x + y, a.get());
154       }
155     }
156   }
157 
158   /** addAndGet adds given value to current, and returns current value */
testAddAndGet()159   public void testAddAndGet() {
160     for (double x : VALUES) {
161       for (double y : VALUES) {
162         AtomicDouble a = new AtomicDouble(x);
163         double z = a.addAndGet(y);
164         assertBitEquals(x + y, z);
165         assertBitEquals(x + y, a.get());
166       }
167     }
168   }
169 
170   /** getAndAccumulate with sum adds given value to current, and returns previous value */
testGetAndAccumulateWithSum()171   public void testGetAndAccumulateWithSum() {
172     for (double x : VALUES) {
173       for (double y : VALUES) {
174         AtomicDouble a = new AtomicDouble(x);
175         double z = a.getAndAccumulate(y, Double::sum);
176         assertBitEquals(x, z);
177         assertBitEquals(x + y, a.get());
178       }
179     }
180   }
181 
182   /** getAndAccumulate with max stores max of given value to current, and returns previous value */
testGetAndAccumulateWithMax()183   public void testGetAndAccumulateWithMax() {
184     for (double x : VALUES) {
185       for (double y : VALUES) {
186         AtomicDouble a = new AtomicDouble(x);
187         double z = a.getAndAccumulate(y, Double::max);
188         double expectedMax = max(x, y);
189         assertBitEquals(x, z);
190         assertBitEquals(expectedMax, a.get());
191       }
192     }
193   }
194 
195   /** accumulateAndGet with sum adds given value to current, and returns current value */
testAccumulateAndGetWithSum()196   public void testAccumulateAndGetWithSum() {
197     for (double x : VALUES) {
198       for (double y : VALUES) {
199         AtomicDouble a = new AtomicDouble(x);
200         double z = a.accumulateAndGet(y, Double::sum);
201         assertBitEquals(x + y, z);
202         assertBitEquals(x + y, a.get());
203       }
204     }
205   }
206 
207   /** accumulateAndGet with max stores max of given value to current, and returns current value */
testAccumulateAndGetWithMax()208   public void testAccumulateAndGetWithMax() {
209     for (double x : VALUES) {
210       for (double y : VALUES) {
211         AtomicDouble a = new AtomicDouble(x);
212         double z = a.accumulateAndGet(y, Double::max);
213         double expectedMax = max(x, y);
214         assertBitEquals(expectedMax, z);
215         assertBitEquals(expectedMax, a.get());
216       }
217     }
218   }
219 
220   /** getAndUpdate with sum stores sum of given value to current, and returns previous value */
testGetAndUpdateWithSum()221   public void testGetAndUpdateWithSum() {
222     for (double x : VALUES) {
223       for (double y : VALUES) {
224         AtomicDouble a = new AtomicDouble(x);
225         double z = a.getAndUpdate(value -> value + y);
226         assertBitEquals(x, z);
227         assertBitEquals(x + y, a.get());
228       }
229     }
230   }
231 
232   /**
233    * getAndUpdate with subtract stores subtraction of value from current, and returns previous value
234    */
testGetAndUpdateWithSubtract()235   public void testGetAndUpdateWithSubtract() {
236     for (double x : VALUES) {
237       for (double y : VALUES) {
238         AtomicDouble a = new AtomicDouble(x);
239         double z = a.getAndUpdate(value -> value - y);
240         assertBitEquals(x, z);
241         assertBitEquals(x - y, a.get());
242       }
243     }
244   }
245 
246   /** updateAndGet with sum stores sum of given value to current, and returns current value */
testUpdateAndGetWithSum()247   public void testUpdateAndGetWithSum() {
248     for (double x : VALUES) {
249       for (double y : VALUES) {
250         AtomicDouble a = new AtomicDouble(x);
251         double z = a.updateAndGet(value -> value + y);
252         assertBitEquals(x + y, z);
253         assertBitEquals(x + y, a.get());
254       }
255     }
256   }
257 
258   /**
259    * updateAndGet with subtract stores subtraction of value from current, and returns current value
260    */
testUpdateAndGetWithSubtract()261   public void testUpdateAndGetWithSubtract() {
262     for (double x : VALUES) {
263       for (double y : VALUES) {
264         AtomicDouble a = new AtomicDouble(x);
265         double z = a.updateAndGet(value -> value - y);
266         assertBitEquals(x - y, z);
267         assertBitEquals(x - y, a.get());
268       }
269     }
270   }
271 
272   /** a deserialized serialized atomic holds same value */
testSerialization()273   public void testSerialization() throws Exception {
274     AtomicDouble a = new AtomicDouble();
275     AtomicDouble b = serialClone(a);
276     assertNotSame(a, b);
277     a.set(-22.0);
278     AtomicDouble c = serialClone(a);
279     assertNotSame(b, c);
280     assertBitEquals(-22.0, a.get());
281     assertBitEquals(0.0, b.get());
282     assertBitEquals(-22.0, c.get());
283     for (double x : VALUES) {
284       AtomicDouble d = new AtomicDouble(x);
285       assertBitEquals(serialClone(d).get(), d.get());
286     }
287   }
288 
289   /** toString returns current value */
testToString()290   public void testToString() {
291     AtomicDouble at = new AtomicDouble();
292     assertEquals("0.0", at.toString());
293     for (double x : VALUES) {
294       at.set(x);
295       assertEquals(Double.toString(x), at.toString());
296     }
297   }
298 
299   /** intValue returns current value. */
testIntValue()300   public void testIntValue() {
301     AtomicDouble at = new AtomicDouble();
302     assertEquals(0, at.intValue());
303     for (double x : VALUES) {
304       at.set(x);
305       assertEquals((int) x, at.intValue());
306     }
307   }
308 
309   /** longValue returns current value. */
testLongValue()310   public void testLongValue() {
311     AtomicDouble at = new AtomicDouble();
312     assertEquals(0L, at.longValue());
313     for (double x : VALUES) {
314       at.set(x);
315       assertEquals((long) x, at.longValue());
316     }
317   }
318 
319   /** floatValue returns current value. */
testFloatValue()320   public void testFloatValue() {
321     AtomicDouble at = new AtomicDouble();
322     assertEquals(0.0f, at.floatValue());
323     for (double x : VALUES) {
324       at.set(x);
325       assertEquals((float) x, at.floatValue());
326     }
327   }
328 
329   /** doubleValue returns current value. */
testDoubleValue()330   public void testDoubleValue() {
331     AtomicDouble at = new AtomicDouble();
332     assertEquals(0.0d, at.doubleValue());
333     for (double x : VALUES) {
334       at.set(x);
335       assertBitEquals(x, at.doubleValue());
336     }
337   }
338 
339   /** compareAndSet treats +0.0 and -0.0 as distinct values */
testDistinctZeros()340   public void testDistinctZeros() {
341     AtomicDouble at = new AtomicDouble(+0.0);
342     assertFalse(at.compareAndSet(-0.0, 7.0));
343     assertFalse(at.weakCompareAndSet(-0.0, 7.0));
344     assertBitEquals(+0.0, at.get());
345     assertTrue(at.compareAndSet(+0.0, -0.0));
346     assertBitEquals(-0.0, at.get());
347     assertFalse(at.compareAndSet(+0.0, 7.0));
348     assertFalse(at.weakCompareAndSet(+0.0, 7.0));
349     assertBitEquals(-0.0, at.get());
350   }
351 }
352