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.Arrays;
37 import java.util.concurrent.atomic.AtomicReferenceArray;
38 
39 import junit.framework.Test;
40 import junit.framework.TestSuite;
41 
42 public class AtomicReferenceArrayTest extends JSR166TestCase {
main(String[] args)43     public static void main(String[] args) {
44         main(suite(), args);
45     }
suite()46     public static Test suite() {
47         return new TestSuite(AtomicReferenceArrayTest.class);
48     }
49 
50     /**
51      * constructor creates array of given size with all elements null
52      */
testConstructor()53     public void testConstructor() {
54         AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
55         for (int i = 0; i < SIZE; i++) {
56             assertNull(aa.get(i));
57         }
58     }
59 
60     /**
61      * constructor with null array throws NPE
62      */
testConstructor2NPE()63     public void testConstructor2NPE() {
64         try {
65             Integer[] a = null;
66             new AtomicReferenceArray<Integer>(a);
67             shouldThrow();
68         } catch (NullPointerException success) {}
69     }
70 
71     /**
72      * constructor with array is of same size and has all elements
73      */
testConstructor2()74     public void testConstructor2() {
75         Integer[] a = { two, one, three, four, seven };
76         AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(a);
77         assertEquals(a.length, aa.length());
78         for (int i = 0; i < a.length; i++)
79             assertEquals(a[i], aa.get(i));
80     }
81 
82     /**
83      * Initialize AtomicReferenceArray<Class> with SubClass[]
84      */
testConstructorSubClassArray()85     public void testConstructorSubClassArray() {
86         Integer[] a = { two, one, three, four, seven };
87         AtomicReferenceArray<Number> aa = new AtomicReferenceArray<>(a);
88         assertEquals(a.length, aa.length());
89         for (int i = 0; i < a.length; i++) {
90             assertSame(a[i], aa.get(i));
91             Long x = Long.valueOf(i);
92             aa.set(i, x);
93             assertSame(x, aa.get(i));
94         }
95     }
96 
97     /**
98      * get and set for out of bound indices throw IndexOutOfBoundsException
99      */
testIndexing()100     public void testIndexing() {
101         AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
102         for (int index : new int[] { -1, SIZE }) {
103             try {
104                 aa.get(index);
105                 shouldThrow();
106             } catch (IndexOutOfBoundsException success) {}
107             try {
108                 aa.set(index, null);
109                 shouldThrow();
110             } catch (IndexOutOfBoundsException success) {}
111             try {
112                 aa.lazySet(index, null);
113                 shouldThrow();
114             } catch (IndexOutOfBoundsException success) {}
115             try {
116                 aa.compareAndSet(index, null, null);
117                 shouldThrow();
118             } catch (IndexOutOfBoundsException success) {}
119             try {
120                 aa.weakCompareAndSet(index, null, null);
121                 shouldThrow();
122             } catch (IndexOutOfBoundsException success) {}
123         }
124     }
125 
126     /**
127      * get returns the last value set at index
128      */
testGetSet()129     public void testGetSet() {
130         AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
131         for (int i = 0; i < SIZE; i++) {
132             aa.set(i, one);
133             assertSame(one, aa.get(i));
134             aa.set(i, two);
135             assertSame(two, aa.get(i));
136             aa.set(i, m3);
137             assertSame(m3, aa.get(i));
138         }
139     }
140 
141     /**
142      * get returns the last value lazySet at index by same thread
143      */
testGetLazySet()144     public void testGetLazySet() {
145         AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
146         for (int i = 0; i < SIZE; i++) {
147             aa.lazySet(i, one);
148             assertSame(one, aa.get(i));
149             aa.lazySet(i, two);
150             assertSame(two, aa.get(i));
151             aa.lazySet(i, m3);
152             assertSame(m3, aa.get(i));
153         }
154     }
155 
156     /**
157      * compareAndSet succeeds in changing value if equal to expected else fails
158      */
testCompareAndSet()159     public void testCompareAndSet() {
160         AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
161         for (int i = 0; i < SIZE; i++) {
162             aa.set(i, one);
163             assertTrue(aa.compareAndSet(i, one, two));
164             assertTrue(aa.compareAndSet(i, two, m4));
165             assertSame(m4, aa.get(i));
166             assertFalse(aa.compareAndSet(i, m5, seven));
167             assertSame(m4, aa.get(i));
168             assertTrue(aa.compareAndSet(i, m4, seven));
169             assertSame(seven, aa.get(i));
170         }
171     }
172 
173     /**
174      * compareAndSet in one thread enables another waiting for value
175      * to succeed
176      */
testCompareAndSetInMultipleThreads()177     public void testCompareAndSetInMultipleThreads() throws InterruptedException {
178         final AtomicReferenceArray a = new AtomicReferenceArray(1);
179         a.set(0, one);
180         Thread t = new Thread(new CheckedRunnable() {
181             public void realRun() {
182                 while (!a.compareAndSet(0, two, three))
183                     Thread.yield();
184             }});
185 
186         t.start();
187         assertTrue(a.compareAndSet(0, one, two));
188         t.join(LONG_DELAY_MS);
189         assertFalse(t.isAlive());
190         assertSame(three, a.get(0));
191     }
192 
193     /**
194      * repeated weakCompareAndSet succeeds in changing value when equal
195      * to expected
196      */
testWeakCompareAndSet()197     public void testWeakCompareAndSet() {
198         AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
199         for (int i = 0; i < SIZE; i++) {
200             aa.set(i, one);
201             do {} while (!aa.weakCompareAndSet(i, one, two));
202             do {} while (!aa.weakCompareAndSet(i, two, m4));
203             assertSame(m4, aa.get(i));
204             do {} while (!aa.weakCompareAndSet(i, m4, seven));
205             assertSame(seven, aa.get(i));
206         }
207     }
208 
209     /**
210      * getAndSet returns previous value and sets to given value at given index
211      */
testGetAndSet()212     public void testGetAndSet() {
213         AtomicReferenceArray aa = new AtomicReferenceArray(SIZE);
214         for (int i = 0; i < SIZE; i++) {
215             aa.set(i, one);
216             assertSame(one, aa.getAndSet(i, zero));
217             assertSame(zero, aa.getAndSet(i, m10));
218             assertSame(m10, aa.getAndSet(i, one));
219         }
220     }
221 
222     /**
223      * a deserialized/reserialized array holds same values in same order
224      */
testSerialization()225     public void testSerialization() throws Exception {
226         AtomicReferenceArray x = new AtomicReferenceArray(SIZE);
227         for (int i = 0; i < SIZE; i++) {
228             x.set(i, new Integer(-i));
229         }
230         AtomicReferenceArray y = serialClone(x);
231         assertNotSame(x, y);
232         assertEquals(x.length(), y.length());
233         for (int i = 0; i < SIZE; i++) {
234             assertEquals(x.get(i), y.get(i));
235         }
236     }
237 
238     /**
239      * toString returns current value.
240      */
testToString()241     public void testToString() {
242         Integer[] a = { two, one, three, four, seven };
243         AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(a);
244         assertEquals(Arrays.toString(a), aa.toString());
245     }
246 
247 }
248