Break up mutation spec in class specific files
* Also add mutation class registry to improve readability. * Calling mutations are still broken.
This commit is contained in:
parent
55c61dfc28
commit
b9b95ebe94
24 changed files with 545 additions and 417 deletions
1
.rspec
1
.rspec
|
@ -1,3 +1,2 @@
|
|||
--color
|
||||
--backtrace
|
||||
#--fail-fast
|
||||
|
|
3
Gemfile
3
Gemfile
|
@ -5,6 +5,9 @@ gemspec
|
|||
# For Veritas::Immutable, will be extracted soon
|
||||
gem 'veritas', :git => 'https://github.com/dkubb/veritas'
|
||||
|
||||
# Until there is a release with explicit sends to self fix
|
||||
gem 'to_source', :git => 'https://github.com/mbj/to_source'
|
||||
|
||||
group :development do
|
||||
gem 'rake', '~> 0.9.2'
|
||||
gem 'yard', '~> 0.8.1'
|
||||
|
|
|
@ -24,6 +24,7 @@ end
|
|||
require 'mutant/support/abstract'
|
||||
require 'mutant/random'
|
||||
require 'mutant/mutator'
|
||||
require 'mutant/mutator/registry'
|
||||
require 'mutant/mutator/literal'
|
||||
require 'mutant/mutator/literal/boolean'
|
||||
require 'mutant/mutator/literal/range'
|
||||
|
@ -38,9 +39,10 @@ require 'mutant/mutator/literal/regex'
|
|||
#require 'mutant/mutator/literal/dynamic'
|
||||
require 'mutant/mutator/block'
|
||||
require 'mutant/mutator/self'
|
||||
require 'mutant/mutator/send'
|
||||
require 'mutant/mutator/send_with_arguments'
|
||||
require 'mutant/loader'
|
||||
require 'mutant/mutator/call'
|
||||
require 'mutant/mutator/call/send'
|
||||
require 'mutant/mutator/call/send_with_arguments'
|
||||
require 'mutant/loader'
|
||||
require 'mutant/context'
|
||||
require 'mutant/context/constant'
|
||||
require 'mutant/mutatee'
|
||||
|
|
|
@ -15,29 +15,11 @@ module Mutant
|
|||
#
|
||||
def self.each(node, &block)
|
||||
return to_enum(__method__, node) unless block_given?
|
||||
mutator(node).new(node, block)
|
||||
Registry.lookup(node.class).new(node, block)
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
# Return mutator for node or raise
|
||||
#
|
||||
# @param [Rubinius::AST::Node] node
|
||||
#
|
||||
# @return [Mutator]
|
||||
#
|
||||
# @raise [NameError]
|
||||
# raises NameError if mutator for node cannot be found
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def self.mutator(node)
|
||||
Mutator.map.fetch(node.class) do
|
||||
raise ArgumentError,"No mutator to handle: #{node.inspect}"
|
||||
end
|
||||
end
|
||||
private_class_method :mutator
|
||||
|
||||
# Register node class handler
|
||||
#
|
||||
# @param [Class:Rubinius::AST::Node] node_class
|
||||
|
@ -47,20 +29,10 @@ module Mutant
|
|||
# @api private
|
||||
#
|
||||
def self.handle(node_class)
|
||||
Mutator.map[node_class]=self
|
||||
Registry.register(node_class,self)
|
||||
end
|
||||
private_class_method :handle
|
||||
|
||||
# Return map of rubinus AST nodes to mutators
|
||||
#
|
||||
# @return [Hash]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def self.map
|
||||
@map ||= {}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Initialize generator
|
||||
|
@ -291,7 +263,6 @@ module Mutant
|
|||
emit_safe(new_nil)
|
||||
end
|
||||
|
||||
|
||||
# Return AST representing send
|
||||
#
|
||||
# @param [Rubinius::AST::Node] receiver
|
||||
|
@ -306,6 +277,16 @@ module Mutant
|
|||
new(Rubinius::AST::SendWithArguments, receiver, name, arguments)
|
||||
end
|
||||
|
||||
# Return duplicated (unfrozen) node each call
|
||||
#
|
||||
# @return [Rubinius::AST::Node]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def dup_node
|
||||
node.dup
|
||||
end
|
||||
|
||||
memoize :sexp
|
||||
end
|
||||
end
|
||||
|
|
42
lib/mutant/mutator/call.rb
Normal file
42
lib/mutant/mutator/call.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
module Mutant
|
||||
class Mutator
|
||||
# Abstract class for mutatiosn where messages are send
|
||||
class Call < Mutator
|
||||
|
||||
private
|
||||
|
||||
|
||||
# Return receiver AST node
|
||||
#
|
||||
# @return [Rubinius::AST::Node]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def receiver
|
||||
node.receiver
|
||||
end
|
||||
|
||||
# Return name of call
|
||||
#
|
||||
# @return [Symbol]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def name
|
||||
node.name
|
||||
end
|
||||
|
||||
# Check if receiver is self
|
||||
#
|
||||
# @return [true]
|
||||
# returns true when receiver is a Rubinius::AST::Self node
|
||||
#
|
||||
# @return [false]
|
||||
# return false otherwise
|
||||
#
|
||||
def self?
|
||||
receiver.kind_of?(Rubinius::AST::Self)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
34
lib/mutant/mutator/call/send.rb
Normal file
34
lib/mutant/mutator/call/send.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
module Mutant
|
||||
class Mutator
|
||||
class Call < Mutator
|
||||
# Mutator for Rubinius::AST::Send
|
||||
class Send < Call
|
||||
|
||||
handle(Rubinius::AST::Send)
|
||||
|
||||
private
|
||||
|
||||
# Emit mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def dispatch
|
||||
emit_explicit_receiver
|
||||
end
|
||||
|
||||
# Emit a private vcall mutation
|
||||
#
|
||||
# Transforms a call on self with implict receiver into one with
|
||||
# explcit receiver.
|
||||
#
|
||||
# foo(1) => self.foo(1)
|
||||
#
|
||||
def emit_explicit_receiver
|
||||
emit_self(receiver,name,false,true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
25
lib/mutant/mutator/call/send_with_arguments.rb
Normal file
25
lib/mutant/mutator/call/send_with_arguments.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
module Mutant
|
||||
class Mutator
|
||||
# Mutator for Rubinius::AST::Send
|
||||
class Call < Mutator
|
||||
class SendWithArguments < Call
|
||||
|
||||
handle(Rubinius::AST::SendWithArguments)
|
||||
|
||||
private
|
||||
|
||||
# Emit mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
# FIXME: There are MANY more mutations here :P
|
||||
#
|
||||
def dispatch
|
||||
emit_explicit_receiver
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
48
lib/mutant/mutator/registry.rb
Normal file
48
lib/mutant/mutator/registry.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
module Mutant
|
||||
class Mutator
|
||||
# Registry for mutators
|
||||
module Registry
|
||||
# Return registry state
|
||||
#
|
||||
# @return [Hash]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def self.registry
|
||||
@registry ||= {}
|
||||
end
|
||||
private_class_method :registry
|
||||
|
||||
# Register mutator class for AST node class
|
||||
#
|
||||
# @param [Class] ast_class
|
||||
# @param [Class] mutator_class
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
# @return [self]
|
||||
#
|
||||
def self.register(ast_class,mutator_class)
|
||||
registry[ast_class]=mutator_class
|
||||
self
|
||||
end
|
||||
|
||||
# Lookup mutator class for AST node class
|
||||
#
|
||||
# @param [Class] ast_class
|
||||
#
|
||||
# @return [Class]
|
||||
#
|
||||
# @raise [ArgumentError]
|
||||
# raises argument error when mutator class cannot be found
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def self.lookup(ast_class)
|
||||
registry.fetch(ast_class) do
|
||||
raise ArgumentError,"No mutator to handle: #{ast_class.inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,22 +0,0 @@
|
|||
module Mutant
|
||||
class Mutator
|
||||
# Mutator for Rubinius::AST::Send
|
||||
class Send < Mutator
|
||||
|
||||
handle(Rubinius::AST::Send)
|
||||
|
||||
private
|
||||
|
||||
# Emit mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def dispatch
|
||||
# Mutate "self.foo" into "foo"
|
||||
emit_self(node.receiver,node.name,true,true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,28 +0,0 @@
|
|||
module Mutant
|
||||
class Mutator
|
||||
# Mutator for Rubinius::AST::Send
|
||||
class SendWithArguments < Mutator
|
||||
|
||||
handle(Rubinius::AST::SendWithArguments)
|
||||
|
||||
private
|
||||
|
||||
# Emit mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
# FIXME: # There are MANY more mutations here :P
|
||||
#
|
||||
def dispatch
|
||||
# Mutate "foo(1)" into "self.foo(1)"
|
||||
emit_self(node.receiver,node.name,arguments,true)
|
||||
end
|
||||
|
||||
def arguments
|
||||
new(Rubinius::AST::ArrayLiteral,node.arguments.array)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
37
spec/shared/mutation_enumeration_method_behavior.rb
Normal file
37
spec/shared/mutation_enumeration_method_behavior.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
shared_examples_for 'a mutation enumerator method' do
|
||||
subject { object.each(node) { |item| yields << item } }
|
||||
|
||||
let(:yields) { [] }
|
||||
let(:object) { described_class }
|
||||
let(:node) { source.to_ast }
|
||||
|
||||
it_should_behave_like 'a command method'
|
||||
|
||||
context 'with no block' do
|
||||
subject { object.each(node) }
|
||||
|
||||
it { should be_instance_of(to_enum.class) }
|
||||
|
||||
let(:expected_mutations) do
|
||||
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
|
||||
|
||||
|
54
spec/unit/mutant/mutator/call/class_methods/each_spec.rb
Normal file
54
spec/unit/mutant/mutator/call/class_methods/each_spec.rb
Normal file
|
@ -0,0 +1,54 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Call,'.each' do
|
||||
pending 'send' do
|
||||
context 'to self' do
|
||||
|
||||
context 'implict' do
|
||||
let(:source) { 'foo' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
|
||||
context 'explict' do
|
||||
let(:source) { 'self.foo' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
mutations << 'foo' # without explict receiver (send privately)
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
pending 'send with arguments' do
|
||||
context 'to self' do
|
||||
context 'implict' do
|
||||
let(:source) { 'foo(1)' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
|
||||
context 'explict' do
|
||||
let(:source) { 'self.foo(1)' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
mutations << 'foo(1)' # without explict receiver (send privately)
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,74 +1,18 @@
|
|||
# This file is big. Once mutation interface does not change
|
||||
# anymore it will be split up in mutation specific stuff.
|
||||
# This file is the sandbox for new mutations.
|
||||
# Once finished mutation test will be moved to class specfic
|
||||
# file.
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
shared_examples_for 'a mutation enumerator method' do
|
||||
it_should_behave_like 'a command method'
|
||||
|
||||
|
||||
context 'with no block' do
|
||||
subject { object.each(node) }
|
||||
|
||||
it { should be_instance_of(to_enum.class) }
|
||||
|
||||
let(:expected_mutations) do
|
||||
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
|
||||
|
||||
|
||||
describe Mutant::Mutator, '.each' do
|
||||
subject { object.each(node) { |item| yields << item } }
|
||||
let(:random_string) { 'bar' }
|
||||
|
||||
let(:yields) { [] }
|
||||
let(:object) { described_class }
|
||||
let(:node) { source.to_ast }
|
||||
let(:random_string) { 'bar' }
|
||||
|
||||
context 'true literal' do
|
||||
let(:source) { 'true' }
|
||||
pending 'interpolated string literal (DynamicString)' do
|
||||
let(:source) { '"foo#{1}bar"' }
|
||||
|
||||
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}"
|
||||
mutations = []
|
||||
mutations << 'nil'
|
||||
end
|
||||
|
||||
before do
|
||||
|
@ -78,212 +22,7 @@ describe Mutant::Mutator, '.each' do
|
|||
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::Random.stub(:hex_string => random_string)
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
|
||||
#context 'interpolated string literal (DynamicString)' do
|
||||
# let(:source) { '"foo#{1}bar"' }
|
||||
|
||||
# let(:mutations) do
|
||||
# mutations = []
|
||||
# mutations << 'nil'
|
||||
# end
|
||||
|
||||
# before do
|
||||
# Mutant::Random.stub(:hex_string => random_string)
|
||||
# end
|
||||
|
||||
# it_should_behave_like 'a mutation enumerator method'
|
||||
#end
|
||||
|
||||
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::Random.stub(:fixnum => random_integer)
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
|
||||
context 'float literal' do
|
||||
let(:source) { '10.0' }
|
||||
|
||||
let(:mutations) do
|
||||
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]
|
||||
end
|
||||
|
||||
let(:random_float) { 7.123 }
|
||||
|
||||
before do
|
||||
Mutant::Random.stub(: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]
|
||||
|
||||
# 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
|
||||
|
||||
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
|
||||
|
||||
context 'range literal' do
|
||||
let(:source) { '1..100' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
mutations << 'nil'
|
||||
mutations << '1...100'
|
||||
mutations << '(0.0/0.0)..100'
|
||||
mutations << [:dot2, [:negate, [:call, [:lit, 1.0], :/, [:arglist, [:lit, 0.0]]]], [:lit, 100]]
|
||||
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
|
||||
let(:source) { '1...100' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
mutations << 'nil'
|
||||
mutations << '1..100'
|
||||
mutations << '(0.0/0.0)...100'
|
||||
mutations << [:dot3, [:negate, [:call, [:lit, 1.0], :/, [:arglist, [:lit, 0.0]]]], [:lit, 100]]
|
||||
mutations << '1...(1.0/0.0)'
|
||||
mutations << '1...(0.0/0.0)'
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
|
||||
context 'regexp literal' do
|
||||
let(:source) { '/foo/' }
|
||||
|
||||
let(:base_mutations) do
|
||||
mutations = []
|
||||
mutations << 'nil'
|
||||
mutations << "/#{random_string}/"
|
||||
end
|
||||
|
||||
before do
|
||||
Mutant::Random.stub(: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
|
||||
|
||||
context 'block literal' do
|
||||
pending 'block literal' do
|
||||
# Two send operations
|
||||
let(:source) { "self.foo\nself.bar" }
|
||||
|
||||
|
@ -301,66 +40,4 @@ describe Mutant::Mutator, '.each' do
|
|||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
|
||||
|
||||
context 'self' do
|
||||
let(:source) { 'self' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
|
||||
context 'send' do
|
||||
context 'to self' do
|
||||
|
||||
context 'implict' do
|
||||
let(:source) { 'foo' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
|
||||
context 'explict' do
|
||||
let(:source) { 'self.foo' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
mutations << 'foo' # without explict receiver (send privately)
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'send with arguments' do
|
||||
context 'to self' do
|
||||
context 'implict' do
|
||||
let(:source) { 'foo(1)' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
|
||||
context 'explict' do
|
||||
let(:source) { 'self.foo(1)' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
mutations << 'foo(1)' # without explict receiver (send privately)
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Literal::Array,'.each' do
|
||||
context 'array literal' do
|
||||
let(:source) { '[true, false]' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
|
||||
# Literal replaced with nil
|
||||
mutations << [:nil]
|
||||
|
||||
# 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
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Literal::Boolean,'.each' do
|
||||
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
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Literal::EmptyArray,'.each' do
|
||||
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
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Literal::Fixnum,'.each' do
|
||||
let(:random_fixnum) { 5 }
|
||||
|
||||
context 'fixnum literal' do
|
||||
let(:source) { '10' }
|
||||
|
||||
let(:mutations) do
|
||||
%W(nil 0 1 #{random_fixnum}) << [:lit, -10]
|
||||
end
|
||||
|
||||
before do
|
||||
Mutant::Random.stub(:fixnum => random_fixnum)
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Literal::Float, '.each' do
|
||||
context 'float literal' do
|
||||
let(:source) { '10.0' }
|
||||
|
||||
let(:mutations) do
|
||||
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]
|
||||
end
|
||||
|
||||
let(:random_float) { 7.123 }
|
||||
|
||||
before do
|
||||
Mutant::Random.stub(:float => random_float)
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Literal::Hash, '.each' do
|
||||
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
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Literal::Range,'.each' do
|
||||
context 'inclusive range literal' do
|
||||
let(:source) { '1..100' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
mutations << 'nil'
|
||||
mutations << '1...100'
|
||||
mutations << '(0.0/0.0)..100'
|
||||
mutations << [:dot2, [:negate, [:call, [:lit, 1.0], :/, [:arglist, [:lit, 0.0]]]], [:lit, 100]]
|
||||
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
|
||||
let(:source) { '1...100' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
mutations << 'nil'
|
||||
mutations << '1..100'
|
||||
mutations << '(0.0/0.0)...100'
|
||||
mutations << [:dot3, [:negate, [:call, [:lit, 1.0], :/, [:arglist, [:lit, 0.0]]]], [:lit, 100]]
|
||||
mutations << '1...(1.0/0.0)'
|
||||
mutations << '1...(0.0/0.0)'
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Literal::Regex,'.each' do
|
||||
let(:random_string) { 'bar' }
|
||||
|
||||
context 'regexp literal' do
|
||||
let(:source) { '/foo/' }
|
||||
|
||||
let(:base_mutations) do
|
||||
mutations = []
|
||||
mutations << 'nil'
|
||||
mutations << "/#{random_string}/"
|
||||
end
|
||||
|
||||
before do
|
||||
Mutant::Random.stub(:hex_string => random_string)
|
||||
end
|
||||
|
||||
let(:mutations) { base_mutations }
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
|
||||
context 'when source is empty regexp' do
|
||||
before do
|
||||
pending
|
||||
end
|
||||
|
||||
let(:source) { '//' }
|
||||
|
||||
let(:mutations) { base_mutations - [source.to_ast] }
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Literal::String,'.each' do
|
||||
let(:random_string) { 'bar' }
|
||||
|
||||
context 'string literal' do
|
||||
let(:source) { '"foo"' }
|
||||
|
||||
let(:mutations) do
|
||||
%W(nil "#{random_string}")
|
||||
end
|
||||
|
||||
before do
|
||||
Mutant::Random.stub(:hex_string => random_string)
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Literal::Symbol,'.each' do
|
||||
let(:random_string) { 'bar' }
|
||||
|
||||
context 'symbol literal' do
|
||||
let(:source) { ':foo' }
|
||||
|
||||
|
||||
let(:mutations) do
|
||||
%w(nil) << ":#{random_string}"
|
||||
end
|
||||
|
||||
before do
|
||||
Mutant::Random.stub(:hex_string => random_string)
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
||||
end
|
11
spec/unit/mutant/mutator/self/class_methods/each_spec.rb
Normal file
11
spec/unit/mutant/mutator/self/class_methods/each_spec.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Self,'.each' do
|
||||
let(:source) { 'self' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutation enumerator method'
|
||||
end
|
Loading…
Add table
Reference in a new issue