1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.rng.simple;
18
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.ArrayList;
22 import java.util.concurrent.Callable;
23 import java.io.IOException;
24 import java.io.ObjectOutputStream;
25 import java.io.ObjectInputStream;
26 import java.io.ByteArrayOutputStream;
27 import java.io.ByteArrayInputStream;
28
29 import org.junit.Assert;
30 import org.junit.Test;
31 import org.junit.Assume;
32 import org.junit.Ignore;
33 import org.junit.runner.RunWith;
34 import org.junit.runners.Parameterized;
35 import org.junit.runners.Parameterized.Parameters;
36
37 import org.apache.commons.rng.UniformRandomProvider;
38 import org.apache.commons.rng.RandomProviderState;
39 import org.apache.commons.rng.RestorableUniformRandomProvider;
40 import org.apache.commons.rng.core.RandomProviderDefaultState;
41
42
43
44
45 @RunWith(value=Parameterized.class)
46 public class ProvidersCommonParametricTest {
47
48 private final UniformRandomProvider generator;
49
50 private final RandomSource originalSource;
51
52 private final Object originalSeed;
53
54 private final Object[] originalArgs;
55
56
57
58
59
60
61 public ProvidersCommonParametricTest(ProvidersList.Data data) {
62 originalSource = data.getSource();
63 originalSeed = data.getSeed();
64 originalArgs = data.getArgs();
65 generator = RandomSource.create(originalSource, originalSeed, originalArgs);
66 }
67
68 @Parameters(name = "{index}: data={0}")
69 public static Iterable<ProvidersList.Data[]> getList() {
70 return ProvidersList.list();
71 }
72
73
74
75 @Test(expected=UnsupportedOperationException.class)
76 public void testUnsupportedSeedType() {
77 final byte seed = 123;
78 RandomSource.create(originalSource, seed, originalArgs);
79 }
80
81 @Test
82 public void testAllSeedTypes() {
83 final Integer intSeed = -12131415;
84 final Long longSeed = -1213141516171819L;
85 final int[] intArraySeed = new int[] { 0, 11, -22, 33, -44, 55, -66, 77, -88, 99 };
86 final long[] longArraySeed = new long[] { 11111L, -222222L, 3333333L, -44444444L };
87 final byte[] byteArraySeed = new byte[] { -128, -91, -45, -32, -1, 0, 11, 23, 54, 88, 127 };
88
89 final Object[] seeds = new Object[] { null,
90 intSeed,
91 longSeed,
92 intArraySeed,
93 longArraySeed,
94 byteArraySeed };
95
96 int nonNativeSeedCount = 0;
97 int seedCount = 0;
98 for (Object s : seeds) {
99 ++seedCount;
100 if (!(originalSource.isNativeSeed(s))) {
101 ++nonNativeSeedCount;
102 }
103
104 Assert.assertNotEquals(intSeed, originalSeed);
105 RandomSource.create(originalSource, s, originalArgs);
106 }
107
108 Assert.assertEquals(6, seedCount);
109 Assert.assertEquals(5, nonNativeSeedCount);
110 }
111
112 @Test
113 public void testEmptyIntArraySeed() {
114 final int[] empty = new int[0];
115 Assume.assumeTrue(originalSource.isNativeSeed(empty));
116
117
118 final UniformRandomProvider rng = RandomSource.create(originalSource, empty, originalArgs);
119 checkNextIntegerInRange(rng, 10, 20000);
120 }
121
122 @Test
123 public void testEmptyLongArraySeed() {
124 final long[] empty = new long[0];
125 Assume.assumeTrue(originalSource.isNativeSeed(empty));
126
127
128 final UniformRandomProvider rng = RandomSource.create(originalSource, empty, originalArgs);
129 checkNextIntegerInRange(rng, 10, 10000);
130 }
131
132 @Ignore@Test
133 public void testZeroIntArraySeed() {
134
135 final int[] zero = new int[2000];
136 final UniformRandomProvider rng = RandomSource.create(originalSource, zero, originalArgs);
137 checkNextIntegerInRange(rng, 10, 10000);
138 }
139
140 @Ignore@Test
141 public void testZeroLongArraySeed() {
142
143 final long[] zero = new long[2000];
144 final UniformRandomProvider rng = RandomSource.create(originalSource, zero, originalArgs);
145 checkNextIntegerInRange(rng, 10, 10000);
146 }
147
148
149
150 @Test
151 public void testUnrestorable() {
152
153 final UniformRandomProvider rng1 = RandomSource.create(originalSource, originalSeed, originalArgs);
154 final UniformRandomProvider rng2 = RandomSource.unrestorable(RandomSource.create(originalSource, originalSeed, originalArgs));
155
156
157 RandomAssert.assertProduceSameSequence(rng1, rng2);
158
159
160 final RestorableUniformRandomProvider restorable = (RestorableUniformRandomProvider) rng1;
161
162 try {
163 final RestorableUniformRandomProvider dummy = (RestorableUniformRandomProvider) rng2;
164 Assert.fail("Cast should have failed");
165 } catch (ClassCastException e) {
166
167 }
168 }
169
170 @Test
171 public void testSerializingState()
172 throws IOException,
173 ClassNotFoundException {
174
175 final int n = 100;
176
177
178 final RestorableUniformRandomProvider restorable = (RestorableUniformRandomProvider) generator;
179
180
181 final RandomProviderState stateOrig = restorable.saveState();
182
183 ByteArrayOutputStream bos = new ByteArrayOutputStream();
184 ObjectOutputStream oos = new ObjectOutputStream(bos);
185 oos.writeObject(((RandomProviderDefaultState) stateOrig).getState());
186
187
188 final List<Number> listOrig = makeList(n);
189
190
191 final List<Number> listDiscard = makeList(n);
192 Assert.assertTrue(listDiscard.size() != 0);
193 Assert.assertFalse(listOrig.equals(listDiscard));
194
195
196 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
197 ObjectInputStream ois = new ObjectInputStream(bis);
198 final RandomProviderState stateNew = new RandomProviderDefaultState((byte[]) ois.readObject());
199
200 Assert.assertTrue(stateOrig != stateNew);
201
202
203 restorable.restoreState(stateNew);
204
205
206 final List<Number> listReplay = makeList(n);
207 Assert.assertFalse(listOrig == listReplay);
208
209
210 Assert.assertTrue(listOrig.equals(listReplay));
211 }
212
213 @Test
214 public void testUnrestorableToString() {
215 Assert.assertEquals(generator.toString(),
216 RandomSource.unrestorable(generator).toString());
217 }
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235 private List<Number> makeList(int n) {
236 final List<Number> list = new ArrayList<Number>();
237
238 for (int i = 0; i < n; i++) {
239
240 list.add(generator.nextInt());
241 list.add(generator.nextInt(21));
242 list.add(generator.nextInt(436));
243 list.add(generator.nextLong());
244 list.add(generator.nextLong(157894));
245 list.add(generator.nextLong(5745833));
246 list.add(generator.nextFloat());
247 list.add(generator.nextFloat());
248 list.add(generator.nextDouble());
249 list.add(generator.nextDouble());
250 list.add(generator.nextDouble());
251 }
252
253 return list;
254 }
255
256
257
258
259
260
261
262
263 private void checkNextIntegerInRange(final UniformRandomProvider rng,
264 final int max,
265 int sampleSize) {
266 final Callable<Integer> nextMethod = new Callable<Integer>() {
267 @Override
268 public Integer call() throws Exception {
269 return rng.nextInt(max);
270 }
271 };
272
273 checkNextInRange(max, sampleSize, nextMethod);
274 }
275
276
277
278
279
280
281
282
283
284
285
286
287
288 private <T extends Number> void checkNextInRange(T max,
289 int sampleSize,
290 Callable<T> nextMethod) {
291 final int numTests = 500;
292
293
294 final int numBins = 10;
295
296
297 final long n = max.longValue();
298 final long[] binUpperBounds = new long[numBins];
299 final double step = n / (double) numBins;
300 for (int k = 0; k < numBins; k++) {
301 binUpperBounds[k] = (long) ((k + 1) * step);
302 }
303
304
305 int numFailures = 0;
306
307 final double[] expected = new double[numBins];
308 long previousUpperBound = 0;
309 for (int k = 0; k < numBins; k++) {
310 final long range = binUpperBounds[k] - previousUpperBound;
311 expected[k] = sampleSize * (range / (double) n);
312 previousUpperBound = binUpperBounds[k];
313 }
314
315 final int[] observed = new int[numBins];
316
317
318 final double chi2CriticalValue = 21.67;
319
320 try {
321 for (int i = 0; i < numTests; i++) {
322 Arrays.fill(observed, 0);
323 for (int j = 0; j < sampleSize; j++) {
324 final long value = nextMethod.call().longValue();
325 Assert.assertTrue("Range", (value >= 0) && (value < n));
326
327 for (int k = 0; k < numBins; k++) {
328 if (value < binUpperBounds[k]) {
329 ++observed[k];
330 break;
331 }
332 }
333 }
334
335
336 double chi2 = 0;
337 for (int k = 0; k < numBins; k++) {
338 final double diff = observed[k] - expected[k];
339 chi2 += diff * diff / expected[k];
340 }
341
342
343 if (chi2 > chi2CriticalValue) {
344 ++numFailures;
345 }
346 }
347 } catch (Exception e) {
348
349 throw new RuntimeException("Unexpected", e);
350 }
351
352 if ((double) numFailures / (double) numTests > 0.02) {
353 Assert.fail(generator + ": Too many failures for n = " + n +
354 " (" + numFailures + " out of " + numTests + " tests failed)");
355 }
356 }
357 }