Home | History | Annotate | Download | only in jsr166
      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