1 /*
   2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  */
  22 
  23 /*
  24  * This file is available under and governed by the GNU General Public
  25  * License version 2 only, as published by the Free Software Foundation.
  26  * However, the following notice accompanied the original version of this
  27  * file:
  28  *
  29  * Written by Doug Lea with assistance from members of JCP JSR-166
  30  * Expert Group and released to the public domain, as explained at
  31  * http://creativecommons.org/publicdomain/zero/1.0/
  32  * Other contributors include Andrew Wright, Jeffrey Hayes,
  33  * Pat Fisher, Mike Judd.
  34  */
  35 
  36 import java.util.concurrent.atomic.AtomicLongFieldUpdater;
  37 
  38 import junit.framework.Test;
  39 import junit.framework.TestSuite;
  40 
  41 public class AtomicLongFieldUpdaterTest extends JSR166TestCase {
  42     volatile long x = 0;
  43     protected volatile long protectedField;
  44     private volatile long privateField;
  45     long w;
  46     float z;
  47     public static void main(String[] args) {
  48         main(suite(), args);
  49     }
  50     public static Test suite() {
  51         return new TestSuite(AtomicLongFieldUpdaterTest.class);
  52     }
  53 
  54     // for testing subclass access
  55     static class AtomicLongFieldUpdaterTestSubclass extends AtomicLongFieldUpdaterTest {
  56         public void checkPrivateAccess() {
  57             try {
  58                 AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
  59                     AtomicLongFieldUpdater.newUpdater
  60                     (AtomicLongFieldUpdaterTest.class, "privateField");
  61                 shouldThrow();
  62             } catch (RuntimeException success) {
  63                 assertNotNull(success.getCause());
  64             }
  65         }
  66 
  67         public void checkCompareAndSetProtectedSub() {
  68             AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
  69                 AtomicLongFieldUpdater.newUpdater
  70                 (AtomicLongFieldUpdaterTest.class, "protectedField");
  71             this.protectedField = 1;
  72             assertTrue(a.compareAndSet(this, 1, 2));
  73             assertTrue(a.compareAndSet(this, 2, -4));
  74             assertEquals(-4, a.get(this));
  75             assertFalse(a.compareAndSet(this, -5, 7));
  76             assertEquals(-4, a.get(this));
  77             assertTrue(a.compareAndSet(this, -4, 7));
  78             assertEquals(7, a.get(this));
  79         }
  80     }
  81 
  82     static class UnrelatedClass {
  83         public void checkPackageAccess(AtomicLongFieldUpdaterTest obj) {
  84             obj.x = 72L;
  85             AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
  86                 AtomicLongFieldUpdater.newUpdater
  87                 (AtomicLongFieldUpdaterTest.class, "x");
  88             assertEquals(72L, a.get(obj));
  89             assertTrue(a.compareAndSet(obj, 72L, 73L));
  90             assertEquals(73L, a.get(obj));
  91         }
  92 
  93         public void checkPrivateAccess(AtomicLongFieldUpdaterTest obj) {
  94             try {
  95                 AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a =
  96                     AtomicLongFieldUpdater.newUpdater
  97                     (AtomicLongFieldUpdaterTest.class, "privateField");
  98                 throw new AssertionError("should throw");
  99             } catch (RuntimeException success) {
 100                 assertNotNull(success.getCause());
 101             }
 102         }
 103     }
 104 
 105     AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> updaterFor(String fieldName) {
 106         return AtomicLongFieldUpdater.newUpdater
 107             (AtomicLongFieldUpdaterTest.class, fieldName);
 108     }
 109 
 110     /**
 111      * Construction with non-existent field throws RuntimeException
 112      */
 113     public void testConstructor() {
 114         try {
 115             updaterFor("y");
 116             shouldThrow();
 117         } catch (RuntimeException success) {
 118             assertNotNull(success.getCause());
 119         }
 120     }
 121 
 122     /**
 123      * construction with field not of given type throws IllegalArgumentException
 124      */
 125     public void testConstructor2() {
 126         try {
 127             updaterFor("z");
 128             shouldThrow();
 129         } catch (IllegalArgumentException success) {}
 130     }
 131 
 132     /**
 133      * construction with non-volatile field throws IllegalArgumentException
 134      */
 135     public void testConstructor3() {
 136         try {
 137             updaterFor("w");
 138             shouldThrow();
 139         } catch (IllegalArgumentException success) {}
 140     }
 141 
 142     /**
 143      * construction using private field from subclass throws RuntimeException
 144      */
 145     public void exclude_8187607_testPrivateFieldInSubclass() {
 146         AtomicLongFieldUpdaterTestSubclass s =
 147             new AtomicLongFieldUpdaterTestSubclass();
 148         s.checkPrivateAccess();
 149     }
 150 
 151     /**
 152      * construction from unrelated class; package access is allowed,
 153      * private access is not
 154      */
 155     public void exclude_8187607_testUnrelatedClassAccess() {
 156         new UnrelatedClass().checkPackageAccess(this);
 157         new UnrelatedClass().checkPrivateAccess(this);
 158     }
 159 
 160     /**
 161      * get returns the last value set or assigned
 162      */
 163     public void testGetSet() {
 164         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 165         a = updaterFor("x");
 166         x = 1;
 167         assertEquals(1, a.get(this));
 168         a.set(this, 2);
 169         assertEquals(2, a.get(this));
 170         a.set(this, -3);
 171         assertEquals(-3, a.get(this));
 172     }
 173 
 174     /**
 175      * get returns the last value lazySet by same thread
 176      */
 177     public void testGetLazySet() {
 178         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 179         a = updaterFor("x");
 180         x = 1;
 181         assertEquals(1, a.get(this));
 182         a.lazySet(this, 2);
 183         assertEquals(2, a.get(this));
 184         a.lazySet(this, -3);
 185         assertEquals(-3, a.get(this));
 186     }
 187 
 188     /**
 189      * compareAndSet succeeds in changing value if equal to expected else fails
 190      */
 191     public void testCompareAndSet() {
 192         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 193         a = updaterFor("x");
 194         x = 1;
 195         assertTrue(a.compareAndSet(this, 1, 2));
 196         assertTrue(a.compareAndSet(this, 2, -4));
 197         assertEquals(-4, a.get(this));
 198         assertFalse(a.compareAndSet(this, -5, 7));
 199         assertEquals(-4, a.get(this));
 200         assertTrue(a.compareAndSet(this, -4, 7));
 201         assertEquals(7, a.get(this));
 202     }
 203 
 204     /**
 205      * compareAndSet succeeds in changing protected field value if
 206      * equal to expected else fails
 207      */
 208     public void testCompareAndSetProtected() {
 209         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 210         a = updaterFor("protectedField");
 211         protectedField = 1;
 212         assertTrue(a.compareAndSet(this, 1, 2));
 213         assertTrue(a.compareAndSet(this, 2, -4));
 214         assertEquals(-4, a.get(this));
 215         assertFalse(a.compareAndSet(this, -5, 7));
 216         assertEquals(-4, a.get(this));
 217         assertTrue(a.compareAndSet(this, -4, 7));
 218         assertEquals(7, a.get(this));
 219     }
 220 
 221     /**
 222      * compareAndSet succeeds in changing protected field value if
 223      * equal to expected else fails
 224      */
 225     public void testCompareAndSetProtectedInSubclass() {
 226         AtomicLongFieldUpdaterTestSubclass s =
 227             new AtomicLongFieldUpdaterTestSubclass();
 228         s.checkCompareAndSetProtectedSub();
 229     }
 230 
 231     /**
 232      * compareAndSet in one thread enables another waiting for value
 233      * to succeed
 234      */
 235     public void testCompareAndSetInMultipleThreads() throws Exception {
 236         x = 1;
 237         final AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 238         a = updaterFor("x");
 239 
 240         Thread t = new Thread(new CheckedRunnable() {
 241             public void realRun() {
 242                 while (!a.compareAndSet(AtomicLongFieldUpdaterTest.this, 2, 3))
 243                     Thread.yield();
 244             }});
 245 
 246         t.start();
 247         assertTrue(a.compareAndSet(this, 1, 2));
 248         t.join(LONG_DELAY_MS);
 249         assertFalse(t.isAlive());
 250         assertEquals(3, a.get(this));
 251     }
 252 
 253     /**
 254      * repeated weakCompareAndSet succeeds in changing value when equal
 255      * to expected
 256      */
 257     public void testWeakCompareAndSet() {
 258         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 259         a = updaterFor("x");
 260         x = 1;
 261         do {} while (!a.weakCompareAndSet(this, 1, 2));
 262         do {} while (!a.weakCompareAndSet(this, 2, -4));
 263         assertEquals(-4, a.get(this));
 264         do {} while (!a.weakCompareAndSet(this, -4, 7));
 265         assertEquals(7, a.get(this));
 266     }
 267 
 268     /**
 269      * getAndSet returns previous value and sets to given value
 270      */
 271     public void testGetAndSet() {
 272         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 273         a = updaterFor("x");
 274         x = 1;
 275         assertEquals(1, a.getAndSet(this, 0));
 276         assertEquals(0, a.getAndSet(this, -10));
 277         assertEquals(-10, a.getAndSet(this, 1));
 278     }
 279 
 280     /**
 281      * getAndAdd returns previous value and adds given value
 282      */
 283     public void testGetAndAdd() {
 284         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 285         a = updaterFor("x");
 286         x = 1;
 287         assertEquals(1, a.getAndAdd(this, 2));
 288         assertEquals(3, a.get(this));
 289         assertEquals(3, a.getAndAdd(this, -4));
 290         assertEquals(-1, a.get(this));
 291     }
 292 
 293     /**
 294      * getAndDecrement returns previous value and decrements
 295      */
 296     public void testGetAndDecrement() {
 297         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 298         a = updaterFor("x");
 299         x = 1;
 300         assertEquals(1, a.getAndDecrement(this));
 301         assertEquals(0, a.getAndDecrement(this));
 302         assertEquals(-1, a.getAndDecrement(this));
 303     }
 304 
 305     /**
 306      * getAndIncrement returns previous value and increments
 307      */
 308     public void testGetAndIncrement() {
 309         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 310         a = updaterFor("x");
 311         x = 1;
 312         assertEquals(1, a.getAndIncrement(this));
 313         assertEquals(2, a.get(this));
 314         a.set(this, -2);
 315         assertEquals(-2, a.getAndIncrement(this));
 316         assertEquals(-1, a.getAndIncrement(this));
 317         assertEquals(0, a.getAndIncrement(this));
 318         assertEquals(1, a.get(this));
 319     }
 320 
 321     /**
 322      * addAndGet adds given value to current, and returns current value
 323      */
 324     public void testAddAndGet() {
 325         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 326         a = updaterFor("x");
 327         x = 1;
 328         assertEquals(3, a.addAndGet(this, 2));
 329         assertEquals(3, a.get(this));
 330         assertEquals(-1, a.addAndGet(this, -4));
 331         assertEquals(-1, a.get(this));
 332     }
 333 
 334     /**
 335      * decrementAndGet decrements and returns current value
 336      */
 337     public void testDecrementAndGet() {
 338         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 339         a = updaterFor("x");
 340         x = 1;
 341         assertEquals(0, a.decrementAndGet(this));
 342         assertEquals(-1, a.decrementAndGet(this));
 343         assertEquals(-2, a.decrementAndGet(this));
 344         assertEquals(-2, a.get(this));
 345     }
 346 
 347     /**
 348      * incrementAndGet increments and returns current value
 349      */
 350     public void testIncrementAndGet() {
 351         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
 352         a = updaterFor("x");
 353         x = 1;
 354         assertEquals(2, a.incrementAndGet(this));
 355         assertEquals(2, a.get(this));
 356         a.set(this, -2);
 357         assertEquals(-1, a.incrementAndGet(this));
 358         assertEquals(0, a.incrementAndGet(this));
 359         assertEquals(1, a.incrementAndGet(this));
 360         assertEquals(1, a.get(this));
 361     }
 362 
 363 }