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