mutant 0.5.10 → 0.5.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/Changelog.md +12 -1
- data/README.md +3 -0
- data/Rakefile +0 -9
- data/bin/mutant +1 -1
- data/config/flay.yml +1 -1
- data/config/mutant.yml +13 -0
- data/config/reek.yml +6 -2
- data/lib/mutant/constants.rb +0 -13
- data/lib/mutant/mutator/node/conditional_loop.rb +2 -1
- data/lib/mutant/mutator/node/generic.rb +1 -1
- data/lib/mutant/mutator/node/if.rb +1 -1
- data/lib/mutant/mutator/node/literal/regex.rb +2 -2
- data/lib/mutant/mutator/node/match_current_line.rb +27 -0
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +1 -1
- data/lib/mutant/mutator/node/nthref.rb +3 -1
- data/lib/mutant/mutator/node/rescue.rb +0 -12
- data/lib/mutant/mutator/node/send/attribute_assignment.rb +51 -0
- data/lib/mutant/mutator/node/send/index.rb +43 -0
- data/lib/mutant/mutator/node/send.rb +7 -37
- data/lib/mutant/mutator/node.rb +4 -12
- data/lib/mutant/mutator.rb +2 -26
- data/lib/mutant/node_helpers.rb +3 -3
- data/lib/mutant/require_highjack.rb +64 -0
- data/lib/mutant/subject/method/instance.rb +9 -1
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warning_expectation.rb +40 -0
- data/lib/mutant/warning_filter.rb +74 -0
- data/lib/mutant/zombifier/file.rb +81 -0
- data/lib/mutant/zombifier.rb +61 -240
- data/lib/mutant.rb +57 -1
- data/lib/parser_extensions.rb +25 -0
- data/mutant.gemspec +4 -3
- data/spec/integration/mutant/corpus_spec.rb +121 -0
- data/spec/integration/mutant/rspec_spec.rb +1 -1
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +1 -1
- data/spec/integration/mutant/zombie_spec.rb +3 -3
- data/spec/integrations.yml +23 -0
- data/spec/shared/mutator_behavior.rb +22 -72
- data/spec/spec_helper.rb +4 -2
- data/spec/support/mutation_verifier.rb +95 -0
- data/spec/unit/mutant/mutator/node/conditional_loop_spec.rb +16 -0
- data/spec/unit/mutant/mutator/node/match_current_line_spec.rb +4 -4
- data/spec/unit/mutant/mutator/node/named_value/access_spec.rb +6 -3
- data/spec/unit/mutant/mutator/node/nthref_spec.rb +2 -2
- data/spec/unit/mutant/mutator/node/op_assgn_spec.rb +3 -1
- data/spec/unit/mutant/mutator/node/send_spec.rb +0 -1
- data/spec/unit/mutant/require_highjack_spec.rb +54 -0
- data/spec/unit/mutant/subject/method/instance_spec.rb +34 -3
- data/spec/unit/mutant/warning_expectation.rb +71 -0
- data/spec/unit/mutant/warning_filter_spec.rb +94 -0
- metadata +40 -9
- data/lib/mutant/singleton_methods.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bff75074f1898f689c4215c2a19f14d02863ccc4
|
4
|
+
data.tar.gz: 576dbee5c9743707641a1f3fac543c0c76d85832
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47b0085d022c5e09f1013c824989f2449838bea7b9681b257e9e8ef7641a39fd522dacdf643e20e177422ff8c8a944b9d34a20c5c0f464f68f4458c02b2f1702
|
7
|
+
data.tar.gz: 47f0863f96176f3c90200a4a6ed46c86e31a39de77a8d35a66d7728446b38422288d162e5a0f1a4e54bc2a750ee34f869958e7019048652522d5e15c346e6cf7
|
data/.rubocop.yml
CHANGED
data/Changelog.md
CHANGED
@@ -1,8 +1,19 @@
|
|
1
|
+
# v0.5.11 2014-04-21
|
2
|
+
|
3
|
+
Changes:
|
4
|
+
|
5
|
+
* Fix crash on while and until without body
|
6
|
+
* Better require highjack based zombifier
|
7
|
+
* Do not mutate nthref $1 to gvar $0
|
8
|
+
* Use faster duplicate guarding hashing AST::Node intances
|
9
|
+
* Fix lots of shadowed invalid ASTs
|
10
|
+
* Fix undefine initialize warnings, Closes #175
|
11
|
+
|
1
12
|
# v0.5.10 2014-04-06
|
2
13
|
|
3
14
|
Changes:
|
4
15
|
|
5
|
-
* Fix crash without
|
16
|
+
* Fix crash on case without conditional
|
6
17
|
* Remove dependency to descendants tracker
|
7
18
|
* Add mutation #== => #eql?, #equal?
|
8
19
|
* Add mutation #eql? => #equal?
|
data/README.md
CHANGED
@@ -17,6 +17,9 @@ Mutant supports MRI and RBX 1.9 and 2.0, while support for jruby is planned.
|
|
17
17
|
It should also work under any ruby engine that supports POSIX-fork(2) semantics.
|
18
18
|
Support for MRI 2.1 is unstable, because this MRI release segfaults on basic metaprogramming mutants dependencies do.
|
19
19
|
|
20
|
+
Mutant uses a pure ruby [parser](https://github.com/whitequark/parser) and an [unparser](https://github.com/mbj/unparser)
|
21
|
+
to do its magic.
|
22
|
+
|
20
23
|
Integrations
|
21
24
|
------------
|
22
25
|
|
data/Rakefile
CHANGED
@@ -3,12 +3,3 @@
|
|
3
3
|
require 'devtools'
|
4
4
|
|
5
5
|
Devtools.init_rake_tasks
|
6
|
-
|
7
|
-
Rake.application.load_imports
|
8
|
-
task('metrics:mutant').clear
|
9
|
-
|
10
|
-
namespace :metrics do
|
11
|
-
task :mutant => :coverage do
|
12
|
-
$stderr.puts 'Mutant self mutation is disable till mutant is fast enough for travis'
|
13
|
-
end
|
14
|
-
end
|
data/bin/mutant
CHANGED
data/config/flay.yml
CHANGED
data/config/mutant.yml
CHANGED
@@ -1,2 +1,15 @@
|
|
1
1
|
name: mutant
|
2
2
|
namespace: Mutant
|
3
|
+
zombify: true
|
4
|
+
expect_coverage: 64.99
|
5
|
+
ignore_subjects:
|
6
|
+
# Mutation causes infinite runtime
|
7
|
+
- Mutant::Runner.lookup
|
8
|
+
# Suboptimal test selection stragegy (will be fixed soon) causes timeouts on CI
|
9
|
+
- Mutant::Zombifier*
|
10
|
+
- Mutant::Reporter*
|
11
|
+
- Mutant::CLI*
|
12
|
+
- Mutant.singleton_subclass_instance
|
13
|
+
- Mutant.symbolset
|
14
|
+
# Executing this has undefined behavior with the zombifier
|
15
|
+
- Mutant.zombify
|
data/config/reek.yml
CHANGED
@@ -52,6 +52,9 @@ NestedIterators:
|
|
52
52
|
- Mutant::CLI#parse
|
53
53
|
- Mutant::Mutator::Util::Array::Element#dispatch
|
54
54
|
- Mutant::Reporter::CLI::Printer::Config::Runner#generic_stats
|
55
|
+
- Mutant::RequireHighjack#infect
|
56
|
+
- Mutant::RequireHighjack#desinfect
|
57
|
+
- Parser::Lexer#self.new
|
55
58
|
max_allowed_nesting: 1
|
56
59
|
ignore_iterators: []
|
57
60
|
NilCheck:
|
@@ -85,7 +88,8 @@ TooManyStatements:
|
|
85
88
|
- Mutant::Reporter::CLI#colorized_diff
|
86
89
|
- Mutant::Reporter::CLI::Printer::Config::Runner#run
|
87
90
|
- Mutant::Runner#dispatch
|
88
|
-
- Mutant::Zombifier::File#self.
|
91
|
+
- Mutant::Zombifier::File#self.find
|
92
|
+
- Mutant::RequireHighjack#infect
|
89
93
|
# How mutant does CLI parsing is shit
|
90
94
|
- Mutant::CLI#parse
|
91
95
|
- Mutant::CLI#initialize
|
@@ -123,7 +127,7 @@ UncommunicativeVariableName:
|
|
123
127
|
- !ruby/regexp /^.$/
|
124
128
|
- !ruby/regexp /[0-9]$/
|
125
129
|
- !ruby/regexp /[A-Z]/
|
126
|
-
accept: []
|
130
|
+
accept: ['force_utf32']
|
127
131
|
UnusedParameters:
|
128
132
|
enabled: true
|
129
133
|
exclude: []
|
data/lib/mutant/constants.rb
CHANGED
@@ -2,19 +2,6 @@
|
|
2
2
|
|
3
3
|
module Mutant
|
4
4
|
|
5
|
-
# Return a frozen set of symbols from string enumerable
|
6
|
-
#
|
7
|
-
# @param [Enumerable<String>]
|
8
|
-
#
|
9
|
-
# @return [Set<Symbol>]
|
10
|
-
#
|
11
|
-
# @api private
|
12
|
-
#
|
13
|
-
def self.symbolset(strings)
|
14
|
-
strings.map(&:to_sym).to_set.freeze
|
15
|
-
end
|
16
|
-
private_class_method :symbolset
|
17
|
-
|
18
5
|
# Set of nodes that cannot be on the LHS of an assignment
|
19
6
|
NOT_ASSIGNABLE = symbolset %w(
|
20
7
|
int float str dstr class module self
|
@@ -13,7 +13,7 @@ module Mutant
|
|
13
13
|
:ensure, :redo, :defined?, :regopt, :retry, :arg_expr,
|
14
14
|
:kwrestarg, :kwoptarg, :kwarg, :undef, :module, :empty,
|
15
15
|
:alias, :for, :xstr, :back_ref, :class,
|
16
|
-
:sclass, :match_with_lvasgn, :
|
16
|
+
:sclass, :match_with_lvasgn, :while_post,
|
17
17
|
:until_post, :preexe, :postexe, :iflipflop, :eflipflop, :kwsplat,
|
18
18
|
:shadowarg
|
19
19
|
)
|
@@ -33,7 +33,7 @@ module Mutant
|
|
33
33
|
#
|
34
34
|
def mutate_condition
|
35
35
|
emit_condition_mutations
|
36
|
-
emit_self(n_not(condition), if_branch, else_branch)
|
36
|
+
emit_self(n_not(condition), if_branch, else_branch) unless condition.type == :match_current_line
|
37
37
|
emit_self(N_TRUE, if_branch, else_branch)
|
38
38
|
emit_self(N_FALSE, if_branch, else_branch)
|
39
39
|
end
|
@@ -31,11 +31,11 @@ module Mutant
|
|
31
31
|
# @api private
|
32
32
|
#
|
33
33
|
def dispatch
|
34
|
-
emit_nil
|
34
|
+
emit_nil unless parent_type == :match_current_line
|
35
35
|
children.each_with_index do |child, index|
|
36
36
|
mutate_child(index) unless child.type == :str
|
37
37
|
end
|
38
|
-
emit_self(
|
38
|
+
emit_self(options)
|
39
39
|
emit_self(s(:str, NULL_REGEXP_SOURCE), options)
|
40
40
|
end
|
41
41
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Mutant
|
2
|
+
class Mutator
|
3
|
+
class Node
|
4
|
+
# Emitter for perl style match current line node
|
5
|
+
class MatchCurrentLine < self
|
6
|
+
|
7
|
+
handle :match_current_line
|
8
|
+
|
9
|
+
children :regexp
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Emit mutants
|
14
|
+
#
|
15
|
+
# @return [undefined]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
def dispatch
|
20
|
+
emit_nil
|
21
|
+
emit_regexp_mutations
|
22
|
+
end
|
23
|
+
|
24
|
+
end # MatchCurrentLine
|
25
|
+
end # Node
|
26
|
+
end # Mutator
|
27
|
+
end # Mutant
|
@@ -8,18 +8,6 @@ module Mutant
|
|
8
8
|
|
9
9
|
handle :rescue
|
10
10
|
|
11
|
-
# Return identity
|
12
|
-
#
|
13
|
-
# @param [Parser::AST::Node] node
|
14
|
-
#
|
15
|
-
# @return [String]
|
16
|
-
#
|
17
|
-
# @api private
|
18
|
-
#
|
19
|
-
def self.identity(node)
|
20
|
-
super(NodeHelpers.s(:kwbegin, node))
|
21
|
-
end
|
22
|
-
|
23
11
|
end # Rescue
|
24
12
|
end # Node
|
25
13
|
end # Mutator
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
class Mutator
|
5
|
+
class Node
|
6
|
+
class Send
|
7
|
+
|
8
|
+
# Mutator for sends that correspond to an attribute assignment
|
9
|
+
class AttributeAssignment < self
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Emit mutations
|
14
|
+
#
|
15
|
+
# @return [undefined]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
def dispatch
|
20
|
+
normal_dispatch
|
21
|
+
emit_attribute_read
|
22
|
+
end
|
23
|
+
|
24
|
+
# Mutate arguments
|
25
|
+
#
|
26
|
+
# @return [undefined]
|
27
|
+
#
|
28
|
+
# @api private
|
29
|
+
#
|
30
|
+
def mutate_arguments
|
31
|
+
remaining_children_indices.each do |index|
|
32
|
+
mutate_child(index)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Emit attribute read
|
37
|
+
#
|
38
|
+
# @return [undefined]
|
39
|
+
#
|
40
|
+
# @api private
|
41
|
+
#
|
42
|
+
def emit_attribute_read
|
43
|
+
emit_self(receiver, selector.to_s[0..-2].to_sym)
|
44
|
+
end
|
45
|
+
|
46
|
+
end # AttributeAssignment
|
47
|
+
|
48
|
+
end # Send
|
49
|
+
end # Node
|
50
|
+
end # Mutator
|
51
|
+
end # Mutant
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
class Mutator
|
5
|
+
class Node
|
6
|
+
class Send
|
7
|
+
# Base mutator for index operations
|
8
|
+
class Index < self
|
9
|
+
|
10
|
+
# Mutator for index references
|
11
|
+
class Reference < self
|
12
|
+
|
13
|
+
# Perform dispatch
|
14
|
+
#
|
15
|
+
# @return [undefined]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
def dispatch
|
20
|
+
emit(receiver)
|
21
|
+
end
|
22
|
+
|
23
|
+
end # Reference
|
24
|
+
|
25
|
+
# Mutator for index assignments
|
26
|
+
class Assign < self
|
27
|
+
|
28
|
+
# Perform dispatch
|
29
|
+
#
|
30
|
+
# @return [undefined]
|
31
|
+
#
|
32
|
+
# @api private
|
33
|
+
#
|
34
|
+
def dispatch
|
35
|
+
emit(receiver)
|
36
|
+
end
|
37
|
+
|
38
|
+
end # Assign
|
39
|
+
end # Index
|
40
|
+
end # Send
|
41
|
+
end # Node
|
42
|
+
end # Mutator
|
43
|
+
end # Mutant
|
@@ -22,40 +22,6 @@ module Mutant
|
|
22
22
|
INDEX_ASSIGN = :[]=
|
23
23
|
ASSIGN_SUFFIX = '='.freeze
|
24
24
|
|
25
|
-
# Base mutator for index operations
|
26
|
-
class Index < self
|
27
|
-
|
28
|
-
# Mutator for index references
|
29
|
-
class Reference < self
|
30
|
-
|
31
|
-
# Perform dispatch
|
32
|
-
#
|
33
|
-
# @return [undefined]
|
34
|
-
#
|
35
|
-
# @api private
|
36
|
-
#
|
37
|
-
def dispatch
|
38
|
-
emit(receiver)
|
39
|
-
end
|
40
|
-
|
41
|
-
end # Reference
|
42
|
-
|
43
|
-
# Mutator for index assignments
|
44
|
-
class Assign < self
|
45
|
-
|
46
|
-
# Perform dispatch
|
47
|
-
#
|
48
|
-
# @return [undefined]
|
49
|
-
#
|
50
|
-
# @api private
|
51
|
-
#
|
52
|
-
def dispatch
|
53
|
-
emit(receiver)
|
54
|
-
end
|
55
|
-
|
56
|
-
end # Assign
|
57
|
-
end # Index
|
58
|
-
|
59
25
|
private
|
60
26
|
|
61
27
|
# Perform dispatch
|
@@ -65,6 +31,7 @@ module Mutant
|
|
65
31
|
# @api private
|
66
32
|
#
|
67
33
|
def dispatch
|
34
|
+
emit_nil
|
68
35
|
case selector
|
69
36
|
when INDEX_REFERENCE
|
70
37
|
run(Index::Reference)
|
@@ -73,7 +40,6 @@ module Mutant
|
|
73
40
|
else
|
74
41
|
non_index_dispatch
|
75
42
|
end
|
76
|
-
emit_nil
|
77
43
|
end
|
78
44
|
|
79
45
|
# Perform non index dispatch
|
@@ -86,6 +52,8 @@ module Mutant
|
|
86
52
|
case
|
87
53
|
when binary_operator?
|
88
54
|
run(Binary)
|
55
|
+
when attribute_assignment?
|
56
|
+
run(AttributeAssignment)
|
89
57
|
else
|
90
58
|
normal_dispatch
|
91
59
|
end
|
@@ -173,7 +141,6 @@ module Mutant
|
|
173
141
|
# @api private
|
174
142
|
#
|
175
143
|
def mutate_arguments
|
176
|
-
return if arguments.empty?
|
177
144
|
emit_self(receiver, selector)
|
178
145
|
remaining_children_with_index.each do |node, index|
|
179
146
|
mutate_child(index)
|
@@ -213,7 +180,10 @@ module Mutant
|
|
213
180
|
# @api private
|
214
181
|
#
|
215
182
|
def emit_implicit_self
|
216
|
-
if receiver.type == :self &&
|
183
|
+
if receiver.type == :self &&
|
184
|
+
!KEYWORDS.include?(selector) &&
|
185
|
+
!attribute_assignment? &&
|
186
|
+
!OP_ASSIGN.include?(parent_type)
|
217
187
|
emit_receiver(nil)
|
218
188
|
end
|
219
189
|
end
|
data/lib/mutant/mutator/node.rb
CHANGED
@@ -9,18 +9,6 @@ module Mutant
|
|
9
9
|
class Node < self
|
10
10
|
include AbstractType, NodeHelpers, Unparser::Constants
|
11
11
|
|
12
|
-
# Return identity of node
|
13
|
-
#
|
14
|
-
# @param [Parser::AST::Node] node
|
15
|
-
#
|
16
|
-
# @return [String]
|
17
|
-
#
|
18
|
-
# @api private
|
19
|
-
#
|
20
|
-
def self.identity(node)
|
21
|
-
Unparser.unparse(node)
|
22
|
-
end
|
23
|
-
|
24
12
|
# Define named child
|
25
13
|
#
|
26
14
|
# @param [Symbol] name
|
@@ -58,6 +46,10 @@ module Mutant
|
|
58
46
|
children.each_with_index.drop(names.length)
|
59
47
|
end
|
60
48
|
|
49
|
+
define_method(:remaining_children_indices) do
|
50
|
+
children.each_index.drop(names.length)
|
51
|
+
end
|
52
|
+
|
61
53
|
define_method(:remaining_children) do
|
62
54
|
children.drop(names.length)
|
63
55
|
end
|
data/lib/mutant/mutator.rb
CHANGED
@@ -33,18 +33,6 @@ module Mutant
|
|
33
33
|
end
|
34
34
|
private_class_method :handle
|
35
35
|
|
36
|
-
# Return identity of object (for deduplication)
|
37
|
-
#
|
38
|
-
# @param [Object] object
|
39
|
-
#
|
40
|
-
# @return [Object]
|
41
|
-
#
|
42
|
-
# @api private
|
43
|
-
#
|
44
|
-
def self.identity(object)
|
45
|
-
object
|
46
|
-
end
|
47
|
-
|
48
36
|
# Return input
|
49
37
|
#
|
50
38
|
# @return [Object]
|
@@ -92,7 +80,7 @@ module Mutant
|
|
92
80
|
# @api private
|
93
81
|
#
|
94
82
|
def new?(object)
|
95
|
-
!@seen.include?(
|
83
|
+
!@seen.include?(object)
|
96
84
|
end
|
97
85
|
|
98
86
|
# Add object to guarded values
|
@@ -104,19 +92,7 @@ module Mutant
|
|
104
92
|
# @api private
|
105
93
|
#
|
106
94
|
def guard(object)
|
107
|
-
@seen <<
|
108
|
-
end
|
109
|
-
|
110
|
-
# Return identity for input
|
111
|
-
#
|
112
|
-
# @param [Object] input
|
113
|
-
#
|
114
|
-
# @return [Object]
|
115
|
-
#
|
116
|
-
# @api private
|
117
|
-
#
|
118
|
-
def identity(input)
|
119
|
-
self.class.identity(input)
|
95
|
+
@seen << object
|
120
96
|
end
|
121
97
|
|
122
98
|
# Dispatch node generations
|
data/lib/mutant/node_helpers.rb
CHANGED
@@ -18,13 +18,13 @@ module Mutant
|
|
18
18
|
module_function :s
|
19
19
|
|
20
20
|
NAN =
|
21
|
-
s(:send, s(:float, 0.0), :/, s(:
|
21
|
+
s(:send, s(:float, 0.0), :/, s(:float, 0.0))
|
22
22
|
INFINITY =
|
23
|
-
s(:send, s(:float, 1.0), :/, s(:
|
23
|
+
s(:send, s(:float, 1.0), :/, s(:float, 0.0))
|
24
24
|
NEW_OBJECT =
|
25
25
|
s(:send, s(:const, s(:cbase), :Object), :new)
|
26
26
|
NEGATIVE_INFINITY =
|
27
|
-
s(:send, s(:float, -1.0), :/, s(:
|
27
|
+
s(:send, s(:float, -1.0), :/, s(:float, 0.0))
|
28
28
|
|
29
29
|
RAISE = s(:send, nil, :raise)
|
30
30
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Mutant
|
2
|
+
# Require highjack
|
3
|
+
class RequireHighjack
|
4
|
+
include Concord.new(:target, :callback)
|
5
|
+
|
6
|
+
# Return original method
|
7
|
+
#
|
8
|
+
# @return [#call]
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
#
|
12
|
+
attr_reader :original
|
13
|
+
|
14
|
+
# Run block with highjacked require
|
15
|
+
#
|
16
|
+
# @return [self]
|
17
|
+
#
|
18
|
+
# @api pivate
|
19
|
+
#
|
20
|
+
def run
|
21
|
+
infect
|
22
|
+
yield
|
23
|
+
self
|
24
|
+
ensure
|
25
|
+
desinfect
|
26
|
+
end
|
27
|
+
|
28
|
+
# Infect kernel with highjack
|
29
|
+
#
|
30
|
+
# @return [self]
|
31
|
+
#
|
32
|
+
# @api pivate
|
33
|
+
#
|
34
|
+
def infect
|
35
|
+
callback = @callback
|
36
|
+
@original = target.method(:require)
|
37
|
+
target.module_eval do
|
38
|
+
undef :require
|
39
|
+
define_method(:require) do |logical_name|
|
40
|
+
callback.call(logical_name)
|
41
|
+
end
|
42
|
+
module_function :require
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Imperfectly desinfect kernel from highjack
|
47
|
+
#
|
48
|
+
# @return [self]
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
#
|
52
|
+
def desinfect
|
53
|
+
original = @original
|
54
|
+
target.module_eval do
|
55
|
+
undef :require
|
56
|
+
define_method(:require) do |logical_name|
|
57
|
+
original.call(logical_name)
|
58
|
+
end
|
59
|
+
module_function :require
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end # RequireHighjack
|
64
|
+
end # Mutant
|
@@ -31,7 +31,15 @@ module Mutant
|
|
31
31
|
# @api private
|
32
32
|
#
|
33
33
|
def prepare
|
34
|
-
|
34
|
+
expected_warnings =
|
35
|
+
if name.equal?(:initialize)
|
36
|
+
["#{__FILE__}:#{__LINE__ + 5}: warning: undefining `initialize' may cause serious problems\n"]
|
37
|
+
else
|
38
|
+
[]
|
39
|
+
end
|
40
|
+
WarningExpectation.new(expected_warnings).execute do
|
41
|
+
scope.send(:undef_method, name)
|
42
|
+
end
|
35
43
|
self
|
36
44
|
end
|
37
45
|
|
data/lib/mutant/version.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Mutant
|
2
|
+
# A class to expect some warning message raising on absence of unexpected warnings
|
3
|
+
class WarningExpectation
|
4
|
+
include Adamantium::Flat, Concord.new(:expected)
|
5
|
+
|
6
|
+
# Error raised on expectation miss
|
7
|
+
class ExpectationError < RuntimeError
|
8
|
+
include Concord.new(:unexpected, :missing)
|
9
|
+
|
10
|
+
# Return exception message
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
#
|
16
|
+
def message
|
17
|
+
"Unexpected warnings: #{unexpected.inspect} missing warnigns: #{missing.inspect}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Execute blocks with warning expectations
|
22
|
+
#
|
23
|
+
# @return [self]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
#
|
27
|
+
def execute(&block)
|
28
|
+
warnings = WarningFilter.use do
|
29
|
+
block.call
|
30
|
+
end
|
31
|
+
missing = expected - warnings
|
32
|
+
unexpected = warnings - expected
|
33
|
+
if missing.any? or unexpected.any?
|
34
|
+
fail ExpectationError.new(unexpected, missing)
|
35
|
+
end
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
end # WarningExpectation
|
40
|
+
end # Mutant
|