1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.rng.core;
18
19 import org.junit.Assert;
20 import org.junit.Assume;
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 import org.junit.runners.Parameterized;
24 import org.junit.runners.Parameterized.Parameters;
25
26 import java.util.Arrays;
27
28 import org.apache.commons.rng.JumpableUniformRandomProvider;
29 import org.apache.commons.rng.LongJumpableUniformRandomProvider;
30 import org.apache.commons.rng.RandomProviderState;
31 import org.apache.commons.rng.RestorableUniformRandomProvider;
32 import org.apache.commons.rng.UniformRandomProvider;
33 import org.apache.commons.rng.core.source32.IntProvider;
34 import org.apache.commons.rng.core.source64.LongProvider;
35
36
37
38
39 @RunWith(value = Parameterized.class)
40 public class JumpableProvidersParametricTest {
41
42 private static final int INT_PROVIDER_STATE_SIZE;
43
44 private static final int LONG_PROVIDER_STATE_SIZE;
45
46 static {
47 INT_PROVIDER_STATE_SIZE = new State32Generator().getStateSize();
48 LONG_PROVIDER_STATE_SIZE = new State64Generator().getStateSize();
49 }
50
51
52 private final JumpableUniformRandomProvider generator;
53
54
55
56
57
58
59 public JumpableProvidersParametricTest(JumpableUniformRandomProvider rng) {
60 generator = rng;
61 }
62
63
64
65
66
67
68 @Parameters(name = "{index}: data={0}")
69 public static Iterable<JumpableUniformRandomProvider[]> getList() {
70 return ProvidersList.listJumpable();
71 }
72
73
74
75
76
77
78 private TestJumpFunction getJumpFunction() {
79 return new TestJumpFunction() {
80 @Override
81 public UniformRandomProvider jump() {
82 return generator.jump();
83 }
84 };
85 }
86
87
88
89
90
91
92 private TestJumpFunction getLongJumpFunction() {
93 Assume.assumeTrue("No long jump function", generator instanceof LongJumpableUniformRandomProvider);
94
95 final LongJumpableUniformRandomProvider rng = (LongJumpableUniformRandomProvider) generator;
96 return new TestJumpFunction() {
97 @Override
98 public UniformRandomProvider jump() {
99 return rng.longJump();
100 }
101 };
102 }
103
104
105
106
107 @Test
108 public void testJumpReturnsACopy() {
109 assertJumpReturnsACopy(getJumpFunction());
110 }
111
112
113
114
115 @Test
116 public void testLongJumpReturnsACopy() {
117 assertJumpReturnsACopy(getLongJumpFunction());
118 }
119
120
121
122
123
124
125 private void assertJumpReturnsACopy(TestJumpFunction jumpFunction) {
126 final UniformRandomProvider copy = jumpFunction.jump();
127 Assert.assertNotSame("The copy instance should be a different object", generator, copy);
128 Assert.assertEquals("The copy instance should be the same class", generator.getClass(), copy.getClass());
129 }
130
131
132
133
134
135 @Test
136 public void testJumpCopyMatchesPreJumpState() {
137 assertCopyMatchesPreJumpState(getJumpFunction());
138 }
139
140
141
142
143
144 @Test
145 public void testLongJumpCopyMatchesPreJumpState() {
146 assertCopyMatchesPreJumpState(getLongJumpFunction());
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 private void assertCopyMatchesPreJumpState(TestJumpFunction jumpFunction) {
168 Assume.assumeTrue("Not a restorable RNG", generator instanceof RestorableUniformRandomProvider);
169
170 for (int repeats = 0; repeats < 2; repeats++) {
171
172
173
174
175 generator.nextInt();
176 generator.nextBoolean();
177
178 final RandomProviderState preJumpState = ((RestorableUniformRandomProvider) generator).saveState();
179 Assume.assumeTrue("Not a recognised state", preJumpState instanceof RandomProviderDefaultState);
180
181 final UniformRandomProvider copy = jumpFunction.jump();
182
183 final RandomProviderState copyState = ((RestorableUniformRandomProvider) copy).saveState();
184 final RandomProviderDefaultState expected = (RandomProviderDefaultState) preJumpState;
185 final RandomProviderDefaultState actual = (RandomProviderDefaultState) copyState;
186 Assert.assertArrayEquals("The copy instance state should match the state of the original",
187 expected.getState(), actual.getState());
188 }
189 }
190
191
192
193
194
195 @Test
196 public void testJumpResetsDefaultState() {
197 if (generator instanceof IntProvider) {
198 assertJumpResetsDefaultState(getJumpFunction(), INT_PROVIDER_STATE_SIZE);
199 } else if (generator instanceof LongProvider) {
200 assertJumpResetsDefaultState(getJumpFunction(), LONG_PROVIDER_STATE_SIZE);
201 }
202 }
203
204
205
206
207
208 @Test
209 public void testLongJumpResetsDefaultState() {
210 if (generator instanceof IntProvider) {
211 assertJumpResetsDefaultState(getLongJumpFunction(), INT_PROVIDER_STATE_SIZE);
212 } else if (generator instanceof LongProvider) {
213 assertJumpResetsDefaultState(getLongJumpFunction(), LONG_PROVIDER_STATE_SIZE);
214 }
215 }
216
217
218
219
220
221
222
223
224
225
226
227 private void assertJumpResetsDefaultState(TestJumpFunction jumpFunction, int stateSize) {
228 final byte[] expected = new byte[stateSize];
229 for (int repeats = 0; repeats < 2; repeats++) {
230
231
232
233
234 generator.nextInt();
235 generator.nextBoolean();
236
237 jumpFunction.jump();
238
239
240 final RandomProviderState postJumpState = ((RestorableUniformRandomProvider) generator).saveState();
241 final byte[] actual = ((RandomProviderDefaultState) postJumpState).getState();
242
243 Assume.assumeTrue("Implementation has removed default state", actual.length >= stateSize);
244
245
246
247 final byte[] defaultState = Arrays.copyOfRange(actual, actual.length - stateSize, actual.length);
248 Assert.assertArrayEquals("The jump should reset the default state to zero", expected, defaultState);
249 }
250 }
251
252
253
254
255 static class State32Generator extends IntProvider {
256
257 @Override
258 public int next() {
259 return 0;
260 }
261
262
263
264
265
266
267 int getStateSize() {
268 return getStateInternal().length;
269 }
270 }
271
272
273
274
275 static class State64Generator extends LongProvider {
276
277 @Override
278 public long next() {
279 return 0;
280 }
281
282
283
284
285
286
287 int getStateSize() {
288 return getStateInternal().length;
289 }
290 }
291
292
293
294
295
296
297
298 interface TestJumpFunction {
299
300
301
302
303
304 UniformRandomProvider jump();
305 }
306 }