From c6e60d9178e3cff43a5d16a7b3a7a41f31f87d09 Mon Sep 17 00:00:00 2001 From: Markus Schirp Date: Thu, 3 Jan 2013 16:52:42 +0100 Subject: [PATCH] Bump version to 0.2.10 --- Changelog.md | 6 +++ lib/mutant.rb | 11 +++++ lib/mutant/mutator/node/send.rb | 8 ++-- mutant.gemspec | 2 +- .../mutant/mutator/node/send/mutation_spec.rb | 48 ++++++++++++++++--- 5 files changed, 64 insertions(+), 11 deletions(-) diff --git a/Changelog.md b/Changelog.md index d89608b3..f0b253dc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,9 @@ +# v0.2.10 2013-01-03 + +* [fixed] Do not mutate receivers away when message name is a keyword + +[Compare v0.2.9..v0.2.10](https://github.com/mbj/mutant/compare/v0.2.9...v0.2.10) + # v0.2.9 2013-01-02 * [feature] Mutate instance and global variable assignments diff --git a/lib/mutant.rb b/lib/mutant.rb index aee9bde2..2595fa6a 100644 --- a/lib/mutant.rb +++ b/lib/mutant.rb @@ -1,4 +1,5 @@ require 'backports' +require 'set' require 'adamantium' require 'ice_nine' require 'abstract_type' @@ -29,6 +30,16 @@ end # Library namespace module Mutant + # The list of ruby kewords from http://ruby-doc.org/docs/keywords/1.9/ + KEYWORDS = IceNine.deep_freeze(%W( + BEGIN END __ENCODING__ __END__ __FILE__ + __LINE__ alias and begin break case class + def define do else elsif end ensure false + for if in module next nil not or redo + rescue retry return self super then true + undef unless until when while yield + ).map(&:to_sym).to_set) + # Define instance of subclassed superclass as constant # # @param [Class] superclass diff --git a/lib/mutant/mutator/node/send.rb b/lib/mutant/mutator/node/send.rb index eaf2d698..225a0236 100644 --- a/lib/mutant/mutator/node/send.rb +++ b/lib/mutant/mutator/node/send.rb @@ -18,9 +18,9 @@ module Mutant # # @api private # - def self.self_class?(node) + def self.keyword_name?(node) node.kind_of?(Rubinius::AST::Send) && - node.name == :class && + Mutant::KEYWORDS.include?(node.name) && node.receiver.kind_of?(Rubinius::AST::Self) end @@ -73,7 +73,7 @@ module Mutant def emit_receiver_mutations util = self.class - unless to_self? or util.self_class?(receiver) + unless to_self? or util.keyword_name?(receiver) emit_attribute_mutations(:receiver) end end @@ -151,7 +151,7 @@ module Mutant # def emit_implicit_self_receiver return unless to_self? - return if self.class.self_class?(node) + return if self.class.keyword_name?(node) mutant = dup_node mutant.privately = true # TODO: Fix rubinius to allow this as an attr_accessor diff --git a/mutant.gemspec b/mutant.gemspec index 1625a7c3..3a1ad0a3 100644 --- a/mutant.gemspec +++ b/mutant.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |gem| gem.name = 'mutant' - gem.version = '0.2.9' + gem.version = '0.2.10' gem.authors = [ 'Markus Schirp' ] gem.email = [ 'mbj@seonic.net' ] gem.description = 'Mutation testing for ruby under rubinius' diff --git a/spec/unit/mutant/mutator/node/send/mutation_spec.rb b/spec/unit/mutant/mutator/node/send/mutation_spec.rb index 9acfe52b..fa17fb3f 100644 --- a/spec/unit/mutant/mutator/node/send/mutation_spec.rb +++ b/spec/unit/mutant/mutator/node/send/mutation_spec.rb @@ -1,5 +1,6 @@ require 'spec_helper' +# FIXME: This spec needs to be structured better! describe Mutant::Mutator, 'send' do context 'send without arguments' do context 'with self as receiver' do @@ -20,6 +21,15 @@ describe Mutant::Mutator, 'send' do it_should_behave_like 'a mutator' end + + context 'explicit with keyword message name' do + Mutant::KEYWORDS.each do |keyword| + context "with keyword: #{keyword}" do + let(:source) { "self.#{keyword}" } + it_should_behave_like 'a noop mutator' + end + end + end end context 'to some object' do @@ -33,12 +43,6 @@ describe Mutant::Mutator, 'send' do it_should_behave_like 'a mutator' end - context 'to self.class' do - let(:source) { 'self.class' } - - it_should_behave_like 'a noop mutator' - end - context 'to self.class.foo' do let(:source) { 'self.class.foo' } @@ -66,6 +70,38 @@ describe Mutant::Mutator, 'send' do it_should_behave_like 'a mutator' end + context 'with explicit self as receiver' do + let(:source) { 'self.foo(nil)' } + + let(:mutations) do + mutations = [] + mutations << 'self.foo' + mutations << 'foo(nil)' + mutations << 'nil' + mutations << 'self.foo(Object.new)' + end + + it_should_behave_like 'a mutator' + end + + context 'to some object with keyword in method name' do + Mutant::KEYWORDS.each do |keyword| + context "with keyword #{keyword}" do + let(:source) { "foo.#{keyword}(nil)" } + + let(:mutations) do + mutations = [] + mutations << "foo.#{keyword}" + mutations << "foo" + mutations << 'nil' + mutations << "foo.#{keyword}(Object.new)" + end + + it_should_behave_like 'a mutator' + end + end + end + context 'two arguments' do let(:source) { 'foo(nil, nil)' }