ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ThreadLocalRandomTest.java
Revision: 1.25
Committed: Tue Sep 19 20:10:49 2017 UTC (6 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.24: +3 -0 lines
Log Message:
Inhibit "An illegal reflective access operation has occurred"

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