chars 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
  require 'chars/char_set'
3
3
 
4
+ require 'securerandom'
5
+
4
6
  describe Chars::CharSet do
5
7
  let(:integer_range) { (0x41..0x43) }
6
8
  let(:string_range) { ('A'..'Z') }
@@ -91,120 +93,311 @@ describe Chars::CharSet do
91
93
  it "should return a random byte" do
92
94
  expect(subject).to include(subject.random_byte)
93
95
  end
96
+
97
+ context "when given random: rng" do
98
+ let(:rng) { SecureRandom }
99
+
100
+ it "must call the #rand method" do
101
+ expect(rng).to receive(:rand).with(subject.length).and_return(1)
102
+
103
+ subject.random_byte(random: rng)
104
+ end
105
+ end
94
106
  end
95
107
 
96
108
  describe "#random_char" do
97
109
  it "should return a random char" do
98
110
  expect(subject.include_char?(subject.random_char)).to be(true)
99
111
  end
112
+
113
+ context "when given random: rng" do
114
+ let(:rng) { SecureRandom }
115
+
116
+ it "must call the #rand method" do
117
+ expect(rng).to receive(:rand).with(subject.length).and_return(1)
118
+
119
+ subject.random_char(random: rng)
120
+ end
121
+ end
100
122
  end
101
123
 
102
124
  describe "#each_random_byte" do
125
+ let(:n) { 10 }
126
+
103
127
  it "should iterate over n random bytes" do
104
- expect(subject.each_random_byte(10).all? { |b|
128
+ expect(subject.each_random_byte(n).all? { |b|
105
129
  subject.include?(b)
106
130
  }).to be(true)
107
131
  end
132
+
133
+ context "when given random: rng" do
134
+ let(:rng) { SecureRandom }
135
+
136
+ it "must call the #rand method n times" do
137
+ n.times do
138
+ expect(rng).to receive(:rand).with(subject.length).and_return(1)
139
+ end
140
+
141
+ subject.each_random_byte(n, random: rng) { |b| }
142
+ end
143
+ end
108
144
  end
109
145
 
110
146
  describe "#each_random_char" do
147
+ let(:n) { 10 }
148
+
111
149
  it "should iterate over n random chars" do
112
150
  expect(subject.each_random_char(10).all? { |c|
113
151
  subject.include_char?(c)
114
152
  }).to be(true)
115
153
  end
154
+
155
+ context "when given random: rng" do
156
+ let(:rng) { SecureRandom }
157
+
158
+ it "must call the #rand method n times" do
159
+ n.times do
160
+ expect(rng).to receive(:rand).with(subject.length).and_return(1)
161
+ end
162
+
163
+ subject.each_random_char(n, random: rng) { |c| }
164
+ end
165
+ end
116
166
  end
117
167
 
118
168
  describe "#random_bytes" do
119
- it "should return a random Array of bytes" do
120
- random_bytes = subject.random_bytes(10)
169
+ context "when given an Integer" do
170
+ let(:n) { 10 }
121
171
 
122
- expect(random_bytes.all? { |b| subject.include?(b) }).to be(true)
172
+ it "should return a random Array of bytes" do
173
+ random_bytes = subject.random_bytes(n)
174
+
175
+ expect(random_bytes.all? { |b| subject.include?(b) }).to be(true)
176
+ end
177
+
178
+ context "when given random: rng" do
179
+ let(:rng) { SecureRandom }
180
+
181
+ it "must call the #rand method n times" do
182
+ n.times do
183
+ expect(rng).to receive(:rand).with(subject.length).and_return(1)
184
+ end
185
+
186
+ subject.random_bytes(n, random: rng)
187
+ end
188
+ end
123
189
  end
124
190
 
125
- context "with a range of lengths" do
191
+ context "when given a Range of lengths" do
192
+ let(:lengths) { 5..10 }
193
+
126
194
  it "should return a random Array of bytes with a varying length" do
127
- random_bytes = subject.random_bytes(5..10)
195
+ random_bytes = subject.random_bytes(lengths)
128
196
 
129
- expect(random_bytes.length).to be_between(5, 10)
197
+ expect(random_bytes.length).to be_between(lengths.begin, lengths.end)
130
198
  expect(random_bytes.all? { |b| subject.include?(b) }).to be(true)
131
199
  end
200
+
201
+ context "and when given random: rng" do
202
+ let(:rng) { SecureRandom }
203
+
204
+ it "must pass random: to Range#sample" do
205
+ expect(rng).to receive(:rand).and_return(rand(lengths)).at_least(:once)
206
+
207
+ random_bytes = subject.random_bytes(lengths, random: rng)
208
+
209
+ expect(random_bytes.length).to be_between(lengths.begin, lengths.end)
210
+ end
211
+ end
132
212
  end
133
213
  end
134
214
 
135
215
  describe "#random_chars" do
136
- it "should return a random Array of chars" do
137
- random_chars = subject.random_chars(10)
216
+ context "when given an Integer" do
217
+ let(:n) { 10 }
138
218
 
139
- expect(random_chars.all? { |c| subject.include_char?(c) }).to be(true)
219
+ it "should return a random Array of chars" do
220
+ random_chars = subject.random_chars(n)
221
+
222
+ expect(random_chars.all? { |c| subject.include_char?(c) }).to be(true)
223
+ end
224
+
225
+ context "when given random: rng" do
226
+ let(:rng) { SecureRandom }
227
+
228
+ it "must call the #rand method n times" do
229
+ n.times do
230
+ expect(rng).to receive(:rand).with(subject.length).and_return(rand(n))
231
+ end
232
+
233
+ subject.random_chars(n, random: rng)
234
+ end
235
+ end
140
236
  end
141
237
 
142
- context "with a range of lengths" do
238
+ context "when given a Range of lengths" do
239
+ let(:lengths) { 5..10 }
240
+
143
241
  it "should return a random Array of chars with a varying length" do
144
- random_chars = subject.random_chars(5..10)
242
+ random_chars = subject.random_chars(lengths)
145
243
 
146
- expect(random_chars.length).to be_between(5, 10)
244
+ expect(random_chars.length).to be_between(lengths.begin, lengths.end)
147
245
  expect(random_chars.all? { |c| subject.include_char?(c) }).to be(true)
148
246
  end
247
+
248
+ context "and when given random: rng" do
249
+ let(:rng) { SecureRandom }
250
+
251
+ it "must pass random: to Range#sample" do
252
+ expect(rng).to receive(:rand).and_return(rand(lengths)).at_least(:once)
253
+
254
+ random_chars = subject.random_chars(lengths, random: rng)
255
+
256
+ expect(random_chars.length).to be_between(lengths.begin, lengths.end)
257
+ end
258
+ end
149
259
  end
150
260
  end
151
261
 
152
262
  describe "#random_string" do
153
- it "should return a random String of chars" do
154
- random_string = subject.random_string(10)
263
+ context "when given an Integer" do
264
+ let(:n) { 10 }
155
265
 
156
- expect(random_string.chars.all? { |b|
157
- subject.include_char?(b)
158
- }).to be(true)
266
+ it "should return a random String of chars" do
267
+ random_string = subject.random_string(n)
268
+
269
+ expect(random_string.chars.all? { |b|
270
+ subject.include_char?(b)
271
+ }).to be(true)
272
+ end
273
+
274
+ context "when given random: rng" do
275
+ let(:rng) { SecureRandom }
276
+
277
+ it "must call the #rand method n times" do
278
+ expect(rng).to receive(:rand).with(subject.length).and_return(rand(n)).at_least(:once)
279
+
280
+ subject.random_chars(n, random: rng)
281
+ end
282
+ end
159
283
  end
160
284
 
161
- context "with a range of lengths" do
285
+ context "when given a Range of lengths" do
286
+ let(:lengths) { 5..10 }
287
+
162
288
  it "should return a random String of chars with a varying length" do
163
- random_string = subject.random_string(5..10)
289
+ random_string = subject.random_string(lengths)
164
290
 
165
- expect(random_string.length).to be_between(5, 10)
291
+ expect(random_string.length).to be_between(lengths.begin, lengths.end)
166
292
  expect(random_string.chars.all? { |b|
167
293
  subject.include_char?(b)
168
294
  }).to be(true)
169
295
  end
296
+
297
+ context "and when given random: rng" do
298
+ let(:rng) { SecureRandom }
299
+
300
+ it "must pass random: to Range#sample" do
301
+ expect(rng).to receive(:rand).and_return(rand(lengths)).at_least(:once)
302
+
303
+ random_string = subject.random_string(lengths, random: rng)
304
+
305
+ expect(random_string.length).to be_between(lengths.begin, lengths.end)
306
+ end
307
+ end
170
308
  end
171
309
  end
172
310
 
173
311
  describe "#random_distinct_bytes" do
174
- it "should return a random Array of unique bytes" do
175
- random_bytes = subject.random_distinct_bytes(10)
312
+ context "when given an Integer" do
313
+ let(:n) { 10 }
314
+
315
+ it "should return a random Array of unique bytes" do
316
+ random_bytes = subject.random_distinct_bytes(n)
317
+
318
+ expect(random_bytes.length).to eq(n)
319
+ expect(random_bytes.uniq).to be == random_bytes
320
+ expect(random_bytes.all? { |b| subject.include_byte?(b) }).to be(true)
321
+ end
322
+
323
+ context "when given random: rng" do
324
+ let(:rng) { SecureRandom }
325
+
326
+ it "must call the Array#shuffle with random: rng" do
327
+ expect_any_instance_of(Array).to receive(:shuffle).with(random: rng).and_return(subject.bytes.shuffle)
176
328
 
177
- expect(random_bytes.uniq).to be == random_bytes
178
- expect(random_bytes.all? { |b| subject.include_byte?(b) }).to be(true)
329
+ subject.random_distinct_bytes(n, random: rng)
330
+ end
331
+ end
179
332
  end
180
333
 
181
334
  context "with a Range of lengths" do
335
+ let(:lengths) { 5..10 }
336
+
182
337
  it "should return a random Array of unique bytes with a varying length" do
183
- random_bytes = subject.random_distinct_bytes(5..10)
338
+ random_bytes = subject.random_distinct_bytes(lengths)
184
339
 
185
340
  expect(random_bytes.uniq).to be == random_bytes
186
- expect(random_bytes.length).to be_between(5, 10)
341
+ expect(random_bytes.length).to be_between(lengths.begin, lengths.end)
187
342
  expect(random_bytes.all? { |b| subject.include_byte?(b) }).to be(true)
188
343
  end
344
+
345
+ context "and when given random: rng" do
346
+ let(:rng) { SecureRandom }
347
+
348
+ it "must pass random: to Range#sample" do
349
+ expect(rng).to receive(:rand).and_return(rand(lengths)).at_least(:once)
350
+
351
+ random_bytes = subject.random_bytes(lengths, random: rng)
352
+
353
+ expect(random_bytes.length).to be_between(lengths.begin, lengths.end)
354
+ end
355
+ end
189
356
  end
190
357
  end
191
358
 
192
359
  describe "#random_distinct_chars" do
360
+ let(:n) { 10 }
361
+
193
362
  it "should return a random Array of unique chars" do
194
- random_chars = subject.random_distinct_chars(10)
363
+ random_chars = subject.random_distinct_chars(n)
195
364
 
196
365
  expect(random_chars.uniq).to be == random_chars
197
366
  expect(random_chars.all? { |c| subject.include_char?(c) }).to be(true)
198
367
  end
199
368
 
200
- context "with a range of lengths" do
369
+ context "when given random: rng" do
370
+ let(:rng) { SecureRandom }
371
+
372
+ it "must call the Array#shuffle with random: rng" do
373
+ expect_any_instance_of(Array).to receive(:shuffle).with(random: rng).and_return(subject.bytes.shuffle(random: rng))
374
+
375
+ subject.random_distinct_bytes(n, random: rng)
376
+ end
377
+ end
378
+
379
+ context "when given a Range of lengths" do
380
+ let(:lengths) { 5..10 }
381
+
201
382
  it "should return a random Array of unique chars with a varying length" do
202
- random_chars = subject.random_distinct_chars(5..10)
383
+ random_chars = subject.random_distinct_chars(lengths)
203
384
 
204
385
  expect(random_chars.uniq).to be == random_chars
205
- expect(random_chars.length).to be_between(5, 10)
386
+ expect(random_chars.length).to be_between(lengths.begin, lengths.end)
206
387
  expect(random_chars.all? { |c| subject.include_char?(c) }).to be(true)
207
388
  end
389
+
390
+ context "and when given random: rng" do
391
+ let(:rng) { SecureRandom }
392
+
393
+ it "must pass random: to Range#sample" do
394
+ expect(rng).to receive(:rand).and_return(rand(lengths)).at_least(:once)
395
+
396
+ random_bytes = subject.random_bytes(lengths, random: rng)
397
+
398
+ expect(random_bytes.length).to be_between(lengths.begin, lengths.end)
399
+ end
400
+ end
208
401
  end
209
402
  end
210
403
 
@@ -232,6 +425,131 @@ describe Chars::CharSet do
232
425
  end
233
426
  end
234
427
 
428
+ describe "#each_substring_with_index" do
429
+ subject { described_class.new(['A', 'B', 'C']) }
430
+
431
+ let(:string) { "....AAAA....BBBB....CCCC...." }
432
+
433
+ it "must yield each matching substring and index" do
434
+ expect { |b|
435
+ subject.each_substring_with_index(string,&b)
436
+ }.to yield_successive_args(
437
+ ["AAAA", string.index("AAAA")],
438
+ ["BBBB", string.index("BBBB")],
439
+ ["CCCC", string.index("CCCC")]
440
+ )
441
+ end
442
+
443
+ context "when the string begins with a matching substring" do
444
+ let(:string) { "AAAA...." }
445
+
446
+ it "must yield the first matching substring" do
447
+ expect(subject.each_substring_with_index(string).first).to eq(
448
+ ["AAAA", 0]
449
+ )
450
+ end
451
+ end
452
+
453
+ context "when the string ends with a matching substring" do
454
+ let(:string) { "AAAA....BBBB....CCCC" }
455
+
456
+ it "must yield the last matching substring" do
457
+ expect(subject.each_substring_with_index(string).to_a.last).to eq(
458
+ ["CCCC", string.rindex("CCCC")]
459
+ )
460
+ end
461
+ end
462
+
463
+ context "when the entire string is a matching substring" do
464
+ let(:string) { "AAAAAAAA" }
465
+
466
+ it "must yield the entire string" do
467
+ expect { |b|
468
+ subject.each_substring_with_index(string,&b)
469
+ }.to yield_successive_args( [string, 0] )
470
+ end
471
+ end
472
+
473
+ context "when the matching substrings are shorter than the min_length" do
474
+ let(:min_length) { 2 }
475
+
476
+ let(:string) { "AA..B...CC.."}
477
+
478
+ it "must ignore the substrings shorter than min_length" do
479
+ expect { |b|
480
+ subject.each_substring_with_index(string, min_length: min_length, &b)
481
+ }.to yield_successive_args(
482
+ ["AA", string.index("AA")],
483
+ ["CC", string.index("CC")]
484
+ )
485
+ end
486
+ end
487
+
488
+ context "when min_length 0" do
489
+ let(:min_length) { 0 }
490
+
491
+ let(:string) { "A.BB..CCC..."}
492
+
493
+ it "must yield all matching substrings, regardless of length" do
494
+ expect { |b|
495
+ subject.each_substring_with_index(string, min_length: min_length, &b)
496
+ }.to yield_successive_args(
497
+ ["A", string.index("A")],
498
+ ["BB", string.index("BB")],
499
+ ["CCC", string.index("CCC")]
500
+ )
501
+ end
502
+ end
503
+ end
504
+
505
+ describe "#substrings_with_indexes" do
506
+ subject { described_class.new(['A', 'B', 'C']) }
507
+
508
+ let(:string) { "....AAAA....BBBB....CCCC...." }
509
+
510
+ it "must return the Array of substrings and their indexes" do
511
+ expect(subject.substrings_with_indexes(string)).to eq(
512
+ [
513
+ ["AAAA", string.index("AAAA")],
514
+ ["BBBB", string.index("BBBB")],
515
+ ["CCCC", string.index("CCCC")]
516
+ ]
517
+ )
518
+ end
519
+ end
520
+
521
+ describe "#each_substring(&block : (String) ->)" do
522
+ subject { described_class.new(['A', 'B', 'C']) }
523
+
524
+ let(:string) { "....AAAA....BBBB....CCCC...." }
525
+
526
+ it "must yield each matching substring" do
527
+ expect { |b|
528
+ subject.each_substring(string,&b)
529
+ }.to yield_successive_args(
530
+ "AAAA",
531
+ "BBBB",
532
+ "CCCC"
533
+ )
534
+ end
535
+ end
536
+
537
+ describe "#substrings" do
538
+ subject { described_class.new(['A', 'B', 'C']) }
539
+
540
+ let(:string) { "....AAAA....BBBB....CCCC...." }
541
+
542
+ it "must return the Array of matching substrings" do
543
+ expect(subject.substrings(string)).to eq(
544
+ [
545
+ "AAAA",
546
+ "BBBB",
547
+ "CCCC"
548
+ ]
549
+ )
550
+ end
551
+ end
552
+
235
553
  describe "#strings_in" do
236
554
  subject { described_class.new(['A', 'B', 'C']) }
237
555
 
@@ -314,6 +632,72 @@ describe Chars::CharSet do
314
632
  end
315
633
  end
316
634
 
635
+ describe "#each_string" do
636
+ let(:length) { 2 }
637
+
638
+ let(:expected_strings) do
639
+ Chars::StringEnumerator.new(subject,length).to_a
640
+ end
641
+
642
+ context "when a block is given" do
643
+ it "must enumerate through the strings belonging to the character set of the desired length" do
644
+ expect { |b|
645
+ subject.each_string_of_length(length,&b)
646
+ }.to yield_successive_args(*expected_strings)
647
+ end
648
+
649
+ context "when given a Range of lengths" do
650
+ let(:length) { 1..2 }
651
+
652
+ let(:expected_strings) do
653
+ Chars::StringEnumerator.new(subject,1).to_a +
654
+ Chars::StringEnumerator.new(subject,2).to_a
655
+ end
656
+
657
+ it "must yield strings of lengths in the Range of lengths" do
658
+ expect { |b|
659
+ subject.each_string_of_length(length,&b)
660
+ }.to yield_successive_args(*expected_strings)
661
+ end
662
+ end
663
+
664
+ context "when given an Array of lengths" do
665
+ let(:length) { [1,2] }
666
+
667
+ let(:expected_strings) do
668
+ Chars::StringEnumerator.new(subject,1).to_a +
669
+ Chars::StringEnumerator.new(subject,2).to_a
670
+ end
671
+
672
+ it "must yield strings of lengths in the Range of lengths" do
673
+ expect { |b|
674
+ subject.each_string_of_length(length,&b)
675
+ }.to yield_successive_args(*expected_strings)
676
+ end
677
+ end
678
+ end
679
+
680
+ context "when no block is given" do
681
+ it "must return an Enumerator" do
682
+ expect(subject.each_string_of_length(length)).to be_kind_of(Enumerator)
683
+ expect(subject.each_string_of_length(length).to_a).to eq(expected_strings)
684
+ end
685
+ end
686
+ end
687
+
688
+ describe "#strings_of_length" do
689
+ let(:length) { 2 }
690
+
691
+ let(:expected_strings) do
692
+ Chars::StringEnumerator.new(subject,length).to_a
693
+ end
694
+
695
+ it "must return an Enumerator" do
696
+ expect(subject.strings_of_length(length)).to be_kind_of(Enumerator)
697
+ expect(subject.strings_of_length(length).to_a).to eq(expected_strings)
698
+ end
699
+ end
700
+
317
701
  describe "#===" do
318
702
  it "should determine if a String is made up of the characters from the char set" do
319
703
  expect(subject).to be === "AABCBAA"