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