metasploit-framework/spec/lib/rex/random_identifier_generator...

142 lines
3.9 KiB
Ruby

require 'spec_helper'
require 'rex/random_identifier_generator'
RSpec.describe Rex::RandomIdentifierGenerator do
let(:options) do
{ :min_length => 10, :max_length => 20 }
end
subject(:rig) { described_class.new(options) }
it { is_expected.to respond_to(:generate) }
it { is_expected.to respond_to(:[]) }
it { is_expected.to respond_to(:get) }
it { is_expected.to respond_to(:store) }
it { is_expected.to respond_to(:to_h) }
describe "#generate" do
it "should respect :min_length" do
1000.times do
expect(rig.generate.length).to be >= options[:min_length]
end
end
it "should respect :max_length" do
1000.times do
expect(rig.generate.length).to be <= options[:max_length]
end
end
it "should allow mangling in a block" do
ident = rig.generate { |identifier| identifier.upcase }
expect(ident).to match(/\A[A-Z0-9_]*\Z/)
ident = subject.generate { |identifier| identifier.downcase }
expect(ident).to match(/\A[a-z0-9_]*\Z/)
ident = subject.generate { |identifier| identifier.gsub("A","B") }
expect(ident).not_to include("A")
end
end
describe "#get" do
let(:options) do
{ :min_length=>3, :max_length=>3 }
end
it "should return the same thing for subsequent calls" do
expect(rig.get(:rspec)).to eq rig.get(:rspec)
end
it "should not return the same for different names" do
# Statistically...
count = 1000
a = Set.new
count.times do |n|
a.add rig.get(n)
end
expect(a.size).to eq count
end
context "with an exhausted set" do
let(:options) do
{ :char_set => "abcd", :min_length=>2, :max_length=>2 }
end
let(:max_permutations) do
# 26 because first char is hardcoded to be lowercase alpha
26 * (options[:char_set].length ** options[:min_length])
end
it "doesn't infinite loop" do
Timeout.timeout(1) do
expect {
(max_permutations + 1).times { |i| rig.get(i) }
}.to raise_error(Rex::RandomIdentifierGenerator::ExhaustedSpaceError)
# don't rescue TimeoutError here because we want that to be a
# failure case
end
end
end
end
describe "#store" do
let(:options) do
{ :char_set => "abcd", :min_length=>8, :max_length=>20 }
end
it "should allow smaller than minimum length" do
value = "a"*(options[:min_length]-1)
rig.store(:spec, value)
expect(rig.get(:spec)).to eq value
end
it "should allow bigger than maximum length" do
value = "a"*(options[:max_length]+1)
rig.store(:spec, value)
expect(rig.get(:spec)).to eq value
end
it "should raise if value is not unique" do
value = "a"*(options[:max_length]+1)
rig.store(:spec0, value)
expect(rig.get(:spec0)).to eq value
expect { rig.store(:spec1, value) }.to raise_error(RuntimeError)
end
it "should overwrite a previously stored value" do
orig_value = "a"*(options[:max_length])
rig.store(:spec, orig_value)
expect(rig.get(:spec)).to eq orig_value
new_value = "b"*(options[:max_length])
rig.store(:spec, new_value)
expect(rig.get(:spec)).to eq new_value
end
it "should overwrite a previously generated value" do
rig.get(:spec)
new_value = "a"*(options[:max_length])
rig.store(:spec, new_value)
expect(rig.get(:spec)).to eq new_value
end
end
describe "#to_h" do
it "should return a Hash" do
expect(rig.to_h).to be_kind_of(Hash)
end
it "should return expected key-value pairs" do
expected_keys = [:var_foo, :var_bar]
expected_keys.shuffle.each do |key|
rig.init_var(key)
end
expect(rig.to_h.size).to eq(expected_keys.size)
expect(rig.to_h.keys).to include(*expected_keys)
expect(rig.to_h.values.map {|v| v.class}.uniq).to eq([String])
end
end
end