chars 0.2.4 → 0.3.1

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.
@@ -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"