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.concurrent.atomic.AtomicReferenceFieldUpdater;
     12 
     13 import junit.framework.Test;
     14 import junit.framework.TestSuite;
     15 
     16 public class AtomicReferenceFieldUpdaterTest extends JSR166TestCase {
     17     volatile Integer x = null;
     18     protected volatile Integer protectedField;
     19     private volatile Integer privateField;
     20     Object z;
     21     Integer w;
     22     volatile int i;
     23 
     24     // android-note: Removed because the CTS runner does a bad job of
     25     // retrying tests that have suite() declarations.
     26     //
     27     // public static void main(String[] args) {
     28     //     main(suite(), args);
     29     // }
     30     // public static Test suite() {
     31     //     return new TestSuite(AtomicReferenceFieldUpdaterTest.class);
     32     // }
     33 
     34     // for testing subclass access
     35     // android-note: Removed because android doesn't restrict reflection access
     36     // static class AtomicReferenceFieldUpdaterTestSubclass extends AtomicReferenceFieldUpdaterTest {
     37     //     public void checkPrivateAccess() {
     38     //         try {
     39     //             AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
     40     //                 AtomicReferenceFieldUpdater.newUpdater
     41     //                 (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField");
     42     //             shouldThrow();
     43     //         } catch (RuntimeException success) {
     44     //             assertNotNull(success.getCause());
     45     //         }
     46     //     }
     47 
     48     //     public void checkCompareAndSetProtectedSub() {
     49     //         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
     50     //             AtomicReferenceFieldUpdater.newUpdater
     51     //             (AtomicReferenceFieldUpdaterTest.class, Integer.class, "protectedField");
     52     //         this.protectedField = one;
     53     //         assertTrue(a.compareAndSet(this, one, two));
     54     //         assertTrue(a.compareAndSet(this, two, m4));
     55     //         assertSame(m4, a.get(this));
     56     //         assertFalse(a.compareAndSet(this, m5, seven));
     57     //         assertFalse(seven == a.get(this));
     58     //         assertTrue(a.compareAndSet(this, m4, seven));
     59     //         assertSame(seven, a.get(this));
     60     //     }
     61     // }
     62 
     63     // static class UnrelatedClass {
     64     //     public void checkPackageAccess(AtomicReferenceFieldUpdaterTest obj) {
     65     //         obj.x = one;
     66     //         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
     67     //             AtomicReferenceFieldUpdater.newUpdater
     68     //             (AtomicReferenceFieldUpdaterTest.class, Integer.class, "x");
     69     //         assertSame(one, a.get(obj));
     70     //         assertTrue(a.compareAndSet(obj, one, two));
     71     //         assertSame(two, a.get(obj));
     72     //     }
     73 
     74     //     public void checkPrivateAccess(AtomicReferenceFieldUpdaterTest obj) {
     75     //         try {
     76     //             AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest,Integer> a =
     77     //                 AtomicReferenceFieldUpdater.newUpdater
     78     //                 (AtomicReferenceFieldUpdaterTest.class, Integer.class, "privateField");
     79     //             throw new AssertionError("should throw");
     80     //         } catch (RuntimeException success) {
     81     //             assertNotNull(success.getCause());
     82     //         }
     83     //     }
     84     // }
     85 
     86     static AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> updaterFor(String fieldName) {
     87         return AtomicReferenceFieldUpdater.newUpdater
     88             (AtomicReferenceFieldUpdaterTest.class, Integer.class, fieldName);
     89     }
     90 
     91     /**
     92      * Construction with non-existent field throws RuntimeException
     93      */
     94     public void testConstructor() {
     95         try {
     96             updaterFor("y");
     97             shouldThrow();
     98         } catch (RuntimeException success) {
     99             assertNotNull(success.getCause());
    100         }
    101     }
    102 
    103     /**
    104      * construction with field not of given type throws ClassCastException
    105      */
    106     public void testConstructor2() {
    107         try {
    108             updaterFor("z");
    109             shouldThrow();
    110         } catch (ClassCastException success) {}
    111     }
    112 
    113     /**
    114      * Constructor with non-volatile field throws IllegalArgumentException
    115      */
    116     public void testConstructor3() {
    117         try {
    118             updaterFor("w");
    119             shouldThrow();
    120         } catch (IllegalArgumentException success) {}
    121     }
    122 
    123     /**
    124      * Constructor with non-reference field throws ClassCastException
    125      */
    126     public void testConstructor4() {
    127         try {
    128             updaterFor("i");
    129             shouldThrow();
    130         } catch (ClassCastException success) {}
    131     }
    132 
    133     /**
    134      * construction using private field from subclass throws RuntimeException
    135      */
    136     // android-note: Removed because android doesn't restrict reflection access
    137     // public void testPrivateFieldInSubclass() {
    138     //     AtomicReferenceFieldUpdaterTestSubclass s =
    139     //         new AtomicReferenceFieldUpdaterTestSubclass();
    140     //     s.checkPrivateAccess();
    141     // }
    142 
    143     /**
    144      * construction from unrelated class; package access is allowed,
    145      * private access is not
    146      */
    147     // android-note: Removed because android doesn't restrict reflection access
    148     // public void testUnrelatedClassAccess() {
    149     //     new UnrelatedClass().checkPackageAccess(this);
    150     //     new UnrelatedClass().checkPrivateAccess(this);
    151     // }
    152 
    153     /**
    154      * get returns the last value set or assigned
    155      */
    156     public void testGetSet() {
    157         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
    158         a = updaterFor("x");
    159         x = one;
    160         assertSame(one, a.get(this));
    161         a.set(this, two);
    162         assertSame(two, a.get(this));
    163         a.set(this, m3);
    164         assertSame(m3, a.get(this));
    165     }
    166 
    167     /**
    168      * get returns the last value lazySet by same thread
    169      */
    170     public void testGetLazySet() {
    171         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
    172         a = updaterFor("x");
    173         x = one;
    174         assertSame(one, a.get(this));
    175         a.lazySet(this, two);
    176         assertSame(two, a.get(this));
    177         a.lazySet(this, m3);
    178         assertSame(m3, a.get(this));
    179     }
    180 
    181     /**
    182      * compareAndSet succeeds in changing value if equal to expected else fails
    183      */
    184     public void testCompareAndSet() {
    185         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
    186         a = updaterFor("x");
    187         x = one;
    188         assertTrue(a.compareAndSet(this, one, two));
    189         assertTrue(a.compareAndSet(this, two, m4));
    190         assertSame(m4, a.get(this));
    191         assertFalse(a.compareAndSet(this, m5, seven));
    192         assertFalse(seven == a.get(this));
    193         assertTrue(a.compareAndSet(this, m4, seven));
    194         assertSame(seven, a.get(this));
    195     }
    196 
    197     /**
    198      * compareAndSet in one thread enables another waiting for value
    199      * to succeed
    200      */
    201     public void testCompareAndSetInMultipleThreads() throws Exception {
    202         x = one;
    203         final AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
    204         a = updaterFor("x");
    205 
    206         Thread t = new Thread(new CheckedRunnable() {
    207             public void realRun() {
    208                 while (!a.compareAndSet(AtomicReferenceFieldUpdaterTest.this, two, three))
    209                     Thread.yield();
    210             }});
    211 
    212         t.start();
    213         assertTrue(a.compareAndSet(this, one, two));
    214         t.join(LONG_DELAY_MS);
    215         assertFalse(t.isAlive());
    216         assertSame(three, a.get(this));
    217     }
    218 
    219     /**
    220      * repeated weakCompareAndSet succeeds in changing value when equal
    221      * to expected
    222      */
    223     public void testWeakCompareAndSet() {
    224         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
    225         a = updaterFor("x");
    226         x = one;
    227         do {} while (!a.weakCompareAndSet(this, one, two));
    228         do {} while (!a.weakCompareAndSet(this, two, m4));
    229         assertSame(m4, a.get(this));
    230         do {} while (!a.weakCompareAndSet(this, m4, seven));
    231         assertSame(seven, a.get(this));
    232     }
    233 
    234     /**
    235      * getAndSet returns previous value and sets to given value
    236      */
    237     public void testGetAndSet() {
    238         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
    239         a = updaterFor("x");
    240         x = one;
    241         assertSame(one, a.getAndSet(this, zero));
    242         assertSame(zero, a.getAndSet(this, m10));
    243         assertSame(m10, a.getAndSet(this, 1));
    244     }
    245 
    246 }
    247