diff --git a/.rspec b/.rspec index 6adb798c..9c3c126f 100644 --- a/.rspec +++ b/.rspec @@ -1,3 +1,2 @@ --color ---backtrace #--fail-fast diff --git a/Gemfile b/Gemfile index 12e20c8f..ab9b05fd 100644 --- a/Gemfile +++ b/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' diff --git a/lib/mutant.rb b/lib/mutant.rb index 8a8362b3..4eda272f 100644 --- a/lib/mutant.rb +++ b/lib/mutant.rb @@ -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' diff --git a/lib/mutant/mutator.rb b/lib/mutant/mutator.rb index 214b096a..86e0673e 100644 --- a/lib/mutant/mutator.rb +++ b/lib/mutant/mutator.rb @@ -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 diff --git a/lib/mutant/mutator/call.rb b/lib/mutant/mutator/call.rb new file mode 100644 index 00000000..3e41ea71 --- /dev/null +++ b/lib/mutant/mutator/call.rb @@ -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 diff --git a/lib/mutant/mutator/call/send.rb b/lib/mutant/mutator/call/send.rb new file mode 100644 index 00000000..64f69eae --- /dev/null +++ b/lib/mutant/mutator/call/send.rb @@ -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 diff --git a/lib/mutant/mutator/call/send_with_arguments.rb b/lib/mutant/mutator/call/send_with_arguments.rb new file mode 100644 index 00000000..ceeb2fcf --- /dev/null +++ b/lib/mutant/mutator/call/send_with_arguments.rb @@ -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 diff --git a/lib/mutant/mutator/registry.rb b/lib/mutant/mutator/registry.rb new file mode 100644 index 00000000..87411f68 --- /dev/null +++ b/lib/mutant/mutator/registry.rb @@ -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 diff --git a/lib/mutant/mutator/send.rb b/lib/mutant/mutator/send.rb deleted file mode 100644 index c3e027c6..00000000 --- a/lib/mutant/mutator/send.rb +++ /dev/null @@ -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 diff --git a/lib/mutant/mutator/send_with_arguments.rb b/lib/mutant/mutator/send_with_arguments.rb deleted file mode 100644 index f3ebc850..00000000 --- a/lib/mutant/mutator/send_with_arguments.rb +++ /dev/null @@ -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 diff --git a/spec/shared/mutation_enumeration_method_behavior.rb b/spec/shared/mutation_enumeration_method_behavior.rb new file mode 100644 index 00000000..e8bf78d0 --- /dev/null +++ b/spec/shared/mutation_enumeration_method_behavior.rb @@ -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 + + diff --git a/spec/unit/mutant/mutator/call/class_methods/each_spec.rb b/spec/unit/mutant/mutator/call/class_methods/each_spec.rb new file mode 100644 index 00000000..66b260dc --- /dev/null +++ b/spec/unit/mutant/mutator/call/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/each_spec.rb b/spec/unit/mutant/mutator/each_spec.rb index f1894f2f..9f2a99f0 100644 --- a/spec/unit/mutant/mutator/each_spec.rb +++ b/spec/unit/mutant/mutator/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/literal/array/class_methods/each_spec.rb b/spec/unit/mutant/mutator/literal/array/class_methods/each_spec.rb new file mode 100644 index 00000000..41f67949 --- /dev/null +++ b/spec/unit/mutant/mutator/literal/array/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/literal/boolean/class_methods/each_spec.rb b/spec/unit/mutant/mutator/literal/boolean/class_methods/each_spec.rb new file mode 100644 index 00000000..1751bb71 --- /dev/null +++ b/spec/unit/mutant/mutator/literal/boolean/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/literal/empty_array/class_methods/each_spec.rb b/spec/unit/mutant/mutator/literal/empty_array/class_methods/each_spec.rb new file mode 100644 index 00000000..687358ea --- /dev/null +++ b/spec/unit/mutant/mutator/literal/empty_array/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/literal/fixnum/class_methods/each_spec.rb b/spec/unit/mutant/mutator/literal/fixnum/class_methods/each_spec.rb new file mode 100644 index 00000000..049ba192 --- /dev/null +++ b/spec/unit/mutant/mutator/literal/fixnum/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/literal/float/class_methods/each_spec.rb b/spec/unit/mutant/mutator/literal/float/class_methods/each_spec.rb new file mode 100644 index 00000000..de14143d --- /dev/null +++ b/spec/unit/mutant/mutator/literal/float/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/literal/hash/class_methods/each_spec.rb b/spec/unit/mutant/mutator/literal/hash/class_methods/each_spec.rb new file mode 100644 index 00000000..7a24d413 --- /dev/null +++ b/spec/unit/mutant/mutator/literal/hash/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/literal/range/class_methods/each_spec.rb b/spec/unit/mutant/mutator/literal/range/class_methods/each_spec.rb new file mode 100644 index 00000000..6fc04a56 --- /dev/null +++ b/spec/unit/mutant/mutator/literal/range/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/literal/regex/class_methods/each_spec.rb b/spec/unit/mutant/mutator/literal/regex/class_methods/each_spec.rb new file mode 100644 index 00000000..8dda0cbb --- /dev/null +++ b/spec/unit/mutant/mutator/literal/regex/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/literal/string/class_methods/each_spec.rb b/spec/unit/mutant/mutator/literal/string/class_methods/each_spec.rb new file mode 100644 index 00000000..6881e8fe --- /dev/null +++ b/spec/unit/mutant/mutator/literal/string/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/literal/symbol/class_methods/each_spec.rb b/spec/unit/mutant/mutator/literal/symbol/class_methods/each_spec.rb new file mode 100644 index 00000000..c242a586 --- /dev/null +++ b/spec/unit/mutant/mutator/literal/symbol/class_methods/each_spec.rb @@ -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 diff --git a/spec/unit/mutant/mutator/self/class_methods/each_spec.rb b/spec/unit/mutant/mutator/self/class_methods/each_spec.rb new file mode 100644 index 00000000..e1b43bee --- /dev/null +++ b/spec/unit/mutant/mutator/self/class_methods/each_spec.rb @@ -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