1   package com.atlassian.util.concurrent.atomic;
2   
3   import static com.google.common.base.Suppliers.ofInstance;
4   import static org.junit.Assert.assertEquals;
5   
6   import org.junit.Test;
7   
8   import com.google.common.base.Supplier;
9   
10  import java.util.concurrent.atomic.AtomicBoolean;
11  import java.util.concurrent.atomic.AtomicInteger;
12  import java.util.concurrent.atomic.AtomicLong;
13  import java.util.concurrent.atomic.AtomicReference;
14  import java.util.concurrent.atomic.AtomicReferenceArray;
15  
16  public class AtomicsTest {
17  
18      //
19      // AtomicReference tests
20      //
21  
22      @Test
23      public void getAndSetIfNormal() {
24          final String from = "from";
25          final String to = "to";
26          final AtomicReference<String> ref = new AtomicReference<String>(from);
27          assertEquals(to, Atomics.getAndSetIf(ref, from, ofInstance(to)));
28      }
29  
30      @Test
31      public void getAndSetIfNormalValue() {
32          final String from = "from";
33          final String to = "to";
34          final AtomicReference<String> ref = new AtomicReference<String>(from);
35          assertEquals(to, Atomics.getAndSetIf(ref, from, to));
36      }
37  
38      @Test(expected = IllegalArgumentException.class)
39      public void getAndSetIfRefNPE() {
40          Atomics.getAndSetIf((AtomicReference<String>) null, "", ofInstance(""));
41      }
42  
43      @Test(expected = IllegalArgumentException.class)
44      public void getAndSetIfRefValueNPE() {
45          Atomics.getAndSetIf((AtomicReference<String>) null, "", "");
46      }
47  
48      @Test
49      public void getAndSetIfNull() {
50          final String to = "to";
51          final AtomicReference<String> ref = new AtomicReference<String>(null);
52          assertEquals(to, Atomics.getAndSetIfNull(ref, ofInstance(to)));
53      }
54  
55      @Test
56      public void getAndSetContended() {
57          final String from = "from";
58          final String to = "to";
59          final String different = "different";
60          final AtomicReference<String> ref = new AtomicReference<String>(from);
61          assertEquals(different, Atomics.getAndSetIf(ref, from, new Supplier<String>() {
62              public String get() {
63                  // being called, set the reference so the CAS fails
64                  ref.set(different);
65                  return to;
66              }
67          }));
68      }
69  
70      @Test
71      public void getAndSetReturnsOldValueIfChanged() {
72          final String old = "old";
73          final String from = "from";
74          final String to = "to";
75          final AtomicReference<String> ref = new AtomicReference<String>(old);
76          assertEquals(old, Atomics.getAndSetIf(ref, from, ofInstance(to)));
77      }
78  
79      @Test
80      public void getAndSetSameValue() {
81          final String from = "from";
82          final String to = from;
83          final AtomicReference<String> ref = new AtomicReference<String>(from);
84          assertEquals(to, Atomics.getAndSetIf(ref, from, ofInstance(to)));
85      }
86  
87      @Test
88      public void getAndSetSameValueDifferent() {
89          final String from = "from";
90          final String to = from;
91          final String different = "blah";
92          final AtomicReference<String> ref = new AtomicReference<String>(different);
93          assertEquals(different, Atomics.getAndSetIf(ref, from, ofInstance(to)));
94      }
95  
96      //
97      // AtomicReferenceArray tests
98      //
99  
100     @Test
101     public void getAndSetArrayIfNormal() {
102         final String from = "from";
103         final String to = "to";
104         final AtomicReferenceArray<String> ref = new AtomicReferenceArray<String>(new String[] { from });
105         assertEquals(to, Atomics.getAndSetIf(ref, 0, from, ofInstance(to)));
106     }
107 
108     @Test
109     public void getAndSetArrayIfNormalValue() {
110         final String from = "from";
111         final String to = "to";
112         final AtomicReferenceArray<String> ref = new AtomicReferenceArray<String>(new String[] { from });
113         assertEquals(to, Atomics.getAndSetIf(ref, 0, from, to));
114     }
115 
116     @Test
117     public void getAndSetArrayIfNormalSupplierValue() {
118         final String from = "from";
119         final String to = "to";
120         final AtomicReferenceArray<String> ref = new AtomicReferenceArray<String>(new String[] { from });
121         assertEquals(to, Atomics.getAndSetIf(ref, 0, from, ofInstance(to)));
122     }
123 
124     @Test(expected = IllegalArgumentException.class)
125     public void getAndSetIfArrayNPE() {
126         Atomics.getAndSetIf((AtomicReferenceArray<String>) null, 0, "", ofInstance(""));
127     }
128 
129     @Test(expected = IllegalArgumentException.class)
130     public void getAndSetIfArrayValueNPE() {
131         Atomics.getAndSetIf((AtomicReferenceArray<String>) null, 0, "", "");
132     }
133 
134     @Test
135     public void getAndSetArrayIfNull() {
136         final String to = "to";
137         final AtomicReferenceArray<String> ref = new AtomicReferenceArray<String>(new String[] { null });
138         assertEquals(to, Atomics.getAndSetIfNull(ref, 0, ofInstance(to)));
139     }
140 
141     @Test
142     public void getAndSetArrayContended() {
143         final String from = "from";
144         final String to = "to";
145         final String different = "different";
146         final AtomicReferenceArray<String> ref = new AtomicReferenceArray<String>(new String[] { from });
147         assertEquals(different, Atomics.getAndSetIf(ref, 0, from, new Supplier<String>() {
148             public String get() {
149                 // being called, set the reference so the CAS fails
150                 ref.set(0, different);
151                 return to;
152             }
153         }));
154     }
155 
156     @Test
157     public void getAndSetArrayReturnsOldValueIfChanged() {
158         final String old = "old";
159         final String from = "from";
160         final String to = "to";
161         final AtomicReferenceArray<String> ref = new AtomicReferenceArray<String>(new String[] { old });
162         assertEquals(old, Atomics.getAndSetIf(ref, 0, from, ofInstance(to)));
163     }
164 
165     @Test
166     public void getAndSetArraySameValue() {
167         final String from = "from";
168         final String to = from;
169         final AtomicReferenceArray<String> ref = new AtomicReferenceArray<String>(new String[] { from });
170         assertEquals(to, Atomics.getAndSetIf(ref, 0, from, ofInstance(to)));
171     }
172 
173     @Test
174     public void getAndSetArraySameValueDifferent() {
175         final String from = "from";
176         final String to = from;
177         final String different = "blah";
178         final AtomicReferenceArray<String> ref = new AtomicReferenceArray<String>(new String[] { different });
179         assertEquals(different, Atomics.getAndSetIf(ref, 0, from, ofInstance(to)));
180     }
181 
182     @Test(expected = IndexOutOfBoundsException.class)
183     public void getAndSetArrayThrowsIndexOutOfBounds() {
184         Atomics.getAndSetIf(new AtomicReferenceArray<String>(new String[0]), 0, "test", ofInstance("blah"));
185     }
186 
187     //
188     // AtomicLong tests
189     //
190 
191     @Test
192     public void getAndSetLongIfNormal() {
193         final long from = 1;
194         final long to = 2;
195         final AtomicLong ref = new AtomicLong(from);
196         assertEquals(to, Atomics.getAndSetIf(ref, from, to));
197     }
198 
199     @Test(expected = IllegalArgumentException.class)
200     public void getAndSetIfLongNPE() {
201         Atomics.getAndSetIf((AtomicLong) null, 0, 0);
202     }
203 
204     @Test
205     public void getAndSetLongReturnsOldValueIfChanged() {
206         final long old = 1;
207         final long from = 2;
208         final long to = 3;
209         final AtomicLong ref = new AtomicLong(old);
210         assertEquals(old, Atomics.getAndSetIf(ref, from, to));
211     }
212 
213     @Test
214     public void getAndSetLongSameValue() {
215         final long from = 1;
216         final long to = from;
217         final AtomicLong ref = new AtomicLong(from);
218         assertEquals(to, Atomics.getAndSetIf(ref, from, to));
219     }
220 
221     @Test
222     public void getAndSetLongSameValueDifferent() {
223         final long from = 1;
224         final long to = from;
225         final int different = 3;
226         final AtomicLong ref = new AtomicLong(different);
227         assertEquals(different, Atomics.getAndSetIf(ref, from, to));
228     }
229 
230     //
231     // AtomicInteger tests
232     //
233 
234     @Test
235     public void getAndSetIntegerIfNormal() {
236         final int from = 1;
237         final int to = 2;
238         final AtomicInteger ref = new AtomicInteger(from);
239         assertEquals(to, Atomics.getAndSetIf(ref, from, to));
240     }
241 
242     @Test(expected = IllegalArgumentException.class)
243     public void getAndSetIfIntegerNPE() {
244         Atomics.getAndSetIf((AtomicInteger) null, 0, 0);
245     }
246 
247     @Test
248     public void getAndSetIntegerReturnsOldValueIfChanged() {
249         final int old = 1;
250         final int from = 2;
251         final int to = 3;
252         final AtomicInteger ref = new AtomicInteger(old);
253         assertEquals(old, Atomics.getAndSetIf(ref, from, to));
254     }
255 
256     @Test
257     public void getAndSetIntegerSameValue() {
258         final int from = 1;
259         final int to = from;
260         final AtomicInteger ref = new AtomicInteger(from);
261         assertEquals(to, Atomics.getAndSetIf(ref, from, to));
262     }
263 
264     @Test
265     public void getAndSetIntegerSameValueDifferent() {
266         final int from = 1;
267         final int to = from;
268         final int different = 3;
269         final AtomicInteger ref = new AtomicInteger(different);
270         assertEquals(different, Atomics.getAndSetIf(ref, from, to));
271     }
272 
273     //
274     // AtomicBoolean tests
275     //
276 
277     @Test
278     public void getAndSetBooleanIfNormal() {
279         final boolean from = false;
280         final boolean to = true;
281         final AtomicBoolean ref = new AtomicBoolean(from);
282         assertEquals(to, Atomics.getAndSetIf(ref, from, to));
283     }
284 
285     @Test(expected = IllegalArgumentException.class)
286     public void getAndSetIfBooleanNPE() {
287         Atomics.getAndSetIf((AtomicBoolean) null, false, false);
288     }
289 
290     @Test
291     public void getAndSetBooleanReturnsOldValueIfChanged() {
292         final boolean old = true;
293         final boolean from = false;
294         final boolean to = true;
295         final AtomicBoolean ref = new AtomicBoolean(old);
296         assertEquals(old, Atomics.getAndSetIf(ref, from, to));
297     }
298 
299     @Test
300     public void getAndSetBooleanSameValue() {
301         final boolean from = false;
302         final boolean to = from;
303         final AtomicBoolean ref = new AtomicBoolean(from);
304         assertEquals(to, Atomics.getAndSetIf(ref, from, to));
305     }
306 
307     @Test
308     public void getAndSetBooleanSameValueDifferent() {
309         final boolean from = false;
310         final boolean to = from;
311         final boolean different = true;
312         final AtomicBoolean ref = new AtomicBoolean(different);
313         assertEquals(different, Atomics.getAndSetIf(ref, from, to));
314     }
315 }