spec/char_set_spec.rb in chars-0.2.4 vs spec/char_set_spec.rb in chars-0.3.0
- old
+ new
@@ -1,8 +1,10 @@
require 'spec_helper'
require 'chars/char_set'
+require 'securerandom'
+
describe Chars::CharSet do
let(:integer_range) { (0x41..0x43) }
let(:string_range) { ('A'..'Z') }
let(:integers) { integer_range.to_a }
let(:strings) { string_range.to_a }
@@ -89,124 +91,315 @@
describe "#random_byte" do
it "should return a random byte" do
expect(subject).to include(subject.random_byte)
end
+
+ context "when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must call the #rand method" do
+ expect(rng).to receive(:rand).with(subject.length).and_return(1)
+
+ subject.random_byte(random: rng)
+ end
+ end
end
describe "#random_char" do
it "should return a random char" do
expect(subject.include_char?(subject.random_char)).to be(true)
end
+
+ context "when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must call the #rand method" do
+ expect(rng).to receive(:rand).with(subject.length).and_return(1)
+
+ subject.random_char(random: rng)
+ end
+ end
end
describe "#each_random_byte" do
+ let(:n) { 10 }
+
it "should iterate over n random bytes" do
- expect(subject.each_random_byte(10).all? { |b|
+ expect(subject.each_random_byte(n).all? { |b|
subject.include?(b)
}).to be(true)
end
+
+ context "when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must call the #rand method n times" do
+ n.times do
+ expect(rng).to receive(:rand).with(subject.length).and_return(1)
+ end
+
+ subject.each_random_byte(n, random: rng) { |b| }
+ end
+ end
end
describe "#each_random_char" do
+ let(:n) { 10 }
+
it "should iterate over n random chars" do
expect(subject.each_random_char(10).all? { |c|
subject.include_char?(c)
}).to be(true)
end
+
+ context "when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must call the #rand method n times" do
+ n.times do
+ expect(rng).to receive(:rand).with(subject.length).and_return(1)
+ end
+
+ subject.each_random_char(n, random: rng) { |c| }
+ end
+ end
end
describe "#random_bytes" do
- it "should return a random Array of bytes" do
- random_bytes = subject.random_bytes(10)
+ context "when given an Integer" do
+ let(:n) { 10 }
- expect(random_bytes.all? { |b| subject.include?(b) }).to be(true)
+ it "should return a random Array of bytes" do
+ random_bytes = subject.random_bytes(n)
+
+ expect(random_bytes.all? { |b| subject.include?(b) }).to be(true)
+ end
+
+ context "when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must call the #rand method n times" do
+ n.times do
+ expect(rng).to receive(:rand).with(subject.length).and_return(1)
+ end
+
+ subject.random_bytes(n, random: rng)
+ end
+ end
end
- context "with a range of lengths" do
+ context "when given a Range of lengths" do
+ let(:lengths) { 5..10 }
+
it "should return a random Array of bytes with a varying length" do
- random_bytes = subject.random_bytes(5..10)
+ random_bytes = subject.random_bytes(lengths)
- expect(random_bytes.length).to be_between(5, 10)
+ expect(random_bytes.length).to be_between(lengths.begin, lengths.end)
expect(random_bytes.all? { |b| subject.include?(b) }).to be(true)
end
+
+ context "and when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must pass random: to Range#sample" do
+ expect(rng).to receive(:rand).and_return(rand(lengths)).at_least(:once)
+
+ random_bytes = subject.random_bytes(lengths, random: rng)
+
+ expect(random_bytes.length).to be_between(lengths.begin, lengths.end)
+ end
+ end
end
end
describe "#random_chars" do
- it "should return a random Array of chars" do
- random_chars = subject.random_chars(10)
+ context "when given an Integer" do
+ let(:n) { 10 }
- expect(random_chars.all? { |c| subject.include_char?(c) }).to be(true)
+ it "should return a random Array of chars" do
+ random_chars = subject.random_chars(n)
+
+ expect(random_chars.all? { |c| subject.include_char?(c) }).to be(true)
+ end
+
+ context "when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must call the #rand method n times" do
+ n.times do
+ expect(rng).to receive(:rand).with(subject.length).and_return(rand(n))
+ end
+
+ subject.random_chars(n, random: rng)
+ end
+ end
end
- context "with a range of lengths" do
+ context "when given a Range of lengths" do
+ let(:lengths) { 5..10 }
+
it "should return a random Array of chars with a varying length" do
- random_chars = subject.random_chars(5..10)
+ random_chars = subject.random_chars(lengths)
- expect(random_chars.length).to be_between(5, 10)
+ expect(random_chars.length).to be_between(lengths.begin, lengths.end)
expect(random_chars.all? { |c| subject.include_char?(c) }).to be(true)
end
+
+ context "and when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must pass random: to Range#sample" do
+ expect(rng).to receive(:rand).and_return(rand(lengths)).at_least(:once)
+
+ random_chars = subject.random_chars(lengths, random: rng)
+
+ expect(random_chars.length).to be_between(lengths.begin, lengths.end)
+ end
+ end
end
end
describe "#random_string" do
- it "should return a random String of chars" do
- random_string = subject.random_string(10)
+ context "when given an Integer" do
+ let(:n) { 10 }
- expect(random_string.chars.all? { |b|
- subject.include_char?(b)
- }).to be(true)
+ it "should return a random String of chars" do
+ random_string = subject.random_string(n)
+
+ expect(random_string.chars.all? { |b|
+ subject.include_char?(b)
+ }).to be(true)
+ end
+
+ context "when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must call the #rand method n times" do
+ expect(rng).to receive(:rand).with(subject.length).and_return(rand(n)).at_least(:once)
+
+ subject.random_chars(n, random: rng)
+ end
+ end
end
- context "with a range of lengths" do
+ context "when given a Range of lengths" do
+ let(:lengths) { 5..10 }
+
it "should return a random String of chars with a varying length" do
- random_string = subject.random_string(5..10)
+ random_string = subject.random_string(lengths)
- expect(random_string.length).to be_between(5, 10)
+ expect(random_string.length).to be_between(lengths.begin, lengths.end)
expect(random_string.chars.all? { |b|
subject.include_char?(b)
}).to be(true)
end
+
+ context "and when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must pass random: to Range#sample" do
+ expect(rng).to receive(:rand).and_return(rand(lengths)).at_least(:once)
+
+ random_string = subject.random_string(lengths, random: rng)
+
+ expect(random_string.length).to be_between(lengths.begin, lengths.end)
+ end
+ end
end
end
describe "#random_distinct_bytes" do
- it "should return a random Array of unique bytes" do
- random_bytes = subject.random_distinct_bytes(10)
+ context "when given an Integer" do
+ let(:n) { 10 }
- expect(random_bytes.uniq).to be == random_bytes
- expect(random_bytes.all? { |b| subject.include_byte?(b) }).to be(true)
+ it "should return a random Array of unique bytes" do
+ random_bytes = subject.random_distinct_bytes(n)
+
+ expect(random_bytes.length).to eq(n)
+ expect(random_bytes.uniq).to be == random_bytes
+ expect(random_bytes.all? { |b| subject.include_byte?(b) }).to be(true)
+ end
+
+ context "when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must call the Array#shuffle with random: rng" do
+ expect_any_instance_of(Array).to receive(:shuffle).with(random: rng).and_return(subject.bytes.shuffle)
+
+ subject.random_distinct_bytes(n, random: rng)
+ end
+ end
end
context "with a Range of lengths" do
+ let(:lengths) { 5..10 }
+
it "should return a random Array of unique bytes with a varying length" do
- random_bytes = subject.random_distinct_bytes(5..10)
+ random_bytes = subject.random_distinct_bytes(lengths)
expect(random_bytes.uniq).to be == random_bytes
- expect(random_bytes.length).to be_between(5, 10)
+ expect(random_bytes.length).to be_between(lengths.begin, lengths.end)
expect(random_bytes.all? { |b| subject.include_byte?(b) }).to be(true)
end
+
+ context "and when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must pass random: to Range#sample" do
+ expect(rng).to receive(:rand).and_return(rand(lengths)).at_least(:once)
+
+ random_bytes = subject.random_bytes(lengths, random: rng)
+
+ expect(random_bytes.length).to be_between(lengths.begin, lengths.end)
+ end
+ end
end
end
describe "#random_distinct_chars" do
+ let(:n) { 10 }
+
it "should return a random Array of unique chars" do
- random_chars = subject.random_distinct_chars(10)
+ random_chars = subject.random_distinct_chars(n)
expect(random_chars.uniq).to be == random_chars
expect(random_chars.all? { |c| subject.include_char?(c) }).to be(true)
end
- context "with a range of lengths" do
+ context "when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must call the Array#shuffle with random: rng" do
+ expect_any_instance_of(Array).to receive(:shuffle).with(random: rng).and_return(subject.bytes.shuffle(random: rng))
+
+ subject.random_distinct_bytes(n, random: rng)
+ end
+ end
+
+ context "when given a Range of lengths" do
+ let(:lengths) { 5..10 }
+
it "should return a random Array of unique chars with a varying length" do
- random_chars = subject.random_distinct_chars(5..10)
+ random_chars = subject.random_distinct_chars(lengths)
expect(random_chars.uniq).to be == random_chars
- expect(random_chars.length).to be_between(5, 10)
+ expect(random_chars.length).to be_between(lengths.begin, lengths.end)
expect(random_chars.all? { |c| subject.include_char?(c) }).to be(true)
end
+
+ context "and when given random: rng" do
+ let(:rng) { SecureRandom }
+
+ it "must pass random: to Range#sample" do
+ expect(rng).to receive(:rand).and_return(rand(lengths)).at_least(:once)
+
+ random_bytes = subject.random_bytes(lengths, random: rng)
+
+ expect(random_bytes.length).to be_between(lengths.begin, lengths.end)
+ end
+ end
end
end
describe "#==" do
it "should be able to be compared with another set of chars" do
@@ -230,10 +423,135 @@
expect(sub_set).to be_kind_of(described_class)
expect(sub_set).to be_subset(subject)
end
end
+ describe "#each_substring_with_index" do
+ subject { described_class.new(['A', 'B', 'C']) }
+
+ let(:string) { "....AAAA....BBBB....CCCC...." }
+
+ it "must yield each matching substring and index" do
+ expect { |b|
+ subject.each_substring_with_index(string,&b)
+ }.to yield_successive_args(
+ ["AAAA", string.index("AAAA")],
+ ["BBBB", string.index("BBBB")],
+ ["CCCC", string.index("CCCC")]
+ )
+ end
+
+ context "when the string begins with a matching substring" do
+ let(:string) { "AAAA...." }
+
+ it "must yield the first matching substring" do
+ expect(subject.each_substring_with_index(string).first).to eq(
+ ["AAAA", 0]
+ )
+ end
+ end
+
+ context "when the string ends with a matching substring" do
+ let(:string) { "AAAA....BBBB....CCCC" }
+
+ it "must yield the last matching substring" do
+ expect(subject.each_substring_with_index(string).to_a.last).to eq(
+ ["CCCC", string.rindex("CCCC")]
+ )
+ end
+ end
+
+ context "when the entire string is a matching substring" do
+ let(:string) { "AAAAAAAA" }
+
+ it "must yield the entire string" do
+ expect { |b|
+ subject.each_substring_with_index(string,&b)
+ }.to yield_successive_args( [string, 0] )
+ end
+ end
+
+ context "when the matching substrings are shorter than the min_length" do
+ let(:min_length) { 2 }
+
+ let(:string) { "AA..B...CC.."}
+
+ it "must ignore the substrings shorter than min_length" do
+ expect { |b|
+ subject.each_substring_with_index(string, min_length: min_length, &b)
+ }.to yield_successive_args(
+ ["AA", string.index("AA")],
+ ["CC", string.index("CC")]
+ )
+ end
+ end
+
+ context "when min_length 0" do
+ let(:min_length) { 0 }
+
+ let(:string) { "A.BB..CCC..."}
+
+ it "must yield all matching substrings, regardless of length" do
+ expect { |b|
+ subject.each_substring_with_index(string, min_length: min_length, &b)
+ }.to yield_successive_args(
+ ["A", string.index("A")],
+ ["BB", string.index("BB")],
+ ["CCC", string.index("CCC")]
+ )
+ end
+ end
+ end
+
+ describe "#substrings_with_indexes" do
+ subject { described_class.new(['A', 'B', 'C']) }
+
+ let(:string) { "....AAAA....BBBB....CCCC...." }
+
+ it "must return the Array of substrings and their indexes" do
+ expect(subject.substrings_with_indexes(string)).to eq(
+ [
+ ["AAAA", string.index("AAAA")],
+ ["BBBB", string.index("BBBB")],
+ ["CCCC", string.index("CCCC")]
+ ]
+ )
+ end
+ end
+
+ describe "#each_substring(&block : (String) ->)" do
+ subject { described_class.new(['A', 'B', 'C']) }
+
+ let(:string) { "....AAAA....BBBB....CCCC...." }
+
+ it "must yield each matching substring" do
+ expect { |b|
+ subject.each_substring(string,&b)
+ }.to yield_successive_args(
+ "AAAA",
+ "BBBB",
+ "CCCC"
+ )
+ end
+ end
+
+ describe "#substrings" do
+ subject { described_class.new(['A', 'B', 'C']) }
+
+ let(:string) { "....AAAA....BBBB....CCCC...." }
+
+ it "must return the Array of matching substrings" do
+ expect(subject.substrings(string)).to eq(
+ [
+ "AAAA",
+ "BBBB",
+ "CCCC"
+ ]
+ )
+ end
+ end
+
describe "#strings_in" do
subject { described_class.new(['A', 'B', 'C']) }
let(:string) { "AAAA....BBBB....CCCC...." }
@@ -309,9 +627,75 @@
"CCCC" => string.index("CCCC")
}
)
end
end
+ end
+ end
+
+ describe "#each_string" do
+ let(:length) { 2 }
+
+ let(:expected_strings) do
+ Chars::StringEnumerator.new(subject,length).to_a
+ end
+
+ context "when a block is given" do
+ it "must enumerate through the strings belonging to the character set of the desired length" do
+ expect { |b|
+ subject.each_string_of_length(length,&b)
+ }.to yield_successive_args(*expected_strings)
+ end
+
+ context "when given a Range of lengths" do
+ let(:length) { 1..2 }
+
+ let(:expected_strings) do
+ Chars::StringEnumerator.new(subject,1).to_a +
+ Chars::StringEnumerator.new(subject,2).to_a
+ end
+
+ it "must yield strings of lengths in the Range of lengths" do
+ expect { |b|
+ subject.each_string_of_length(length,&b)
+ }.to yield_successive_args(*expected_strings)
+ end
+ end
+
+ context "when given an Array of lengths" do
+ let(:length) { [1,2] }
+
+ let(:expected_strings) do
+ Chars::StringEnumerator.new(subject,1).to_a +
+ Chars::StringEnumerator.new(subject,2).to_a
+ end
+
+ it "must yield strings of lengths in the Range of lengths" do
+ expect { |b|
+ subject.each_string_of_length(length,&b)
+ }.to yield_successive_args(*expected_strings)
+ end
+ end
+ end
+
+ context "when no block is given" do
+ it "must return an Enumerator" do
+ expect(subject.each_string_of_length(length)).to be_kind_of(Enumerator)
+ expect(subject.each_string_of_length(length).to_a).to eq(expected_strings)
+ end
+ end
+ end
+
+ describe "#strings_of_length" do
+ let(:length) { 2 }
+
+ let(:expected_strings) do
+ Chars::StringEnumerator.new(subject,length).to_a
+ end
+
+ it "must return an Enumerator" do
+ expect(subject.strings_of_length(length)).to be_kind_of(Enumerator)
+ expect(subject.strings_of_length(length).to_a).to eq(expected_strings)
end
end
describe "#===" do
it "should determine if a String is made up of the characters from the char set" do