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 junit.framework.*; 17 import java.util.Arrays; 18 19 /** 20 * Unit test for {@link AtomicDoubleArray}. 21 */ 22 public class AtomicDoubleArrayTest extends JSR166TestCase { 23 24 private static final double[] VALUES = { 25 Double.NEGATIVE_INFINITY, 26 -Double.MAX_VALUE, 27 (double) Long.MIN_VALUE, 28 (double) Integer.MIN_VALUE, 29 -Math.PI, 30 -1.0, 31 -Double.MIN_VALUE, 32 -0.0, 33 +0.0, 34 Double.MIN_VALUE, 35 1.0, 36 Math.PI, 37 (double) Integer.MAX_VALUE, 38 (double) Long.MAX_VALUE, 39 Double.MAX_VALUE, 40 Double.POSITIVE_INFINITY, 41 Double.NaN, 42 Float.MAX_VALUE, 43 }; 44 45 /** The notion of equality used by AtomicDoubleArray */ 46 static boolean bitEquals(double x, double y) { 47 return Double.doubleToRawLongBits(x) == Double.doubleToRawLongBits(y); 48 } 49 50 static void assertBitEquals(double x, double y) { 51 assertEquals(Double.doubleToRawLongBits(x), 52 Double.doubleToRawLongBits(y)); 53 } 54 55 /** 56 * constructor creates array of given size with all elements zero 57 */ 58 public void testConstructor() { 59 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 60 for (int i = 0; i < SIZE; i++) { 61 assertBitEquals(0.0, aa.get(i)); 62 } 63 } 64 65 /** 66 * constructor with null array throws NPE 67 */ 68 public void testConstructor2NPE() { 69 try { 70 double[] a = null; 71 AtomicDoubleArray aa = new AtomicDoubleArray(a); 72 shouldThrow(); 73 } catch (NullPointerException success) {} 74 } 75 76 /** 77 * constructor with array is of same size and has all elements 78 */ 79 public void testConstructor2() { 80 AtomicDoubleArray aa = new AtomicDoubleArray(VALUES); 81 assertEquals(VALUES.length, aa.length()); 82 for (int i = 0; i < VALUES.length; i++) { 83 assertBitEquals(VALUES[i], aa.get(i)); 84 } 85 } 86 87 /** 88 * constructor with empty array has size 0 and contains no elements 89 */ 90 public void testConstructorEmptyArray() { 91 AtomicDoubleArray aa = new AtomicDoubleArray(new double[0]); 92 assertEquals(0, aa.length()); 93 try { 94 aa.get(0); 95 shouldThrow(); 96 } catch (IndexOutOfBoundsException success) {} 97 } 98 99 /** 100 * constructor with length zero has size 0 and contains no elements 101 */ 102 public void testConstructorZeroLength() { 103 AtomicDoubleArray aa = new AtomicDoubleArray(0); 104 assertEquals(0, aa.length()); 105 try { 106 aa.get(0); 107 shouldThrow(); 108 } catch (IndexOutOfBoundsException success) {} 109 } 110 111 /** 112 * get and set for out of bound indices throw IndexOutOfBoundsException 113 */ 114 public void testIndexing() { 115 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 116 for (int index : new int[] { -1, SIZE }) { 117 try { 118 aa.get(index); 119 shouldThrow(); 120 } catch (IndexOutOfBoundsException success) {} 121 try { 122 aa.set(index, 1.0); 123 shouldThrow(); 124 } catch (IndexOutOfBoundsException success) {} 125 try { 126 aa.lazySet(index, 1.0); 127 shouldThrow(); 128 } catch (IndexOutOfBoundsException success) {} 129 try { 130 aa.compareAndSet(index, 1.0, 2.0); 131 shouldThrow(); 132 } catch (IndexOutOfBoundsException success) {} 133 try { 134 aa.weakCompareAndSet(index, 1.0, 2.0); 135 shouldThrow(); 136 } catch (IndexOutOfBoundsException success) {} 137 try { 138 aa.getAndAdd(index, 1.0); 139 shouldThrow(); 140 } catch (IndexOutOfBoundsException success) {} 141 try { 142 aa.addAndGet(index, 1.0); 143 shouldThrow(); 144 } catch (IndexOutOfBoundsException success) {} 145 } 146 } 147 148 /** 149 * get returns the last value set at index 150 */ 151 public void testGetSet() { 152 AtomicDoubleArray aa = new AtomicDoubleArray(VALUES.length); 153 for (int i = 0; i < VALUES.length; i++) { 154 assertBitEquals(0.0, aa.get(i)); 155 aa.set(i, VALUES[i]); 156 assertBitEquals(VALUES[i], aa.get(i)); 157 aa.set(i, -3.0); 158 assertBitEquals(-3.0, aa.get(i)); 159 } 160 } 161 162 /** 163 * get returns the last value lazySet at index by same thread 164 */ 165 public void testGetLazySet() { 166 AtomicDoubleArray aa = new AtomicDoubleArray(VALUES.length); 167 for (int i = 0; i < VALUES.length; i++) { 168 assertBitEquals(0.0, aa.get(i)); 169 aa.lazySet(i, VALUES[i]); 170 assertBitEquals(VALUES[i], aa.get(i)); 171 aa.lazySet(i, -3.0); 172 assertBitEquals(-3.0, aa.get(i)); 173 } 174 } 175 176 /** 177 * compareAndSet succeeds in changing value if equal to expected else fails 178 */ 179 public void testCompareAndSet() { 180 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 181 for (int i : new int[] { 0, SIZE - 1}) { 182 double prev = 0.0; 183 double unused = Math.E + Math.PI; 184 for (double x : VALUES) { 185 assertBitEquals(prev, aa.get(i)); 186 assertFalse(aa.compareAndSet(i, unused, x)); 187 assertBitEquals(prev, aa.get(i)); 188 assertTrue(aa.compareAndSet(i, prev, x)); 189 assertBitEquals(x, aa.get(i)); 190 prev = x; 191 } 192 } 193 } 194 195 /** 196 * compareAndSet in one thread enables another waiting for value 197 * to succeed 198 */ 199 200 public void testCompareAndSetInMultipleThreads() throws InterruptedException { 201 final AtomicDoubleArray a = new AtomicDoubleArray(1); 202 a.set(0, 1.0); 203 Thread t = newStartedThread(new CheckedRunnable() { 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 public void realRun() { 292 for (;;) { 293 boolean done = true; 294 for (int i = 0; i < aa.length(); i++) { 295 double v = aa.get(i); 296 assertTrue(v >= 0); 297 if (v != 0) { 298 done = false; 299 if (aa.compareAndSet(i, v, v - 1.0)) { 300 ++counts; 301 } 302 } 303 } 304 if (done) { 305 break; 306 } 307 } 308 } 309 } 310 311 /** 312 * Multiple threads using same array of counters successfully 313 * update a number of times equal to total count 314 */ 315 316 public void testCountingInMultipleThreads() throws InterruptedException { 317 final AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 318 for (int i = 0; i < SIZE; i++) { 319 aa.set(i, (double) COUNTDOWN); 320 } 321 Counter c1 = new Counter(aa); 322 Counter c2 = new Counter(aa); 323 Thread t1 = newStartedThread(c1); 324 Thread t2 = newStartedThread(c2); 325 awaitTermination(t1); 326 awaitTermination(t2); 327 assertEquals(c1.counts + c2.counts, SIZE * COUNTDOWN); 328 } 329 330 /** 331 * a deserialized serialized array holds same values 332 */ 333 public void testSerialization() throws Exception { 334 AtomicDoubleArray x = new AtomicDoubleArray(SIZE); 335 for (int i = 0; i < SIZE; i++) { 336 x.set(i, (double) -i); 337 } 338 AtomicDoubleArray y = serialClone(x); 339 assertTrue(x != y); 340 assertEquals(x.length(), y.length()); 341 for (int i = 0; i < SIZE; i++) { 342 assertBitEquals(x.get(i), y.get(i)); 343 } 344 345 AtomicDoubleArray a = new AtomicDoubleArray(VALUES); 346 AtomicDoubleArray b = serialClone(a); 347 assertFalse(a.equals(b)); 348 assertFalse(b.equals(a)); 349 assertEquals(a.length(), b.length()); 350 for (int i = 0; i < VALUES.length; i++) { 351 assertBitEquals(a.get(i), b.get(i)); 352 } 353 } 354 355 /** 356 * toString returns current value 357 */ 358 public void testToString() { 359 AtomicDoubleArray aa = new AtomicDoubleArray(VALUES); 360 assertEquals(Arrays.toString(VALUES), aa.toString()); 361 assertEquals("[]", new AtomicDoubleArray(0).toString()); 362 assertEquals("[]", new AtomicDoubleArray(new double[0]).toString()); 363 } 364 365 /** 366 * compareAndSet treats +0.0 and -0.0 as distinct values 367 */ 368 public void testDistinctZeros() { 369 AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); 370 for (int i : new int[] { 0, SIZE - 1}) { 371 assertFalse(aa.compareAndSet(i, -0.0, 7.0)); 372 assertFalse(aa.weakCompareAndSet(i, -0.0, 7.0)); 373 assertBitEquals(+0.0, aa.get(i)); 374 assertTrue(aa.compareAndSet(i, +0.0, -0.0)); 375 assertBitEquals(-0.0, aa.get(i)); 376 assertFalse(aa.compareAndSet(i, +0.0, 7.0)); 377 assertFalse(aa.weakCompareAndSet(i, +0.0, 7.0)); 378 assertBitEquals(-0.0, aa.get(i)); 379 } 380 } 381 } 382