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.
Files changed (225) hide show
  1. data/.gitignore +5 -11
  2. data/.rspec +0 -1
  3. data/.travis.yml +14 -3
  4. data/Changelog.md +3 -0
  5. data/Gemfile +5 -1
  6. data/Gemfile.devtools +49 -0
  7. data/Guardfile +18 -0
  8. data/README.md +67 -0
  9. data/Rakefile +4 -1
  10. data/TODO +13 -0
  11. data/bin/mutant +14 -0
  12. data/bin/zombie +14 -0
  13. data/config/flay.yml +3 -0
  14. data/config/flog.yml +2 -0
  15. data/config/roodi.yml +26 -0
  16. data/config/site.reek +93 -0
  17. data/config/yardstick.yml +2 -0
  18. data/lib/inflector.rb +7 -0
  19. data/lib/inflector/defaults.rb +62 -0
  20. data/lib/inflector/inflections.rb +209 -0
  21. data/lib/inflector/methods.rb +149 -0
  22. data/lib/inflector/version.rb +3 -0
  23. data/lib/mutant.rb +96 -21
  24. data/lib/mutant/cli.rb +309 -0
  25. data/lib/mutant/color.rb +61 -0
  26. data/lib/mutant/context.rb +36 -0
  27. data/lib/mutant/context/scope.rb +138 -0
  28. data/lib/mutant/differ.rb +100 -0
  29. data/lib/mutant/helper.rb +38 -0
  30. data/lib/mutant/killer.rb +136 -0
  31. data/lib/mutant/killer/forking.rb +41 -0
  32. data/lib/mutant/killer/rspec.rb +49 -0
  33. data/lib/mutant/killer/static.rb +19 -0
  34. data/lib/mutant/loader.rb +129 -0
  35. data/lib/mutant/matcher.rb +55 -0
  36. data/lib/mutant/matcher/chain.rb +66 -0
  37. data/lib/mutant/matcher/method.rb +173 -0
  38. data/lib/mutant/matcher/method/classifier.rb +126 -0
  39. data/lib/mutant/matcher/method/instance.rb +67 -0
  40. data/lib/mutant/matcher/method/singleton.rb +141 -0
  41. data/lib/mutant/matcher/object_space.rb +114 -0
  42. data/lib/mutant/matcher/scope_methods.rb +127 -0
  43. data/lib/mutant/mutation.rb +101 -12
  44. data/lib/mutant/mutation/filter.rb +75 -0
  45. data/lib/mutant/mutation/filter/code.rb +68 -0
  46. data/lib/mutant/mutation/filter/regexp.rb +39 -0
  47. data/lib/mutant/mutation/filter/whitelist.rb +47 -0
  48. data/lib/mutant/mutator.rb +134 -30
  49. data/lib/mutant/mutator/node.rb +163 -0
  50. data/lib/mutant/mutator/node/arguments.rb +24 -0
  51. data/lib/mutant/mutator/node/block.rb +24 -0
  52. data/lib/mutant/mutator/node/define.rb +24 -0
  53. data/lib/mutant/mutator/node/if_statement.rb +93 -0
  54. data/lib/mutant/mutator/node/literal.rb +54 -0
  55. data/lib/mutant/mutator/node/literal/array.rb +28 -0
  56. data/lib/mutant/mutator/node/literal/boolean.rb +49 -0
  57. data/lib/mutant/mutator/node/literal/dynamic.rb +24 -0
  58. data/lib/mutant/mutator/node/literal/empty_array.rb +26 -0
  59. data/lib/mutant/mutator/node/literal/fixnum.rb +37 -0
  60. data/lib/mutant/mutator/node/literal/float.rb +48 -0
  61. data/lib/mutant/mutator/node/literal/hash.rb +89 -0
  62. data/lib/mutant/mutator/node/literal/nil.rb +25 -0
  63. data/lib/mutant/mutator/node/literal/range.rb +94 -0
  64. data/lib/mutant/mutator/node/literal/regex.rb +43 -0
  65. data/lib/mutant/mutator/node/literal/string.rb +26 -0
  66. data/lib/mutant/mutator/node/literal/symbol.rb +26 -0
  67. data/lib/mutant/mutator/node/noop.rb +55 -0
  68. data/lib/mutant/mutator/node/receiver_case.rb +140 -0
  69. data/lib/mutant/mutator/node/return.rb +31 -0
  70. data/lib/mutant/mutator/node/send.rb +112 -0
  71. data/lib/mutant/mutator/registry.rb +48 -0
  72. data/lib/mutant/mutator/util.rb +87 -0
  73. data/lib/mutant/random.rb +24 -27
  74. data/lib/mutant/reporter.rb +48 -30
  75. data/lib/mutant/reporter/cli.rb +221 -0
  76. data/lib/mutant/reporter/null.rb +42 -0
  77. data/lib/mutant/reporter/stats.rb +64 -0
  78. data/lib/mutant/runner.rb +112 -0
  79. data/lib/mutant/strategy.rb +42 -0
  80. data/lib/mutant/strategy/rspec.rb +59 -0
  81. data/lib/mutant/strategy/rspec/example_lookup.rb +122 -0
  82. data/lib/mutant/subject.rb +115 -0
  83. data/lib/mutant/support/method_object.rb +31 -0
  84. data/locator.rb +87 -0
  85. data/mutant.gemspec +21 -21
  86. data/spec/integration/mutant/differ_spec.rb +15 -0
  87. data/spec/integration/mutant/loader_spec.rb +21 -0
  88. data/spec/integration/mutant/method_matching_spec.rb +269 -0
  89. data/spec/integration/mutant/rspec_killer_spec.rb +24 -0
  90. data/spec/integration/mutant/runner_spec.rb +26 -0
  91. data/spec/integration/mutant/zombie_spec.rb +8 -0
  92. data/spec/rcov.opts +7 -0
  93. data/spec/shared/command_method_behavior.rb +7 -0
  94. data/spec/shared/each_method_behaviour.rb +15 -0
  95. data/spec/shared/hash_method_behavior.rb +17 -0
  96. data/spec/shared/idempotent_method_behavior.rb +7 -0
  97. data/spec/shared/invertible_method_behaviour.rb +9 -0
  98. data/spec/shared/method_filter_parse_behavior.rb +16 -0
  99. data/spec/shared/method_match_behavior.rb +39 -0
  100. data/spec/shared/mutator_behavior.rb +46 -0
  101. data/spec/spec_helper.rb +11 -14
  102. data/spec/support/compress_helper.rb +10 -0
  103. data/spec/support/rspec.rb +22 -0
  104. data/spec/support/test_app.rb +5 -0
  105. data/spec/support/zombie.rb +141 -0
  106. data/spec/unit/mutant/cli/class_methods/new_spec.rb +87 -0
  107. data/spec/unit/mutant/cli/class_methods/run_spec.rb +38 -0
  108. data/spec/unit/mutant/context/root_spec.rb +11 -0
  109. data/spec/unit/mutant/context/scope/class_methods/build_spec.rb +29 -0
  110. data/spec/unit/mutant/context/scope/root_spec.rb +22 -0
  111. data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +27 -0
  112. data/spec/unit/mutant/killer/fail_ques_spec.rb +39 -0
  113. data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +32 -0
  114. data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +33 -0
  115. data/spec/unit/mutant/loader/rubinius/class_methods/run_spec.rb +42 -0
  116. data/spec/unit/mutant/matcher/chain/each_spec.rb +37 -0
  117. data/spec/unit/mutant/matcher/chain/matchers_spec.rb +12 -0
  118. data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +49 -0
  119. data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +12 -0
  120. data/spec/unit/mutant/matcher/each_spec.rb +14 -0
  121. data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +21 -0
  122. data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +34 -0
  123. data/spec/unit/mutant/matcher/method/method_spec.rb +11 -0
  124. data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +24 -0
  125. data/spec/unit/mutant/matcher/object_space/each_spec.rb +31 -0
  126. data/spec/unit/mutant/mutator/each_spec.rb +25 -0
  127. data/spec/unit/mutant/mutator/emit_new_spec.rb +51 -0
  128. data/spec/unit/mutant/mutator/emit_spec.rb +52 -0
  129. data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +36 -0
  130. data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +47 -0
  131. data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +30 -0
  132. data/spec/unit/mutant/mutator/node/literal/array_spec.rb +30 -0
  133. data/spec/unit/mutant/mutator/node/literal/boolean/mutation_spec.rb +23 -0
  134. data/spec/unit/mutant/mutator/node/literal/empty_array_spec.rb +17 -0
  135. data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +17 -0
  136. data/spec/unit/mutant/mutator/node/literal/float_spec.rb +25 -0
  137. data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +34 -0
  138. data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +13 -0
  139. data/spec/unit/mutant/mutator/node/literal/range_spec.rb +35 -0
  140. data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +23 -0
  141. data/spec/unit/mutant/mutator/node/literal/string_spec.rb +17 -0
  142. data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +17 -0
  143. data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +27 -0
  144. data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +21 -0
  145. data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +78 -0
  146. data/spec/unit/mutant/mutator/self_spec.rb +7 -0
  147. data/spec/unit/mutant/subject/class_methods/new_spec.rb +13 -0
  148. data/spec/unit/mutant/subject/context_spec.rb +14 -0
  149. data/spec/unit/mutant/subject/each_spec.rb +35 -0
  150. data/spec/unit/mutant/subject/node_spec.rb +13 -0
  151. data/tasks/metrics/ci.rake +7 -0
  152. data/tasks/metrics/flay.rake +41 -0
  153. data/tasks/metrics/flog.rake +43 -0
  154. data/tasks/metrics/heckle.rake +216 -0
  155. data/tasks/metrics/metric_fu.rake +31 -0
  156. data/tasks/metrics/reek.rake +15 -0
  157. data/tasks/metrics/roodi.rake +15 -0
  158. data/tasks/metrics/yardstick.rake +23 -0
  159. data/tasks/spec.rake +45 -0
  160. data/tasks/yard.rake +9 -0
  161. data/test_app/.rspec +1 -0
  162. data/test_app/lib/test_app.rb +5 -0
  163. data/test_app/lib/test_app/literal.rb +32 -0
  164. data/test_app/spec/shared/command_method_behavior.rb +7 -0
  165. data/test_app/spec/shared/each_method_behaviour.rb +15 -0
  166. data/test_app/spec/shared/hash_method_behavior.rb +17 -0
  167. data/test_app/spec/shared/idempotent_method_behavior.rb +7 -0
  168. data/test_app/spec/shared/invertible_method_behaviour.rb +9 -0
  169. data/test_app/spec/shared/method_filter_parse_behavior.rb +16 -0
  170. data/test_app/spec/shared/method_match_behavior.rb +39 -0
  171. data/test_app/spec/shared/mutator_behavior.rb +44 -0
  172. data/test_app/spec/spec_helper.rb +7 -0
  173. data/test_app/spec/unit/test_app/literal/command_spec.rb +9 -0
  174. data/test_app/spec/unit/test_app/literal/string_spec.rb +9 -0
  175. metadata +346 -124
  176. data/.rvmrc +0 -1
  177. data/Readme.md +0 -13
  178. data/exe/mutate +0 -6
  179. data/lib/mutant/extensions.rb +0 -8
  180. data/lib/mutant/formatter.rb +0 -19
  181. data/lib/mutant/implementation.rb +0 -70
  182. data/lib/mutant/literal.rb +0 -147
  183. data/lib/mutant/method.rb +0 -31
  184. data/lib/mutant/mutatee.rb +0 -61
  185. data/lib/mutant/node.rb +0 -26
  186. data/lib/mutant/runners/rspec.rb +0 -34
  187. data/lib/mutant/version.rb +0 -3
  188. data/spec/functional/class_spec.rb +0 -46
  189. data/spec/functional/instance_method/array_spec.rb +0 -53
  190. data/spec/functional/instance_method/boolean_spec.rb +0 -101
  191. data/spec/functional/instance_method/call_spec.rb +0 -161
  192. data/spec/functional/instance_method/fixnum_spec.rb +0 -53
  193. data/spec/functional/instance_method/float_spec.rb +0 -53
  194. data/spec/functional/instance_method/hash_spec.rb +0 -53
  195. data/spec/functional/instance_method/if_spec.rb +0 -57
  196. data/spec/functional/instance_method/ivar_assign_spec.rb +0 -62
  197. data/spec/functional/instance_method/range_spec.rb +0 -53
  198. data/spec/functional/instance_method/regex_spec.rb +0 -55
  199. data/spec/functional/instance_method/string_spec.rb +0 -53
  200. data/spec/functional/instance_method/symbol_spec.rb +0 -53
  201. data/spec/functional/reporter/method_loaded_spec.rb +0 -62
  202. data/spec/functional/reporter/running_mutations_spec.rb +0 -60
  203. data/spec/functional/runners/rspec_spec.rb +0 -26
  204. data/spec/functional/singleton_method/array_spec.rb +0 -53
  205. data/spec/functional/singleton_method/boolean_spec.rb +0 -101
  206. data/spec/functional/singleton_method/call_spec.rb +0 -161
  207. data/spec/functional/singleton_method/fixnum_spec.rb +0 -53
  208. data/spec/functional/singleton_method/float_spec.rb +0 -53
  209. data/spec/functional/singleton_method/hash_spec.rb +0 -53
  210. data/spec/functional/singleton_method/if_spec.rb +0 -57
  211. data/spec/functional/singleton_method/ivar_assign_spec.rb +0 -60
  212. data/spec/functional/singleton_method/range_spec.rb +0 -53
  213. data/spec/functional/singleton_method/regex_spec.rb +0 -55
  214. data/spec/functional/singleton_method/string_spec.rb +0 -53
  215. data/spec/functional/singleton_method/symbol_spec.rb +0 -53
  216. data/spec/mutant/extensions_spec.rb +0 -13
  217. data/spec/mutant/implementation_spec.rb +0 -223
  218. data/spec/mutant/literal_spec.rb +0 -129
  219. data/spec/mutant/mutatee_spec.rb +0 -28
  220. data/spec/mutant/node_spec.rb +0 -41
  221. data/spec/mutant/random_spec.rb +0 -33
  222. data/spec/mutant/reporter_spec.rb +0 -17
  223. data/spec/mutant_spec.rb +0 -28
  224. data/spec/support/example_group_helpers.rb +0 -11
  225. data/spec/support/example_helpers.rb +0 -5
@@ -0,0 +1,100 @@
1
+ module Mutant
2
+ # Class to create diffs from source code
3
+ class Differ
4
+ include Adamantium::Flat
5
+
6
+ # Return source diff
7
+ #
8
+ # @return [String]
9
+ #
10
+ # @api private
11
+ #
12
+ def diff
13
+ output = ''
14
+ @diffs.each do |piece|
15
+ hunk = Diff::LCS::Hunk.new(@old, @new, piece, CONTEXT_LINES, length_difference)
16
+ output << hunk.diff(FORMAT)
17
+ output << "\n"
18
+ end
19
+ output
20
+ end
21
+ memoize :diff
22
+
23
+ # Return colorized source diff
24
+ #
25
+ # @return [String]
26
+ #
27
+ # @api private
28
+ #
29
+ def colorized_diff
30
+ diff.lines.map do |line|
31
+ self.class.colorize_line(line)
32
+ end.join
33
+ end
34
+ memoize :colorized_diff
35
+
36
+ private
37
+
38
+ FORMAT = :unified
39
+ CONTEXT_LINES = 3
40
+
41
+ # Initialize differ object
42
+ #
43
+ # @param [String] old
44
+ # @param [String] new
45
+ #
46
+ # @return [undefined]
47
+ #
48
+ # @api private
49
+ #
50
+ def initialize(old, new)
51
+ @old, @new = self.class.lines(old), self.class.lines(new)
52
+ @diffs = Diff::LCS.diff(@old, @new)
53
+ end
54
+
55
+ # Return length difference
56
+ #
57
+ # @return [Fixnum]
58
+ #
59
+ # @api private
60
+ #
61
+ def length_difference
62
+ @new.size - @old.size
63
+ end
64
+
65
+ # Break up source into lines
66
+ #
67
+ # @param [String] source
68
+ #
69
+ # @return [Array<String>]
70
+ #
71
+ # @api private
72
+ #
73
+ def self.lines(source)
74
+ source.lines.map { |line| line.chomp }
75
+ end
76
+
77
+ # Return colorized diff line
78
+ #
79
+ # @param [String] line
80
+ #
81
+ # @return [String]
82
+ # returns colorized line
83
+ #
84
+ # @api private
85
+ #
86
+ def self.colorize_line(line)
87
+ case line[0].chr
88
+ when '+'
89
+ Color::GREEN
90
+ when '-'
91
+ Color::RED
92
+ when '@'
93
+ line[1].chr == '@' ? Color::BLUE : Color::NONE
94
+ else
95
+ Color::NONE
96
+ end.format(line)
97
+ end
98
+ end
99
+ end
100
+
@@ -0,0 +1,38 @@
1
+ module Mutant
2
+ # Module for support methods
3
+ #
4
+ # They would normally be defined on the root namespace.
5
+ # But it is easier to create the Zombie when there are no
6
+ # References to the root namespace name within the library.
7
+ #
8
+ module Helper
9
+
10
+ # Return deep clone of object
11
+ #
12
+ # @param [Object] object
13
+ #
14
+ # @return [Object] object
15
+ #
16
+ # @api private
17
+ #
18
+ def self.deep_clone(object)
19
+ Marshal.load(Marshal.dump(object))
20
+ end
21
+
22
+ # Extract option from options hash
23
+ #
24
+ # @param [Hash] options
25
+ # @param [Object] key
26
+ #
27
+ # @return [Object] value
28
+ #
29
+ # @api private
30
+ #
31
+ def self.extract_option(options, key)
32
+ options.fetch(key) do
33
+ raise ArgumentError,"Missing #{key.inspect} in options"
34
+ end
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,136 @@
1
+ module Mutant
2
+ # Abstract base class for mutant killers
3
+ class Killer
4
+ include Adamantium::Flat, AbstractType
5
+
6
+ # Test for kill failure
7
+ #
8
+ # @return [true]
9
+ # returns true when mutant was killed
10
+ #
11
+ # @return [false]
12
+ # returns false otherwise
13
+ #
14
+ # @api private
15
+ #
16
+ def fail?
17
+ !@killed
18
+ end
19
+
20
+ # Return runtime of killer
21
+ #
22
+ # @return [Float]
23
+ #
24
+ # @api private
25
+ #
26
+ attr_reader :runtime
27
+
28
+ # Return original source
29
+ #
30
+ # @return [String]
31
+ #
32
+ # @api private
33
+ #
34
+ def original_source
35
+ mutation.original_source
36
+ end
37
+
38
+ # Return mutated source
39
+ #
40
+ # @return [String]
41
+ #
42
+ # @api private
43
+ #
44
+ def mutation_source
45
+ mutation.source
46
+ end
47
+
48
+ # Return strategy
49
+ #
50
+ # @return [Strategy]
51
+ #
52
+ # @api private
53
+ #
54
+ attr_reader :strategy
55
+
56
+ # Return name of killer
57
+ #
58
+ # @return [String]
59
+ #
60
+ # @api private
61
+ #
62
+ def self.type
63
+ self::TYPE
64
+ end
65
+
66
+ # Return identification
67
+ #
68
+ # @return [String]
69
+ #
70
+ # @api private
71
+ #
72
+ def identification
73
+ "#{type}:#{mutation.identification}".freeze
74
+ end
75
+ memoize :identification
76
+
77
+ # Return mae of killer
78
+ #
79
+ # @return [String]
80
+ #
81
+ # @api private
82
+ #
83
+ def type
84
+ self.class.type
85
+ end
86
+
87
+ # Return mutation to kill
88
+ #
89
+ # @return [Mutation]
90
+ #
91
+ # @api private
92
+ #
93
+ attr_reader :mutation
94
+
95
+ private
96
+
97
+ # Initialize killer object
98
+ #
99
+ # @param [Mutation] mutation
100
+ #
101
+ # @return [undefined]
102
+ #
103
+ # @api private
104
+ #
105
+ def initialize(strategy, mutation)
106
+ @strategy, @mutation = strategy, mutation
107
+
108
+ run_with_benchmark
109
+ end
110
+
111
+ # Run with taking the time
112
+ #
113
+ # @return [undefined]
114
+ #
115
+ # @api private
116
+ #
117
+ def run_with_benchmark
118
+ start_time = Time.now
119
+ @killed = run
120
+ end_time = Time.now
121
+ @runtime = end_time - start_time
122
+ end
123
+
124
+ # Run test
125
+ #
126
+ # @return [true]
127
+ # returns true when mutant was killed
128
+ #
129
+ # @return [false]
130
+ # returns false otherwise
131
+ #
132
+ # @api private
133
+ #
134
+ abstract_method :run
135
+ end
136
+ end
@@ -0,0 +1,41 @@
1
+ module Mutant
2
+ class Killer
3
+
4
+ class Forked < self
5
+ def initialize(killer, strategy, mutation)
6
+ @killer = killer
7
+ super(strategy, mutation)
8
+ end
9
+
10
+ def type
11
+ @killer.type
12
+ end
13
+
14
+ def run
15
+ fork do
16
+ killer = @killer.new(strategy, mutation)
17
+ Kernel.exit(killer.fail? ? 1 : 0)
18
+ end
19
+
20
+ status = Process.wait2.last
21
+ status.exitstatus.zero?
22
+ end
23
+ end
24
+
25
+ class Forking < self
26
+ include Equalizer.new(:killer)
27
+
28
+ attr_reader :killer
29
+
30
+ def initialize(killer)
31
+ @killer = killer
32
+ end
33
+
34
+ def new(strategy, mutation)
35
+ Forked.new(killer, strategy, mutation)
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,49 @@
1
+ module Mutant
2
+ class Killer
3
+ # Runner for rspec tests
4
+ class Rspec < self
5
+ TYPE = 'rspec'.freeze
6
+
7
+ private
8
+
9
+ # Initialize rspec runner
10
+ #
11
+ # @return [undefined]
12
+ #
13
+ # @api private
14
+ #
15
+ def initialize(*)
16
+ @error_stream, @output_stream = StringIO.new, StringIO.new
17
+ super
18
+ end
19
+
20
+ # Run rspec test
21
+ #
22
+ # @return [true]
23
+ # returns true when test is NOT successful and the mutant was killed
24
+ #
25
+ # @return [false]
26
+ # returns false otherwise
27
+ #
28
+ # @api private
29
+ #
30
+ def run
31
+ mutation.insert
32
+ !::RSpec::Core::Runner.run(command_line_arguments, @error_stream, @output_stream).zero?
33
+ end
34
+ memoize :run
35
+
36
+ # Return command line arguments
37
+ #
38
+ # @return [Array]
39
+ #
40
+ # @api private
41
+ #
42
+ def command_line_arguments
43
+ %W(
44
+ --fail-fast
45
+ ) + strategy.spec_files(mutation)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,19 @@
1
+ module Mutant
2
+ class Killer
3
+ class Static < self
4
+ def run
5
+ self.class::RESULT
6
+ end
7
+
8
+ class Success < self
9
+ TYPE = 'success'.freeze
10
+ RESULT = true
11
+ end
12
+
13
+ class Fail < self
14
+ TYPE = 'fail'.freeze
15
+ RESULT = false
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,129 @@
1
+ module Mutant
2
+ # Base class for code loaders
3
+ class Loader
4
+ include AbstractType
5
+ extend MethodObject
6
+
7
+ private
8
+
9
+ # Run the loader
10
+ #
11
+ # @return [undefined]
12
+ #
13
+ # @api private
14
+ #
15
+ abstract_method :run
16
+
17
+ # Initialize and insert mutation into vm
18
+ #
19
+ # @param [Rubinius::AST::Script] root
20
+ #
21
+ # @return [undefined]
22
+ #
23
+ # @api private
24
+ #
25
+ def initialize(root)
26
+ @root = Helper.deep_clone(root)
27
+ run
28
+ end
29
+
30
+ # Eval based loader
31
+ class Eval < self
32
+ private
33
+
34
+ # Run loader
35
+ #
36
+ # @return [undefined]
37
+ #
38
+ # @api private
39
+ #
40
+ def run
41
+ eval(source, TOPLEVEL_BINDING)
42
+ end
43
+
44
+ # Return source
45
+ #
46
+ # @return [String]
47
+ #
48
+ # @api private
49
+ #
50
+ def source
51
+ ToSource.to_source(@root)
52
+ end
53
+ end
54
+
55
+ # Rubinius script node based loaded
56
+ class Rubinius < self
57
+ private
58
+
59
+ # Run loader
60
+ #
61
+ # @return [undefined]
62
+ #
63
+ # @api private
64
+ #
65
+ def run(root)
66
+ Rubinius.run_script(compiled_code)
67
+ end
68
+
69
+ # Return compiled code
70
+ #
71
+ # @return [Rubinius::CompiledCode]
72
+ #
73
+ # @api private
74
+ #
75
+ # FIXME: rbx on travis is older than on my devbox.
76
+ #
77
+ def compiled_code
78
+ _script = script
79
+ _script.respond_to?(:compiled_code) ? _script.compiled_code : _script.compiled_method
80
+ end
81
+
82
+ # Return code script
83
+ #
84
+ # @return [Rubinius::CompiledCode::Script]
85
+ #
86
+ # @api private
87
+ #
88
+ def script
89
+ compiled_code_raw.create_script
90
+ end
91
+
92
+ # Return compiled code for node
93
+ #
94
+ # @return [Rubinius::CompiledCode]
95
+ #
96
+ # @api private
97
+ #
98
+ def compiled_code_raw
99
+ compiler.run
100
+ end
101
+
102
+ # Return compiler loaded with mutated ast
103
+ #
104
+ # @return [Rubinius::Compiler]
105
+ #
106
+ # @api private
107
+ #
108
+ def compiler
109
+ Rubinius::Compiler.new(:bytecode, :compiled_method).tap do |compiler|
110
+ compiler.generator.input(@root)
111
+ end
112
+ end
113
+
114
+ # Return script node
115
+ #
116
+ # @param [Rubinius::AST::Node] node
117
+ #
118
+ # @return [Rubinius::AST::Script]
119
+ #
120
+ # @api private
121
+ #
122
+ def script(node)
123
+ Rubinius::AST::Script.new(node).tap do |script|
124
+ script.file = source_path
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end