blob: 665a2b78e6dd834f43ea8cf2904a6e41972d3bdd [file] [log] [blame]
Calin Juravle8f0d92b2013-08-01 17:26:00 +01001/*
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 */
6
7package jsr166;
8
9import junit.framework.*;
10import java.util.*;
11import java.util.concurrent.ThreadLocalRandom;
12import java.util.concurrent.atomic.AtomicLong;
13import java.util.concurrent.atomic.AtomicReference;
14
15public class ThreadLocalRandomTest extends JSR166TestCase {
16
17 /*
18 * Testing coverage notes:
19 *
20 * We don't test randomness properties, but only that repeated
21 * calls, up to NCALLS tries, produce at least one different
22 * result. For bounded versions, we sample various intervals
23 * across multiples of primes.
24 */
25
26 //
27 static final int NCALLS = 10000;
28
29 // max sampled int bound
30 static final int MAX_INT_BOUND = (1 << 28);
31
32 // Max sampled long bound
33 static final long MAX_LONG_BOUND = (1L << 42);
34
35 /**
36 * setSeed throws UnsupportedOperationException
37 */
38 public void testSetSeed() {
39 try {
40 ThreadLocalRandom.current().setSeed(17);
41 shouldThrow();
42 } catch (UnsupportedOperationException success) {}
43 }
44
45 /**
46 * Repeated calls to nextInt produce at least one different result
47 */
48 public void testNextInt() {
49 int f = ThreadLocalRandom.current().nextInt();
50 int i = 0;
51 while (i < NCALLS && ThreadLocalRandom.current().nextInt() == f)
52 ++i;
53 assertTrue(i < NCALLS);
54 }
55
56 /**
57 * Repeated calls to nextLong produce at least one different result
58 */
59 public void testNextLong() {
60 long f = ThreadLocalRandom.current().nextLong();
61 int i = 0;
62 while (i < NCALLS && ThreadLocalRandom.current().nextLong() == f)
63 ++i;
64 assertTrue(i < NCALLS);
65 }
66
67 /**
68 * Repeated calls to nextBoolean produce at least one different result
69 */
70 public void testNextBoolean() {
71 boolean f = ThreadLocalRandom.current().nextBoolean();
72 int i = 0;
73 while (i < NCALLS && ThreadLocalRandom.current().nextBoolean() == f)
74 ++i;
75 assertTrue(i < NCALLS);
76 }
77
78 /**
79 * Repeated calls to nextFloat produce at least one different result
80 */
81 public void testNextFloat() {
82 float f = ThreadLocalRandom.current().nextFloat();
83 int i = 0;
84 while (i < NCALLS && ThreadLocalRandom.current().nextFloat() == f)
85 ++i;
86 assertTrue(i < NCALLS);
87 }
88
89 /**
90 * Repeated calls to nextDouble produce at least one different result
91 */
92 public void testNextDouble() {
93 double f = ThreadLocalRandom.current().nextDouble();
94 double i = 0;
95 while (i < NCALLS && ThreadLocalRandom.current().nextDouble() == f)
96 ++i;
97 assertTrue(i < NCALLS);
98 }
99
100 /**
101 * Repeated calls to nextGaussian produce at least one different result
102 */
103 public void testNextGaussian() {
104 double f = ThreadLocalRandom.current().nextGaussian();
105 int i = 0;
106 while (i < NCALLS && ThreadLocalRandom.current().nextGaussian() == f)
107 ++i;
108 assertTrue(i < NCALLS);
109 }
110
111 /**
112 * nextInt(negative) throws IllegalArgumentException;
113 */
114 public void testNextIntBoundedNeg() {
115 try {
116 int f = ThreadLocalRandom.current().nextInt(-17);
117 shouldThrow();
118 } catch (IllegalArgumentException success) {}
119 }
120
121 /**
122 * nextInt(least >= bound) throws IllegalArgumentException;
123 */
124 public void testNextIntBadBounds() {
125 try {
126 int f = ThreadLocalRandom.current().nextInt(17, 2);
127 shouldThrow();
128 } catch (IllegalArgumentException success) {}
129 }
130
131 /**
132 * nextInt(bound) returns 0 <= value < bound;
133 * repeated calls produce at least one different result
134 */
135 public void testNextIntBounded() {
136 // sample bound space across prime number increments
137 for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
138 int f = ThreadLocalRandom.current().nextInt(bound);
139 assertTrue(0 <= f && f < bound);
140 int i = 0;
141 int j;
142 while (i < NCALLS &&
143 (j = ThreadLocalRandom.current().nextInt(bound)) == f) {
144 assertTrue(0 <= j && j < bound);
145 ++i;
146 }
147 assertTrue(i < NCALLS);
148 }
149 }
150
151 /**
152 * nextInt(least, bound) returns least <= value < bound;
153 * repeated calls produce at least one different result
154 */
155 public void testNextIntBounded2() {
156 for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) {
157 for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) {
158 int f = ThreadLocalRandom.current().nextInt(least, bound);
159 assertTrue(least <= f && f < bound);
160 int i = 0;
161 int j;
162 while (i < NCALLS &&
163 (j = ThreadLocalRandom.current().nextInt(least, bound)) == f) {
164 assertTrue(least <= j && j < bound);
165 ++i;
166 }
167 assertTrue(i < NCALLS);
168 }
169 }
170 }
171
172 /**
173 * nextLong(negative) throws IllegalArgumentException;
174 */
175 public void testNextLongBoundedNeg() {
176 try {
177 long f = ThreadLocalRandom.current().nextLong(-17);
178 shouldThrow();
179 } catch (IllegalArgumentException success) {}
180 }
181
182 /**
183 * nextLong(least >= bound) throws IllegalArgumentException;
184 */
185 public void testNextLongBadBounds() {
186 try {
187 long f = ThreadLocalRandom.current().nextLong(17, 2);
188 shouldThrow();
189 } catch (IllegalArgumentException success) {}
190 }
191
192 /**
193 * nextLong(bound) returns 0 <= value < bound;
194 * repeated calls produce at least one different result
195 */
196 public void testNextLongBounded() {
197 for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) {
198 long f = ThreadLocalRandom.current().nextLong(bound);
199 assertTrue(0 <= f && f < bound);
200 int i = 0;
201 long j;
202 while (i < NCALLS &&
203 (j = ThreadLocalRandom.current().nextLong(bound)) == f) {
204 assertTrue(0 <= j && j < bound);
205 ++i;
206 }
207 assertTrue(i < NCALLS);
208 }
209 }
210
211 /**
212 * nextLong(least, bound) returns least <= value < bound;
213 * repeated calls produce at least one different result
214 */
215 public void testNextLongBounded2() {
216 for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) {
217 for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
218 long f = ThreadLocalRandom.current().nextLong(least, bound);
219 assertTrue(least <= f && f < bound);
220 int i = 0;
221 long j;
222 while (i < NCALLS &&
223 (j = ThreadLocalRandom.current().nextLong(least, bound)) == f) {
224 assertTrue(least <= j && j < bound);
225 ++i;
226 }
227 assertTrue(i < NCALLS);
228 }
229 }
230 }
231
232 /**
233 * nextDouble(least, bound) returns least <= value < bound;
234 * repeated calls produce at least one different result
235 */
236 public void testNextDoubleBounded2() {
237 for (double least = 0.0001; least < 1.0e20; least *= 8) {
238 for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) {
239 double f = ThreadLocalRandom.current().nextDouble(least, bound);
240 assertTrue(least <= f && f < bound);
241 int i = 0;
242 double j;
243 while (i < NCALLS &&
244 (j = ThreadLocalRandom.current().nextDouble(least, bound)) == f) {
245 assertTrue(least <= j && j < bound);
246 ++i;
247 }
248 assertTrue(i < NCALLS);
249 }
250 }
251 }
252
253 /**
254 * Different threads produce different pseudo-random sequences
255 */
256 public void testDifferentSequences() {
257 // Don't use main thread's ThreadLocalRandom - it is likely to
258 // be polluted by previous tests.
259 final AtomicReference<ThreadLocalRandom> threadLocalRandom =
260 new AtomicReference<ThreadLocalRandom>();
261 final AtomicLong rand = new AtomicLong();
262
263 long firstRand = 0;
264 ThreadLocalRandom firstThreadLocalRandom = null;
265
266 final CheckedRunnable getRandomState = new CheckedRunnable() {
267 public void realRun() {
268 ThreadLocalRandom current = ThreadLocalRandom.current();
269 assertSame(current, ThreadLocalRandom.current());
270 // test bug: the following is not guaranteed and not true in JDK8
271 // assertNotSame(current, threadLocalRandom.get());
272 rand.set(current.nextLong());
273 threadLocalRandom.set(current);
274 }};
275
276 Thread first = newStartedThread(getRandomState);
277 awaitTermination(first);
278 firstRand = rand.get();
279 firstThreadLocalRandom = threadLocalRandom.get();
280
281 for (int i = 0; i < NCALLS; i++) {
282 Thread t = newStartedThread(getRandomState);
283 awaitTermination(t);
284 if (firstRand != rand.get())
285 return;
286 }
287 fail("all threads generate the same pseudo-random sequence");
288 }
289
290}