1 /* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/publicdomain/zero/1.0/ 5 * Other contributors include Andrew Wright, Jeffrey Hayes, 6 * Pat Fisher, Mike Judd. 7 */ 8 9 package jsr166; 10 11 import junit.framework.*; 12 import java.util.Arrays; 13 import java.util.concurrent.atomic.AtomicIntegerArray; 14 15 public class AtomicIntegerArrayTest extends JSR166TestCase { 16 17 /** 18 * constructor creates array of given size with all elements zero 19 */ testConstructor()20 public void testConstructor() { 21 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 22 for (int i = 0; i < SIZE; i++) 23 assertEquals(0, aa.get(i)); 24 } 25 26 /** 27 * constructor with null array throws NPE 28 */ testConstructor2NPE()29 public void testConstructor2NPE() { 30 try { 31 int[] a = null; 32 AtomicIntegerArray aa = new AtomicIntegerArray(a); 33 shouldThrow(); 34 } catch (NullPointerException success) {} 35 } 36 37 /** 38 * constructor with array is of same size and has all elements 39 */ testConstructor2()40 public void testConstructor2() { 41 int[] a = { 17, 3, -42, 99, -7 }; 42 AtomicIntegerArray aa = new AtomicIntegerArray(a); 43 assertEquals(a.length, aa.length()); 44 for (int i = 0; i < a.length; i++) 45 assertEquals(a[i], aa.get(i)); 46 } 47 48 /** 49 * get and set for out of bound indices throw IndexOutOfBoundsException 50 */ testIndexing()51 public void testIndexing() { 52 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 53 for (int index : new int[] { -1, SIZE }) { 54 try { 55 aa.get(index); 56 shouldThrow(); 57 } catch (IndexOutOfBoundsException success) {} 58 try { 59 aa.set(index, 1); 60 shouldThrow(); 61 } catch (IndexOutOfBoundsException success) {} 62 try { 63 aa.lazySet(index, 1); 64 shouldThrow(); 65 } catch (IndexOutOfBoundsException success) {} 66 try { 67 aa.compareAndSet(index, 1, 2); 68 shouldThrow(); 69 } catch (IndexOutOfBoundsException success) {} 70 try { 71 aa.weakCompareAndSet(index, 1, 2); 72 shouldThrow(); 73 } catch (IndexOutOfBoundsException success) {} 74 try { 75 aa.getAndAdd(index, 1); 76 shouldThrow(); 77 } catch (IndexOutOfBoundsException success) {} 78 try { 79 aa.addAndGet(index, 1); 80 shouldThrow(); 81 } catch (IndexOutOfBoundsException success) {} 82 } 83 } 84 85 /** 86 * get returns the last value set at index 87 */ testGetSet()88 public void testGetSet() { 89 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 90 for (int i = 0; i < SIZE; i++) { 91 aa.set(i, 1); 92 assertEquals(1, aa.get(i)); 93 aa.set(i, 2); 94 assertEquals(2, aa.get(i)); 95 aa.set(i, -3); 96 assertEquals(-3, aa.get(i)); 97 } 98 } 99 100 /** 101 * get returns the last value lazySet at index by same thread 102 */ testGetLazySet()103 public void testGetLazySet() { 104 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 105 for (int i = 0; i < SIZE; i++) { 106 aa.lazySet(i, 1); 107 assertEquals(1, aa.get(i)); 108 aa.lazySet(i, 2); 109 assertEquals(2, aa.get(i)); 110 aa.lazySet(i, -3); 111 assertEquals(-3, aa.get(i)); 112 } 113 } 114 115 /** 116 * compareAndSet succeeds in changing value if equal to expected else fails 117 */ testCompareAndSet()118 public void testCompareAndSet() { 119 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 120 for (int i = 0; i < SIZE; i++) { 121 aa.set(i, 1); 122 assertTrue(aa.compareAndSet(i, 1, 2)); 123 assertTrue(aa.compareAndSet(i, 2, -4)); 124 assertEquals(-4, aa.get(i)); 125 assertFalse(aa.compareAndSet(i, -5, 7)); 126 assertEquals(-4, aa.get(i)); 127 assertTrue(aa.compareAndSet(i, -4, 7)); 128 assertEquals(7, aa.get(i)); 129 } 130 } 131 132 /** 133 * compareAndSet in one thread enables another waiting for value 134 * to succeed 135 */ testCompareAndSetInMultipleThreads()136 public void testCompareAndSetInMultipleThreads() throws Exception { 137 final AtomicIntegerArray a = new AtomicIntegerArray(1); 138 a.set(0, 1); 139 Thread t = new Thread(new CheckedRunnable() { 140 public void realRun() { 141 while (!a.compareAndSet(0, 2, 3)) 142 Thread.yield(); 143 }}); 144 145 t.start(); 146 assertTrue(a.compareAndSet(0, 1, 2)); 147 t.join(LONG_DELAY_MS); 148 assertFalse(t.isAlive()); 149 assertEquals(3, a.get(0)); 150 } 151 152 /** 153 * repeated weakCompareAndSet succeeds in changing value when equal 154 * to expected 155 */ testWeakCompareAndSet()156 public void testWeakCompareAndSet() { 157 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 158 for (int i = 0; i < SIZE; i++) { 159 aa.set(i, 1); 160 while (!aa.weakCompareAndSet(i, 1, 2)); 161 while (!aa.weakCompareAndSet(i, 2, -4)); 162 assertEquals(-4, aa.get(i)); 163 while (!aa.weakCompareAndSet(i, -4, 7)); 164 assertEquals(7, aa.get(i)); 165 } 166 } 167 168 /** 169 * getAndSet returns previous value and sets to given value at given index 170 */ testGetAndSet()171 public void testGetAndSet() { 172 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 173 for (int i = 0; i < SIZE; i++) { 174 aa.set(i, 1); 175 assertEquals(1, aa.getAndSet(i, 0)); 176 assertEquals(0, aa.getAndSet(i, -10)); 177 assertEquals(-10, aa.getAndSet(i, 1)); 178 } 179 } 180 181 /** 182 * getAndAdd returns previous value and adds given value 183 */ testGetAndAdd()184 public void testGetAndAdd() { 185 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 186 for (int i = 0; i < SIZE; i++) { 187 aa.set(i, 1); 188 assertEquals(1, aa.getAndAdd(i, 2)); 189 assertEquals(3, aa.get(i)); 190 assertEquals(3, aa.getAndAdd(i, -4)); 191 assertEquals(-1, aa.get(i)); 192 } 193 } 194 195 /** 196 * getAndDecrement returns previous value and decrements 197 */ testGetAndDecrement()198 public void testGetAndDecrement() { 199 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 200 for (int i = 0; i < SIZE; i++) { 201 aa.set(i, 1); 202 assertEquals(1, aa.getAndDecrement(i)); 203 assertEquals(0, aa.getAndDecrement(i)); 204 assertEquals(-1, aa.getAndDecrement(i)); 205 } 206 } 207 208 /** 209 * getAndIncrement returns previous value and increments 210 */ testGetAndIncrement()211 public void testGetAndIncrement() { 212 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 213 for (int i = 0; i < SIZE; i++) { 214 aa.set(i, 1); 215 assertEquals(1, aa.getAndIncrement(i)); 216 assertEquals(2, aa.get(i)); 217 aa.set(i, -2); 218 assertEquals(-2, aa.getAndIncrement(i)); 219 assertEquals(-1, aa.getAndIncrement(i)); 220 assertEquals(0, aa.getAndIncrement(i)); 221 assertEquals(1, aa.get(i)); 222 } 223 } 224 225 /** 226 * addAndGet adds given value to current, and returns current value 227 */ testAddAndGet()228 public void testAddAndGet() { 229 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 230 for (int i = 0; i < SIZE; i++) { 231 aa.set(i, 1); 232 assertEquals(3, aa.addAndGet(i, 2)); 233 assertEquals(3, aa.get(i)); 234 assertEquals(-1, aa.addAndGet(i, -4)); 235 assertEquals(-1, aa.get(i)); 236 } 237 } 238 239 /** 240 * decrementAndGet decrements and returns current value 241 */ testDecrementAndGet()242 public void testDecrementAndGet() { 243 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 244 for (int i = 0; i < SIZE; i++) { 245 aa.set(i, 1); 246 assertEquals(0, aa.decrementAndGet(i)); 247 assertEquals(-1, aa.decrementAndGet(i)); 248 assertEquals(-2, aa.decrementAndGet(i)); 249 assertEquals(-2, aa.get(i)); 250 } 251 } 252 253 /** 254 * incrementAndGet increments and returns current value 255 */ testIncrementAndGet()256 public void testIncrementAndGet() { 257 AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 258 for (int i = 0; i < SIZE; i++) { 259 aa.set(i, 1); 260 assertEquals(2, aa.incrementAndGet(i)); 261 assertEquals(2, aa.get(i)); 262 aa.set(i, -2); 263 assertEquals(-1, aa.incrementAndGet(i)); 264 assertEquals(0, aa.incrementAndGet(i)); 265 assertEquals(1, aa.incrementAndGet(i)); 266 assertEquals(1, aa.get(i)); 267 } 268 } 269 270 static final int COUNTDOWN = 100000; 271 272 class Counter extends CheckedRunnable { 273 final AtomicIntegerArray aa; 274 volatile int counts; Counter(AtomicIntegerArray a)275 Counter(AtomicIntegerArray a) { aa = a; } realRun()276 public void realRun() { 277 for (;;) { 278 boolean done = true; 279 for (int i = 0; i < aa.length(); i++) { 280 int v = aa.get(i); 281 assertTrue(v >= 0); 282 if (v != 0) { 283 done = false; 284 if (aa.compareAndSet(i, v, v-1)) 285 ++counts; 286 } 287 } 288 if (done) 289 break; 290 } 291 } 292 } 293 294 /** 295 * Multiple threads using same array of counters successfully 296 * update a number of times equal to total count 297 */ testCountingInMultipleThreads()298 public void testCountingInMultipleThreads() throws InterruptedException { 299 final AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); 300 for (int i = 0; i < SIZE; i++) 301 aa.set(i, COUNTDOWN); 302 Counter c1 = new Counter(aa); 303 Counter c2 = new Counter(aa); 304 Thread t1 = new Thread(c1); 305 Thread t2 = new Thread(c2); 306 t1.start(); 307 t2.start(); 308 t1.join(); 309 t2.join(); 310 assertEquals(c1.counts+c2.counts, SIZE * COUNTDOWN); 311 } 312 313 /** 314 * a deserialized serialized array holds same values 315 */ testSerialization()316 public void testSerialization() throws Exception { 317 AtomicIntegerArray x = new AtomicIntegerArray(SIZE); 318 for (int i = 0; i < SIZE; i++) 319 x.set(i, -i); 320 AtomicIntegerArray y = serialClone(x); 321 assertNotSame(x, y); 322 assertEquals(x.length(), y.length()); 323 for (int i = 0; i < SIZE; i++) { 324 assertEquals(x.get(i), y.get(i)); 325 } 326 } 327 328 /** 329 * toString returns current value. 330 */ testToString()331 public void testToString() { 332 int[] a = { 17, 3, -42, 99, -7 }; 333 AtomicIntegerArray aa = new AtomicIntegerArray(a); 334 assertEquals(Arrays.toString(a), aa.toString()); 335 } 336 337 } 338