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.AtomicLongArray;
     13 
     14 import junit.framework.Test;
     15 import junit.framework.TestSuite;
     16 
     17 public class AtomicLongArrayTest 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(AtomicLongArrayTest.class);
     26     // }
     27 
     28     /**
     29      * constructor creates array of given size with all elements zero
     30      */
     31     public void testConstructor() {
     32         AtomicLongArray aa = new AtomicLongArray(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             long[] a = null;
     43             new AtomicLongArray(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         long[] a = { 17L, 3L, -42L, 99L, -7L };
     53         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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 InterruptedException {
    148         final AtomicLongArray a = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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         AtomicLongArray aa = new AtomicLongArray(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 AtomicLongArray aa;
    283         volatile long counts;
    284         Counter(AtomicLongArray a) { aa = a; }
    285         public void realRun() {
    286             for (;;) {
    287                 boolean done = true;
    288                 for (int i = 0; i < aa.length(); i++) {
    289                     long 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 AtomicLongArray aa = new AtomicLongArray(SIZE);
    309         long 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         AtomicLongArray x = new AtomicLongArray(SIZE);
    328         for (int i = 0; i < SIZE; i++)
    329             x.set(i, -i);
    330         AtomicLongArray 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         long[] a = { 17, 3, -42, 99, -7 };
    343         AtomicLongArray aa = new AtomicLongArray(a);
    344         assertEquals(Arrays.toString(a), aa.toString());
    345     }
    346 
    347 }
    348