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