ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ThreadLocalRandomTest.java
Revision: 1.24
Committed: Sat Dec 10 12:39:15 2016 UTC (7 years, 5 months ago) by jsr166
Branch: MAIN
Changes since 1.23: +8 -3 lines
Log Message:
testNext: make test work with pre-jdk9

File Contents

# Content
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 */
6
7 import java.util.concurrent.ThreadLocalRandom;
8 import java.util.concurrent.atomic.AtomicLong;
9 import java.util.concurrent.atomic.AtomicReference;
10
11 import junit.framework.Test;
12 import junit.framework.TestSuite;
13
14 public class ThreadLocalRandomTest extends JSR166TestCase {
15
16 public static void main(String[] args) {
17 main(suite(), args);
18 }
19 public static Test suite() {
20 return new TestSuite(ThreadLocalRandomTest.class);
21 }
22
23 /*
24 * Testing coverage notes:
25 *
26 * We don't test randomness properties, but only that repeated
27 * calls, up to NCALLS tries, produce at least one different
28 * result. For bounded versions, we sample various intervals
29 * across multiples of primes.
30 */
31
32 // max numbers of calls to detect getting stuck on one value
33 static final int NCALLS = 10000;
34
35 // max sampled int bound
36 static final int MAX_INT_BOUND = (1 << 28);
37
38 // max sampled long bound
39 static final long MAX_LONG_BOUND = (1L << 42);
40
41 // Number of replications for other checks
42 static final int REPS = 20;
43
44 /**
45 * setSeed throws UnsupportedOperationException
46 */
47 public void testSetSeed() {
48 try {
49 ThreadLocalRandom.current().setSeed(17);
50 shouldThrow();
51 } catch (UnsupportedOperationException success) {}
52 }
53
54 /**
55 * Repeated calls to next (only accessible via reflection) produce
56 * at least two distinct results, and repeated calls produce all
57 * possible values.
58 */
59 public void testNext() throws ReflectiveOperationException {
60 ThreadLocalRandom rnd = ThreadLocalRandom.current();
61 final java.lang.reflect.Method m;
62 try {
63 m = ThreadLocalRandom.class.getDeclaredMethod(
64 "next", new Class[] { int.class });
65 m.setAccessible(true);
66 } catch (SecurityException acceptable) {
67 // Security manager may deny access
68 return;
69 } catch (Exception ex) {
70 // jdk9 module system may deny access
71 if (ex.getClass().getSimpleName()
72 .equals("InaccessibleObjectException"))
73 return;
74 throw ex;
75 }
76
77 int i;
78 {
79 int val = new java.util.Random().nextInt(4);
80 for (i = 0; i < NCALLS; i++) {
81 int q = (int) m.invoke(rnd, new Object[] { 2 });
82 if (val == q) break;
83 }
84 assertTrue(i < NCALLS);
85 }
86
87 {
88 int r = (int) m.invoke(rnd, new Object[] { 3 });
89 for (i = 0; i < NCALLS; i++) {
90 int q = (int) m.invoke(rnd, new Object[] { 3 });
91 assertTrue(q < (1<<3));
92 if (r != q) break;
93 }
94 assertTrue(i < NCALLS);
95 }
96 }
97
98 /**
99 * Repeated calls to nextInt produce at least two distinct results
100 */
101 public void testNextInt() {
102 int f = ThreadLocalRandom.current().nextInt();
103 int i = 0;
104 while (i < NCALLS && ThreadLocalRandom.current().nextInt() == f)
105 ++i;
106 assertTrue(i < NCALLS);
107 }
108
109 /**
110 * Repeated calls to nextLong produce at least two distinct results
111 */
112 public void testNextLong() {
113 long f = ThreadLocalRandom.current().nextLong();
114 int i = 0;
115 while (i < NCALLS && ThreadLocalRandom.current().nextLong() == f)
116 ++i;
117 assertTrue(i < NCALLS);
118 }
119
120 /**
121 * Repeated calls to nextBoolean produce at least two distinct results
122 */
123 public void testNextBoolean() {
124 boolean f = ThreadLocalRandom.current().nextBoolean();
125 int i = 0;
126 while (i < NCALLS && ThreadLocalRandom.current().nextBoolean() == f)
127 ++i;
128 assertTrue(i < NCALLS);
129 }
130
131 /**
132 * Repeated calls to nextFloat produce at least two distinct results
133 */
134 public void testNextFloat() {
135 float f = ThreadLocalRandom.current().nextFloat();
136 int i = 0;
137 while (i < NCALLS && ThreadLocalRandom.current().nextFloat() == f)
138 ++i;
139 assertTrue(i < NCALLS);
140 }
141
142 /**
143 * Repeated calls to nextDouble produce at least two distinct results
144 */
145 public void testNextDouble() {
146 double f = ThreadLocalRandom.current().nextDouble();
147 int i = 0;
148 while (i < NCALLS && ThreadLocalRandom.current().nextDouble() == f)
149 ++i;
150 assertTrue(i < NCALLS);
151 }
152
153 /**
154 * Repeated calls to nextGaussian produce at least two distinct results
155 */
156 public void testNextGaussian() {
157 double f = ThreadLocalRandom.current().nextGaussian();
158 int i = 0;
159 while (i < NCALLS && ThreadLocalRandom.current().nextGaussian() == f)
160 ++i;
161 assertTrue(i < NCALLS);
162 }
163
164 /**
165 * nextInt(non-positive) throws IllegalArgumentException
166 */
167 public void testNextIntBoundNonPositive() {
168 ThreadLocalRandom rnd = ThreadLocalRandom.current();
169 for (int bound : new int[] { 0, -17, Integer.MIN_VALUE }) {
170 try {
171 rnd.nextInt(bound);
172 shouldThrow();
173 } catch (IllegalArgumentException success) {}
174 }
175 }
176
177 /**
178 * nextInt(least >= bound) throws IllegalArgumentException
179 */
180 public void testNextIntBadBounds() {
181 int[][] badBoundss = {
182 { 17, 2 },
183 { -42, -42 },
184 { Integer.MAX_VALUE, Integer.MIN_VALUE },
185 };
186 ThreadLocalRandom rnd = ThreadLocalRandom.current();
187 for (int[] badBounds : badBoundss) {
188 try {
189 rnd.nextInt(badBounds[0], badBounds[1]);
190 shouldThrow();
191 } catch (IllegalArgumentException success) {}
192 }
193 }
194
195 /**
196 * nextInt(bound) returns 0 <= value < bound;
197 * repeated calls produce at least two distinct results
198 */
199 public void testNextIntBounded() {
200 // sample bound space across prime number increments
201 for (int bound = 2; bound < MAX_INT_BOUND; bound += 524959) {
202 int f = ThreadLocalRandom.current().nextInt(bound);
203 assertTrue(0 <= f && f < bound);
204 int i = 0;
205 int j;
206 while (i < NCALLS &&
207 (j = ThreadLocalRandom.current().nextInt(bound)) == f) {
208 assertTrue(0 <= j && j < bound);
209 ++i;
210 }
211 assertTrue(i < NCALLS);
212 }
213 }
214
215 /**
216 * nextInt(least, bound) returns least <= value < bound;
217 * repeated calls produce at least two distinct results
218 */
219 public void testNextIntBounded2() {
220 for (int least = -15485863; least < MAX_INT_BOUND; least += 524959) {
221 for (int bound = least + 2; bound > least && bound < MAX_INT_BOUND; bound += 49979687) {
222 int f = ThreadLocalRandom.current().nextInt(least, bound);
223 assertTrue(least <= f && f < bound);
224 int i = 0;
225 int j;
226 while (i < NCALLS &&
227 (j = ThreadLocalRandom.current().nextInt(least, bound)) == f) {
228 assertTrue(least <= j && j < bound);
229 ++i;
230 }
231 assertTrue(i < NCALLS);
232 }
233 }
234 }
235
236 /**
237 * nextLong(non-positive) throws IllegalArgumentException
238 */
239 public void testNextLongBoundNonPositive() {
240 ThreadLocalRandom rnd = ThreadLocalRandom.current();
241 for (long bound : new long[] { 0L, -17L, Long.MIN_VALUE }) {
242 try {
243 rnd.nextLong(bound);
244 shouldThrow();
245 } catch (IllegalArgumentException success) {}
246 }
247 }
248
249 /**
250 * nextLong(least >= bound) throws IllegalArgumentException
251 */
252 public void testNextLongBadBounds() {
253 long[][] badBoundss = {
254 { 17L, 2L },
255 { -42L, -42L },
256 { Long.MAX_VALUE, Long.MIN_VALUE },
257 };
258 ThreadLocalRandom rnd = ThreadLocalRandom.current();
259 for (long[] badBounds : badBoundss) {
260 try {
261 rnd.nextLong(badBounds[0], badBounds[1]);
262 shouldThrow();
263 } catch (IllegalArgumentException success) {}
264 }
265 }
266
267 /**
268 * nextLong(bound) returns 0 <= value < bound;
269 * repeated calls produce at least two distinct results
270 */
271 public void testNextLongBounded() {
272 for (long bound = 2; bound < MAX_LONG_BOUND; bound += 15485863) {
273 long f = ThreadLocalRandom.current().nextLong(bound);
274 assertTrue(0 <= f && f < bound);
275 int i = 0;
276 long j;
277 while (i < NCALLS &&
278 (j = ThreadLocalRandom.current().nextLong(bound)) == f) {
279 assertTrue(0 <= j && j < bound);
280 ++i;
281 }
282 assertTrue(i < NCALLS);
283 }
284 }
285
286 /**
287 * nextLong(least, bound) returns least <= value < bound;
288 * repeated calls produce at least two distinct results
289 */
290 public void testNextLongBounded2() {
291 for (long least = -86028121; least < MAX_LONG_BOUND; least += 982451653L) {
292 for (long bound = least + 2; bound > least && bound < MAX_LONG_BOUND; bound += Math.abs(bound * 7919)) {
293 long f = ThreadLocalRandom.current().nextLong(least, bound);
294 assertTrue(least <= f && f < bound);
295 int i = 0;
296 long j;
297 while (i < NCALLS &&
298 (j = ThreadLocalRandom.current().nextLong(least, bound)) == f) {
299 assertTrue(least <= j && j < bound);
300 ++i;
301 }
302 assertTrue(i < NCALLS);
303 }
304 }
305 }
306
307 /**
308 * nextDouble(non-positive) throws IllegalArgumentException
309 */
310 public void testNextDoubleBoundNonPositive() {
311 ThreadLocalRandom rnd = ThreadLocalRandom.current();
312 double[] badBounds = {
313 0.0d,
314 -17.0d,
315 -Double.MIN_VALUE,
316 Double.NEGATIVE_INFINITY,
317 Double.NaN,
318 };
319 for (double bound : badBounds) {
320 try {
321 rnd.nextDouble(bound);
322 shouldThrow();
323 } catch (IllegalArgumentException success) {}
324 }
325 }
326
327 /**
328 * nextDouble(least, bound) returns least <= value < bound;
329 * repeated calls produce at least two distinct results
330 */
331 public void testNextDoubleBounded2() {
332 for (double least = 0.0001; least < 1.0e20; least *= 8) {
333 for (double bound = least * 1.001; bound < 1.0e20; bound *= 16) {
334 double f = ThreadLocalRandom.current().nextDouble(least, bound);
335 assertTrue(least <= f && f < bound);
336 int i = 0;
337 double j;
338 while (i < NCALLS &&
339 (j = ThreadLocalRandom.current().nextDouble(least, bound)) == f) {
340 assertTrue(least <= j && j < bound);
341 ++i;
342 }
343 assertTrue(i < NCALLS);
344 }
345 }
346 }
347
348 /**
349 * Different threads produce different pseudo-random sequences
350 */
351 public void testDifferentSequences() {
352 // Don't use main thread's ThreadLocalRandom - it is likely to
353 // be polluted by previous tests.
354 final AtomicReference<ThreadLocalRandom> threadLocalRandom =
355 new AtomicReference<ThreadLocalRandom>();
356 final AtomicLong rand = new AtomicLong();
357
358 long firstRand = 0;
359 ThreadLocalRandom firstThreadLocalRandom = null;
360
361 Runnable getRandomState = new CheckedRunnable() {
362 public void realRun() {
363 ThreadLocalRandom current = ThreadLocalRandom.current();
364 assertSame(current, ThreadLocalRandom.current());
365 // test bug: the following is not guaranteed and not true in JDK8
366 // assertNotSame(current, threadLocalRandom.get());
367 rand.set(current.nextLong());
368 threadLocalRandom.set(current);
369 }};
370
371 Thread first = newStartedThread(getRandomState);
372 awaitTermination(first);
373 firstRand = rand.get();
374 firstThreadLocalRandom = threadLocalRandom.get();
375
376 for (int i = 0; i < NCALLS; i++) {
377 Thread t = newStartedThread(getRandomState);
378 awaitTermination(t);
379 if (firstRand != rand.get())
380 return;
381 }
382 fail("all threads generate the same pseudo-random sequence");
383 }
384
385 }