mutant 0.8.24 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +3 -3
- data/Changelog.md +14 -654
- data/Gemfile +13 -0
- data/Gemfile.lock +59 -64
- data/LICENSE +271 -20
- data/README.md +73 -140
- data/Rakefile +0 -21
- data/bin/mutant +7 -2
- data/config/reek.yml +2 -1
- data/config/rubocop.yml +5 -9
- data/docs/incremental.md +76 -0
- data/docs/known-problems.md +0 -14
- data/docs/mutant-minitest.md +1 -1
- data/docs/mutant-rspec.md +2 -24
- data/lib/mutant.rb +45 -53
- data/lib/mutant/ast/nodes.rb +0 -2
- data/lib/mutant/ast/types.rb +1 -117
- data/lib/mutant/base.rb +192 -0
- data/lib/mutant/bootstrap.rb +145 -0
- data/lib/mutant/cli.rb +68 -54
- data/lib/mutant/config.rb +119 -6
- data/lib/mutant/env.rb +94 -8
- data/lib/mutant/expression.rb +6 -1
- data/lib/mutant/expression/parser.rb +9 -31
- data/lib/mutant/integration.rb +64 -36
- data/lib/mutant/isolation.rb +16 -1
- data/lib/mutant/isolation/fork.rb +105 -40
- data/lib/mutant/license.rb +34 -0
- data/lib/mutant/license/subscription.rb +47 -0
- data/lib/mutant/license/subscription/commercial.rb +57 -0
- data/lib/mutant/license/subscription/opensource.rb +77 -0
- data/lib/mutant/loader.rb +27 -4
- data/lib/mutant/matcher.rb +48 -1
- data/lib/mutant/matcher/chain.rb +1 -1
- data/lib/mutant/matcher/config.rb +0 -2
- data/lib/mutant/matcher/filter.rb +1 -1
- data/lib/mutant/matcher/method.rb +11 -7
- data/lib/mutant/matcher/methods.rb +1 -1
- data/lib/mutant/matcher/namespace.rb +1 -1
- data/lib/mutant/matcher/null.rb +1 -1
- data/lib/mutant/matcher/scope.rb +1 -1
- data/lib/mutant/meta/example/dsl.rb +0 -8
- data/lib/mutant/mutation.rb +1 -2
- data/lib/mutant/mutator/node.rb +2 -9
- data/lib/mutant/mutator/node/arguments.rb +1 -1
- data/lib/mutant/mutator/node/class.rb +0 -8
- data/lib/mutant/mutator/node/define.rb +0 -12
- data/lib/mutant/mutator/node/generic.rb +30 -44
- data/lib/mutant/mutator/node/index.rb +4 -4
- data/lib/mutant/mutator/node/literal/regex.rb +0 -39
- data/lib/mutant/mutator/node/send.rb +13 -12
- data/lib/mutant/parallel.rb +61 -40
- data/lib/mutant/parallel/driver.rb +59 -0
- data/lib/mutant/parallel/source.rb +6 -2
- data/lib/mutant/parallel/worker.rb +63 -45
- data/lib/mutant/range.rb +15 -0
- data/lib/mutant/reporter/cli.rb +5 -11
- data/lib/mutant/reporter/cli/format.rb +3 -46
- data/lib/mutant/reporter/cli/printer/config.rb +5 -6
- data/lib/mutant/reporter/cli/printer/env.rb +40 -0
- data/lib/mutant/reporter/cli/printer/env_progress.rb +13 -17
- data/lib/mutant/reporter/cli/printer/isolation_result.rb +17 -3
- data/lib/mutant/reporter/cli/printer/mutation_result.rb +2 -3
- data/lib/mutant/reporter/cli/printer/status_progressive.rb +19 -10
- data/lib/mutant/repository.rb +0 -65
- data/lib/mutant/repository/diff.rb +104 -0
- data/lib/mutant/repository/diff/ranges.rb +52 -0
- data/lib/mutant/result.rb +16 -7
- data/lib/mutant/runner.rb +38 -47
- data/lib/mutant/runner/sink.rb +1 -1
- data/lib/mutant/selector/null.rb +19 -0
- data/lib/mutant/subject.rb +3 -1
- data/lib/mutant/subject/method/instance.rb +3 -1
- data/lib/mutant/transform.rb +511 -0
- data/lib/mutant/variable.rb +282 -0
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warnings.rb +113 -0
- data/meta/case.rb +1 -0
- data/meta/class.rb +0 -9
- data/meta/def.rb +1 -26
- data/meta/regexp.rb +10 -20
- data/meta/send.rb +14 -46
- data/mutant-minitest.gemspec +1 -1
- data/mutant-rspec.gemspec +2 -2
- data/mutant.gemspec +15 -16
- data/mutant.yml +6 -0
- data/spec/integration/mutant/isolation/fork_spec.rb +22 -5
- data/spec/integration/mutant/minitest_spec.rb +3 -2
- data/spec/integration/mutant/rspec_spec.rb +4 -3
- data/spec/integrations.yml +16 -13
- data/spec/shared/base_behavior.rb +45 -0
- data/spec/shared/framework_integration_behavior.rb +43 -14
- data/spec/spec_helper.rb +21 -17
- data/spec/support/corpus.rb +56 -95
- data/spec/support/shared_context.rb +37 -14
- data/spec/support/xspec.rb +7 -3
- data/spec/unit/mutant/bootstrap_spec.rb +216 -0
- data/spec/unit/mutant/cli_spec.rb +173 -117
- data/spec/unit/mutant/config_spec.rb +126 -0
- data/spec/unit/mutant/either_spec.rb +247 -0
- data/spec/unit/mutant/env_spec.rb +162 -40
- data/spec/unit/mutant/expression/method_spec.rb +16 -0
- data/spec/unit/mutant/expression/parser_spec.rb +29 -33
- data/spec/unit/mutant/expression_spec.rb +5 -7
- data/spec/unit/mutant/integration_spec.rb +100 -9
- data/spec/unit/mutant/isolation/fork_spec.rb +125 -67
- data/spec/unit/mutant/isolation/result_spec.rb +33 -1
- data/spec/unit/mutant/license_spec.rb +257 -0
- data/spec/unit/mutant/loader_spec.rb +50 -11
- data/spec/unit/mutant/matcher/compiler_spec.rb +0 -78
- data/spec/unit/mutant/matcher/method/instance_spec.rb +55 -11
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +12 -2
- data/spec/unit/mutant/matcher_spec.rb +102 -0
- data/spec/unit/mutant/maybe_spec.rb +60 -0
- data/spec/unit/mutant/meta/example/dsl_spec.rb +1 -17
- data/spec/unit/mutant/mutation_spec.rb +13 -6
- data/spec/unit/mutant/parallel/driver_spec.rb +112 -14
- data/spec/unit/mutant/parallel/source/array_spec.rb +25 -17
- data/spec/unit/mutant/parallel/worker_spec.rb +182 -44
- data/spec/unit/mutant/parallel_spec.rb +105 -8
- data/spec/unit/mutant/range_spec.rb +141 -0
- data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +7 -21
- data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +15 -6
- data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +10 -2
- data/spec/unit/mutant/reporter/cli/printer/isolation_result_spec.rb +12 -4
- data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +31 -2
- data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +4 -4
- data/spec/unit/mutant/reporter/cli/printer/subject_result_spec.rb +5 -0
- data/spec/unit/mutant/reporter/cli_spec.rb +46 -123
- data/spec/unit/mutant/repository/diff/ranges_spec.rb +180 -0
- data/spec/unit/mutant/repository/diff_spec.rb +84 -71
- data/spec/unit/mutant/require_highjack_spec.rb +1 -1
- data/spec/unit/mutant/result/env_spec.rb +39 -9
- data/spec/unit/mutant/result/test_spec.rb +14 -0
- data/spec/unit/mutant/runner_spec.rb +88 -41
- data/spec/unit/mutant/selector/expression_spec.rb +11 -10
- data/spec/unit/mutant/selector/null_spec.rb +17 -0
- data/spec/unit/mutant/subject/method/instance_spec.rb +44 -5
- data/spec/unit/mutant/subject/method/singleton_spec.rb +9 -2
- data/spec/unit/mutant/subject_spec.rb +9 -1
- data/spec/unit/mutant/transform/array_spec.rb +92 -0
- data/spec/unit/mutant/transform/bool_spec.rb +63 -0
- data/spec/unit/mutant/transform/error_spec.rb +132 -0
- data/spec/unit/mutant/transform/exception_spec.rb +44 -0
- data/spec/unit/mutant/transform/hash_spec.rb +236 -0
- data/spec/unit/mutant/transform/index_spec.rb +92 -0
- data/spec/unit/mutant/transform/named_spec.rb +49 -0
- data/spec/unit/mutant/transform/primitive_spec.rb +56 -0
- data/spec/unit/mutant/transform/sequence_spec.rb +98 -0
- data/spec/unit/mutant/variable_spec.rb +618 -0
- data/spec/unit/mutant/warnings_spec.rb +89 -0
- data/spec/unit/mutant/world_spec.rb +63 -0
- data/test_app/Gemfile.minitest +0 -2
- metadata +79 -113
- data/.gitattributes +0 -1
- data/.ruby-gemset +0 -1
- data/config/triage.yml +0 -2
- data/lib/mutant/actor.rb +0 -57
- data/lib/mutant/actor/env.rb +0 -31
- data/lib/mutant/actor/mailbox.rb +0 -34
- data/lib/mutant/actor/receiver.rb +0 -42
- data/lib/mutant/actor/sender.rb +0 -26
- data/lib/mutant/ast/meta/restarg.rb +0 -19
- data/lib/mutant/ast/regexp.rb +0 -42
- data/lib/mutant/ast/regexp/transformer.rb +0 -187
- data/lib/mutant/ast/regexp/transformer/direct.rb +0 -123
- data/lib/mutant/ast/regexp/transformer/named_group.rb +0 -59
- data/lib/mutant/ast/regexp/transformer/options_group.rb +0 -83
- data/lib/mutant/ast/regexp/transformer/quantifier.rb +0 -114
- data/lib/mutant/ast/regexp/transformer/recursive.rb +0 -58
- data/lib/mutant/ast/regexp/transformer/root.rb +0 -31
- data/lib/mutant/ast/regexp/transformer/text.rb +0 -60
- data/lib/mutant/env/bootstrap.rb +0 -160
- data/lib/mutant/matcher/compiler.rb +0 -60
- data/lib/mutant/mutator/node/regexp.rb +0 -35
- data/lib/mutant/mutator/node/regexp/alternation_meta.rb +0 -23
- data/lib/mutant/mutator/node/regexp/capture_group.rb +0 -28
- data/lib/mutant/mutator/node/regexp/character_type.rb +0 -32
- data/lib/mutant/mutator/node/regexp/end_of_line_anchor.rb +0 -23
- data/lib/mutant/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor.rb +0 -23
- data/lib/mutant/mutator/node/regexp/greedy_zero_or_more.rb +0 -27
- data/lib/mutant/parallel/master.rb +0 -181
- data/lib/mutant/reporter/cli/printer/status.rb +0 -53
- data/lib/mutant/reporter/cli/tput.rb +0 -46
- data/lib/mutant/warning_filter.rb +0 -61
- data/meta/regexp/character_types.rb +0 -23
- data/meta/regexp/regexp_alternation_meta.rb +0 -13
- data/meta/regexp/regexp_bol_anchor.rb +0 -10
- data/meta/regexp/regexp_bos_anchor.rb +0 -18
- data/meta/regexp/regexp_capture_group.rb +0 -19
- data/meta/regexp/regexp_eol_anchor.rb +0 -10
- data/meta/regexp/regexp_eos_anchor.rb +0 -8
- data/meta/regexp/regexp_eos_ob_eol_anchor.rb +0 -10
- data/meta/regexp/regexp_greedy_zero_or_more.rb +0 -12
- data/meta/regexp/regexp_root_expression.rb +0 -10
- data/meta/restarg.rb +0 -10
- data/spec/support/fake_actor.rb +0 -111
- data/spec/support/warning.rb +0 -66
- data/spec/unit/mutant/actor/binding_spec.rb +0 -34
- data/spec/unit/mutant/actor/env_spec.rb +0 -31
- data/spec/unit/mutant/actor/mailbox_spec.rb +0 -28
- data/spec/unit/mutant/actor/message_spec.rb +0 -25
- data/spec/unit/mutant/actor/receiver_spec.rb +0 -58
- data/spec/unit/mutant/actor/sender_spec.rb +0 -24
- data/spec/unit/mutant/ast/regexp/parse_spec.rb +0 -19
- data/spec/unit/mutant/ast/regexp/transformer/lookup_table/table_spec.rb +0 -21
- data/spec/unit/mutant/ast/regexp/transformer/lookup_table_spec.rb +0 -35
- data/spec/unit/mutant/ast/regexp/transformer_spec.rb +0 -21
- data/spec/unit/mutant/ast/regexp_spec.rb +0 -704
- data/spec/unit/mutant/env/bootstrap_spec.rb +0 -188
- data/spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb +0 -26
- data/spec/unit/mutant/parallel/master_spec.rb +0 -338
- data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +0 -121
- data/spec/unit/mutant/reporter/cli/tput_spec.rb +0 -50
- data/spec/unit/mutant/warning_filter_spec.rb +0 -106
- data/spec/unit/mutant_spec.rb +0 -17
- data/test_app/Gemfile.rspec3.7 +0 -7
data/lib/mutant/matcher/scope.rb
CHANGED
@@ -80,14 +80,6 @@ module Mutant
|
|
80
80
|
mutation('self')
|
81
81
|
end
|
82
82
|
|
83
|
-
# Add regexp mutations
|
84
|
-
#
|
85
|
-
# @return [undefined]
|
86
|
-
def regexp_mutations
|
87
|
-
mutation('//')
|
88
|
-
mutation('/nomatch\A/')
|
89
|
-
end
|
90
|
-
|
91
83
|
# Helper method to coerce input to node
|
92
84
|
#
|
93
85
|
# @param [String,Parser::AST::Node] input
|
data/lib/mutant/mutation.rb
CHANGED
@@ -61,7 +61,7 @@ module Mutant
|
|
61
61
|
#
|
62
62
|
# @param kernel [Kernel]
|
63
63
|
#
|
64
|
-
# @return [
|
64
|
+
# @return [Loader::Result]
|
65
65
|
def insert(kernel)
|
66
66
|
subject.prepare
|
67
67
|
Loader.call(
|
@@ -70,7 +70,6 @@ module Mutant
|
|
70
70
|
source: monkeypatch,
|
71
71
|
subject: subject
|
72
72
|
)
|
73
|
-
self
|
74
73
|
end
|
75
74
|
|
76
75
|
private
|
data/lib/mutant/mutator/node.rb
CHANGED
@@ -44,13 +44,6 @@ module Mutant
|
|
44
44
|
# @return [Parser::AST::Node]
|
45
45
|
alias_method :dup_node, :dup_input
|
46
46
|
|
47
|
-
# Original nodes children
|
48
|
-
#
|
49
|
-
# @return [Array<Parser::AST::Node>]
|
50
|
-
def children
|
51
|
-
node.children
|
52
|
-
end
|
53
|
-
|
54
47
|
# Dispatch on child index
|
55
48
|
#
|
56
49
|
# @param [Integer] index
|
@@ -122,7 +115,7 @@ module Mutant
|
|
122
115
|
#
|
123
116
|
# @return [undefined]
|
124
117
|
def emit_nil
|
125
|
-
emit(N_NIL) unless
|
118
|
+
emit(N_NIL) unless left_assignment?
|
126
119
|
end
|
127
120
|
|
128
121
|
# Parent node
|
@@ -150,7 +143,7 @@ module Mutant
|
|
150
143
|
# Test if the node is the left of an or_asgn or op_asgn
|
151
144
|
#
|
152
145
|
# @return [Boolean]
|
153
|
-
def
|
146
|
+
def left_assignment?
|
154
147
|
AST::Types::OP_ASSIGN.include?(parent_type) && parent.node.children.first.equal?(node)
|
155
148
|
end
|
156
149
|
|
@@ -15,16 +15,8 @@ module Mutant
|
|
15
15
|
#
|
16
16
|
# @return [undefined]
|
17
17
|
def dispatch
|
18
|
-
mutate_type
|
19
18
|
emit_body_mutations if body
|
20
19
|
end
|
21
|
-
|
22
|
-
# Emit class -> type mutations
|
23
|
-
#
|
24
|
-
# @return [undefined]
|
25
|
-
def mutate_type
|
26
|
-
emit(s(:module, klass, body))
|
27
|
-
end
|
28
20
|
end # Class
|
29
21
|
end # Node
|
30
22
|
end # Mutator
|
@@ -14,7 +14,6 @@ module Mutant
|
|
14
14
|
def dispatch
|
15
15
|
emit_arguments_mutations
|
16
16
|
emit_optarg_body_assignments
|
17
|
-
emit_restarg_body_mutation
|
18
17
|
emit_body(N_RAISE)
|
19
18
|
emit_body(N_ZSUPER)
|
20
19
|
emit_body(nil)
|
@@ -32,17 +31,6 @@ module Mutant
|
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
|
-
# Emit mutation with arg splat as empty array assignment in method
|
36
|
-
#
|
37
|
-
# @return [undefined]
|
38
|
-
def emit_restarg_body_mutation
|
39
|
-
arguments.children.each do |argument|
|
40
|
-
next unless n_restarg?(argument) && argument.children.one?
|
41
|
-
|
42
|
-
emit_body_prepend(s(:lvasgn, AST::Meta::Restarg.new(argument).name, s(:array)))
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
34
|
# Emit valid body ASTs depending on instance body
|
47
35
|
#
|
48
36
|
# @param node [Parser::AST::Node]
|
@@ -8,61 +8,47 @@ module Mutant
|
|
8
8
|
class Generic < self
|
9
9
|
|
10
10
|
unsupported_nodes = %i[
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
__FILE__
|
12
|
+
__LINE__
|
13
|
+
alias
|
14
14
|
arg_expr
|
15
|
+
back_ref
|
15
16
|
blockarg
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
blockarg_expr
|
18
|
+
complex
|
19
|
+
eflipflop
|
19
20
|
empty
|
20
|
-
|
21
|
+
ensure
|
21
22
|
for
|
22
|
-
|
23
|
-
back_ref
|
24
|
-
restarg
|
25
|
-
sclass
|
26
|
-
match_with_lvasgn
|
27
|
-
while_post
|
28
|
-
until_post
|
29
|
-
preexe
|
30
|
-
postexe
|
23
|
+
ident
|
31
24
|
iflipflop
|
32
|
-
|
25
|
+
kwrestarg
|
33
26
|
kwsplat
|
34
|
-
|
27
|
+
match_with_lvasgn
|
28
|
+
meth_ref
|
29
|
+
module
|
30
|
+
objc_kwarg
|
31
|
+
objc_restarg
|
32
|
+
objc_varargs
|
33
|
+
postexe
|
34
|
+
preexe
|
35
35
|
rational
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
regexp_eos_ob_eol_anchor
|
48
|
-
regexp_greedy_zero_or_more
|
49
|
-
regexp_hex_type
|
50
|
-
regexp_linebreak_type
|
51
|
-
regexp_nondigit_type
|
52
|
-
regexp_nonhex_type
|
53
|
-
regexp_nonspace_type
|
54
|
-
regexp_nonword_boundary_anchor
|
55
|
-
regexp_nonword_type
|
56
|
-
regexp_root_expression
|
57
|
-
regexp_space_type
|
58
|
-
regexp_word_boundary_anchor
|
59
|
-
regexp_word_type
|
60
|
-
regexp_xgrapheme_type
|
36
|
+
redo
|
37
|
+
restarg
|
38
|
+
restarg_expr
|
39
|
+
retry
|
40
|
+
root
|
41
|
+
sclass
|
42
|
+
shadowarg
|
43
|
+
undef
|
44
|
+
until_post
|
45
|
+
while_post
|
46
|
+
xstr
|
61
47
|
]
|
62
48
|
|
63
49
|
# These nodes still need a dedicated mutator,
|
64
50
|
# your contribution is that close!
|
65
|
-
handle(*
|
51
|
+
handle(*unsupported_nodes)
|
66
52
|
|
67
53
|
private
|
68
54
|
|
@@ -30,7 +30,7 @@ module Mutant
|
|
30
30
|
#
|
31
31
|
# @return [undefined]
|
32
32
|
def emit_send_forms
|
33
|
-
return if
|
33
|
+
return if left_assignment?
|
34
34
|
|
35
35
|
SEND_REPLACEMENTS.each do |selector|
|
36
36
|
emit(s(:send, receiver, selector, *indices))
|
@@ -55,7 +55,7 @@ module Mutant
|
|
55
55
|
# @return [undefined]
|
56
56
|
def mutate_indices
|
57
57
|
children_indices(index_range).each do |index|
|
58
|
-
emit_propagation(children.fetch(index)) unless
|
58
|
+
emit_propagation(children.fetch(index)) unless left_assignment?
|
59
59
|
delete_child(index)
|
60
60
|
mutate_child(index)
|
61
61
|
end
|
@@ -98,7 +98,7 @@ module Mutant
|
|
98
98
|
def dispatch
|
99
99
|
super()
|
100
100
|
|
101
|
-
return if
|
101
|
+
return if left_assignment?
|
102
102
|
|
103
103
|
emit_index_read
|
104
104
|
emit(children.last)
|
@@ -116,7 +116,7 @@ module Mutant
|
|
116
116
|
#
|
117
117
|
# @return [Range<Integer>]
|
118
118
|
def index_range
|
119
|
-
if
|
119
|
+
if left_assignment?
|
120
120
|
NO_VALUE_RANGE
|
121
121
|
else
|
122
122
|
REGULAR_RANGE
|
@@ -25,7 +25,6 @@ module Mutant
|
|
25
25
|
#
|
26
26
|
# @return [undefined]
|
27
27
|
def dispatch
|
28
|
-
mutate_body
|
29
28
|
emit_singletons unless parent_node
|
30
29
|
children.each_with_index do |child, index|
|
31
30
|
mutate_child(index) unless n_str?(child)
|
@@ -34,44 +33,6 @@ module Mutant
|
|
34
33
|
emit_type(s(:str, NULL_REGEXP_SOURCE), options)
|
35
34
|
end
|
36
35
|
|
37
|
-
# Mutate regexp body
|
38
|
-
#
|
39
|
-
# @note will only mutate parts of regexp body if the
|
40
|
-
# body is composed of only strings. Regular expressions
|
41
|
-
# with interpolation are skipped
|
42
|
-
#
|
43
|
-
# @return [undefined]
|
44
|
-
def mutate_body
|
45
|
-
return unless body.all?(&method(:n_str?)) && body_ast
|
46
|
-
|
47
|
-
Mutator.mutate(body_ast).each do |mutation|
|
48
|
-
source = AST::Regexp.to_expression(mutation).to_s
|
49
|
-
emit_type(s(:str, source), options)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# AST representation of regexp body
|
54
|
-
#
|
55
|
-
# @return [Parser::AST::Node, nil]
|
56
|
-
def body_ast
|
57
|
-
body_expression and AST::Regexp.to_ast(body_expression)
|
58
|
-
end
|
59
|
-
|
60
|
-
# Expression representation of regexp body
|
61
|
-
#
|
62
|
-
# @return [Regexp::Expression, nil]
|
63
|
-
def body_expression
|
64
|
-
AST::Regexp.parse(body.map(&:children).join)
|
65
|
-
end
|
66
|
-
memoize :body_expression
|
67
|
-
|
68
|
-
# Children of regexp node which compose regular expression source
|
69
|
-
#
|
70
|
-
# @return [Array<Parser::AST::Node>]
|
71
|
-
def body
|
72
|
-
children.slice(0...-1)
|
73
|
-
end
|
74
|
-
|
75
36
|
end # Regex
|
76
37
|
end # Literal
|
77
38
|
end # Node
|
@@ -21,11 +21,6 @@ module Mutant
|
|
21
21
|
reverse_merge: %i[merge],
|
22
22
|
map: %i[each],
|
23
23
|
flat_map: %i[map],
|
24
|
-
sample: %i[first last],
|
25
|
-
pop: %i[last],
|
26
|
-
shift: %i[first],
|
27
|
-
first: %i[last],
|
28
|
-
last: %i[first],
|
29
24
|
send: %i[public_send __send__],
|
30
25
|
__send__: %i[public_send],
|
31
26
|
method: %i[public_method],
|
@@ -33,13 +28,11 @@ module Mutant
|
|
33
28
|
eql?: %i[equal?],
|
34
29
|
to_s: %i[to_str],
|
35
30
|
to_i: %i[to_int],
|
36
|
-
to_a: %i[to_ary
|
31
|
+
to_a: %i[to_ary],
|
37
32
|
to_h: %i[to_hash],
|
38
33
|
at: %i[fetch key?],
|
39
34
|
fetch: %i[key?],
|
40
35
|
values_at: %i[fetch_values],
|
41
|
-
match: %i[match?],
|
42
|
-
'=~': %i[match?],
|
43
36
|
:== => %i[eql? equal?],
|
44
37
|
:>= => %i[> == eql? equal?],
|
45
38
|
:<= => %i[< == eql? equal?],
|
@@ -159,7 +152,7 @@ module Mutant
|
|
159
152
|
#
|
160
153
|
# @return [undefined]
|
161
154
|
def emit_integer_mutation
|
162
|
-
return unless
|
155
|
+
return unless selector.equal?(:to_i)
|
163
156
|
|
164
157
|
emit(s(:send, nil, :Integer, receiver))
|
165
158
|
end
|
@@ -193,11 +186,20 @@ module Mutant
|
|
193
186
|
def mutate_arguments
|
194
187
|
emit_type(receiver, selector)
|
195
188
|
remaining_children_with_index.each do |_node, index|
|
196
|
-
|
189
|
+
mutate_argument_index(index)
|
197
190
|
delete_child(index)
|
198
191
|
end
|
199
192
|
end
|
200
193
|
|
194
|
+
# Mutate argument
|
195
|
+
#
|
196
|
+
# @param [Integer] index
|
197
|
+
#
|
198
|
+
# @return [undefined]
|
199
|
+
def mutate_argument_index(index)
|
200
|
+
mutate_child(index) { |node| !n_begin?(node) }
|
201
|
+
end
|
202
|
+
|
201
203
|
# Emit argument propagation
|
202
204
|
#
|
203
205
|
# @return [undefined]
|
@@ -221,8 +223,7 @@ module Mutant
|
|
221
223
|
# @return [undefined]
|
222
224
|
def emit_implicit_self
|
223
225
|
emit_receiver(nil) if n_self?(receiver) && !(
|
224
|
-
KEYWORDS.include?(selector)
|
225
|
-
METHOD_OPERATORS.include?(selector) ||
|
226
|
+
KEYWORDS.include?(selector) ||
|
226
227
|
meta.attribute_assignment?
|
227
228
|
)
|
228
229
|
end
|
data/lib/mutant/parallel.rb
CHANGED
@@ -4,32 +4,65 @@ module Mutant
|
|
4
4
|
# Parallel execution engine of arbitrary payloads
|
5
5
|
module Parallel
|
6
6
|
|
7
|
-
# Driver for parallelized execution
|
8
|
-
class Driver
|
9
|
-
include Concord.new(:binding)
|
10
|
-
|
11
|
-
# Scheduler status
|
12
|
-
#
|
13
|
-
# @return [Object]
|
14
|
-
def status
|
15
|
-
binding.call(__method__)
|
16
|
-
end
|
17
|
-
|
18
|
-
# Stop master gracefully
|
19
|
-
#
|
20
|
-
# @return [self]
|
21
|
-
def stop
|
22
|
-
binding.call(__method__)
|
23
|
-
self
|
24
|
-
end
|
25
|
-
end # Driver
|
26
|
-
|
27
7
|
# Run async computation returning driver
|
28
8
|
#
|
9
|
+
# @param [Config] config
|
10
|
+
#
|
29
11
|
# @return [Driver]
|
30
12
|
def self.async(config)
|
31
|
-
|
13
|
+
shared = {
|
14
|
+
var_active_jobs: shared(Variable::IVar, config, value: Set.new),
|
15
|
+
var_final: shared(Variable::IVar, config),
|
16
|
+
var_sink: shared(Variable::IVar, config, value: config.sink)
|
17
|
+
}
|
18
|
+
|
19
|
+
Driver.new(
|
20
|
+
threads: threads(config, worker(config, **shared)),
|
21
|
+
**shared
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
# The worker
|
26
|
+
#
|
27
|
+
# @param [Config] config
|
28
|
+
#
|
29
|
+
# @return [Worker]
|
30
|
+
def self.worker(config, **shared)
|
31
|
+
Worker.new(
|
32
|
+
processor: config.processor,
|
33
|
+
var_running: shared(Variable::MVar, config, value: config.jobs),
|
34
|
+
var_source: shared(Variable::IVar, config, value: config.source),
|
35
|
+
**shared
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Start threads
|
40
|
+
#
|
41
|
+
# @param [Config] config
|
42
|
+
# @param [Worker] worker
|
43
|
+
#
|
44
|
+
# @return [Array<Thread>]
|
45
|
+
def self.threads(config, worker)
|
46
|
+
Array.new(config.jobs) { config.thread.new(&worker.method(:call)) }
|
32
47
|
end
|
48
|
+
private_class_method :threads
|
49
|
+
|
50
|
+
# Create shared variable
|
51
|
+
#
|
52
|
+
# @param [Class] klass
|
53
|
+
# @param [Config] config
|
54
|
+
#
|
55
|
+
# @return [Mutant::Variable]
|
56
|
+
#
|
57
|
+
# ignore :reek:LongParameterList
|
58
|
+
def self.shared(klass, config, **attributes)
|
59
|
+
klass.new(
|
60
|
+
condition_variable: config.condition_variable,
|
61
|
+
mutex: config.mutex,
|
62
|
+
**attributes
|
63
|
+
)
|
64
|
+
end
|
65
|
+
private_class_method :shared
|
33
66
|
|
34
67
|
# Job result sink
|
35
68
|
class Sink
|
@@ -42,7 +75,7 @@ module Mutant
|
|
42
75
|
# @return [self]
|
43
76
|
abstract_method :result
|
44
77
|
|
45
|
-
#
|
78
|
+
# The sink status
|
46
79
|
#
|
47
80
|
# @return [Object]
|
48
81
|
abstract_method :status
|
@@ -53,30 +86,16 @@ module Mutant
|
|
53
86
|
abstract_method :stop?
|
54
87
|
end # Sink
|
55
88
|
|
56
|
-
# Job to push to workers
|
57
|
-
class Job
|
58
|
-
include Adamantium::Flat, Anima.new(
|
59
|
-
:index,
|
60
|
-
:payload
|
61
|
-
)
|
62
|
-
end # Job
|
63
|
-
|
64
|
-
# Job result object received from workers
|
65
|
-
class JobResult
|
66
|
-
include Adamantium::Flat, Anima.new(
|
67
|
-
:job,
|
68
|
-
:payload
|
69
|
-
)
|
70
|
-
end # JobResult
|
71
|
-
|
72
89
|
# Parallel run configuration
|
73
90
|
class Config
|
74
91
|
include Adamantium::Flat, Anima.new(
|
75
|
-
:
|
92
|
+
:condition_variable,
|
76
93
|
:jobs,
|
94
|
+
:mutex,
|
77
95
|
:processor,
|
78
96
|
:sink,
|
79
|
-
:source
|
97
|
+
:source,
|
98
|
+
:thread
|
80
99
|
)
|
81
100
|
end # Config
|
82
101
|
|
@@ -87,6 +106,8 @@ module Mutant
|
|
87
106
|
:done,
|
88
107
|
:payload
|
89
108
|
)
|
109
|
+
|
110
|
+
alias_method :done?, :done
|
90
111
|
end # Status
|
91
112
|
|
92
113
|
end # Parallel
|