2012-07-27 16:39:31 -04:00
|
|
|
# This file is big. Once mutation interface does not change
|
|
|
|
# anymore it will be split up in mutation specific stuff.
|
|
|
|
|
|
|
|
require 'spec_helper'
|
|
|
|
|
|
|
|
shared_examples_for 'a mutation enumerator method' do
|
|
|
|
it_should_behave_like 'a command method'
|
|
|
|
|
|
|
|
|
|
|
|
context 'with no block' do
|
2012-07-30 22:00:05 -04:00
|
|
|
subject { object.each(node) }
|
2012-07-27 16:39:31 -04:00
|
|
|
|
|
|
|
it { should be_instance_of(to_enum.class) }
|
|
|
|
|
2012-07-30 22:10:37 -04:00
|
|
|
let(:expected_mutations) do
|
2012-07-27 16:39:31 -04:00
|
|
|
mutations.map do |mutation|
|
|
|
|
if mutation.respond_to?(:to_ast)
|
|
|
|
mutation.to_ast.to_sexp
|
|
|
|
else
|
|
|
|
mutation
|
|
|
|
end
|
|
|
|
end.to_set
|
|
|
|
end
|
|
|
|
|
|
|
|
it 'generates the expected mutations' do
|
|
|
|
subject = self.subject.map(&:to_sexp).to_set
|
|
|
|
|
|
|
|
unless subject == expected_mutations
|
|
|
|
message = "Missing mutations: %s\nUnexpected mutations: %s" %
|
|
|
|
[expected_mutations - subject, subject - expected_mutations ].map(&:to_a).map(&:inspect)
|
|
|
|
fail message
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2012-07-30 22:00:05 -04:00
|
|
|
describe Mutant::Mutator, '.each' do
|
|
|
|
subject { object.each(node) { |item| yields << item } }
|
2012-07-27 16:39:31 -04:00
|
|
|
|
2012-07-30 22:00:05 -04:00
|
|
|
let(:yields) { [] }
|
|
|
|
let(:object) { described_class }
|
|
|
|
let(:node) { source.to_ast }
|
|
|
|
let(:random_string) { 'bar' }
|
2012-07-27 16:39:31 -04:00
|
|
|
|
|
|
|
context 'true literal' do
|
|
|
|
let(:source) { 'true' }
|
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
%w(nil false)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'false literal' do
|
|
|
|
let(:source) { 'false' }
|
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
%w(nil true)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'symbol literal' do
|
|
|
|
let(:source) { ':foo' }
|
|
|
|
|
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
%w(nil) << ":#{random_string}"
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
Mutant.stub(:random_hex_string => random_string)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'string literal' do
|
|
|
|
let(:source) { '"foo"' }
|
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
%W(nil "#{random_string}")
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
Mutant.stub(:random_hex_string => random_string)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
2012-07-30 16:18:00 -04:00
|
|
|
context 'interpolated string literal (DynamicString)' do
|
|
|
|
let(:source) { '"foo#{1}bar"' }
|
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
mutations = []
|
|
|
|
mutations << 'nil'
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
Mutant.stub(:random_hex_string => random_string)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
2012-07-27 16:39:31 -04:00
|
|
|
context 'fixnum literal' do
|
|
|
|
let(:source) { '10' }
|
|
|
|
|
|
|
|
let(:random_integer) { 5 }
|
|
|
|
let(:mutations) do
|
|
|
|
%W(nil 0 1 #{random_integer}) << [:lit, -10]
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
Mutant.stub(:random_fixnum => random_integer)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'float literal' do
|
|
|
|
let(:source) { '10.0' }
|
|
|
|
|
|
|
|
let(:mutations) do
|
2012-07-30 22:00:05 -04:00
|
|
|
mutations = []
|
|
|
|
mutations << 'nil'
|
|
|
|
mutations << '0.0'
|
|
|
|
mutations << '1.0'
|
|
|
|
mutations << random_float.to_s
|
|
|
|
mutations << '0.0/0.0'
|
|
|
|
mutations << '1.0/0.0'
|
|
|
|
mutations << [:negate, [:call, [:lit, 1.0], :/, [:arglist, [:lit, 0.0]]]]
|
|
|
|
mutations << [:lit, -10.0]
|
2012-07-27 16:39:31 -04:00
|
|
|
end
|
2012-07-30 22:10:37 -04:00
|
|
|
|
2012-07-27 16:39:31 -04:00
|
|
|
let(:random_float) { 7.123 }
|
|
|
|
|
|
|
|
before do
|
|
|
|
Mutant.stub(:random_float => random_float)
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'empty array literal' do
|
|
|
|
let(:source) { '[]' }
|
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
mutations = []
|
|
|
|
|
|
|
|
# Literal replaced with nil
|
|
|
|
mutations << [:nil]
|
|
|
|
|
|
|
|
# Extra element
|
|
|
|
mutations << '[nil]'
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
context 'array literal' do
|
|
|
|
let(:source) { '[true, false]' }
|
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
mutations = []
|
|
|
|
|
|
|
|
# Literal replaced with nil
|
|
|
|
mutations << [:nil]
|
2012-07-30 22:10:37 -04:00
|
|
|
|
2012-07-27 16:39:31 -04:00
|
|
|
# Mutation of each element in array
|
|
|
|
mutations << '[nil, false]'
|
|
|
|
mutations << '[false, false]'
|
|
|
|
mutations << '[true, nil]'
|
|
|
|
mutations << '[true, true]'
|
|
|
|
|
|
|
|
# Remove each element of array once
|
|
|
|
mutations << '[true]'
|
|
|
|
mutations << '[false]'
|
|
|
|
|
|
|
|
# Empty array
|
|
|
|
mutations << '[]'
|
|
|
|
|
|
|
|
# Extra element
|
|
|
|
mutations << '[true, false, nil]'
|
|
|
|
end
|
2012-07-30 22:10:37 -04:00
|
|
|
|
2012-07-27 16:39:31 -04:00
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'hash literal' do
|
|
|
|
let(:source) { '{true => true, false => false}' }
|
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
mutations = []
|
|
|
|
|
|
|
|
# Literal replaced with nil
|
|
|
|
mutations << [:nil]
|
|
|
|
|
|
|
|
# Mutation of each key and value in hash
|
|
|
|
mutations << [:hash, [:false ], [:true ], [:false], [:false]]
|
|
|
|
mutations << [:hash, [:nil ], [:true ], [:false], [:false]]
|
|
|
|
mutations << [:hash, [:true ], [:false], [:false], [:false]]
|
|
|
|
mutations << [:hash, [:true ], [:nil ], [:false], [:false]]
|
|
|
|
mutations << [:hash, [:true ], [:true ], [:true ], [:false]]
|
|
|
|
mutations << [:hash, [:true ], [:true ], [:nil ], [:false]]
|
|
|
|
mutations << [:hash, [:true ], [:true ], [:false], [:true ]]
|
|
|
|
mutations << [:hash, [:true ], [:true ], [:false], [:nil ]]
|
|
|
|
|
|
|
|
# Remove each key once
|
|
|
|
mutations << [:hash, [:true ], [:true ]]
|
|
|
|
mutations << [:hash, [:false ], [:false ]]
|
|
|
|
|
|
|
|
# Empty hash
|
|
|
|
mutations << [:hash]
|
|
|
|
|
|
|
|
# Extra element
|
|
|
|
mutations << [:hash, [:true ], [:true ], [:false], [:false ], [:nil], [:nil] ]
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
2012-07-27 18:17:00 -04:00
|
|
|
context 'range literal' do
|
2012-07-30 22:10:37 -04:00
|
|
|
let(:source) { '1..100' }
|
2012-07-27 18:17:00 -04:00
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
mutations = []
|
|
|
|
mutations << 'nil'
|
|
|
|
mutations << '1...100'
|
|
|
|
mutations << '(0.0/0.0)..100'
|
2012-07-30 22:00:05 -04:00
|
|
|
mutations << [:dot2, [:negate, [:call, [:lit, 1.0], :/, [:arglist, [:lit, 0.0]]]], [:lit, 100]]
|
2012-07-27 18:17:00 -04:00
|
|
|
mutations << '1..(1.0/0.0)'
|
|
|
|
mutations << '1..(0.0/0.0)'
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
|
|
|
context 'exclusive range literal' do
|
2012-07-30 22:10:37 -04:00
|
|
|
let(:source) { '1...100' }
|
2012-07-27 18:17:00 -04:00
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
mutations = []
|
|
|
|
mutations << 'nil'
|
|
|
|
mutations << '1..100'
|
|
|
|
mutations << '(0.0/0.0)...100'
|
2012-07-30 22:00:05 -04:00
|
|
|
mutations << [:dot3, [:negate, [:call, [:lit, 1.0], :/, [:arglist, [:lit, 0.0]]]], [:lit, 100]]
|
2012-07-27 18:17:00 -04:00
|
|
|
mutations << '1...(1.0/0.0)'
|
|
|
|
mutations << '1...(0.0/0.0)'
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
|
2012-07-30 16:18:00 -04:00
|
|
|
context 'regexp literal' do
|
|
|
|
let(:source) { '/foo/' }
|
|
|
|
|
|
|
|
let(:base_mutations) do
|
|
|
|
mutations = []
|
|
|
|
mutations << 'nil'
|
|
|
|
mutations << "/#{random_string}/"
|
|
|
|
end
|
|
|
|
|
|
|
|
before do
|
|
|
|
Mutant.stub(:random_hex_string => random_string)
|
|
|
|
end
|
|
|
|
|
|
|
|
let(:mutations) { base_mutations }
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
|
|
|
|
#it 'when source is empty regexp' do
|
|
|
|
# let(:source) { '//' }
|
|
|
|
|
|
|
|
# let(:mutations) { base_mutations - [source.to_ast] }
|
|
|
|
|
|
|
|
# it_should_behave_like 'a mutation enumerator method'
|
|
|
|
#end
|
|
|
|
end
|
|
|
|
|
2012-07-27 16:39:31 -04:00
|
|
|
context 'block literal' do
|
|
|
|
let(:source) { "true\nfalse" }
|
|
|
|
|
|
|
|
let(:mutations) do
|
|
|
|
mutations = []
|
2012-07-30 22:10:37 -04:00
|
|
|
|
2012-07-27 16:39:31 -04:00
|
|
|
# Mutation of each statement in block
|
|
|
|
mutations << "nil\nfalse"
|
|
|
|
mutations << "false\nfalse"
|
|
|
|
mutations << "true\nnil"
|
|
|
|
mutations << "true\ntrue"
|
|
|
|
|
|
|
|
# Remove statement in block
|
|
|
|
mutations << [:block, [:true]]
|
|
|
|
mutations << [:block, [:false]]
|
|
|
|
end
|
|
|
|
|
|
|
|
it_should_behave_like 'a mutation enumerator method'
|
|
|
|
end
|
|
|
|
end
|