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