ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/ThreadLocalRandomTest.java
Revision: 1.23
Committed: Fri Dec 9 06:56:30 2016 UTC (7 years, 5 months ago) by jsr166
Branch: MAIN
Changes since 1.22: +23 -19 lines
Log Message:
testNext: tolerate InaccessibleObjectException

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