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