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/AtomicDoubleArrayTest.java?revision=1.13 11 * (Modified to adapt to guava coding conventions) 12 */ 13 14 package com.google.common.util.concurrent; 15 16 import java.util.Arrays; 17 18 /** Unit test for {@link AtomicDoubleArray}. */ 19 public class AtomicDoubleArrayTest 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 AtomicDoubleArray */ 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 creates array of given size with all elements zero */ testConstructor()52 public void testConstructor() { 53 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 54 for (int i = 0; i < SIZE; i++) { 55 assertBitEquals(0.0, aa.get(i)); 56 } 57 } 58 59 /** constructor with null array throws NPE */ testConstructor2NPE()60 public void testConstructor2NPE() { 61 double[] a = null; 62 try { 63 new AtomicDoubleArray(a); 64 fail(); 65 } catch (NullPointerException success) { 66 } 67 } 68 69 /** constructor with array is of same size and has all elements */ testConstructor2()70 public void testConstructor2() { 71 AtomicDoubleArray aa = new AtomicDoubleArray(VALUES); 72 assertEquals(VALUES.length, aa.length()); 73 for (int i = 0; i < VALUES.length; i++) { 74 assertBitEquals(VALUES[i], aa.get(i)); 75 } 76 } 77 78 /** constructor with empty array has size 0 and contains no elements */ testConstructorEmptyArray()79 public void testConstructorEmptyArray() { 80 AtomicDoubleArray aa = new AtomicDoubleArray(new double[0]); 81 assertEquals(0, aa.length()); 82 try { 83 aa.get(0); 84 fail(); 85 } catch (IndexOutOfBoundsException success) { 86 } 87 } 88 89 /** constructor with length zero has size 0 and contains no elements */ testConstructorZeroLength()90 public void testConstructorZeroLength() { 91 AtomicDoubleArray aa = new AtomicDoubleArray(0); 92 assertEquals(0, aa.length()); 93 try { 94 aa.get(0); 95 fail(); 96 } catch (IndexOutOfBoundsException success) { 97 } 98 } 99 100 /** get and set for out of bound indices throw IndexOutOfBoundsException */ testIndexing()101 public void testIndexing() { 102 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 103 for (int index : new int[] {-1, SIZE}) { 104 try { 105 aa.get(index); 106 fail(); 107 } catch (IndexOutOfBoundsException success) { 108 } 109 try { 110 aa.set(index, 1.0); 111 fail(); 112 } catch (IndexOutOfBoundsException success) { 113 } 114 try { 115 aa.lazySet(index, 1.0); 116 fail(); 117 } catch (IndexOutOfBoundsException success) { 118 } 119 try { 120 aa.compareAndSet(index, 1.0, 2.0); 121 fail(); 122 } catch (IndexOutOfBoundsException success) { 123 } 124 try { 125 aa.weakCompareAndSet(index, 1.0, 2.0); 126 fail(); 127 } catch (IndexOutOfBoundsException success) { 128 } 129 try { 130 aa.getAndAdd(index, 1.0); 131 fail(); 132 } catch (IndexOutOfBoundsException success) { 133 } 134 try { 135 aa.addAndGet(index, 1.0); 136 fail(); 137 } catch (IndexOutOfBoundsException success) { 138 } 139 } 140 } 141 142 /** get returns the last value set at index */ testGetSet()143 public void testGetSet() { 144 AtomicDoubleArray aa = new AtomicDoubleArray(VALUES.length); 145 for (int i = 0; i < VALUES.length; i++) { 146 assertBitEquals(0.0, aa.get(i)); 147 aa.set(i, VALUES[i]); 148 assertBitEquals(VALUES[i], aa.get(i)); 149 aa.set(i, -3.0); 150 assertBitEquals(-3.0, aa.get(i)); 151 } 152 } 153 154 /** get returns the last value lazySet at index by same thread */ testGetLazySet()155 public void testGetLazySet() { 156 AtomicDoubleArray aa = new AtomicDoubleArray(VALUES.length); 157 for (int i = 0; i < VALUES.length; i++) { 158 assertBitEquals(0.0, aa.get(i)); 159 aa.lazySet(i, VALUES[i]); 160 assertBitEquals(VALUES[i], aa.get(i)); 161 aa.lazySet(i, -3.0); 162 assertBitEquals(-3.0, aa.get(i)); 163 } 164 } 165 166 /** compareAndSet succeeds in changing value if equal to expected else fails */ testCompareAndSet()167 public void testCompareAndSet() { 168 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 169 for (int i : new int[] {0, SIZE - 1}) { 170 double prev = 0.0; 171 double unused = Math.E + Math.PI; 172 for (double x : VALUES) { 173 assertBitEquals(prev, aa.get(i)); 174 assertFalse(aa.compareAndSet(i, unused, x)); 175 assertBitEquals(prev, aa.get(i)); 176 assertTrue(aa.compareAndSet(i, prev, x)); 177 assertBitEquals(x, aa.get(i)); 178 prev = x; 179 } 180 } 181 } 182 183 /** compareAndSet in one thread enables another waiting for value to succeed */ 184 testCompareAndSetInMultipleThreads()185 public void testCompareAndSetInMultipleThreads() throws InterruptedException { 186 final AtomicDoubleArray a = new AtomicDoubleArray(1); 187 a.set(0, 1.0); 188 Thread t = 189 newStartedThread( 190 new CheckedRunnable() { 191 @Override 192 public void realRun() { 193 while (!a.compareAndSet(0, 2.0, 3.0)) { 194 Thread.yield(); 195 } 196 } 197 }); 198 199 assertTrue(a.compareAndSet(0, 1.0, 2.0)); 200 awaitTermination(t); 201 assertBitEquals(3.0, a.get(0)); 202 } 203 204 /** repeated weakCompareAndSet succeeds in changing value when equal to expected */ testWeakCompareAndSet()205 public void testWeakCompareAndSet() { 206 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 207 for (int i : new int[] {0, SIZE - 1}) { 208 double prev = 0.0; 209 double unused = Math.E + Math.PI; 210 for (double x : VALUES) { 211 assertBitEquals(prev, aa.get(i)); 212 assertFalse(aa.weakCompareAndSet(i, unused, x)); 213 assertBitEquals(prev, aa.get(i)); 214 while (!aa.weakCompareAndSet(i, prev, x)) {; 215 } 216 assertBitEquals(x, aa.get(i)); 217 prev = x; 218 } 219 } 220 } 221 222 /** getAndSet returns previous value and sets to given value at given index */ testGetAndSet()223 public void testGetAndSet() { 224 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 225 for (int i : new int[] {0, SIZE - 1}) { 226 double prev = 0.0; 227 for (double x : VALUES) { 228 assertBitEquals(prev, aa.getAndSet(i, x)); 229 prev = x; 230 } 231 } 232 } 233 234 /** getAndAdd returns previous value and adds given value */ testGetAndAdd()235 public void testGetAndAdd() { 236 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 237 for (int i : new int[] {0, SIZE - 1}) { 238 for (double x : VALUES) { 239 for (double y : VALUES) { 240 aa.set(i, x); 241 double z = aa.getAndAdd(i, y); 242 assertBitEquals(x, z); 243 assertBitEquals(x + y, aa.get(i)); 244 } 245 } 246 } 247 } 248 249 /** addAndGet adds given value to current, and returns current value */ testAddAndGet()250 public void testAddAndGet() { 251 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 252 for (int i : new int[] {0, SIZE - 1}) { 253 for (double x : VALUES) { 254 for (double y : VALUES) { 255 aa.set(i, x); 256 double z = aa.addAndGet(i, y); 257 assertBitEquals(x + y, z); 258 assertBitEquals(x + y, aa.get(i)); 259 } 260 } 261 } 262 } 263 264 static final long COUNTDOWN = 100000; 265 266 class Counter extends CheckedRunnable { 267 final AtomicDoubleArray aa; 268 volatile long counts; 269 Counter(AtomicDoubleArray a)270 Counter(AtomicDoubleArray a) { 271 aa = a; 272 } 273 274 @Override realRun()275 public void realRun() { 276 for (; ; ) { 277 boolean done = true; 278 for (int i = 0; i < aa.length(); i++) { 279 double v = aa.get(i); 280 assertTrue(v >= 0); 281 if (v != 0) { 282 done = false; 283 if (aa.compareAndSet(i, v, v - 1.0)) { 284 ++counts; 285 } 286 } 287 } 288 if (done) { 289 break; 290 } 291 } 292 } 293 } 294 295 /** 296 * Multiple threads using same array of counters successfully update a number of times equal to 297 * total count 298 */ 299 testCountingInMultipleThreads()300 public void testCountingInMultipleThreads() throws InterruptedException { 301 final AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 302 for (int i = 0; i < SIZE; i++) { 303 aa.set(i, (double) COUNTDOWN); 304 } 305 Counter c1 = new Counter(aa); 306 Counter c2 = new Counter(aa); 307 Thread t1 = newStartedThread(c1); 308 Thread t2 = newStartedThread(c2); 309 awaitTermination(t1); 310 awaitTermination(t2); 311 assertEquals(SIZE * COUNTDOWN, c1.counts + c2.counts); 312 } 313 314 /** a deserialized serialized array holds same values */ testSerialization()315 public void testSerialization() throws Exception { 316 AtomicDoubleArray x = new AtomicDoubleArray(SIZE); 317 for (int i = 0; i < SIZE; i++) { 318 x.set(i, (double) -i); 319 } 320 AtomicDoubleArray y = serialClone(x); 321 assertTrue(x != y); 322 assertEquals(x.length(), y.length()); 323 for (int i = 0; i < SIZE; i++) { 324 assertBitEquals(x.get(i), y.get(i)); 325 } 326 327 AtomicDoubleArray a = new AtomicDoubleArray(VALUES); 328 AtomicDoubleArray b = serialClone(a); 329 assertFalse(a.equals(b)); 330 assertFalse(b.equals(a)); 331 assertEquals(a.length(), b.length()); 332 for (int i = 0; i < VALUES.length; i++) { 333 assertBitEquals(a.get(i), b.get(i)); 334 } 335 } 336 337 /** toString returns current value */ testToString()338 public void testToString() { 339 AtomicDoubleArray aa = new AtomicDoubleArray(VALUES); 340 assertEquals(Arrays.toString(VALUES), aa.toString()); 341 assertEquals("[]", new AtomicDoubleArray(0).toString()); 342 assertEquals("[]", new AtomicDoubleArray(new double[0]).toString()); 343 } 344 345 /** compareAndSet treats +0.0 and -0.0 as distinct values */ testDistinctZeros()346 public void testDistinctZeros() { 347 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 348 for (int i : new int[] {0, SIZE - 1}) { 349 assertFalse(aa.compareAndSet(i, -0.0, 7.0)); 350 assertFalse(aa.weakCompareAndSet(i, -0.0, 7.0)); 351 assertBitEquals(+0.0, aa.get(i)); 352 assertTrue(aa.compareAndSet(i, +0.0, -0.0)); 353 assertBitEquals(-0.0, aa.get(i)); 354 assertFalse(aa.compareAndSet(i, +0.0, 7.0)); 355 assertFalse(aa.weakCompareAndSet(i, +0.0, 7.0)); 356 assertBitEquals(-0.0, aa.get(i)); 357 } 358 } 359 } 360