evilution 0.13.0 → 0.14.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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/.beads/.migration-hint-ts +1 -1
  3. data/.beads/issues.jsonl +8 -8
  4. data/CHANGELOG.md +17 -0
  5. data/lib/evilution/ast/parser.rb +69 -68
  6. data/lib/evilution/ast/source_surgeon.rb +7 -9
  7. data/lib/evilution/ast.rb +4 -0
  8. data/lib/evilution/baseline.rb +73 -75
  9. data/lib/evilution/cache.rb +75 -77
  10. data/lib/evilution/cli.rb +408 -173
  11. data/lib/evilution/config.rb +141 -136
  12. data/lib/evilution/equivalent/detector.rb +25 -27
  13. data/lib/evilution/equivalent/heuristic/alias_swap.rb +29 -33
  14. data/lib/evilution/equivalent/heuristic/dead_code.rb +41 -45
  15. data/lib/evilution/equivalent/heuristic/method_body_nil.rb +11 -15
  16. data/lib/evilution/equivalent/heuristic/noop_source.rb +5 -9
  17. data/lib/evilution/equivalent/heuristic.rb +6 -0
  18. data/lib/evilution/equivalent.rb +4 -0
  19. data/lib/evilution/git/changed_files.rb +35 -37
  20. data/lib/evilution/git.rb +4 -0
  21. data/lib/evilution/integration/base.rb +5 -7
  22. data/lib/evilution/integration/rspec.rb +114 -116
  23. data/lib/evilution/integration.rb +4 -0
  24. data/lib/evilution/isolation/fork.rb +98 -100
  25. data/lib/evilution/isolation/in_process.rb +59 -61
  26. data/lib/evilution/isolation.rb +4 -0
  27. data/lib/evilution/mcp/mutate_tool.rb +172 -143
  28. data/lib/evilution/mcp/server.rb +12 -11
  29. data/lib/evilution/mcp/session_diff_tool.rb +89 -0
  30. data/lib/evilution/mcp/session_list_tool.rb +46 -0
  31. data/lib/evilution/mcp/session_show_tool.rb +53 -0
  32. data/lib/evilution/mcp.rb +4 -0
  33. data/lib/evilution/memory/leak_check.rb +80 -84
  34. data/lib/evilution/memory.rb +34 -36
  35. data/lib/evilution/mutation.rb +40 -42
  36. data/lib/evilution/mutator/base.rb +46 -48
  37. data/lib/evilution/mutator/operator/argument_nil_substitution.rb +32 -36
  38. data/lib/evilution/mutator/operator/argument_removal.rb +32 -36
  39. data/lib/evilution/mutator/operator/arithmetic_replacement.rb +26 -30
  40. data/lib/evilution/mutator/operator/array_literal.rb +18 -22
  41. data/lib/evilution/mutator/operator/block_removal.rb +16 -20
  42. data/lib/evilution/mutator/operator/boolean_literal_replacement.rb +38 -42
  43. data/lib/evilution/mutator/operator/boolean_operator_replacement.rb +41 -45
  44. data/lib/evilution/mutator/operator/collection_replacement.rb +32 -36
  45. data/lib/evilution/mutator/operator/comparison_replacement.rb +24 -28
  46. data/lib/evilution/mutator/operator/compound_assignment.rb +114 -118
  47. data/lib/evilution/mutator/operator/conditional_branch.rb +25 -29
  48. data/lib/evilution/mutator/operator/conditional_flip.rb +26 -30
  49. data/lib/evilution/mutator/operator/conditional_negation.rb +25 -29
  50. data/lib/evilution/mutator/operator/float_literal.rb +22 -26
  51. data/lib/evilution/mutator/operator/hash_literal.rb +18 -22
  52. data/lib/evilution/mutator/operator/integer_literal.rb +2 -0
  53. data/lib/evilution/mutator/operator/method_body_replacement.rb +12 -16
  54. data/lib/evilution/mutator/operator/method_call_removal.rb +12 -16
  55. data/lib/evilution/mutator/operator/negation_insertion.rb +12 -16
  56. data/lib/evilution/mutator/operator/nil_replacement.rb +13 -17
  57. data/lib/evilution/mutator/operator/range_replacement.rb +12 -16
  58. data/lib/evilution/mutator/operator/receiver_replacement.rb +16 -20
  59. data/lib/evilution/mutator/operator/regexp_mutation.rb +15 -19
  60. data/lib/evilution/mutator/operator/return_value_removal.rb +12 -16
  61. data/lib/evilution/mutator/operator/send_mutation.rb +36 -40
  62. data/lib/evilution/mutator/operator/statement_deletion.rb +13 -17
  63. data/lib/evilution/mutator/operator/string_literal.rb +18 -22
  64. data/lib/evilution/mutator/operator/symbol_literal.rb +17 -21
  65. data/lib/evilution/mutator/operator.rb +6 -0
  66. data/lib/evilution/mutator/registry.rb +54 -56
  67. data/lib/evilution/mutator.rb +4 -0
  68. data/lib/evilution/parallel/pool.rb +56 -58
  69. data/lib/evilution/parallel.rb +4 -0
  70. data/lib/evilution/reporter/cli.rb +99 -101
  71. data/lib/evilution/reporter/html.rb +242 -244
  72. data/lib/evilution/reporter/json.rb +57 -59
  73. data/lib/evilution/reporter/suggestion.rb +326 -328
  74. data/lib/evilution/reporter.rb +4 -0
  75. data/lib/evilution/result/mutation_result.rb +43 -46
  76. data/lib/evilution/result/summary.rb +80 -81
  77. data/lib/evilution/result.rb +4 -0
  78. data/lib/evilution/runner.rb +334 -323
  79. data/lib/evilution/session/store.rb +147 -0
  80. data/lib/evilution/session.rb +4 -0
  81. data/lib/evilution/spec_resolver.rb +49 -47
  82. data/lib/evilution/subject.rb +14 -16
  83. data/lib/evilution/version.rb +1 -1
  84. data/lib/evilution.rb +13 -0
  85. metadata +19 -2
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Evilution::Reporter
4
+ end
@@ -1,50 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Evilution
4
- module Result
5
- class MutationResult
6
- STATUSES = %i[killed survived timeout error neutral equivalent].freeze
7
-
8
- attr_reader :mutation, :status, :duration, :killing_test, :test_command,
9
- :child_rss_kb, :memory_delta_kb
10
-
11
- def initialize(mutation:, status:, duration: 0.0, killing_test: nil, test_command: nil,
12
- child_rss_kb: nil, memory_delta_kb: nil)
13
- raise ArgumentError, "invalid status: #{status}" unless STATUSES.include?(status)
14
-
15
- @mutation = mutation
16
- @status = status
17
- @duration = duration
18
- @killing_test = killing_test
19
- @test_command = test_command
20
- @child_rss_kb = child_rss_kb
21
- @memory_delta_kb = memory_delta_kb
22
- freeze
23
- end
24
-
25
- def killed?
26
- status == :killed
27
- end
28
-
29
- def survived?
30
- status == :survived
31
- end
32
-
33
- def timeout?
34
- status == :timeout
35
- end
36
-
37
- def error?
38
- status == :error
39
- end
40
-
41
- def neutral?
42
- status == :neutral
43
- end
44
-
45
- def equivalent?
46
- status == :equivalent
47
- end
48
- end
3
+ require_relative "../result"
4
+
5
+ class Evilution::Result::MutationResult
6
+ STATUSES = %i[killed survived timeout error neutral equivalent].freeze
7
+
8
+ attr_reader :mutation, :status, :duration, :killing_test, :test_command,
9
+ :child_rss_kb, :memory_delta_kb
10
+
11
+ def initialize(mutation:, status:, duration: 0.0, killing_test: nil, test_command: nil, child_rss_kb: nil, memory_delta_kb: nil)
12
+ raise ArgumentError, "invalid status: #{status}" unless STATUSES.include?(status)
13
+
14
+ @mutation = mutation
15
+ @status = status
16
+ @duration = duration
17
+ @killing_test = killing_test
18
+ @test_command = test_command
19
+ @child_rss_kb = child_rss_kb
20
+ @memory_delta_kb = memory_delta_kb
21
+ freeze
22
+ end
23
+
24
+ def killed?
25
+ status == :killed
26
+ end
27
+
28
+ def survived?
29
+ status == :survived
30
+ end
31
+
32
+ def timeout?
33
+ status == :timeout
34
+ end
35
+
36
+ def error?
37
+ status == :error
38
+ end
39
+
40
+ def neutral?
41
+ status == :neutral
42
+ end
43
+
44
+ def equivalent?
45
+ status == :equivalent
49
46
  end
50
47
  end
@@ -1,86 +1,85 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Evilution
4
- module Result
5
- class Summary
6
- attr_reader :results, :duration
7
-
8
- def initialize(results:, duration: 0.0, truncated: false)
9
- @results = results
10
- @duration = duration
11
- @truncated = truncated
12
- freeze
13
- end
14
-
15
- def truncated?
16
- @truncated
17
- end
18
-
19
- def total
20
- results.length
21
- end
22
-
23
- def killed
24
- results.count(&:killed?)
25
- end
26
-
27
- def survived
28
- results.count(&:survived?)
29
- end
30
-
31
- def timed_out
32
- results.count(&:timeout?)
33
- end
34
-
35
- def errors
36
- results.count(&:error?)
37
- end
38
-
39
- def neutral
40
- results.count(&:neutral?)
41
- end
42
-
43
- def equivalent
44
- results.count(&:equivalent?)
45
- end
46
-
47
- def score
48
- denominator = total - errors - neutral - equivalent
49
- return 0.0 if denominator.zero?
50
-
51
- killed.to_f / denominator
52
- end
53
-
54
- def success?(min_score: 1.0)
55
- score >= min_score
56
- end
57
-
58
- def survived_results
59
- results.select(&:survived?)
60
- end
61
-
62
- def killed_results
63
- results.select(&:killed?)
64
- end
65
-
66
- def neutral_results
67
- results.select(&:neutral?)
68
- end
69
-
70
- def equivalent_results
71
- results.select(&:equivalent?)
72
- end
73
-
74
- def peak_memory_mb
75
- max_rss = nil
76
- results.each do |result|
77
- kb = result.child_rss_kb
78
- next unless kb
79
-
80
- max_rss = kb if max_rss.nil? || kb > max_rss
81
- end
82
- max_rss && (max_rss / 1024.0)
83
- end
3
+ require_relative "../result"
4
+
5
+ class Evilution::Result::Summary
6
+ attr_reader :results, :duration
7
+
8
+ def initialize(results:, duration: 0.0, truncated: false)
9
+ @results = results
10
+ @duration = duration
11
+ @truncated = truncated
12
+ freeze
13
+ end
14
+
15
+ def truncated?
16
+ @truncated
17
+ end
18
+
19
+ def total
20
+ results.length
21
+ end
22
+
23
+ def killed
24
+ results.count(&:killed?)
25
+ end
26
+
27
+ def survived
28
+ results.count(&:survived?)
29
+ end
30
+
31
+ def timed_out
32
+ results.count(&:timeout?)
33
+ end
34
+
35
+ def errors
36
+ results.count(&:error?)
37
+ end
38
+
39
+ def neutral
40
+ results.count(&:neutral?)
41
+ end
42
+
43
+ def equivalent
44
+ results.count(&:equivalent?)
45
+ end
46
+
47
+ def score
48
+ denominator = total - errors - neutral - equivalent
49
+ return 0.0 if denominator.zero?
50
+
51
+ killed.to_f / denominator
52
+ end
53
+
54
+ def success?(min_score: 1.0)
55
+ score >= min_score
56
+ end
57
+
58
+ def survived_results
59
+ results.select(&:survived?)
60
+ end
61
+
62
+ def killed_results
63
+ results.select(&:killed?)
64
+ end
65
+
66
+ def neutral_results
67
+ results.select(&:neutral?)
68
+ end
69
+
70
+ def equivalent_results
71
+ results.select(&:equivalent?)
72
+ end
73
+
74
+ def peak_memory_mb
75
+ max_rss = nil
76
+ results.each do |result|
77
+ kb = result.child_rss_kb
78
+ next unless kb
79
+
80
+ max_rss = kb if max_rss.nil? || kb > max_rss
84
81
  end
82
+
83
+ max_rss && (max_rss / 1024.0)
85
84
  end
86
85
  end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Evilution::Result
4
+ end