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
14package com.google.common.util.concurrent;
15
16import junit.framework.*;
17
18/**
19 * Unit test for {@link AtomicDouble}.
20 */
21public class AtomicDoubleTest extends JSR166TestCase {
22
23  private static final double[] VALUES = {
24    Double.NEGATIVE_INFINITY,
25    -Double.MAX_VALUE,
26    (double) Long.MIN_VALUE,
27    (double) Integer.MIN_VALUE,
28    -Math.PI,
29    -1.0,
30    -Double.MIN_VALUE,
31    -0.0,
32    +0.0,
33    Double.MIN_VALUE,
34    1.0,
35    Math.PI,
36    (double) Integer.MAX_VALUE,
37    (double) Long.MAX_VALUE,
38    Double.MAX_VALUE,
39    Double.POSITIVE_INFINITY,
40    Double.NaN,
41    Float.MAX_VALUE,
42  };
43
44  /** The notion of equality used by AtomicDouble */
45  static boolean bitEquals(double x, double y) {
46    return Double.doubleToRawLongBits(x) == Double.doubleToRawLongBits(y);
47  }
48
49  static void assertBitEquals(double x, double y) {
50    assertEquals(Double.doubleToRawLongBits(x),
51                 Double.doubleToRawLongBits(y));
52  }
53
54  /**
55   * constructor initializes to given value
56   */
57  public void testConstructor() {
58    for (double x : VALUES) {
59      AtomicDouble a = new AtomicDouble(x);
60      assertBitEquals(x, a.get());
61    }
62  }
63
64  /**
65   * default constructed initializes to zero
66   */
67  public void testConstructor2() {
68    AtomicDouble a = new AtomicDouble();
69    assertBitEquals(0.0, a.get());
70  }
71
72  /**
73   * get returns the last value set
74   */
75  public void testGetSet() {
76    AtomicDouble at = new AtomicDouble(1.0);
77    assertBitEquals(1.0, at.get());
78    for (double x : VALUES) {
79      at.set(x);
80      assertBitEquals(x, at.get());
81    }
82  }
83
84  /**
85   * get returns the last value lazySet in same thread
86   */
87  public void testGetLazySet() {
88    AtomicDouble at = new AtomicDouble(1.0);
89    assertBitEquals(1.0, at.get());
90    for (double x : VALUES) {
91      at.lazySet(x);
92      assertBitEquals(x, at.get());
93    }
94  }
95
96  /**
97   * compareAndSet succeeds in changing value if equal to expected else fails
98   */
99  public void testCompareAndSet() {
100    double prev = Math.E;
101    double unused = Math.E + Math.PI;
102    AtomicDouble at = new AtomicDouble(prev);
103    for (double x : VALUES) {
104      assertBitEquals(prev, at.get());
105      assertFalse(at.compareAndSet(unused, x));
106      assertBitEquals(prev, at.get());
107      assertTrue(at.compareAndSet(prev, x));
108      assertBitEquals(x, at.get());
109      prev = x;
110    }
111  }
112
113  /**
114   * compareAndSet in one thread enables another waiting for value
115   * to succeed
116   */
117
118      public void testCompareAndSetInMultipleThreads() throws Exception {
119    final AtomicDouble at = new AtomicDouble(1.0);
120    Thread t = newStartedThread(new CheckedRunnable() {
121        public void realRun() {
122          while (!at.compareAndSet(2.0, 3.0)) {
123            Thread.yield();
124          }
125        }});
126
127    assertTrue(at.compareAndSet(1.0, 2.0));
128    awaitTermination(t);
129    assertBitEquals(3.0, at.get());
130  }
131
132  /**
133   * repeated weakCompareAndSet succeeds in changing value when equal
134   * to expected
135   */
136  public void testWeakCompareAndSet() {
137    double prev = Math.E;
138    double unused = Math.E + Math.PI;
139    AtomicDouble at = new AtomicDouble(prev);
140    for (double x : VALUES) {
141      assertBitEquals(prev, at.get());
142      assertFalse(at.weakCompareAndSet(unused, x));
143      assertBitEquals(prev, at.get());
144      while (!at.weakCompareAndSet(prev, x)) {
145        ;
146      }
147      assertBitEquals(x, at.get());
148      prev = x;
149    }
150  }
151
152  /**
153   * getAndSet returns previous value and sets to given value
154   */
155  public void testGetAndSet() {
156    double prev = Math.E;
157    AtomicDouble at = new AtomicDouble(prev);
158    for (double x : VALUES) {
159      assertBitEquals(prev, at.getAndSet(x));
160      prev = x;
161    }
162  }
163
164  /**
165   * getAndAdd returns previous value and adds given value
166   */
167  public void testGetAndAdd() {
168    for (double x : VALUES) {
169      for (double y : VALUES) {
170        AtomicDouble a = new AtomicDouble(x);
171        double z = a.getAndAdd(y);
172        assertBitEquals(x, z);
173        assertBitEquals(x + y, a.get());
174      }
175    }
176  }
177
178  /**
179   * addAndGet adds given value to current, and returns current value
180   */
181  public void testAddAndGet() {
182    for (double x : VALUES) {
183      for (double y : VALUES) {
184        AtomicDouble a = new AtomicDouble(x);
185        double z = a.addAndGet(y);
186        assertBitEquals(x + y, z);
187        assertBitEquals(x + y, a.get());
188      }
189    }
190  }
191
192  /**
193   * a deserialized serialized atomic holds same value
194   */
195  public void testSerialization() throws Exception {
196    AtomicDouble a = new AtomicDouble();
197    AtomicDouble b = serialClone(a);
198    assertTrue(a != b);
199    a.set(-22.0);
200    AtomicDouble c = serialClone(a);
201    assertBitEquals(-22.0, a.get());
202    assertBitEquals(0.0, b.get());
203    assertBitEquals(-22.0, c.get());
204    for (double x : VALUES) {
205      AtomicDouble d = new AtomicDouble(x);
206      assertBitEquals(serialClone(d).get(), d.get());
207    }
208  }
209
210  /**
211   * toString returns current value
212   */
213  public void testToString() {
214    AtomicDouble at = new AtomicDouble();
215    assertEquals("0.0", at.toString());
216    for (double x : VALUES) {
217      at.set(x);
218      assertEquals(Double.toString(x), at.toString());
219    }
220  }
221
222  /**
223   * intValue returns current value.
224   */
225  public void testIntValue() {
226    AtomicDouble at = new AtomicDouble();
227    assertEquals(0, at.intValue());
228    for (double x : VALUES) {
229      at.set(x);
230      assertEquals((int) x, at.intValue());
231    }
232  }
233
234  /**
235   * longValue returns current value.
236   */
237  public void testLongValue() {
238    AtomicDouble at = new AtomicDouble();
239    assertEquals(0L, at.longValue());
240    for (double x : VALUES) {
241      at.set(x);
242      assertEquals((long) x, at.longValue());
243    }
244  }
245
246  /**
247   * floatValue returns current value.
248   */
249  public void testFloatValue() {
250    AtomicDouble at = new AtomicDouble();
251    assertEquals(0.0f, at.floatValue());
252    for (double x : VALUES) {
253      at.set(x);
254      assertEquals((float) x, at.floatValue());
255    }
256  }
257
258  /**
259   * doubleValue returns current value.
260   */
261  public void testDoubleValue() {
262    AtomicDouble at = new AtomicDouble();
263    assertEquals(0.0d, at.doubleValue());
264    for (double x : VALUES) {
265      at.set(x);
266      assertBitEquals(x, at.doubleValue());
267    }
268  }
269
270  /**
271   * compareAndSet treats +0.0 and -0.0 as distinct values
272   */
273  public void testDistinctZeros() {
274    AtomicDouble at = new AtomicDouble(+0.0);
275    assertFalse(at.compareAndSet(-0.0, 7.0));
276    assertFalse(at.weakCompareAndSet(-0.0, 7.0));
277    assertBitEquals(+0.0, at.get());
278    assertTrue(at.compareAndSet(+0.0, -0.0));
279    assertBitEquals(-0.0, at.get());
280    assertFalse(at.compareAndSet(+0.0, 7.0));
281    assertFalse(at.weakCompareAndSet(+0.0, 7.0));
282    assertBitEquals(-0.0, at.get());
283  }
284}
285