mutant 0.1.1 → 0.2.0
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.
- data/.gitignore +5 -11
- data/.rspec +0 -1
- data/.travis.yml +14 -3
- data/Changelog.md +3 -0
- data/Gemfile +5 -1
- data/Gemfile.devtools +49 -0
- data/Guardfile +18 -0
- data/README.md +67 -0
- data/Rakefile +4 -1
- data/TODO +13 -0
- data/bin/mutant +14 -0
- data/bin/zombie +14 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/roodi.yml +26 -0
- data/config/site.reek +93 -0
- data/config/yardstick.yml +2 -0
- data/lib/inflector.rb +7 -0
- data/lib/inflector/defaults.rb +62 -0
- data/lib/inflector/inflections.rb +209 -0
- data/lib/inflector/methods.rb +149 -0
- data/lib/inflector/version.rb +3 -0
- data/lib/mutant.rb +96 -21
- data/lib/mutant/cli.rb +309 -0
- data/lib/mutant/color.rb +61 -0
- data/lib/mutant/context.rb +36 -0
- data/lib/mutant/context/scope.rb +138 -0
- data/lib/mutant/differ.rb +100 -0
- data/lib/mutant/helper.rb +38 -0
- data/lib/mutant/killer.rb +136 -0
- data/lib/mutant/killer/forking.rb +41 -0
- data/lib/mutant/killer/rspec.rb +49 -0
- data/lib/mutant/killer/static.rb +19 -0
- data/lib/mutant/loader.rb +129 -0
- data/lib/mutant/matcher.rb +55 -0
- data/lib/mutant/matcher/chain.rb +66 -0
- data/lib/mutant/matcher/method.rb +173 -0
- data/lib/mutant/matcher/method/classifier.rb +126 -0
- data/lib/mutant/matcher/method/instance.rb +67 -0
- data/lib/mutant/matcher/method/singleton.rb +141 -0
- data/lib/mutant/matcher/object_space.rb +114 -0
- data/lib/mutant/matcher/scope_methods.rb +127 -0
- data/lib/mutant/mutation.rb +101 -12
- data/lib/mutant/mutation/filter.rb +75 -0
- data/lib/mutant/mutation/filter/code.rb +68 -0
- data/lib/mutant/mutation/filter/regexp.rb +39 -0
- data/lib/mutant/mutation/filter/whitelist.rb +47 -0
- data/lib/mutant/mutator.rb +134 -30
- data/lib/mutant/mutator/node.rb +163 -0
- data/lib/mutant/mutator/node/arguments.rb +24 -0
- data/lib/mutant/mutator/node/block.rb +24 -0
- data/lib/mutant/mutator/node/define.rb +24 -0
- data/lib/mutant/mutator/node/if_statement.rb +93 -0
- data/lib/mutant/mutator/node/literal.rb +54 -0
- data/lib/mutant/mutator/node/literal/array.rb +28 -0
- data/lib/mutant/mutator/node/literal/boolean.rb +49 -0
- data/lib/mutant/mutator/node/literal/dynamic.rb +24 -0
- data/lib/mutant/mutator/node/literal/empty_array.rb +26 -0
- data/lib/mutant/mutator/node/literal/fixnum.rb +37 -0
- data/lib/mutant/mutator/node/literal/float.rb +48 -0
- data/lib/mutant/mutator/node/literal/hash.rb +89 -0
- data/lib/mutant/mutator/node/literal/nil.rb +25 -0
- data/lib/mutant/mutator/node/literal/range.rb +94 -0
- data/lib/mutant/mutator/node/literal/regex.rb +43 -0
- data/lib/mutant/mutator/node/literal/string.rb +26 -0
- data/lib/mutant/mutator/node/literal/symbol.rb +26 -0
- data/lib/mutant/mutator/node/noop.rb +55 -0
- data/lib/mutant/mutator/node/receiver_case.rb +140 -0
- data/lib/mutant/mutator/node/return.rb +31 -0
- data/lib/mutant/mutator/node/send.rb +112 -0
- data/lib/mutant/mutator/registry.rb +48 -0
- data/lib/mutant/mutator/util.rb +87 -0
- data/lib/mutant/random.rb +24 -27
- data/lib/mutant/reporter.rb +48 -30
- data/lib/mutant/reporter/cli.rb +221 -0
- data/lib/mutant/reporter/null.rb +42 -0
- data/lib/mutant/reporter/stats.rb +64 -0
- data/lib/mutant/runner.rb +112 -0
- data/lib/mutant/strategy.rb +42 -0
- data/lib/mutant/strategy/rspec.rb +59 -0
- data/lib/mutant/strategy/rspec/example_lookup.rb +122 -0
- data/lib/mutant/subject.rb +115 -0
- data/lib/mutant/support/method_object.rb +31 -0
- data/locator.rb +87 -0
- data/mutant.gemspec +21 -21
- data/spec/integration/mutant/differ_spec.rb +15 -0
- data/spec/integration/mutant/loader_spec.rb +21 -0
- data/spec/integration/mutant/method_matching_spec.rb +269 -0
- data/spec/integration/mutant/rspec_killer_spec.rb +24 -0
- data/spec/integration/mutant/runner_spec.rb +26 -0
- data/spec/integration/mutant/zombie_spec.rb +8 -0
- data/spec/rcov.opts +7 -0
- data/spec/shared/command_method_behavior.rb +7 -0
- data/spec/shared/each_method_behaviour.rb +15 -0
- data/spec/shared/hash_method_behavior.rb +17 -0
- data/spec/shared/idempotent_method_behavior.rb +7 -0
- data/spec/shared/invertible_method_behaviour.rb +9 -0
- data/spec/shared/method_filter_parse_behavior.rb +16 -0
- data/spec/shared/method_match_behavior.rb +39 -0
- data/spec/shared/mutator_behavior.rb +46 -0
- data/spec/spec_helper.rb +11 -14
- data/spec/support/compress_helper.rb +10 -0
- data/spec/support/rspec.rb +22 -0
- data/spec/support/test_app.rb +5 -0
- data/spec/support/zombie.rb +141 -0
- data/spec/unit/mutant/cli/class_methods/new_spec.rb +87 -0
- data/spec/unit/mutant/cli/class_methods/run_spec.rb +38 -0
- data/spec/unit/mutant/context/root_spec.rb +11 -0
- data/spec/unit/mutant/context/scope/class_methods/build_spec.rb +29 -0
- data/spec/unit/mutant/context/scope/root_spec.rb +22 -0
- data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +27 -0
- data/spec/unit/mutant/killer/fail_ques_spec.rb +39 -0
- data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +32 -0
- data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +33 -0
- data/spec/unit/mutant/loader/rubinius/class_methods/run_spec.rb +42 -0
- data/spec/unit/mutant/matcher/chain/each_spec.rb +37 -0
- data/spec/unit/mutant/matcher/chain/matchers_spec.rb +12 -0
- data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +49 -0
- data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +12 -0
- data/spec/unit/mutant/matcher/each_spec.rb +14 -0
- data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +21 -0
- data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +34 -0
- data/spec/unit/mutant/matcher/method/method_spec.rb +11 -0
- data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +24 -0
- data/spec/unit/mutant/matcher/object_space/each_spec.rb +31 -0
- data/spec/unit/mutant/mutator/each_spec.rb +25 -0
- data/spec/unit/mutant/mutator/emit_new_spec.rb +51 -0
- data/spec/unit/mutant/mutator/emit_spec.rb +52 -0
- data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +36 -0
- data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +47 -0
- data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +30 -0
- data/spec/unit/mutant/mutator/node/literal/array_spec.rb +30 -0
- data/spec/unit/mutant/mutator/node/literal/boolean/mutation_spec.rb +23 -0
- data/spec/unit/mutant/mutator/node/literal/empty_array_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/literal/float_spec.rb +25 -0
- data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +34 -0
- data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +13 -0
- data/spec/unit/mutant/mutator/node/literal/range_spec.rb +35 -0
- data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +23 -0
- data/spec/unit/mutant/mutator/node/literal/string_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +27 -0
- data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +21 -0
- data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +78 -0
- data/spec/unit/mutant/mutator/self_spec.rb +7 -0
- data/spec/unit/mutant/subject/class_methods/new_spec.rb +13 -0
- data/spec/unit/mutant/subject/context_spec.rb +14 -0
- data/spec/unit/mutant/subject/each_spec.rb +35 -0
- data/spec/unit/mutant/subject/node_spec.rb +13 -0
- data/tasks/metrics/ci.rake +7 -0
- data/tasks/metrics/flay.rake +41 -0
- data/tasks/metrics/flog.rake +43 -0
- data/tasks/metrics/heckle.rake +216 -0
- data/tasks/metrics/metric_fu.rake +31 -0
- data/tasks/metrics/reek.rake +15 -0
- data/tasks/metrics/roodi.rake +15 -0
- data/tasks/metrics/yardstick.rake +23 -0
- data/tasks/spec.rake +45 -0
- data/tasks/yard.rake +9 -0
- data/test_app/.rspec +1 -0
- data/test_app/lib/test_app.rb +5 -0
- data/test_app/lib/test_app/literal.rb +32 -0
- data/test_app/spec/shared/command_method_behavior.rb +7 -0
- data/test_app/spec/shared/each_method_behaviour.rb +15 -0
- data/test_app/spec/shared/hash_method_behavior.rb +17 -0
- data/test_app/spec/shared/idempotent_method_behavior.rb +7 -0
- data/test_app/spec/shared/invertible_method_behaviour.rb +9 -0
- data/test_app/spec/shared/method_filter_parse_behavior.rb +16 -0
- data/test_app/spec/shared/method_match_behavior.rb +39 -0
- data/test_app/spec/shared/mutator_behavior.rb +44 -0
- data/test_app/spec/spec_helper.rb +7 -0
- data/test_app/spec/unit/test_app/literal/command_spec.rb +9 -0
- data/test_app/spec/unit/test_app/literal/string_spec.rb +9 -0
- metadata +346 -124
- data/.rvmrc +0 -1
- data/Readme.md +0 -13
- data/exe/mutate +0 -6
- data/lib/mutant/extensions.rb +0 -8
- data/lib/mutant/formatter.rb +0 -19
- data/lib/mutant/implementation.rb +0 -70
- data/lib/mutant/literal.rb +0 -147
- data/lib/mutant/method.rb +0 -31
- data/lib/mutant/mutatee.rb +0 -61
- data/lib/mutant/node.rb +0 -26
- data/lib/mutant/runners/rspec.rb +0 -34
- data/lib/mutant/version.rb +0 -3
- data/spec/functional/class_spec.rb +0 -46
- data/spec/functional/instance_method/array_spec.rb +0 -53
- data/spec/functional/instance_method/boolean_spec.rb +0 -101
- data/spec/functional/instance_method/call_spec.rb +0 -161
- data/spec/functional/instance_method/fixnum_spec.rb +0 -53
- data/spec/functional/instance_method/float_spec.rb +0 -53
- data/spec/functional/instance_method/hash_spec.rb +0 -53
- data/spec/functional/instance_method/if_spec.rb +0 -57
- data/spec/functional/instance_method/ivar_assign_spec.rb +0 -62
- data/spec/functional/instance_method/range_spec.rb +0 -53
- data/spec/functional/instance_method/regex_spec.rb +0 -55
- data/spec/functional/instance_method/string_spec.rb +0 -53
- data/spec/functional/instance_method/symbol_spec.rb +0 -53
- data/spec/functional/reporter/method_loaded_spec.rb +0 -62
- data/spec/functional/reporter/running_mutations_spec.rb +0 -60
- data/spec/functional/runners/rspec_spec.rb +0 -26
- data/spec/functional/singleton_method/array_spec.rb +0 -53
- data/spec/functional/singleton_method/boolean_spec.rb +0 -101
- data/spec/functional/singleton_method/call_spec.rb +0 -161
- data/spec/functional/singleton_method/fixnum_spec.rb +0 -53
- data/spec/functional/singleton_method/float_spec.rb +0 -53
- data/spec/functional/singleton_method/hash_spec.rb +0 -53
- data/spec/functional/singleton_method/if_spec.rb +0 -57
- data/spec/functional/singleton_method/ivar_assign_spec.rb +0 -60
- data/spec/functional/singleton_method/range_spec.rb +0 -53
- data/spec/functional/singleton_method/regex_spec.rb +0 -55
- data/spec/functional/singleton_method/string_spec.rb +0 -53
- data/spec/functional/singleton_method/symbol_spec.rb +0 -53
- data/spec/mutant/extensions_spec.rb +0 -13
- data/spec/mutant/implementation_spec.rb +0 -223
- data/spec/mutant/literal_spec.rb +0 -129
- data/spec/mutant/mutatee_spec.rb +0 -28
- data/spec/mutant/node_spec.rb +0 -41
- data/spec/mutant/random_spec.rb +0 -33
- data/spec/mutant/reporter_spec.rb +0 -17
- data/spec/mutant_spec.rb +0 -28
- data/spec/support/example_group_helpers.rb +0 -11
- data/spec/support/example_helpers.rb +0 -5
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Reporter
|
|
3
|
+
# Null reporter
|
|
4
|
+
Null = Class.new(self) do
|
|
5
|
+
# Report subject
|
|
6
|
+
#
|
|
7
|
+
# @param [Subject] subject
|
|
8
|
+
#
|
|
9
|
+
# @return [self]
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
#
|
|
13
|
+
def subject(*)
|
|
14
|
+
self
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Report mutation
|
|
18
|
+
#
|
|
19
|
+
# @param [Mutation] mutation
|
|
20
|
+
#
|
|
21
|
+
# @return [self]
|
|
22
|
+
#
|
|
23
|
+
# @api private
|
|
24
|
+
#
|
|
25
|
+
def mutation(*)
|
|
26
|
+
self
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Report killer
|
|
30
|
+
#
|
|
31
|
+
# @param [Killer] killer
|
|
32
|
+
#
|
|
33
|
+
# @return [self]
|
|
34
|
+
#
|
|
35
|
+
# @api private
|
|
36
|
+
#
|
|
37
|
+
def killer(*)
|
|
38
|
+
self
|
|
39
|
+
end
|
|
40
|
+
end.new.freeze
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Reporter
|
|
3
|
+
|
|
4
|
+
# Stats gathered while reporter is running
|
|
5
|
+
class Stats
|
|
6
|
+
|
|
7
|
+
# Return subject count
|
|
8
|
+
#
|
|
9
|
+
# @return [Fixnum]
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
#
|
|
13
|
+
attr_reader :subject
|
|
14
|
+
|
|
15
|
+
# Return mutation count
|
|
16
|
+
#
|
|
17
|
+
# @return [Fixnum]
|
|
18
|
+
#
|
|
19
|
+
# @api private
|
|
20
|
+
#
|
|
21
|
+
attr_reader :mutation
|
|
22
|
+
|
|
23
|
+
# Return kill count
|
|
24
|
+
#
|
|
25
|
+
# @return [Fixnum]
|
|
26
|
+
#
|
|
27
|
+
# @api private
|
|
28
|
+
#
|
|
29
|
+
attr_reader :kill
|
|
30
|
+
|
|
31
|
+
# Return mutation runtime
|
|
32
|
+
#
|
|
33
|
+
# @return [Float]
|
|
34
|
+
#
|
|
35
|
+
# @api private
|
|
36
|
+
#
|
|
37
|
+
attr_reader :time
|
|
38
|
+
|
|
39
|
+
def initialize
|
|
40
|
+
@start = Time.now
|
|
41
|
+
@subject = @mutation = @kill = @time = 0
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def runtime
|
|
45
|
+
Time.now - @start
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def subject
|
|
49
|
+
@subject +=1
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def alive
|
|
53
|
+
@mutation - @kill
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def killer(killer)
|
|
57
|
+
@mutation +=1
|
|
58
|
+
@kill +=1 unless killer.fail?
|
|
59
|
+
@time += killer.runtime
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
# Runner that allows to mutate an entire project
|
|
3
|
+
class Runner
|
|
4
|
+
include Adamantium::Flat
|
|
5
|
+
extend MethodObject
|
|
6
|
+
|
|
7
|
+
# Return killers with errors
|
|
8
|
+
#
|
|
9
|
+
# @return [Enumerable<Killer>]
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
#
|
|
13
|
+
attr_reader :errors
|
|
14
|
+
|
|
15
|
+
# Test for failure
|
|
16
|
+
#
|
|
17
|
+
# @return [true]
|
|
18
|
+
# returns true when there are left mutations
|
|
19
|
+
#
|
|
20
|
+
# @return [false]
|
|
21
|
+
# returns false othewise
|
|
22
|
+
#
|
|
23
|
+
# @api private
|
|
24
|
+
#
|
|
25
|
+
def fail?
|
|
26
|
+
!errors.empty?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Return config
|
|
30
|
+
#
|
|
31
|
+
# @return [Mutant::Config]
|
|
32
|
+
#
|
|
33
|
+
# @api private
|
|
34
|
+
#
|
|
35
|
+
attr_reader :config
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# Initialize object
|
|
40
|
+
#
|
|
41
|
+
# @param [Config] config
|
|
42
|
+
#
|
|
43
|
+
# @return [undefined]
|
|
44
|
+
#
|
|
45
|
+
# @api private
|
|
46
|
+
#
|
|
47
|
+
def initialize(config)
|
|
48
|
+
@config, @errors = config, []
|
|
49
|
+
|
|
50
|
+
reporter.config(config)
|
|
51
|
+
|
|
52
|
+
run
|
|
53
|
+
|
|
54
|
+
reporter.errors(@errors)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Return reporter
|
|
58
|
+
#
|
|
59
|
+
# @return [Reporter]
|
|
60
|
+
#
|
|
61
|
+
# @api private
|
|
62
|
+
#
|
|
63
|
+
def reporter
|
|
64
|
+
config.reporter
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Run mutation killers on subjects
|
|
68
|
+
#
|
|
69
|
+
# @return [undefined]
|
|
70
|
+
#
|
|
71
|
+
# @api private
|
|
72
|
+
#
|
|
73
|
+
def run
|
|
74
|
+
config.matcher.each do |subject|
|
|
75
|
+
reporter.subject(subject)
|
|
76
|
+
run_subject(subject)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Run mutation killers on subject
|
|
81
|
+
#
|
|
82
|
+
# @param [Subject] subject
|
|
83
|
+
#
|
|
84
|
+
# @return [undefined]
|
|
85
|
+
#
|
|
86
|
+
# @api private
|
|
87
|
+
#
|
|
88
|
+
def run_subject(subject)
|
|
89
|
+
subject.each do |mutation|
|
|
90
|
+
next unless config.filter.match?(mutation)
|
|
91
|
+
reporter.mutation(mutation)
|
|
92
|
+
kill(mutation)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Run killer on mutation
|
|
97
|
+
#
|
|
98
|
+
# @param [Mutation] mutation
|
|
99
|
+
#
|
|
100
|
+
# @return [undefined]
|
|
101
|
+
#
|
|
102
|
+
# @api private
|
|
103
|
+
#
|
|
104
|
+
def kill(mutation)
|
|
105
|
+
killer = config.strategy.kill(mutation)
|
|
106
|
+
reporter.killer(killer)
|
|
107
|
+
if killer.fail?
|
|
108
|
+
@errors << killer
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Strategy
|
|
3
|
+
include AbstractType
|
|
4
|
+
|
|
5
|
+
# Kill mutation
|
|
6
|
+
#
|
|
7
|
+
# @param [Mutation]
|
|
8
|
+
#
|
|
9
|
+
# @return [Killer]
|
|
10
|
+
#
|
|
11
|
+
# @api private
|
|
12
|
+
#
|
|
13
|
+
def self.kill(mutation)
|
|
14
|
+
killer.new(self, mutation)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Return killer
|
|
18
|
+
#
|
|
19
|
+
# @return [Class:Killer]
|
|
20
|
+
#
|
|
21
|
+
# @api private
|
|
22
|
+
#
|
|
23
|
+
def self.killer
|
|
24
|
+
self::KILLER
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Static strategies
|
|
28
|
+
class Static < self
|
|
29
|
+
|
|
30
|
+
# Always fail to kill strategy
|
|
31
|
+
class Fail < self
|
|
32
|
+
KILLER = Killer::Static::Fail
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Always succeed to kill strategy
|
|
36
|
+
class Success < self
|
|
37
|
+
KILLER = Killer::Static::Success
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Strategy
|
|
3
|
+
|
|
4
|
+
# Rspec strategy base class
|
|
5
|
+
class Rspec < self
|
|
6
|
+
|
|
7
|
+
KILLER = Killer::Forking.new(Killer::Rspec)
|
|
8
|
+
|
|
9
|
+
# DM2-style strategy
|
|
10
|
+
class DM2 < self
|
|
11
|
+
|
|
12
|
+
# Return filename pattern
|
|
13
|
+
#
|
|
14
|
+
# @return [String]
|
|
15
|
+
#
|
|
16
|
+
# @api private
|
|
17
|
+
#
|
|
18
|
+
def self.spec_files(mutation)
|
|
19
|
+
ExampleLookup.run(mutation)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Run all unit specs per mutation
|
|
24
|
+
class Unit < self
|
|
25
|
+
|
|
26
|
+
# Return file name pattern for mutation
|
|
27
|
+
#
|
|
28
|
+
# @return [Mutation]
|
|
29
|
+
#
|
|
30
|
+
# @api private
|
|
31
|
+
#
|
|
32
|
+
def self.spec_files(mutation)
|
|
33
|
+
Dir['spec/unit/**/*_spec.rb']
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Run all integration specs per mutation
|
|
38
|
+
class Unit < self
|
|
39
|
+
|
|
40
|
+
# Return file name pattern for mutation
|
|
41
|
+
#
|
|
42
|
+
# @return [Mutation]
|
|
43
|
+
#
|
|
44
|
+
# @api private
|
|
45
|
+
#
|
|
46
|
+
def self.spec_files(mutation)
|
|
47
|
+
Dir['spec/integration/**/*_spec.rb']
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Run all specs per mutation
|
|
52
|
+
class Full < self
|
|
53
|
+
def self.spec_files(mutation)
|
|
54
|
+
Dir['spec/**/*_spec.rb']
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Strategy
|
|
3
|
+
class Rspec
|
|
4
|
+
|
|
5
|
+
# Example lookup for rspec
|
|
6
|
+
class ExampleLookup
|
|
7
|
+
include Adamantium::Flat, Equalizer.new(:mutation)
|
|
8
|
+
|
|
9
|
+
# Perform example lookup
|
|
10
|
+
#
|
|
11
|
+
# @param [Mutation]
|
|
12
|
+
#
|
|
13
|
+
# @return [Enumerable<String>]
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
#
|
|
17
|
+
def self.run(mutation)
|
|
18
|
+
new(mutation).spec_files
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Return mutation
|
|
22
|
+
#
|
|
23
|
+
# @return [Mutation]
|
|
24
|
+
#
|
|
25
|
+
# @api private
|
|
26
|
+
#
|
|
27
|
+
attr_reader :mutation
|
|
28
|
+
|
|
29
|
+
# Return spec files
|
|
30
|
+
#
|
|
31
|
+
# @return [Enumerable<String>]
|
|
32
|
+
#
|
|
33
|
+
# @api private
|
|
34
|
+
#
|
|
35
|
+
def spec_files
|
|
36
|
+
expression = glob_expression
|
|
37
|
+
files = Dir[expression]
|
|
38
|
+
|
|
39
|
+
if files.empty?
|
|
40
|
+
$stderr.puts("Spec file(s): #{expression.inspect} not found for #{mutation.identification}")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
files
|
|
44
|
+
end
|
|
45
|
+
memoize :spec_files
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# Return method matcher
|
|
50
|
+
#
|
|
51
|
+
# @return [Matcher]
|
|
52
|
+
#
|
|
53
|
+
# @api private
|
|
54
|
+
#
|
|
55
|
+
def matcher
|
|
56
|
+
mutation.subject.matcher
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Return spec file
|
|
60
|
+
#
|
|
61
|
+
# @return [String]
|
|
62
|
+
#
|
|
63
|
+
# @api private
|
|
64
|
+
#
|
|
65
|
+
def spec_file
|
|
66
|
+
matcher.method_name.to_s.
|
|
67
|
+
gsub(/\?\z/, '_predicate').
|
|
68
|
+
gsub(/\=\z/, '_writer').
|
|
69
|
+
gsub(/!\z/, '_bang') + '_spec.rb'
|
|
70
|
+
end
|
|
71
|
+
memoize :spec_file
|
|
72
|
+
|
|
73
|
+
# Return glob expression
|
|
74
|
+
#
|
|
75
|
+
# @return [String]
|
|
76
|
+
#
|
|
77
|
+
# @api private
|
|
78
|
+
#
|
|
79
|
+
def glob_expression
|
|
80
|
+
if mutation.subject.matcher.public?
|
|
81
|
+
"#{base_path}/#{spec_file}"
|
|
82
|
+
else
|
|
83
|
+
"#{base_path}/*_spec.rb"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Return instance of singleton path appendo
|
|
88
|
+
#
|
|
89
|
+
# @return [String]
|
|
90
|
+
#
|
|
91
|
+
# @api private
|
|
92
|
+
#
|
|
93
|
+
def scope_append
|
|
94
|
+
matcher.kind_of?(Matcher::Method::Singleton) ? '/class_methods' : ''
|
|
95
|
+
end
|
|
96
|
+
memoize :scope_append
|
|
97
|
+
|
|
98
|
+
# Return base path
|
|
99
|
+
#
|
|
100
|
+
# @return [String]
|
|
101
|
+
#
|
|
102
|
+
# @api private
|
|
103
|
+
#
|
|
104
|
+
def base_path
|
|
105
|
+
"spec/unit/#{Inflector.underscore(mutation.subject.context.scope.name)}#{scope_append}"
|
|
106
|
+
end
|
|
107
|
+
memoize :base_path
|
|
108
|
+
|
|
109
|
+
# Initalize object
|
|
110
|
+
#
|
|
111
|
+
# @param [Mutation] mutation
|
|
112
|
+
#
|
|
113
|
+
# @api private
|
|
114
|
+
#
|
|
115
|
+
def initialize(mutation)
|
|
116
|
+
@mutation = mutation
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
# Subject of a mutation
|
|
3
|
+
class Subject
|
|
4
|
+
include Adamantium::Flat, Enumerable, Equalizer.new(:context, :matcher, :node)
|
|
5
|
+
|
|
6
|
+
# Return context
|
|
7
|
+
#
|
|
8
|
+
# @return [Context]
|
|
9
|
+
#
|
|
10
|
+
# @api private
|
|
11
|
+
#
|
|
12
|
+
attr_reader :context
|
|
13
|
+
|
|
14
|
+
# Return matcher
|
|
15
|
+
#
|
|
16
|
+
# @return [Matcher]
|
|
17
|
+
#
|
|
18
|
+
# @api private
|
|
19
|
+
#
|
|
20
|
+
attr_reader :matcher
|
|
21
|
+
|
|
22
|
+
# Return AST node
|
|
23
|
+
#
|
|
24
|
+
# @return [Rubinius::AST::Node]
|
|
25
|
+
#
|
|
26
|
+
# @api private
|
|
27
|
+
#
|
|
28
|
+
attr_reader :node
|
|
29
|
+
|
|
30
|
+
# Enumerate possible mutations
|
|
31
|
+
#
|
|
32
|
+
# @return [self]
|
|
33
|
+
# returns self if block given
|
|
34
|
+
#
|
|
35
|
+
# @return [Enumerator<Mutation>]
|
|
36
|
+
# returns eumerator if no block given
|
|
37
|
+
#
|
|
38
|
+
# @api private
|
|
39
|
+
#
|
|
40
|
+
def each
|
|
41
|
+
return to_enum unless block_given?
|
|
42
|
+
Mutator.each(node) do |mutant|
|
|
43
|
+
yield Mutation.new(self, mutant)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
self
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Return subject identicication
|
|
50
|
+
#
|
|
51
|
+
# @return [String]
|
|
52
|
+
#
|
|
53
|
+
# @api private
|
|
54
|
+
#
|
|
55
|
+
def identification
|
|
56
|
+
source_path = context.source_path
|
|
57
|
+
source_line = node.line
|
|
58
|
+
"#{matcher.identification}:#{source_path}:#{source_line}"
|
|
59
|
+
end
|
|
60
|
+
memoize :identification
|
|
61
|
+
|
|
62
|
+
# Return source representation of ast
|
|
63
|
+
#
|
|
64
|
+
# @return [Source]
|
|
65
|
+
#
|
|
66
|
+
# @api private
|
|
67
|
+
#
|
|
68
|
+
def source
|
|
69
|
+
ToSource.to_source(node)
|
|
70
|
+
end
|
|
71
|
+
memoize :source
|
|
72
|
+
|
|
73
|
+
# Return root AST for node
|
|
74
|
+
#
|
|
75
|
+
# @param [Rubinius::AST::Node] node
|
|
76
|
+
#
|
|
77
|
+
# @return [Rubinius::AST::Node]
|
|
78
|
+
#
|
|
79
|
+
# @api private
|
|
80
|
+
#
|
|
81
|
+
def root(node)
|
|
82
|
+
context.root(node)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Return root AST node for original AST ndoe
|
|
86
|
+
#
|
|
87
|
+
# @return [Rubinius::AST::Node]
|
|
88
|
+
#
|
|
89
|
+
# @api private
|
|
90
|
+
#
|
|
91
|
+
def original_root
|
|
92
|
+
root(node)
|
|
93
|
+
end
|
|
94
|
+
memoize :original_root
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
# Initialize subject
|
|
99
|
+
#
|
|
100
|
+
# @param [Matcher] matcher
|
|
101
|
+
# the context of mutations
|
|
102
|
+
#
|
|
103
|
+
# @param [Rubinius::AST::Node] node
|
|
104
|
+
# the node to be mutated
|
|
105
|
+
#
|
|
106
|
+
# @return [unkown]
|
|
107
|
+
#
|
|
108
|
+
# @api private
|
|
109
|
+
#
|
|
110
|
+
def initialize(matcher, context, node)
|
|
111
|
+
@matcher, @context, @node = matcher, context, node
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|
|
115
|
+
end
|