pool_of_entropy 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/rspec.yml +23 -0
- data/.rubocop.yml +18 -0
- data/Gemfile +11 -1
- data/README.md +0 -4
- data/Rakefile +7 -5
- data/lib/pool_of_entropy/core_prng.rb +149 -143
- data/lib/pool_of_entropy/version.rb +3 -1
- data/lib/pool_of_entropy.rb +57 -57
- data/pool_of_entropy.gemspec +15 -16
- data/spec/pool_of_entropy/core_prng_spec.rb +386 -0
- data/spec/pool_of_entropy_spec.rb +264 -303
- data/spec/spec_helper.rb +49 -3
- metadata +12 -88
- data/.travis.yml +0 -7
- data/spec/core_prng_spec.rb +0 -543
data/spec/core_prng_spec.rb
DELETED
|
@@ -1,543 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe PoolOfEntropy::CorePRNG do
|
|
4
|
-
describe "class methods" do
|
|
5
|
-
|
|
6
|
-
describe "#new" do
|
|
7
|
-
it "should instantiate a default object" do
|
|
8
|
-
prng = PoolOfEntropy::CorePRNG.new
|
|
9
|
-
prng.should be_a PoolOfEntropy::CorePRNG
|
|
10
|
-
prng.size.should == 1
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
it "should allow setting number of blocks in pool" do
|
|
14
|
-
prng = PoolOfEntropy::CorePRNG.new( 10 )
|
|
15
|
-
prng.should be_a PoolOfEntropy::CorePRNG
|
|
16
|
-
prng.size.should == 10
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
it "should fail with incorrect block number" do
|
|
20
|
-
expect { PoolOfEntropy::CorePRNG.new( -43 ) }.to raise_error ArgumentError
|
|
21
|
-
expect { PoolOfEntropy::CorePRNG.new( -1 ) }.to raise_error ArgumentError
|
|
22
|
-
expect { PoolOfEntropy::CorePRNG.new( 0 ) }.to raise_error ArgumentError
|
|
23
|
-
expect { PoolOfEntropy::CorePRNG.new( 257 ) }.to raise_error ArgumentError
|
|
24
|
-
expect { PoolOfEntropy::CorePRNG.new( 1000) }.to raise_error ArgumentError
|
|
25
|
-
expect { PoolOfEntropy::CorePRNG.new( nil ) }.to raise_error TypeError
|
|
26
|
-
expect { PoolOfEntropy::CorePRNG.new( '' ) }.to raise_error ArgumentError
|
|
27
|
-
expect { PoolOfEntropy::CorePRNG.new( :foo => 2 ) }.to raise_error TypeError
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it "should allow setting internal state" do
|
|
31
|
-
prng = PoolOfEntropy::CorePRNG.new( 1, "\x0" * 64 )
|
|
32
|
-
prng.should be_a PoolOfEntropy::CorePRNG
|
|
33
|
-
prng.size.should == 1
|
|
34
|
-
prng.state.should == "\x0" * 64
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
it "should fail with bad state data" do
|
|
38
|
-
expect { PoolOfEntropy::CorePRNG.new( 1, :boo ) }.to raise_error TypeError
|
|
39
|
-
expect { PoolOfEntropy::CorePRNG.new( 1, [] ) }.to raise_error TypeError
|
|
40
|
-
expect { PoolOfEntropy::CorePRNG.new( 1, '' ) }.to raise_error ArgumentError
|
|
41
|
-
expect { PoolOfEntropy::CorePRNG.new( 1, "\x0" * 63 ) }.to raise_error ArgumentError
|
|
42
|
-
expect { PoolOfEntropy::CorePRNG.new( 1, "\x0" * 200 ) }.to raise_error ArgumentError
|
|
43
|
-
expect { PoolOfEntropy::CorePRNG.new( 2, "\x0" * 64 ) }.to raise_error ArgumentError
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it "should allow setting mix_block_id" do
|
|
47
|
-
prng = PoolOfEntropy::CorePRNG.new( 3, "\x12" * 192, 1 )
|
|
48
|
-
prng.should be_a PoolOfEntropy::CorePRNG
|
|
49
|
-
prng.size.should == 3
|
|
50
|
-
prng.state.should == "\x12" * 192
|
|
51
|
-
prng.mix_block_id.should == 1
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
describe "instance methods" do
|
|
57
|
-
|
|
58
|
-
describe "#clone" do
|
|
59
|
-
it "should copy all attributes" do
|
|
60
|
-
prng_orig = PoolOfEntropy::CorePRNG.new
|
|
61
|
-
prng_copy = prng_orig.clone
|
|
62
|
-
|
|
63
|
-
prng_copy.size.should == prng_orig.size
|
|
64
|
-
prng_copy.state.should == prng_orig.state
|
|
65
|
-
prng_copy.mix_block_id.should == prng_orig.mix_block_id
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
it "should deep clone the internal state string" do
|
|
69
|
-
prng_orig = PoolOfEntropy::CorePRNG.new
|
|
70
|
-
prng_copy = prng_orig.clone
|
|
71
|
-
prng_copy.state.should_not be prng_orig.state
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
describe "#update" do
|
|
76
|
-
it "should change the internal state" do
|
|
77
|
-
prng = PoolOfEntropy::CorePRNG.new
|
|
78
|
-
init_state = prng.state.clone
|
|
79
|
-
prng.update( 'boo' )
|
|
80
|
-
prng.state.should_not == init_state
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
it "should not change the length of the internal state" do
|
|
84
|
-
prng = PoolOfEntropy::CorePRNG.new
|
|
85
|
-
prng.update( 'boo' )
|
|
86
|
-
prng.state.length.should == 64
|
|
87
|
-
prng.update( 'boowgkjwrhqgioueqrhgiue2hguirhqwiughreuioghreuifhqwoifhr3iufghfwrgrwgetdfwd' )
|
|
88
|
-
prng.state.length.should == 64
|
|
89
|
-
|
|
90
|
-
prng = PoolOfEntropy::CorePRNG.new( 5 )
|
|
91
|
-
prng.update( 'boo' )
|
|
92
|
-
prng.state.length.should == 5 * 64
|
|
93
|
-
prng.update( 'getdfwd' * 1000 )
|
|
94
|
-
prng.state.length.should == 5 * 64
|
|
95
|
-
prng.update( 'boefewfweo' )
|
|
96
|
-
prng.state.length.should == 5 * 64
|
|
97
|
-
prng.update( 'geefewftdfwd' * 1000 )
|
|
98
|
-
prng.state.length.should == 5 * 64
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
it "should only change 64 bytes of state at a time" do
|
|
102
|
-
prng = PoolOfEntropy::CorePRNG.new( 5 )
|
|
103
|
-
init_state = prng.state.clone
|
|
104
|
-
|
|
105
|
-
prng.update( 'boo' )
|
|
106
|
-
prng.state[64,4*64].should == init_state[64,4*64]
|
|
107
|
-
next_state = prng.state.clone
|
|
108
|
-
|
|
109
|
-
prng.update( 'getdfwd' * 1000 )
|
|
110
|
-
prng.state[128,3*64].should == init_state[128,3*64]
|
|
111
|
-
prng.state[0,1*64].should == next_state[0,1*64]
|
|
112
|
-
next_state = prng.state.clone
|
|
113
|
-
|
|
114
|
-
prng.update( 'boefewfweo' )
|
|
115
|
-
prng.state[192,2*64].should == init_state[192,2*64]
|
|
116
|
-
prng.state[0,2*64].should == next_state[0,2*64]
|
|
117
|
-
next_state = prng.state.clone
|
|
118
|
-
|
|
119
|
-
prng.update( 'geefewftdfwd' * 1000 )
|
|
120
|
-
prng.state[256,1*64].should == init_state[256,1*64]
|
|
121
|
-
prng.state[0,3*64].should == next_state[0,3*64]
|
|
122
|
-
end
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
instance01 = PoolOfEntropy::CorePRNG.new
|
|
126
|
-
instance01.update( 'QWertyuiopp' )
|
|
127
|
-
instance01.update( 'Asdfghjkjl' )
|
|
128
|
-
instance01.update( 'Zxcvbnm' )
|
|
129
|
-
|
|
130
|
-
pool_types = [
|
|
131
|
-
[
|
|
132
|
-
'default instance',
|
|
133
|
-
PoolOfEntropy::CorePRNG.new
|
|
134
|
-
],
|
|
135
|
-
[
|
|
136
|
-
'instance with 2KB pool size',
|
|
137
|
-
PoolOfEntropy::CorePRNG.new( 32 )
|
|
138
|
-
],
|
|
139
|
-
[
|
|
140
|
-
'instance with initial state all 0',
|
|
141
|
-
PoolOfEntropy::CorePRNG.new( 1, "\x0" * 64 )
|
|
142
|
-
],
|
|
143
|
-
[
|
|
144
|
-
'instance with fixed initial state',
|
|
145
|
-
PoolOfEntropy::CorePRNG.new( 5, "fiver" * 64, 3 )
|
|
146
|
-
],
|
|
147
|
-
[
|
|
148
|
-
'instance cloned from 2KB instance',
|
|
149
|
-
PoolOfEntropy::CorePRNG.new( 32 ).clone
|
|
150
|
-
],
|
|
151
|
-
[
|
|
152
|
-
'instance that has been updated with user data',
|
|
153
|
-
instance01
|
|
154
|
-
],
|
|
155
|
-
]
|
|
156
|
-
|
|
157
|
-
# NB "probability" and "randomness" tests in the following block are very light, just
|
|
158
|
-
# intended to capture high-level failures in logic. See DIEHARDER_TEST.md for thorough
|
|
159
|
-
# checks on statistical randomness of PoolOfEntropy::CorePRNG
|
|
160
|
-
pool_types.each do |prng_name, prng|
|
|
161
|
-
|
|
162
|
-
context "using #{prng_name}" do
|
|
163
|
-
|
|
164
|
-
describe "#read_bytes" do
|
|
165
|
-
it "always returns a 16 byte string" do
|
|
166
|
-
100.times { prng.read_bytes.length.should == 16 }
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
it "has a high probability of returning a different string each time" do
|
|
170
|
-
Set[ *(1..100).map {prng.read_bytes} ].size.should == 100
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
describe "with adjustments" do
|
|
174
|
-
it "always returns a 16 byte string" do
|
|
175
|
-
100.times { prng.read_bytes('654321').length.should == 16 }
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
it "has a high probability of returning a different string each time" do
|
|
179
|
-
Set[ *(1..100).map {prng.read_bytes('654321')} ].size.should == 100
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
it "changes output, but does not include adjustments in changes to state" do
|
|
183
|
-
prng_copy = prng.clone
|
|
184
|
-
10.times do
|
|
185
|
-
prng.read_bytes('Hello!').should == prng_copy.read_bytes('Hello!')
|
|
186
|
-
prng.state.should == prng_copy.state
|
|
187
|
-
prng.read_bytes('Hello!').should_not == prng_copy.read_bytes('Goodbye!')
|
|
188
|
-
prng.state.should == prng_copy.state
|
|
189
|
-
prng.read_bytes.should_not == prng_copy.read_bytes('Goodbye!')
|
|
190
|
-
prng.state.should == prng_copy.state
|
|
191
|
-
prng.read_bytes('Hello!').should_not == prng_copy.read_bytes
|
|
192
|
-
prng.state.should == prng_copy.state
|
|
193
|
-
prng.read_bytes('Hello','Goodbye').should_not == prng_copy.read_bytes
|
|
194
|
-
prng.state.should == prng_copy.state
|
|
195
|
-
# Verify that output remains same for next rolls
|
|
196
|
-
prng.read_bytes('Foobar','Wibble').should == prng_copy.read_bytes('Foobar','Wibble')
|
|
197
|
-
prng.state.should == prng_copy.state
|
|
198
|
-
prng.read_bytes.should == prng_copy.read_bytes
|
|
199
|
-
prng.state.should == prng_copy.state
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
describe "#read_hex" do
|
|
206
|
-
it "always returns a 32 digit hex string" do
|
|
207
|
-
100.times do
|
|
208
|
-
hex = prng.read_hex
|
|
209
|
-
hex.length.should == 32
|
|
210
|
-
hex.should match /\A[0-9a-f]{32}\z/
|
|
211
|
-
end
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
it "has a high probability of returning a different string each time" do
|
|
215
|
-
Set[ *(1..100).map {prng.read_hex} ].size.should == 100
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
describe "with adjustments" do
|
|
219
|
-
it "always returns a 32 digit hex string" do
|
|
220
|
-
100.times do
|
|
221
|
-
hex = prng.read_hex('QWertyeu')
|
|
222
|
-
hex.length.should == 32
|
|
223
|
-
hex.should match /\A[0-9a-f]{32}\z/
|
|
224
|
-
end
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
it "has a high probability of returning a different string each time" do
|
|
228
|
-
Set[ *(1..100).map {prng.read_hex('654321')} ].size.should == 100
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
it "changes output, but does not include adjustments in changes to state" do
|
|
232
|
-
prng_copy = prng.clone
|
|
233
|
-
10.times do
|
|
234
|
-
prng.read_hex('Hello!').should == prng_copy.read_hex('Hello!')
|
|
235
|
-
prng.state.should == prng_copy.state
|
|
236
|
-
prng.read_hex('Hello!').should_not == prng_copy.read_hex('Goodbye!')
|
|
237
|
-
prng.state.should == prng_copy.state
|
|
238
|
-
prng.read_hex.should_not == prng_copy.read_hex('Goodbye!')
|
|
239
|
-
prng.state.should == prng_copy.state
|
|
240
|
-
prng.read_hex('Hello!').should_not == prng_copy.read_hex
|
|
241
|
-
prng.state.should == prng_copy.state
|
|
242
|
-
prng.read_hex('Hello','Goodbye').should_not == prng_copy.read_hex
|
|
243
|
-
prng.state.should == prng_copy.state
|
|
244
|
-
# Verify that output remains same for next rolls
|
|
245
|
-
prng.read_hex('Foobar','Wibble').should == prng_copy.read_hex('Foobar','Wibble')
|
|
246
|
-
prng.state.should == prng_copy.state
|
|
247
|
-
prng.read_hex.should == prng_copy.read_hex
|
|
248
|
-
prng.state.should == prng_copy.state
|
|
249
|
-
end
|
|
250
|
-
end
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
describe "#read_bignum" do
|
|
255
|
-
it "always returns a 128-bit unsigned integer" do
|
|
256
|
-
100.times do
|
|
257
|
-
num = prng.read_bignum
|
|
258
|
-
num.should >= 0
|
|
259
|
-
num.should < 2**128
|
|
260
|
-
end
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
it "has a high probability of returning a different number each time" do
|
|
264
|
-
Set[ *(1..100).map {prng.read_bignum} ].size.should == 100
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
describe "with adjustments" do
|
|
268
|
-
it "always returns a 128-bit unsigned integer" do
|
|
269
|
-
100.times do
|
|
270
|
-
num = prng.read_bignum( 'Biggest' )
|
|
271
|
-
num.should >= 0
|
|
272
|
-
num.should < 2**128
|
|
273
|
-
end
|
|
274
|
-
end
|
|
275
|
-
|
|
276
|
-
it "has a high probability of returning a different number each time" do
|
|
277
|
-
Set[ *(1..100).map {prng.read_bignum('654321')} ].size.should == 100
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
it "changes output, but does not include adjustments in changes to state" do
|
|
281
|
-
prng_copy = prng.clone
|
|
282
|
-
10.times do
|
|
283
|
-
prng.read_bignum('Hello!').should == prng_copy.read_bignum('Hello!')
|
|
284
|
-
prng.state.should == prng_copy.state
|
|
285
|
-
prng.read_bignum('Hello!').should_not == prng_copy.read_bignum('Goodbye!')
|
|
286
|
-
prng.state.should == prng_copy.state
|
|
287
|
-
prng.read_bignum.should_not == prng_copy.read_bignum('Goodbye!')
|
|
288
|
-
prng.state.should == prng_copy.state
|
|
289
|
-
prng.read_bignum('Hello!').should_not == prng_copy.read_bignum
|
|
290
|
-
prng.state.should == prng_copy.state
|
|
291
|
-
prng.read_bignum('Hello','Goodbye').should_not == prng_copy.read_bignum
|
|
292
|
-
prng.state.should == prng_copy.state
|
|
293
|
-
# Verify that output remains same for next rolls
|
|
294
|
-
prng.read_bignum('Foobar','Wibble').should == prng_copy.read_bignum('Foobar','Wibble')
|
|
295
|
-
prng.state.should == prng_copy.state
|
|
296
|
-
prng.read_bignum.should == prng_copy.read_bignum
|
|
297
|
-
prng.state.should == prng_copy.state
|
|
298
|
-
end
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
describe "#read_float" do
|
|
304
|
-
it "always returns a Float between 0.0 (inclusive) and 1.0 (exclusive)" do
|
|
305
|
-
100.times do
|
|
306
|
-
num = prng.read_float
|
|
307
|
-
num.should be_a Float
|
|
308
|
-
num.should >= 0.0
|
|
309
|
-
num.should < 1.0
|
|
310
|
-
end
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
it "has a high probability of returning a different Float each time" do
|
|
314
|
-
Set[ *(1..100).map {prng.read_float} ].size.should == 100
|
|
315
|
-
end
|
|
316
|
-
|
|
317
|
-
describe "with adjustments" do
|
|
318
|
-
it "always returns a Float between 0.0 (inclusive) and 1.0 (exclusive)" do
|
|
319
|
-
100.times do
|
|
320
|
-
num = prng.read_float('Boom')
|
|
321
|
-
num.should be_a Float
|
|
322
|
-
num.should >= 0.0
|
|
323
|
-
num.should < 1.0
|
|
324
|
-
end
|
|
325
|
-
end
|
|
326
|
-
|
|
327
|
-
it "has a high probability of returning a different Float each time" do
|
|
328
|
-
Set[ *(1..100).map {prng.read_float('654321')} ].size.should == 100
|
|
329
|
-
end
|
|
330
|
-
|
|
331
|
-
it "changes output, but does not include adjustments in changes to state" do
|
|
332
|
-
prng_copy = prng.clone
|
|
333
|
-
10.times do
|
|
334
|
-
prng.read_float('Hello!').should == prng_copy.read_float('Hello!')
|
|
335
|
-
prng.state.should == prng_copy.state
|
|
336
|
-
prng.read_float('Hello!').should_not == prng_copy.read_float('Goodbye!')
|
|
337
|
-
prng.state.should == prng_copy.state
|
|
338
|
-
prng.read_float.should_not == prng_copy.read_float('Goodbye!')
|
|
339
|
-
prng.state.should == prng_copy.state
|
|
340
|
-
prng.read_float('Hello!').should_not == prng_copy.read_float
|
|
341
|
-
prng.state.should == prng_copy.state
|
|
342
|
-
prng.read_float('Hello','Goodbye').should_not == prng_copy.read_float
|
|
343
|
-
prng.state.should == prng_copy.state
|
|
344
|
-
# Verify that output remains same for next rolls
|
|
345
|
-
prng.read_float('Foobar','Wibble').should == prng_copy.read_float('Foobar','Wibble')
|
|
346
|
-
prng.state.should == prng_copy.state
|
|
347
|
-
prng.read_float.should == prng_copy.read_float
|
|
348
|
-
prng.state.should == prng_copy.state
|
|
349
|
-
end
|
|
350
|
-
end
|
|
351
|
-
end
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
describe "#generate_integer" do
|
|
355
|
-
it "always returns an integer between 0 (inclusive) and supplied top (exclusive)" do
|
|
356
|
-
100.times do
|
|
357
|
-
num = prng.generate_integer( 10 )
|
|
358
|
-
num.should be_a Fixnum
|
|
359
|
-
num.should >= 0
|
|
360
|
-
num.should < 10
|
|
361
|
-
end
|
|
362
|
-
|
|
363
|
-
100.times do
|
|
364
|
-
num = prng.generate_integer( 100 )
|
|
365
|
-
num.should be_a Fixnum
|
|
366
|
-
num.should >= 0
|
|
367
|
-
num.should < 100
|
|
368
|
-
end
|
|
369
|
-
|
|
370
|
-
100.times do
|
|
371
|
-
num = prng.generate_integer( 1000 )
|
|
372
|
-
num.should be_a Fixnum
|
|
373
|
-
num.should >= 0
|
|
374
|
-
num.should < 1000
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
100.times do
|
|
378
|
-
num = prng.generate_integer( 647218456 )
|
|
379
|
-
num.should be_a Fixnum
|
|
380
|
-
num.should >= 0
|
|
381
|
-
num.should < 647218456
|
|
382
|
-
end
|
|
383
|
-
end
|
|
384
|
-
|
|
385
|
-
it "can generate integers larger than 2**128" do
|
|
386
|
-
results = (0..100).map do
|
|
387
|
-
num = prng.generate_integer( 2 ** 1024 )
|
|
388
|
-
num.should >= 0
|
|
389
|
-
num.should < 2 ** 1024
|
|
390
|
-
num
|
|
391
|
-
end
|
|
392
|
-
results.select { |n| n > 2 ** 1020 }.count.should > 50
|
|
393
|
-
end
|
|
394
|
-
|
|
395
|
-
it "with a large enough value for top, has a high probability of returning a different integer each time" do
|
|
396
|
-
Set[ *(1..100).map {prng.generate_integer( 2**75 - 7 )} ].size.should == 100
|
|
397
|
-
end
|
|
398
|
-
|
|
399
|
-
it "covers a distribution 0...top" do
|
|
400
|
-
Set[ *(1..100).map {prng.generate_integer(10)} ].size.should == 10
|
|
401
|
-
end
|
|
402
|
-
|
|
403
|
-
describe "with adjustments" do
|
|
404
|
-
it "always returns an integer between 0 (inclusive) and supplied top (exclusive)" do
|
|
405
|
-
100.times do
|
|
406
|
-
num = prng.generate_integer( 10, 'jkffwe' )
|
|
407
|
-
num.should be_a Fixnum
|
|
408
|
-
num.should >= 0
|
|
409
|
-
num.should < 10
|
|
410
|
-
end
|
|
411
|
-
|
|
412
|
-
100.times do
|
|
413
|
-
num = prng.generate_integer( 100, 'jkffweefewg' )
|
|
414
|
-
num.should be_a Fixnum
|
|
415
|
-
num.should >= 0
|
|
416
|
-
num.should < 100
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
100.times do
|
|
420
|
-
num = prng.generate_integer( 1000, 'jkffweefewg', 'efhwjkfgw' )
|
|
421
|
-
num.should be_a Fixnum
|
|
422
|
-
num.should >= 0
|
|
423
|
-
num.should < 1000
|
|
424
|
-
end
|
|
425
|
-
|
|
426
|
-
100.times do
|
|
427
|
-
num = prng.generate_integer( 647218456, 'j*****g', 'efhwjkfgw' )
|
|
428
|
-
num.should be_a Fixnum
|
|
429
|
-
num.should >= 0
|
|
430
|
-
num.should < 647218456
|
|
431
|
-
end
|
|
432
|
-
end
|
|
433
|
-
|
|
434
|
-
it "with a large enough value for top, has a high probability of returning a different integer each time" do
|
|
435
|
-
Set[ *(1..100).map {prng.generate_integer( 2**80 - 5, '654321')} ].size.should == 100
|
|
436
|
-
end
|
|
437
|
-
|
|
438
|
-
it "changes output, but does not include adjustments in changes to state" do
|
|
439
|
-
prng_copy = prng.clone
|
|
440
|
-
big = 2 ** 64 - 3
|
|
441
|
-
small = 20
|
|
442
|
-
10.times do
|
|
443
|
-
prng.generate_integer( small, 'Hello!').should == prng_copy.generate_integer( small, 'Hello!')
|
|
444
|
-
prng.state.should == prng_copy.state
|
|
445
|
-
prng.generate_integer( big, 'Hello!').should_not == prng_copy.generate_integer( big, 'Goodbye!')
|
|
446
|
-
prng.state.should == prng_copy.state
|
|
447
|
-
prng.generate_integer( big ).should_not == prng_copy.generate_integer( big, 'Goodbye!')
|
|
448
|
-
prng.state.should == prng_copy.state
|
|
449
|
-
prng.generate_integer( big, 'Hello!').should_not == prng_copy.generate_integer( big )
|
|
450
|
-
prng.state.should == prng_copy.state
|
|
451
|
-
prng.generate_integer( big, 'Hello','Goodbye').should_not == prng_copy.generate_integer( big )
|
|
452
|
-
prng.state.should == prng_copy.state
|
|
453
|
-
# Verify that output remains same for next rolls
|
|
454
|
-
prng.generate_integer( small, 'Foobar','Wibble').should == prng_copy.generate_integer( small, 'Foobar','Wibble')
|
|
455
|
-
prng.state.should == prng_copy.state
|
|
456
|
-
prng.generate_integer( big ).should == prng_copy.generate_integer( big )
|
|
457
|
-
prng.state.should == prng_copy.state
|
|
458
|
-
end
|
|
459
|
-
end
|
|
460
|
-
end
|
|
461
|
-
end
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
describe "all read methods" do
|
|
465
|
-
|
|
466
|
-
it "generate higher and lower values in sync" do
|
|
467
|
-
prngs = (0..4).map { prng.clone }
|
|
468
|
-
results = (1..20).map do
|
|
469
|
-
Hash[
|
|
470
|
-
:bytes => prngs[0].read_bytes,
|
|
471
|
-
:hex => prngs[1].read_hex,
|
|
472
|
-
:float => prngs[2].read_float,
|
|
473
|
-
:num => prngs[3].read_bignum,
|
|
474
|
-
:int => prngs[4].generate_integer( 1_000_000_000 ),
|
|
475
|
-
]
|
|
476
|
-
end
|
|
477
|
-
results.sort_by { |h| h[:int] }.should == results.sort_by { |h| h[:hex] }
|
|
478
|
-
results.sort_by { |h| h[:float] }.should == results.sort_by { |h| h[:hex] }
|
|
479
|
-
results.sort_by { |h| h[:num] }.should == results.sort_by { |h| h[:bytes] }
|
|
480
|
-
results.sort_by { |h| h[:float] }.should == results.sort_by { |h| h[:int] }
|
|
481
|
-
end
|
|
482
|
-
end
|
|
483
|
-
|
|
484
|
-
end
|
|
485
|
-
end
|
|
486
|
-
|
|
487
|
-
describe "using predictable sequences" do
|
|
488
|
-
it "generates expected hex strings from simple zeroed pool" do
|
|
489
|
-
prng = PoolOfEntropy::CorePRNG.new( 1, "\x0" * 64 )
|
|
490
|
-
(0..24).map { prng.read_hex }.should == [ "da0cd77eb1c84458ddcc91e36b9dcb35",
|
|
491
|
-
"498ec24d1126440047eed396d836b5e1", "0b90df55c5e7c1513b072367eae4a4ce",
|
|
492
|
-
"f12b5b54b5594e785bbb9a4ac50ccec8", "d506bd4e201a00dc30499bd8e59a30d8",
|
|
493
|
-
"2557893cf995fe43bd00721fce6ab16a", "41ee50244cdd02334bafc3e9d8f564d9",
|
|
494
|
-
"8156c7c7bcfd856cb9d1012243cfc662", "1116f840e2aee924bd2c7d722c602635",
|
|
495
|
-
"96cf31967465b83f5ef3476c60afe20a", "f041f6df72aa2eab7394f08e83d52a0c",
|
|
496
|
-
"5ccbb30077f2433bd765ddc86840a880", "6a4339fd5d445024048ea8f91a3e02fd",
|
|
497
|
-
"707e9499b9f0e9e906a0c0ddd0530803", "553704d95703284df323f0aa4244cf81",
|
|
498
|
-
"cb1522ce0bdf2504fdd62df7416be73e", "05c4932cb9d3a7c0675b0228826e661a",
|
|
499
|
-
"59606f23e34e726a7912dacfde533d97", "188cf17dde6947264ce05f8274874ffa",
|
|
500
|
-
"24c184b56453891657953f557635b742", "a5f969e50228b2ee0f38cc37c5033541",
|
|
501
|
-
"f1de0e5d149cc5a7f0e38c0ee501d7bc", "5ca3a6beb0b810568be83ab2179eb550",
|
|
502
|
-
"756fb9c58277eb8c6092142224caecf4", "0ed9505eadb3def60ec42051f0bf15ef" ]
|
|
503
|
-
end
|
|
504
|
-
|
|
505
|
-
it "generates expected hex strings from simple zeroed pool and an adjustment" do
|
|
506
|
-
prng = PoolOfEntropy::CorePRNG.new( 1, "\x0" * 64 )
|
|
507
|
-
(0..24).map { prng.read_hex( 'bananas' ) }.should == [
|
|
508
|
-
"fed9de9a612f4157ebb49582ca557a50", "a7adc2374a4df2ed67846ac09a3b6645",
|
|
509
|
-
"cbdf8bbbe6145751fe14004719915160", "8cd84be95376f72918c305bdea43e36d",
|
|
510
|
-
"9e08e80ff40c942f0cf4d479b5378fa0", "54d80c5330873f9733a0adef0197220f",
|
|
511
|
-
"2abe07bd85d2066a624dd3630e59730a", "88b6a697fe74aeb8ec83845e103b7b63",
|
|
512
|
-
"9c6c9d613855f6535adb419cc564fd10", "23f9b778b254035a0e4219423a52da77",
|
|
513
|
-
"4cd50c14ee17fa29c8b1f209432a36b3", "2b5646b164d863de716f67adef653859",
|
|
514
|
-
"fd81d0bbbd2828ecdfcba0b486ef786c", "08e6594fc277ff7fafbf37475ecadbf6",
|
|
515
|
-
"5e2333ecc800eb9a06e347924ed42e94", "8a14e48013028b2c9f174a07ddd5ef49",
|
|
516
|
-
"e9a5c331f54b155f570c2cf2bcd37209", "1ce84279195a5b23ffeb3063edbfab21",
|
|
517
|
-
"7422e19e58f2fcf20805f601266bf676", "8df0226465b74d830360ea8609d181bf",
|
|
518
|
-
"3e5d5e8cf8ad032fb4005826bdf7bb94", "65e3f9ab28c26bead6647c21bcc6245e",
|
|
519
|
-
"8ed5d8892d464ebeaa8dcbcef0968936", "2f000bc1ab14d914196cc1d5055db189",
|
|
520
|
-
"8e9c4b8152f14e47ac31f25a80765ebf" ]
|
|
521
|
-
end
|
|
522
|
-
|
|
523
|
-
it "generates expected hex strings from simple zeroed pool and alternating adjustments" do
|
|
524
|
-
prng = PoolOfEntropy::CorePRNG.new( 1, "\x0" * 64 )
|
|
525
|
-
(0..24).map { |x| x.odd? ? prng.read_hex( 'bananas', x.to_s ) : prng.read_hex }.should == [
|
|
526
|
-
"da0cd77eb1c84458ddcc91e36b9dcb35", "de4b20a0560263090c6fe11ebba6256e",
|
|
527
|
-
"0b90df55c5e7c1513b072367eae4a4ce", "0c92d534160cb268cb3282a9dd3f1efe",
|
|
528
|
-
"d506bd4e201a00dc30499bd8e59a30d8", "089f799236a9cf64f22f1deafbe28214",
|
|
529
|
-
"41ee50244cdd02334bafc3e9d8f564d9", "84477b9a3d51bb72868ccb85bea71cad",
|
|
530
|
-
"1116f840e2aee924bd2c7d722c602635", "469e4bb2f38719c7f85d79c8900a8fa8",
|
|
531
|
-
"f041f6df72aa2eab7394f08e83d52a0c", "e21bf2508b8e1755ae70c74c0d36ec2e",
|
|
532
|
-
"6a4339fd5d445024048ea8f91a3e02fd", "a94a80c80c9edd95808a67775c2b42d4",
|
|
533
|
-
"553704d95703284df323f0aa4244cf81", "edd6aea5bda7b2d9c494067c5cdbe410",
|
|
534
|
-
"05c4932cb9d3a7c0675b0228826e661a", "cf81635ca2fa910fd11cf45508dc658b",
|
|
535
|
-
"188cf17dde6947264ce05f8274874ffa", "bb4aaeb98e13400c1216c674a872ba93",
|
|
536
|
-
"a5f969e50228b2ee0f38cc37c5033541", "1a795355f979575247b3fa9c92d97917",
|
|
537
|
-
"5ca3a6beb0b810568be83ab2179eb550", "1a98419cca1dd1b370ce8a4a2ab721b7",
|
|
538
|
-
"0ed9505eadb3def60ec42051f0bf15ef" ]
|
|
539
|
-
end
|
|
540
|
-
end
|
|
541
|
-
end
|
|
542
|
-
|
|
543
|
-
end
|