mutant 0.2.12 → 0.2.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/Changelog.md +4 -0
  2. data/Gemfile +1 -1
  3. data/Gemfile.devtools +39 -19
  4. data/README.md +3 -2
  5. data/TODO +3 -1
  6. data/config/flay.yml +1 -1
  7. data/config/site.reek +10 -3
  8. data/lib/mutant.rb +6 -73
  9. data/lib/mutant/constants.rb +49 -0
  10. data/lib/mutant/killer/forking.rb +6 -2
  11. data/lib/mutant/loader.rb +6 -79
  12. data/lib/mutant/matcher/scope_methods.rb +2 -2
  13. data/lib/mutant/mutation.rb +3 -2
  14. data/lib/mutant/mutation/filter/whitelist.rb +2 -0
  15. data/lib/mutant/mutator/node.rb +20 -9
  16. data/lib/mutant/mutator/node/assignment.rb +8 -1
  17. data/lib/mutant/mutator/node/block.rb +1 -0
  18. data/lib/mutant/mutator/node/default_arguments.rb +1 -0
  19. data/lib/mutant/mutator/node/formal_arguments_19.rb +1 -0
  20. data/lib/mutant/mutator/node/formal_arguments_19/default_mutations.rb +1 -0
  21. data/lib/mutant/mutator/node/{if_statement.rb → if.rb} +21 -6
  22. data/lib/mutant/mutator/node/iter_19.rb +1 -0
  23. data/lib/mutant/mutator/node/literal.rb +4 -3
  24. data/lib/mutant/mutator/node/literal/hash.rb +2 -1
  25. data/lib/mutant/mutator/node/literal/range.rb +2 -1
  26. data/lib/mutant/mutator/node/noop.rb +2 -0
  27. data/lib/mutant/mutator/node/receiver_case.rb +1 -19
  28. data/lib/mutant/mutator/node/send.rb +8 -136
  29. data/lib/mutant/mutator/node/send/binary_operator_method.rb +61 -0
  30. data/lib/mutant/mutator/node/send/with_arguments.rb +81 -0
  31. data/lib/mutant/mutator/node/super.rb +2 -0
  32. data/lib/mutant/mutator/node/{arguments.rb → when.rb} +4 -4
  33. data/lib/mutant/mutator/node/while.rb +2 -0
  34. data/lib/mutant/mutator/util/array.rb +2 -1
  35. data/lib/mutant/mutator/util/symbol.rb +1 -1
  36. data/lib/mutant/reporter/null.rb +1 -0
  37. data/lib/mutant/runner.rb +3 -4
  38. data/lib/mutant/singleton_methods.rb +28 -0
  39. data/lib/mutant/strategy.rb +2 -0
  40. data/lib/mutant/strategy/rspec/example_lookup.rb +4 -2
  41. data/mutant.gemspec +4 -4
  42. data/spec/shared/mutator_behavior.rb +1 -2
  43. data/spec/support/zombie.rb +35 -2
  44. data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +5 -6
  45. data/spec/unit/mutant/mutator/node/literal/float_spec.rb +1 -1
  46. data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +61 -61
  47. metadata +12 -10
  48. data/spec/unit/mutant/loader/rubinius/class_methods/run_spec.rb +0 -42
@@ -1,3 +1,7 @@
1
+ # v0.2.13 2013-01-05
2
+
3
+ * [fixed] Capture failures that occur in the window between mutation insertion and spec run as kills
4
+
1
5
  # v0.2.12 2013-01-03
2
6
 
3
7
  * [fixed] Do not crash when trying to load methods from precompiled ruby under rbx
data/Gemfile CHANGED
@@ -2,5 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'devtools', :git => 'https://github.com/mbj/devtools.git'
5
+ gem 'devtools', :git => 'https://github.com/datamapper/devtools.git'
6
6
  eval(File.read(File.join(File.dirname(__FILE__),'Gemfile.devtools')))
@@ -1,30 +1,36 @@
1
+ # encoding: utf-8
2
+
1
3
  group :development do
2
- gem 'rake', '~> 10.0'
3
- gem 'rspec', '~> 2.12.0'
4
- gem 'yard', '~> 0.8.3'
4
+ gem 'rake', '~> 10.0.3'
5
+ gem 'rspec', '~> 2.12.0'
6
+ gem 'yard', '~> 0.8.3'
7
+ end
8
+
9
+ group :yard do
10
+ gem 'redcarpet', '~> 2.2.2', :platforms => [ :mri, :rbx ]
5
11
  end
6
12
 
7
13
  group :guard do
8
- gem 'guard', '~> 1.5.4'
14
+ gem 'guard', '~> 1.6.1'
9
15
  gem 'guard-bundler', '~> 1.0.0'
10
- gem 'guard-rspec', '~> 2.1.1'
11
- gem 'rb-inotify', :git => 'https://github.com/mbj/rb-inotify'
12
- end
16
+ gem 'guard-rspec', '~> 2.3.3'
13
17
 
14
- group :benchmarks do
15
- gem 'rbench', '~> 0.2.3'
16
- end
18
+ # file system change event handling
19
+ gem 'rb-fchange', '~> 0.0.6', :require => false
20
+ gem 'rb-fsevent', '~> 0.9.3', :require => false
21
+ gem 'rb-inotify', '~> 0.8.8', :require => false, :git => 'https://github.com/nex3/rb-inotify'
17
22
 
18
- platform :jruby do
19
- group :jruby do
20
- gem 'jruby-openssl', '~> 0.7.4'
21
- end
23
+ # notification handling
24
+ gem 'libnotify', '~> 0.8.0', :require => false
25
+ gem 'rb-notifu', '~> 0.0.4', :require => false
26
+ gem 'terminal-notifier-guard', '~> 1.5.3', :require => false
22
27
  end
23
28
 
24
29
  group :metrics do
25
- gem 'flay', '~> 1.4.2'
26
- gem 'flog', '~> 2.5.1'
27
- gem 'reek', '~> 1.2.8', :git => 'https://github.com/dkubb/reek.git'
30
+ gem 'backports', '~> 2.6.5'
31
+ gem 'flay', '~> 1.4.3'
32
+ gem 'flog', '~> 2.5.3'
33
+ gem 'reek', '~> 1.2.13', :git => 'https://github.com/dkubb/reek.git', :branch => 'fix-redundant-irresponsible-module-warnings'
28
34
  gem 'roodi', '~> 2.1.0'
29
35
  gem 'yardstick', '~> 0.8.0'
30
36
 
@@ -33,11 +39,25 @@ group :metrics do
33
39
  gem 'yard-spellcheck', '~> 0.1.5'
34
40
  end
35
41
 
42
+ platforms :mri_18 do
43
+ gem 'rcov', '~> 1.0.0'
44
+ end
45
+
36
46
  platforms :mri_19 do
37
- gem 'simplecov', '~> 0.7'
47
+ gem 'simplecov', '~> 0.7.1'
38
48
  end
39
49
 
40
50
  platforms :rbx do
41
- gem 'pelusa', '~> 0.2.1'
51
+ gem 'pelusa', '~> 0.2.2'
52
+ end
53
+ end
54
+
55
+ group :benchmarks do
56
+ gem 'rbench', '~> 0.2.3'
57
+ end
58
+
59
+ platform :jruby do
60
+ group :jruby do
61
+ gem 'jruby-openssl', '~> 0.8.2'
42
62
  end
43
63
  end
data/README.md CHANGED
@@ -64,8 +64,8 @@ The following specs are executed to kill a mutation on:
64
64
  ```
65
65
  Public instance methods: spec/unit/#{namespace}/#{class_name}/#{method_name}_spec.rb
66
66
  Public singleton methods: spec/unit/#{namespace}/#{class_name}/class_methods/#{method_name}_spec.rb
67
- Public instance methods: spec/unit/#{namespace}/#{class_name}/
68
- Public singleton methods: spec/unit/#{namespace}/#{class_name}/class_methods
67
+ Private instance methods: spec/unit/#{namespace}/#{class_name}/*_spec.rb
68
+ Private singleton methods: spec/unit/#{namespace}/#{class_name}/class_methods/*_spec.rb
69
69
  ```
70
70
 
71
71
  ### --rspec-unit
@@ -91,6 +91,7 @@ Alternatives
91
91
  Credits
92
92
  -------
93
93
 
94
+ * [Markus Schirp (mbj)](https://github.com/mbj)
94
95
  * A [gist](https://gist.github.com/1065789) from [dkubb](https://github.com/dkubb) showing ideas.
95
96
  * Older abandoned [mutant](https://github.com/txus/mutant). For motivating me doing this one.
96
97
  * [heckle](https://github.com/seattlerb/heckle). For getting me into mutation testing.
data/TODO CHANGED
@@ -2,6 +2,7 @@ Code:
2
2
  * Test mutant with dynamically created zombie.
3
3
  * Fix ugly code within default parameter mutations
4
4
  * Break up lib/mutant/mutator/node/send.rb in class specific files
5
+ * Log all warnings throug reporter, so remove random $stderr.puts calls
5
6
 
6
7
  AST:
7
8
  * Fix the rubinius AST to allow setting @vcall_style variable in Rubinius::AST::Send nodes.
@@ -27,11 +28,12 @@ Loader:
27
28
  * Make sure loader does not change visibility of injected mutants
28
29
 
29
30
  Killers:
30
- * Aggregate warnings on missing spec files
31
+ * Move test framework specific stuff to strategy
31
32
  * Add a general master <=> killer IPC interface. So different strategies of isolation
32
33
  (fork, vs jruby runtime creation) will work without big impact.
33
34
 
34
35
  Strategy:
36
+ * Aggregate warnings on missing spec files
35
37
  * Provide "expicit files to kill with" strategy
36
38
  * Automatically load ./spec/spec_helper.rb for rspec strategies (No need to specify -I and -r anymore)
37
39
 
@@ -1,3 +1,3 @@
1
1
  ---
2
2
  threshold: 25 # Todo bring down to ~20
3
- total_score: 902
3
+ total_score: 914
@@ -10,13 +10,14 @@ UncommunicativeParameterName:
10
10
  LargeClass:
11
11
  max_methods: 10
12
12
  exclude:
13
- #- "Mutant::Matcher::Method" # 13 methods
14
13
  - "Mutant::Reporter::CLI" # 16 methods TODO Reduce!
14
+ - "Mutant::Reporter::Stats" # 6 ivars TODO Reduce!
15
15
  - "Mutant::CLI" # 19 methods and 7 ivars, TODO Reduce!
16
16
  enabled: true
17
17
  max_instance_variables: 3
18
18
  UncommunicativeMethodName:
19
- accept: []
19
+ accept:
20
+ - sha1
20
21
  exclude: []
21
22
  enabled: true
22
23
  reject:
@@ -26,7 +27,9 @@ UncommunicativeMethodName:
26
27
  LongParameterList:
27
28
  max_params: 2
28
29
  exclude:
30
+ - "Mutant::Mutator::Node#new_send_with_arguments" # 3 params
29
31
  - "Mutant::Context::Constant#initialize" # 3 params
32
+ - "Mutant::Subject#initialize" # 3 params
30
33
  enabled: true
31
34
  overrides: {}
32
35
  FeatureEnvy:
@@ -43,6 +46,7 @@ IrresponsibleModule:
43
46
  enabled: true
44
47
  UncommunicativeModuleName:
45
48
  accept:
49
+ - Mutant::Mutator::Node::Iter19
46
50
  - Mutant::Strategy::Rspec::DM2
47
51
  exclude: []
48
52
  enabled: true
@@ -53,6 +57,8 @@ NestedIterators:
53
57
  ignore_iterators: []
54
58
  exclude:
55
59
  - Mutant#self.define_singleton_subclass
60
+ - Mutant::Mutator::Util::Array::Element#dispatch
61
+ - Mutant::Mutator::Node::ReceiverCase#emit_when_branch_mutation
56
62
  enabled: true
57
63
  max_allowed_nesting: 1
58
64
  LongMethod:
@@ -61,7 +67,8 @@ LongMethod:
61
67
  enabled: true
62
68
  Duplication:
63
69
  allow_calls: []
64
- exclude: []
70
+ exclude:
71
+ - Mutant::Mutator::Node::Literal::Hash#emit_element_presence
65
72
  enabled: true
66
73
  max_calls: 1
67
74
  UtilityFunction:
@@ -29,80 +29,10 @@ end
29
29
 
30
30
  # Library namespace
31
31
  module Mutant
32
-
33
- # The list of ruby kewords from http://ruby-doc.org/docs/keywords/1.9/
34
- KEYWORDS = %w(
35
- BEGIN END __ENCODING__ __END__ __FILE__
36
- __LINE__ alias and begin break case class
37
- def define do else elsif end ensure false
38
- for if in module next nil not or redo
39
- rescue retry return self super then true
40
- undef unless until when while yield
41
- ).map(&:to_sym).to_set.freeze
42
-
43
- BINARY_METHOD_OPERATOR_EXPANSIONS = {
44
- :<=> => :spaceship_operator,
45
- :=== => :case_equality_operator,
46
- :[]= => :element_writer,
47
- :[] => :element_reader,
48
- :<= => :less_than_or_equal_to_operator,
49
- :>= => :greater_than_or_equal_to_operator,
50
- :== => :equality_operator,
51
- :'!~' => :nomatch_operator,
52
- :'!=' => :inequality_operator,
53
- :=~ => :match_operator,
54
- :<< => :left_shift_operator,
55
- :>> => :right_shift_operator,
56
- :** => :exponentation_operator,
57
- :* => :multiplication_operator,
58
- :% => :modulo_operator,
59
- :/ => :division_operator,
60
- :| => :bitwise_or_operator,
61
- :^ => :bitwise_xor_operator,
62
- :& => :bitwise_and_operator,
63
- :< => :less_than_operator,
64
- :> => :greater_than_operator,
65
- :+ => :addition_operator,
66
- :- => :substraction_operator
67
- }.freeze
68
-
69
- UNARY_METHOD_OPERATOR_EXPANSIONS = {
70
- :~@ => :unary_match_operator,
71
- :+@ => :unary_addition_operator,
72
- :-@ => :unary_substraction_operator,
73
- :'!' => :negation_operator
74
- }.freeze
75
-
76
- BINARY_METHOD_OPERATORS = BINARY_METHOD_OPERATOR_EXPANSIONS.keys.to_set.freeze
77
-
78
- OPERATOR_EXPANSIONS = BINARY_METHOD_OPERATOR_EXPANSIONS.merge(UNARY_METHOD_OPERATOR_EXPANSIONS).freeze
79
-
80
- # Define instance of subclassed superclass as constant
81
- #
82
- # @param [Class] superclass
83
- # @param [Symbol] name
84
- #
85
- # @return [self]
86
- #
87
- # @api private
88
- #
89
- def self.define_singleton_subclass(name, superclass, &block)
90
- klass = Class.new(superclass) do
91
-
92
- def inspect; self.class.name; end
93
-
94
- define_singleton_method(:name) do
95
- "#{superclass.name}::#{name}".freeze
96
- end
97
-
98
- end
99
- klass.class_eval(&block)
100
- superclass.const_set(name, klass.new)
101
- self
102
- end
103
-
104
32
  end
105
33
 
34
+ require 'mutant/singleton_methods'
35
+ require 'mutant/constants'
106
36
  require 'mutant/support/method_object'
107
37
  require 'mutant/helper'
108
38
  require 'mutant/random'
@@ -133,6 +63,9 @@ require 'mutant/mutator/node/block'
133
63
  require 'mutant/mutator/node/while'
134
64
  require 'mutant/mutator/node/super'
135
65
  require 'mutant/mutator/node/send'
66
+ require 'mutant/mutator/node/send/with_arguments'
67
+ require 'mutant/mutator/node/send/binary_operator_method'
68
+ require 'mutant/mutator/node/when'
136
69
  require 'mutant/mutator/node/assignment'
137
70
  require 'mutant/mutator/node/define'
138
71
  require 'mutant/mutator/node/formal_arguments_19'
@@ -145,7 +78,7 @@ require 'mutant/mutator/node/pattern_variable'
145
78
  require 'mutant/mutator/node/default_arguments'
146
79
  require 'mutant/mutator/node/return'
147
80
  require 'mutant/mutator/node/iter_19'
148
- require 'mutant/mutator/node/if_statement'
81
+ require 'mutant/mutator/node/if'
149
82
  require 'mutant/mutator/node/receiver_case'
150
83
  require 'mutant/loader'
151
84
  require 'mutant/context'
@@ -0,0 +1,49 @@
1
+ module Mutant
2
+
3
+ # The list of ruby kewords from http://ruby-doc.org/docs/keywords/1.9/
4
+ KEYWORDS = %w(
5
+ BEGIN END __ENCODING__ __END__ __FILE__
6
+ __LINE__ alias and begin break case class
7
+ def define do else elsif end ensure false
8
+ for if in module next nil not or redo
9
+ rescue retry return self super then true
10
+ undef unless until when while yield
11
+ ).map(&:to_sym).to_set.freeze
12
+
13
+ BINARY_METHOD_OPERATOR_EXPANSIONS = {
14
+ :<=> => :spaceship_operator,
15
+ :=== => :case_equality_operator,
16
+ :[]= => :element_writer,
17
+ :[] => :element_reader,
18
+ :<= => :less_than_or_equal_to_operator,
19
+ :>= => :greater_than_or_equal_to_operator,
20
+ :== => :equality_operator,
21
+ :'!~' => :nomatch_operator,
22
+ :'!=' => :inequality_operator,
23
+ :=~ => :match_operator,
24
+ :<< => :left_shift_operator,
25
+ :>> => :right_shift_operator,
26
+ :** => :exponentation_operator,
27
+ :* => :multiplication_operator,
28
+ :% => :modulo_operator,
29
+ :/ => :division_operator,
30
+ :| => :bitwise_or_operator,
31
+ :^ => :bitwise_xor_operator,
32
+ :& => :bitwise_and_operator,
33
+ :< => :less_than_operator,
34
+ :> => :greater_than_operator,
35
+ :+ => :addition_operator,
36
+ :- => :substraction_operator
37
+ }.freeze
38
+
39
+ UNARY_METHOD_OPERATOR_EXPANSIONS = {
40
+ :~@ => :unary_match_operator,
41
+ :+@ => :unary_addition_operator,
42
+ :-@ => :unary_substraction_operator,
43
+ :'!' => :negation_operator
44
+ }.freeze
45
+
46
+ BINARY_METHOD_OPERATORS = BINARY_METHOD_OPERATOR_EXPANSIONS.keys.to_set.freeze
47
+
48
+ OPERATOR_EXPANSIONS = BINARY_METHOD_OPERATOR_EXPANSIONS.merge(UNARY_METHOD_OPERATOR_EXPANSIONS).freeze
49
+ end
@@ -41,8 +41,12 @@ module Mutant
41
41
  #
42
42
  def run
43
43
  fork do
44
- killer = @killer.new(strategy, mutation)
45
- Kernel.exit(killer.fail? ? 1 : 0)
44
+ begin
45
+ killer = @killer.new(strategy, mutation)
46
+ Kernel.exit(killer.fail? ? 1 : 0)
47
+ rescue
48
+ Kernel.exit(1)
49
+ end
46
50
  end
47
51
 
48
52
  status = Process.wait2.last
@@ -17,21 +17,21 @@ module Mutant
17
17
  # Initialize and insert mutation into vm
18
18
  #
19
19
  # @param [Rubinius::AST::Script] root
20
- # @param [String] file
21
- # @param [Fixnum] line
20
+ # @param [Subject] subject
22
21
  #
23
22
  # @return [undefined]
24
23
  #
25
24
  # @api private
26
25
  #
27
- def initialize(root, file, line)
28
- @root, @file, @line = root, file, line
26
+ def initialize(root, subject)
27
+ @root, @subject = root, subject
29
28
  run
30
29
  end
31
30
 
32
31
  # Eval based loader
33
32
  class Eval < self
34
- private
33
+
34
+ private
35
35
 
36
36
  # Run loader
37
37
  #
@@ -40,7 +40,7 @@ module Mutant
40
40
  # @api private
41
41
  #
42
42
  def run
43
- eval(source, TOPLEVEL_BINDING, @file, @line)
43
+ Kernel.eval(source, TOPLEVEL_BINDING, @subject.source_path, @subject.source_line)
44
44
  end
45
45
 
46
46
  # Return source
@@ -54,78 +54,5 @@ module Mutant
54
54
  end
55
55
  end
56
56
 
57
- # Rubinius script node based loaded
58
- class Rubinius < self
59
- private
60
-
61
- # Run loader
62
- #
63
- # @return [undefined]
64
- #
65
- # @api private
66
- #
67
- def run(root)
68
- Rubinius.run_script(compiled_code)
69
- end
70
-
71
- # Return compiled code
72
- #
73
- # @return [Rubinius::CompiledCode]
74
- #
75
- # @api private
76
- #
77
- # FIXME: rbx on travis is older than on my devbox.
78
- #
79
- def compiled_code
80
- _script = script
81
- _script.respond_to?(:compiled_code) ? _script.compiled_code : _script.compiled_method
82
- end
83
-
84
- # Return code script
85
- #
86
- # @return [Rubinius::CompiledCode::Script]
87
- #
88
- # @api private
89
- #
90
- def script
91
- compiled_code_raw.create_script
92
- end
93
-
94
- # Return compiled code for node
95
- #
96
- # @return [Rubinius::CompiledCode]
97
- #
98
- # @api private
99
- #
100
- def compiled_code_raw
101
- compiler.run
102
- end
103
-
104
- # Return compiler loaded with mutated ast
105
- #
106
- # @return [Rubinius::Compiler]
107
- #
108
- # @api private
109
- #
110
- def compiler
111
- Rubinius::Compiler.new(:bytecode, :compiled_method).tap do |compiler|
112
- compiler.generator.input(@root)
113
- end
114
- end
115
-
116
- # Return script node
117
- #
118
- # @param [Rubinius::AST::Node] node
119
- #
120
- # @return [Rubinius::AST::Script]
121
- #
122
- # @api private
123
- #
124
- def script(node)
125
- Rubinius::AST::Script.new(node).tap do |script|
126
- script.file = source_path
127
- end
128
- end
129
- end
130
57
  end
131
58
  end