evilution 0.27.0 → 0.28.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.
- checksums.yaml +4 -4
- data/.beads/interactions.jsonl +13 -0
- data/.rubocop_todo.yml +0 -1
- data/CHANGELOG.md +32 -0
- data/README.md +19 -0
- data/lib/evilution/baseline.rb +5 -4
- data/lib/evilution/cli/parser/options_builder.rb +7 -0
- data/lib/evilution/compare/diff_extractor/evilution.rb +22 -0
- data/lib/evilution/compare/diff_extractor/mutant.rb +30 -0
- data/lib/evilution/compare/diff_extractor.rb +6 -0
- data/lib/evilution/compare/fingerprint.rb +15 -72
- data/lib/evilution/compare/line_normalizer.rb +72 -0
- data/lib/evilution/compare/normalizer.rb +17 -4
- data/lib/evilution/config/validators/profile.rb +11 -0
- data/lib/evilution/config.rb +40 -23
- data/lib/evilution/integration/crash_detector.rb +2 -2
- data/lib/evilution/integration/loading/source_evaluator.rb +6 -2
- data/lib/evilution/integration/minitest_crash_detector.rb +2 -2
- data/lib/evilution/integration/rspec/state_guard/object_space_example_groups.rb +11 -3
- data/lib/evilution/isolation/fork.rb +16 -11
- data/lib/evilution/isolation/in_process.rb +10 -6
- data/lib/evilution/mcp/info_tool.rb +0 -2
- data/lib/evilution/mcp/mutate_tool/progress_streamer.rb +5 -1
- data/lib/evilution/mcp/session_tool.rb +0 -2
- data/lib/evilution/mutation.rb +47 -27
- data/lib/evilution/mutator/base.rb +8 -8
- data/lib/evilution/mutator/operator/predicate_to_nil.rb +20 -0
- data/lib/evilution/mutator/registry.rb +20 -0
- data/lib/evilution/parallel/work_queue/channel/frame.rb +5 -1
- data/lib/evilution/parallel/work_queue/worker/loop.rb +1 -1
- data/lib/evilution/process_cleanup.rb +19 -0
- data/lib/evilution/reporter/html/baseline_keys.rb +1 -1
- data/lib/evilution/reporter/html/diff_formatter.rb +1 -1
- data/lib/evilution/reporter/html/escape.rb +1 -1
- data/lib/evilution/reporter/html/section.rb +1 -1
- data/lib/evilution/reporter/html/sections.rb +4 -2
- data/lib/evilution/reporter/html/stylesheet.rb +1 -1
- data/lib/evilution/reporter/html.rb +8 -3
- data/lib/evilution/reporter/suggestion/registry.rb +1 -5
- data/lib/evilution/reporter/suggestion/templates/generic.rb +1 -1
- data/lib/evilution/reporter/suggestion/templates/minitest.rb +349 -643
- data/lib/evilution/reporter/suggestion/templates/rspec.rb +351 -598
- data/lib/evilution/reporter/suggestion/templates.rb +6 -0
- data/lib/evilution/result/error_info.rb +20 -0
- data/lib/evilution/result/memory_stats.rb +20 -0
- data/lib/evilution/result/mutation_result.rb +30 -14
- data/lib/evilution/runner/baseline_runner.rb +1 -2
- data/lib/evilution/runner/diagnostics.rb +1 -2
- data/lib/evilution/runner/isolation_resolver.rb +1 -2
- data/lib/evilution/runner/mutation_executor/mutation_runner.rb +1 -3
- data/lib/evilution/runner/mutation_executor/neutralization_pipeline.rb +1 -2
- data/lib/evilution/runner/mutation_executor/neutralizer/baseline_failed.rb +3 -10
- data/lib/evilution/runner/mutation_executor/neutralizer/infra_error.rb +3 -10
- data/lib/evilution/runner/mutation_executor/neutralizer.rb +11 -0
- data/lib/evilution/runner/mutation_executor/result_cache.rb +1 -3
- data/lib/evilution/runner/mutation_executor/result_notifier.rb +1 -3
- data/lib/evilution/runner/mutation_executor/result_packer.rb +11 -9
- data/lib/evilution/runner/mutation_executor/strategy/parallel.rb +1 -3
- data/lib/evilution/runner/mutation_executor/strategy/sequential.rb +1 -3
- data/lib/evilution/runner/mutation_executor/strategy.rb +11 -0
- data/lib/evilution/runner/mutation_executor.rb +12 -20
- data/lib/evilution/runner/mutation_planner.rb +1 -2
- data/lib/evilution/runner/report_publisher.rb +1 -2
- data/lib/evilution/runner/subject_pipeline.rb +1 -2
- data/lib/evilution/runner.rb +33 -31
- data/lib/evilution/version.rb +1 -1
- data/lib/evilution.rb +1 -0
- data/script/memory_check +3 -1
- metadata +14 -3
- data/lib/evilution/reporter/html/namespace.rb +0 -11
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../result"
|
|
4
|
+
|
|
5
|
+
class Evilution::Result::ErrorInfo
|
|
6
|
+
attr_reader :message, :klass, :backtrace
|
|
7
|
+
|
|
8
|
+
def self.from_fields(message: nil, klass: nil, backtrace: nil)
|
|
9
|
+
return nil if message.nil? && klass.nil? && backtrace.nil?
|
|
10
|
+
|
|
11
|
+
new(message: message, klass: klass, backtrace: backtrace)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(message: nil, klass: nil, backtrace: nil)
|
|
15
|
+
@message = message
|
|
16
|
+
@klass = klass
|
|
17
|
+
@backtrace = backtrace.nil? ? nil : backtrace.dup.freeze
|
|
18
|
+
freeze
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../result"
|
|
4
|
+
|
|
5
|
+
class Evilution::Result::MemoryStats
|
|
6
|
+
attr_reader :child_rss_kb, :memory_delta_kb, :parent_rss_kb
|
|
7
|
+
|
|
8
|
+
def self.from_fields(child_rss_kb: nil, memory_delta_kb: nil, parent_rss_kb: nil)
|
|
9
|
+
return nil if child_rss_kb.nil? && memory_delta_kb.nil? && parent_rss_kb.nil?
|
|
10
|
+
|
|
11
|
+
new(child_rss_kb: child_rss_kb, memory_delta_kb: memory_delta_kb, parent_rss_kb: parent_rss_kb)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize(child_rss_kb: nil, memory_delta_kb: nil, parent_rss_kb: nil)
|
|
15
|
+
@child_rss_kb = child_rss_kb
|
|
16
|
+
@memory_delta_kb = memory_delta_kb
|
|
17
|
+
@parent_rss_kb = parent_rss_kb
|
|
18
|
+
freeze
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "../result"
|
|
4
|
+
require_relative "error_info"
|
|
5
|
+
require_relative "memory_stats"
|
|
4
6
|
|
|
5
7
|
class Evilution::Result::MutationResult
|
|
6
8
|
STATUSES = %i[killed survived timeout error neutral equivalent unresolved unparseable].freeze
|
|
7
9
|
|
|
8
|
-
attr_reader :mutation, :status, :duration, :killing_test, :test_command,
|
|
9
|
-
:child_rss_kb, :memory_delta_kb, :parent_rss_kb,
|
|
10
|
-
:error_message, :error_class, :error_backtrace
|
|
10
|
+
attr_reader :mutation, :status, :duration, :killing_test, :test_command, :memory, :error
|
|
11
11
|
|
|
12
|
-
# rubocop:disable Metrics/ParameterLists
|
|
13
12
|
def initialize(mutation:, status:, duration: 0.0, killing_test: nil,
|
|
14
|
-
test_command: nil,
|
|
15
|
-
parent_rss_kb: nil, error_message: nil, error_class: nil,
|
|
16
|
-
error_backtrace: nil)
|
|
17
|
-
# rubocop:enable Metrics/ParameterLists
|
|
13
|
+
test_command: nil, memory: nil, error: nil)
|
|
18
14
|
raise ArgumentError, "invalid status: #{status}" unless STATUSES.include?(status)
|
|
19
15
|
|
|
20
16
|
@mutation = mutation
|
|
@@ -22,15 +18,35 @@ class Evilution::Result::MutationResult
|
|
|
22
18
|
@duration = duration
|
|
23
19
|
@killing_test = killing_test
|
|
24
20
|
@test_command = test_command
|
|
25
|
-
@
|
|
26
|
-
@
|
|
27
|
-
@parent_rss_kb = parent_rss_kb
|
|
28
|
-
@error_message = error_message
|
|
29
|
-
@error_class = error_class
|
|
30
|
-
@error_backtrace = error_backtrace.nil? ? nil : error_backtrace.dup.freeze
|
|
21
|
+
@memory = memory
|
|
22
|
+
@error = error
|
|
31
23
|
freeze
|
|
32
24
|
end
|
|
33
25
|
|
|
26
|
+
def child_rss_kb
|
|
27
|
+
@memory.nil? ? nil : @memory.child_rss_kb
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def memory_delta_kb
|
|
31
|
+
@memory.nil? ? nil : @memory.memory_delta_kb
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def parent_rss_kb
|
|
35
|
+
@memory.nil? ? nil : @memory.parent_rss_kb
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def error_message
|
|
39
|
+
@error.nil? ? nil : @error.message
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def error_class
|
|
43
|
+
@error.nil? ? nil : @error.klass
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def error_backtrace
|
|
47
|
+
@error.nil? ? nil : @error.backtrace
|
|
48
|
+
end
|
|
49
|
+
|
|
34
50
|
def killed?
|
|
35
51
|
status == :killed
|
|
36
52
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../runner"
|
|
3
4
|
require_relative "../baseline"
|
|
4
5
|
require_relative "../spec_resolver"
|
|
5
6
|
require_relative "../integration/rspec"
|
|
@@ -8,8 +9,6 @@ require_relative "../example_filter"
|
|
|
8
9
|
require_relative "../spec_ast_cache"
|
|
9
10
|
require_relative "../source_ast_cache"
|
|
10
11
|
|
|
11
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
12
|
-
|
|
13
12
|
unless defined?(Evilution::Runner::INTEGRATIONS)
|
|
14
13
|
Evilution::Runner::INTEGRATIONS = {
|
|
15
14
|
rspec: Evilution::Integration::RSpec,
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../runner"
|
|
3
4
|
require_relative "../memory"
|
|
4
5
|
require_relative "../parallel/pool"
|
|
5
6
|
|
|
6
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
7
|
-
|
|
8
7
|
class Evilution::Runner::Diagnostics
|
|
9
8
|
def initialize(config, stderr: $stderr)
|
|
10
9
|
@config = config
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../runner"
|
|
3
4
|
require_relative "../isolation/fork"
|
|
4
5
|
require_relative "../isolation/in_process"
|
|
5
6
|
require_relative "../rails_detector"
|
|
6
7
|
|
|
7
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
8
|
-
|
|
9
8
|
class Evilution::Runner::IsolationResolver
|
|
10
9
|
PRELOAD_CANDIDATES = [
|
|
11
10
|
File.join("spec", "rails_helper.rb"),
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../mutation_executor"
|
|
3
4
|
require_relative "../../result/mutation_result"
|
|
4
5
|
|
|
5
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
6
|
-
class Evilution::Runner::MutationExecutor; end unless defined?(Evilution::Runner::MutationExecutor) # rubocop:disable Lint/EmptyClass
|
|
7
|
-
|
|
8
6
|
class Evilution::Runner::MutationExecutor::MutationRunner
|
|
9
7
|
def initialize(config:, cache:, isolator:)
|
|
10
8
|
@config = config
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
class Evilution::Runner::MutationExecutor; end unless defined?(Evilution::Runner::MutationExecutor) # rubocop:disable Lint/EmptyClass
|
|
3
|
+
require_relative "../mutation_executor"
|
|
5
4
|
|
|
6
5
|
class Evilution::Runner::MutationExecutor::NeutralizationPipeline
|
|
7
6
|
def initialize(neutralizers)
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../neutralizer"
|
|
3
4
|
require_relative "../../../result/mutation_result"
|
|
4
5
|
|
|
5
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
6
|
-
class Evilution::Runner::MutationExecutor; end unless defined?(Evilution::Runner::MutationExecutor) # rubocop:disable Lint/EmptyClass
|
|
7
|
-
module Evilution::Runner::MutationExecutor::Neutralizer; end unless defined?(Evilution::Runner::MutationExecutor::Neutralizer)
|
|
8
|
-
|
|
9
6
|
class Evilution::Runner::MutationExecutor::Neutralizer::BaselineFailed
|
|
10
7
|
def initialize(config:, spec_resolver:, fallback_dir:)
|
|
11
8
|
@config = config
|
|
@@ -35,12 +32,8 @@ class Evilution::Runner::MutationExecutor::Neutralizer::BaselineFailed
|
|
|
35
32
|
status: :neutral,
|
|
36
33
|
duration: result.duration,
|
|
37
34
|
test_command: result.test_command,
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
parent_rss_kb: result.parent_rss_kb,
|
|
41
|
-
error_message: result.error_message,
|
|
42
|
-
error_class: result.error_class,
|
|
43
|
-
error_backtrace: result.error_backtrace
|
|
35
|
+
memory: result.memory,
|
|
36
|
+
error: result.error
|
|
44
37
|
)
|
|
45
38
|
end
|
|
46
39
|
end
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../neutralizer"
|
|
3
4
|
require_relative "../../../result/mutation_result"
|
|
4
5
|
|
|
5
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
6
|
-
class Evilution::Runner::MutationExecutor; end unless defined?(Evilution::Runner::MutationExecutor) # rubocop:disable Lint/EmptyClass
|
|
7
|
-
module Evilution::Runner::MutationExecutor::Neutralizer; end unless defined?(Evilution::Runner::MutationExecutor::Neutralizer)
|
|
8
|
-
|
|
9
6
|
# Reclassify results as :neutral when the failure was caused by test
|
|
10
7
|
# infrastructure rather than by the mutation. Two independent paths:
|
|
11
8
|
#
|
|
@@ -64,12 +61,8 @@ class Evilution::Runner::MutationExecutor::Neutralizer::InfraError
|
|
|
64
61
|
status: :neutral,
|
|
65
62
|
duration: result.duration,
|
|
66
63
|
test_command: result.test_command,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
parent_rss_kb: result.parent_rss_kb,
|
|
70
|
-
error_message: result.error_message,
|
|
71
|
-
error_class: result.error_class,
|
|
72
|
-
error_backtrace: result.error_backtrace
|
|
64
|
+
memory: result.memory,
|
|
65
|
+
error: result.error
|
|
73
66
|
)
|
|
74
67
|
end
|
|
75
68
|
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../mutation_executor"
|
|
4
|
+
|
|
5
|
+
# Namespace for MutationExecutor's neutralization rules (InfraError,
|
|
6
|
+
# BaselineFailed). Concrete neutralizer classes live in neutralizer/*.rb and
|
|
7
|
+
# are autoloaded on first reference.
|
|
8
|
+
module Evilution::Runner::MutationExecutor::Neutralizer
|
|
9
|
+
autoload :InfraError, File.expand_path("neutralizer/infra_error", __dir__)
|
|
10
|
+
autoload :BaselineFailed, File.expand_path("neutralizer/baseline_failed", __dir__)
|
|
11
|
+
end
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../mutation_executor"
|
|
3
4
|
require_relative "../../result/mutation_result"
|
|
4
5
|
|
|
5
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
6
|
-
class Evilution::Runner::MutationExecutor; end unless defined?(Evilution::Runner::MutationExecutor) # rubocop:disable Lint/EmptyClass
|
|
7
|
-
|
|
8
6
|
class Evilution::Runner::MutationExecutor::ResultCache
|
|
9
7
|
CACHEABLE_STATUSES = %i[killed timeout].freeze
|
|
10
8
|
private_constant :CACHEABLE_STATUSES
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../mutation_executor"
|
|
3
4
|
require_relative "../../reporter/progress_bar"
|
|
4
5
|
|
|
5
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
6
|
-
class Evilution::Runner::MutationExecutor; end unless defined?(Evilution::Runner::MutationExecutor) # rubocop:disable Lint/EmptyClass
|
|
7
|
-
|
|
8
6
|
class Evilution::Runner::MutationExecutor::ResultNotifier
|
|
9
7
|
def initialize(config, diagnostics:, on_result:)
|
|
10
8
|
@config = config
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../mutation_executor"
|
|
3
4
|
require_relative "../../result/mutation_result"
|
|
4
5
|
|
|
5
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
6
|
-
class Evilution::Runner::MutationExecutor; end unless defined?(Evilution::Runner::MutationExecutor) # rubocop:disable Lint/EmptyClass
|
|
7
|
-
|
|
8
6
|
class Evilution::Runner::MutationExecutor::ResultPacker
|
|
9
7
|
def compact(result)
|
|
10
8
|
{
|
|
@@ -28,12 +26,16 @@ class Evilution::Runner::MutationExecutor::ResultPacker
|
|
|
28
26
|
duration: data[:duration],
|
|
29
27
|
killing_test: data[:killing_test],
|
|
30
28
|
test_command: data[:test_command],
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
memory: Evilution::Result::MemoryStats.from_fields(
|
|
30
|
+
child_rss_kb: data[:child_rss_kb],
|
|
31
|
+
memory_delta_kb: data[:memory_delta_kb],
|
|
32
|
+
parent_rss_kb: data[:parent_rss_kb]
|
|
33
|
+
),
|
|
34
|
+
error: Evilution::Result::ErrorInfo.from_fields(
|
|
35
|
+
message: data[:error_message],
|
|
36
|
+
klass: data[:error_class],
|
|
37
|
+
backtrace: data[:error_backtrace]
|
|
38
|
+
)
|
|
37
39
|
)
|
|
38
40
|
end
|
|
39
41
|
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
class Evilution::Runner::MutationExecutor; end unless defined?(Evilution::Runner::MutationExecutor) # rubocop:disable Lint/EmptyClass
|
|
5
|
-
module Evilution::Runner::MutationExecutor::Strategy; end unless defined?(Evilution::Runner::MutationExecutor::Strategy)
|
|
3
|
+
require_relative "../strategy"
|
|
6
4
|
|
|
7
5
|
class Evilution::Runner::MutationExecutor::Strategy::Parallel
|
|
8
6
|
def initialize(cache:, isolator:, packer:, pipeline:, notifier:, pool_factory:, config:, diagnostics: nil)
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
class Evilution::Runner::MutationExecutor; end unless defined?(Evilution::Runner::MutationExecutor) # rubocop:disable Lint/EmptyClass
|
|
5
|
-
module Evilution::Runner::MutationExecutor::Strategy; end unless defined?(Evilution::Runner::MutationExecutor::Strategy)
|
|
3
|
+
require_relative "../strategy"
|
|
6
4
|
|
|
7
5
|
class Evilution::Runner::MutationExecutor::Strategy::Sequential
|
|
8
6
|
def initialize(runner:, pipeline:, notifier:)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../mutation_executor"
|
|
4
|
+
|
|
5
|
+
# Namespace for MutationExecutor's execution strategies (Sequential, Parallel).
|
|
6
|
+
# Concrete strategy classes live in strategy/{sequential,parallel}.rb and are
|
|
7
|
+
# autoloaded on first reference.
|
|
8
|
+
module Evilution::Runner::MutationExecutor::Strategy
|
|
9
|
+
autoload :Sequential, File.expand_path("strategy/sequential", __dir__)
|
|
10
|
+
autoload :Parallel, File.expand_path("strategy/parallel", __dir__)
|
|
11
|
+
end
|
|
@@ -1,23 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../
|
|
4
|
-
require_relative "mutation_executor/result_cache"
|
|
5
|
-
require_relative "mutation_executor/result_packer"
|
|
6
|
-
require_relative "mutation_executor/result_notifier"
|
|
7
|
-
require_relative "mutation_executor/mutation_runner"
|
|
8
|
-
require_relative "mutation_executor/neutralization_pipeline"
|
|
9
|
-
require_relative "mutation_executor/neutralizer/infra_error"
|
|
10
|
-
require_relative "mutation_executor/neutralizer/baseline_failed"
|
|
11
|
-
require_relative "mutation_executor/strategy/sequential"
|
|
12
|
-
require_relative "mutation_executor/strategy/parallel"
|
|
13
|
-
|
|
14
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
3
|
+
require_relative "../runner"
|
|
15
4
|
|
|
16
5
|
class Evilution::Runner::MutationExecutor
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
autoload :ResultCache, File.expand_path("mutation_executor/result_cache", __dir__)
|
|
7
|
+
autoload :ResultPacker, File.expand_path("mutation_executor/result_packer", __dir__)
|
|
8
|
+
autoload :ResultNotifier, File.expand_path("mutation_executor/result_notifier", __dir__)
|
|
9
|
+
autoload :MutationRunner, File.expand_path("mutation_executor/mutation_runner", __dir__)
|
|
10
|
+
autoload :NeutralizationPipeline, File.expand_path("mutation_executor/neutralization_pipeline", __dir__)
|
|
11
|
+
autoload :Strategy, File.expand_path("mutation_executor/strategy", __dir__)
|
|
12
|
+
autoload :Neutralizer, File.expand_path("mutation_executor/neutralizer", __dir__)
|
|
21
13
|
|
|
22
14
|
def initialize(config, isolator:, baseline_runner:, cache:, hooks:, diagnostics:, on_result: nil)
|
|
23
15
|
@config = config
|
|
@@ -53,8 +45,8 @@ class Evilution::Runner::MutationExecutor
|
|
|
53
45
|
def build_pipeline(spec_resolver)
|
|
54
46
|
NeutralizationPipeline.new(
|
|
55
47
|
[
|
|
56
|
-
InfraError.new,
|
|
57
|
-
BaselineFailed.new(
|
|
48
|
+
Neutralizer::InfraError.new,
|
|
49
|
+
Neutralizer::BaselineFailed.new(
|
|
58
50
|
config: @config,
|
|
59
51
|
spec_resolver: spec_resolver || ->(_f) {},
|
|
60
52
|
fallback_dir: @baseline_runner.neutralization_fallback_dir
|
|
@@ -64,7 +56,7 @@ class Evilution::Runner::MutationExecutor
|
|
|
64
56
|
end
|
|
65
57
|
|
|
66
58
|
def build_sequential(notifier, pipeline)
|
|
67
|
-
Sequential.new(
|
|
59
|
+
Strategy::Sequential.new(
|
|
68
60
|
runner: MutationRunner.new(config: @config, cache: @cache, isolator: @isolator),
|
|
69
61
|
pipeline: pipeline,
|
|
70
62
|
notifier: notifier
|
|
@@ -72,7 +64,7 @@ class Evilution::Runner::MutationExecutor
|
|
|
72
64
|
end
|
|
73
65
|
|
|
74
66
|
def build_parallel(notifier, pipeline)
|
|
75
|
-
Parallel.new(
|
|
67
|
+
Strategy::Parallel.new(
|
|
76
68
|
cache: @cache,
|
|
77
69
|
isolator: @isolator,
|
|
78
70
|
packer: @packer,
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../runner"
|
|
3
4
|
require_relative "../disable_comment"
|
|
4
5
|
require_relative "../ast/sorbet_sig_detector"
|
|
5
6
|
require_relative "../ast/pattern/filter"
|
|
6
7
|
require_relative "../equivalent/detector"
|
|
7
8
|
|
|
8
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
9
|
-
|
|
10
9
|
class Evilution::Runner::MutationPlanner
|
|
11
10
|
Plan = Struct.new(:enabled, :equivalent, :skipped_count, :disabled_mutations, keyword_init: true)
|
|
12
11
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../runner"
|
|
3
4
|
require_relative "../reporter/json"
|
|
4
5
|
require_relative "../reporter/cli"
|
|
5
6
|
require_relative "../reporter/html"
|
|
6
7
|
require_relative "../session/store"
|
|
7
8
|
|
|
8
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
9
|
-
|
|
10
9
|
class Evilution::Runner::ReportPublisher
|
|
11
10
|
def initialize(config)
|
|
12
11
|
@config = config
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "../runner"
|
|
3
4
|
require_relative "../ast/inheritance_scanner"
|
|
4
5
|
require_relative "../git/changed_files"
|
|
5
6
|
|
|
6
|
-
class Evilution::Runner; end unless defined?(Evilution::Runner) # rubocop:disable Lint/EmptyClass
|
|
7
|
-
|
|
8
7
|
class Evilution::Runner::SubjectPipeline
|
|
9
8
|
def initialize(config, parser:)
|
|
10
9
|
@config = config
|
data/lib/evilution/runner.rb
CHANGED
|
@@ -1,36 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "fileutils"
|
|
4
|
-
require_relative "
|
|
5
|
-
require_relative "ast/parser"
|
|
6
|
-
require_relative "memory"
|
|
7
|
-
require_relative "mutator/registry"
|
|
8
|
-
require_relative "isolation/fork"
|
|
9
|
-
require_relative "isolation/in_process"
|
|
10
|
-
require_relative "integration/rspec"
|
|
11
|
-
require_relative "integration/minitest"
|
|
12
|
-
require_relative "reporter/json"
|
|
13
|
-
require_relative "reporter/cli"
|
|
14
|
-
require_relative "reporter/html"
|
|
15
|
-
require_relative "reporter/suggestion"
|
|
16
|
-
require_relative "git/changed_files"
|
|
17
|
-
require_relative "result/mutation_result"
|
|
18
|
-
require_relative "result/summary"
|
|
19
|
-
require_relative "baseline"
|
|
20
|
-
require_relative "cache"
|
|
21
|
-
require_relative "parallel/pool"
|
|
22
|
-
require_relative "session/store"
|
|
23
|
-
require_relative "temp_dir_tracker"
|
|
24
|
-
require_relative "rails_detector"
|
|
25
|
-
require_relative "parallel_db_warning"
|
|
26
|
-
require_relative "child_output"
|
|
27
|
-
require_relative "runner/subject_pipeline"
|
|
28
|
-
require_relative "runner/mutation_planner"
|
|
29
|
-
require_relative "runner/isolation_resolver"
|
|
30
|
-
require_relative "runner/baseline_runner"
|
|
31
|
-
require_relative "runner/diagnostics"
|
|
32
|
-
require_relative "runner/mutation_executor"
|
|
33
|
-
require_relative "runner/report_publisher"
|
|
4
|
+
require_relative "../evilution"
|
|
34
5
|
|
|
35
6
|
class Evilution::Runner
|
|
36
7
|
attr_reader :config
|
|
@@ -40,7 +11,7 @@ class Evilution::Runner
|
|
|
40
11
|
@on_result = on_result
|
|
41
12
|
@hooks = hooks
|
|
42
13
|
@parser = Evilution::AST::Parser.new
|
|
43
|
-
@registry = Evilution::Mutator::Registry.
|
|
14
|
+
@registry = Evilution::Mutator::Registry.for_profile(config.profile)
|
|
44
15
|
@cache = config.incremental? ? Evilution::Cache.new : nil
|
|
45
16
|
end
|
|
46
17
|
|
|
@@ -213,3 +184,34 @@ class Evilution::Runner
|
|
|
213
184
|
diagnostics.log_memory(phase, context)
|
|
214
185
|
end
|
|
215
186
|
end
|
|
187
|
+
|
|
188
|
+
require_relative "config"
|
|
189
|
+
require_relative "ast/parser"
|
|
190
|
+
require_relative "memory"
|
|
191
|
+
require_relative "mutator/registry"
|
|
192
|
+
require_relative "isolation/fork"
|
|
193
|
+
require_relative "isolation/in_process"
|
|
194
|
+
require_relative "integration/rspec"
|
|
195
|
+
require_relative "integration/minitest"
|
|
196
|
+
require_relative "reporter/json"
|
|
197
|
+
require_relative "reporter/cli"
|
|
198
|
+
require_relative "reporter/html"
|
|
199
|
+
require_relative "reporter/suggestion"
|
|
200
|
+
require_relative "git/changed_files"
|
|
201
|
+
require_relative "result/mutation_result"
|
|
202
|
+
require_relative "result/summary"
|
|
203
|
+
require_relative "baseline"
|
|
204
|
+
require_relative "cache"
|
|
205
|
+
require_relative "parallel/pool"
|
|
206
|
+
require_relative "session/store"
|
|
207
|
+
require_relative "temp_dir_tracker"
|
|
208
|
+
require_relative "rails_detector"
|
|
209
|
+
require_relative "parallel_db_warning"
|
|
210
|
+
require_relative "child_output"
|
|
211
|
+
require_relative "runner/subject_pipeline"
|
|
212
|
+
require_relative "runner/mutation_planner"
|
|
213
|
+
require_relative "runner/isolation_resolver"
|
|
214
|
+
require_relative "runner/baseline_runner"
|
|
215
|
+
require_relative "runner/diagnostics"
|
|
216
|
+
require_relative "runner/mutation_executor"
|
|
217
|
+
require_relative "runner/report_publisher"
|
data/lib/evilution/version.rb
CHANGED
data/lib/evilution.rb
CHANGED
|
@@ -89,6 +89,7 @@ require_relative "evilution/mutator/operator/string_interpolation"
|
|
|
89
89
|
require_relative "evilution/mutator/operator/retry_removal"
|
|
90
90
|
require_relative "evilution/mutator/operator/case_when"
|
|
91
91
|
require_relative "evilution/mutator/operator/predicate_replacement"
|
|
92
|
+
require_relative "evilution/mutator/operator/predicate_to_nil"
|
|
92
93
|
require_relative "evilution/mutator/operator/equality_to_identity"
|
|
93
94
|
require_relative "evilution/mutator/operator/lambda_body"
|
|
94
95
|
require_relative "evilution/mutator/operator/begin_unwrap"
|
data/script/memory_check
CHANGED
|
@@ -88,7 +88,9 @@ if mutations.size >= 2
|
|
|
88
88
|
batch.zip(compact_results).map do |mutation, data|
|
|
89
89
|
Evilution::Result::MutationResult.new(
|
|
90
90
|
mutation: mutation, status: data[:status], duration: data[:duration],
|
|
91
|
-
|
|
91
|
+
memory: Evilution::Result::MemoryStats.new(
|
|
92
|
+
child_rss_kb: data[:child_rss_kb], memory_delta_kb: data[:memory_delta_kb]
|
|
93
|
+
)
|
|
92
94
|
)
|
|
93
95
|
end
|
|
94
96
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: evilution
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.28.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Denis Kiselev
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-05-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diff-lcs
|
|
@@ -158,8 +158,12 @@ files:
|
|
|
158
158
|
- lib/evilution/compare.rb
|
|
159
159
|
- lib/evilution/compare/categorizer.rb
|
|
160
160
|
- lib/evilution/compare/detector.rb
|
|
161
|
+
- lib/evilution/compare/diff_extractor.rb
|
|
162
|
+
- lib/evilution/compare/diff_extractor/evilution.rb
|
|
163
|
+
- lib/evilution/compare/diff_extractor/mutant.rb
|
|
161
164
|
- lib/evilution/compare/fingerprint.rb
|
|
162
165
|
- lib/evilution/compare/invalid_input.rb
|
|
166
|
+
- lib/evilution/compare/line_normalizer.rb
|
|
163
167
|
- lib/evilution/compare/normalizer.rb
|
|
164
168
|
- lib/evilution/compare/record.rb
|
|
165
169
|
- lib/evilution/config.rb
|
|
@@ -180,6 +184,7 @@ files:
|
|
|
180
184
|
- lib/evilution/config/validators/isolation.rb
|
|
181
185
|
- lib/evilution/config/validators/jobs.rb
|
|
182
186
|
- lib/evilution/config/validators/preload.rb
|
|
187
|
+
- lib/evilution/config/validators/profile.rb
|
|
183
188
|
- lib/evilution/config/validators/spec_mappings.rb
|
|
184
189
|
- lib/evilution/config/validators/spec_pattern.rb
|
|
185
190
|
- lib/evilution/disable_comment.rb
|
|
@@ -316,6 +321,7 @@ files:
|
|
|
316
321
|
- lib/evilution/mutator/operator/pattern_matching_array.rb
|
|
317
322
|
- lib/evilution/mutator/operator/pattern_matching_guard.rb
|
|
318
323
|
- lib/evilution/mutator/operator/predicate_replacement.rb
|
|
324
|
+
- lib/evilution/mutator/operator/predicate_to_nil.rb
|
|
319
325
|
- lib/evilution/mutator/operator/range_replacement.rb
|
|
320
326
|
- lib/evilution/mutator/operator/receiver_replacement.rb
|
|
321
327
|
- lib/evilution/mutator/operator/redo_statement.rb
|
|
@@ -352,6 +358,7 @@ files:
|
|
|
352
358
|
- lib/evilution/parallel/work_queue/worker/loop.rb
|
|
353
359
|
- lib/evilution/parallel/work_queue/worker_stat.rb
|
|
354
360
|
- lib/evilution/parallel_db_warning.rb
|
|
361
|
+
- lib/evilution/process_cleanup.rb
|
|
355
362
|
- lib/evilution/rails_detector.rb
|
|
356
363
|
- lib/evilution/related_spec_heuristic.rb
|
|
357
364
|
- lib/evilution/reporter.rb
|
|
@@ -381,7 +388,6 @@ files:
|
|
|
381
388
|
- lib/evilution/reporter/html/baseline_keys.rb
|
|
382
389
|
- lib/evilution/reporter/html/diff_formatter.rb
|
|
383
390
|
- lib/evilution/reporter/html/escape.rb
|
|
384
|
-
- lib/evilution/reporter/html/namespace.rb
|
|
385
391
|
- lib/evilution/reporter/html/report.rb
|
|
386
392
|
- lib/evilution/reporter/html/section.rb
|
|
387
393
|
- lib/evilution/reporter/html/sections.rb
|
|
@@ -418,12 +424,15 @@ files:
|
|
|
418
424
|
- lib/evilution/reporter/suggestion.rb
|
|
419
425
|
- lib/evilution/reporter/suggestion/diff_helpers.rb
|
|
420
426
|
- lib/evilution/reporter/suggestion/registry.rb
|
|
427
|
+
- lib/evilution/reporter/suggestion/templates.rb
|
|
421
428
|
- lib/evilution/reporter/suggestion/templates/generic.rb
|
|
422
429
|
- lib/evilution/reporter/suggestion/templates/minitest.rb
|
|
423
430
|
- lib/evilution/reporter/suggestion/templates/rspec.rb
|
|
424
431
|
- lib/evilution/result.rb
|
|
425
432
|
- lib/evilution/result/coverage_gap.rb
|
|
426
433
|
- lib/evilution/result/coverage_gap_grouper.rb
|
|
434
|
+
- lib/evilution/result/error_info.rb
|
|
435
|
+
- lib/evilution/result/memory_stats.rb
|
|
427
436
|
- lib/evilution/result/mutation_result.rb
|
|
428
437
|
- lib/evilution/result/summary.rb
|
|
429
438
|
- lib/evilution/runner.rb
|
|
@@ -433,11 +442,13 @@ files:
|
|
|
433
442
|
- lib/evilution/runner/mutation_executor.rb
|
|
434
443
|
- lib/evilution/runner/mutation_executor/mutation_runner.rb
|
|
435
444
|
- lib/evilution/runner/mutation_executor/neutralization_pipeline.rb
|
|
445
|
+
- lib/evilution/runner/mutation_executor/neutralizer.rb
|
|
436
446
|
- lib/evilution/runner/mutation_executor/neutralizer/baseline_failed.rb
|
|
437
447
|
- lib/evilution/runner/mutation_executor/neutralizer/infra_error.rb
|
|
438
448
|
- lib/evilution/runner/mutation_executor/result_cache.rb
|
|
439
449
|
- lib/evilution/runner/mutation_executor/result_notifier.rb
|
|
440
450
|
- lib/evilution/runner/mutation_executor/result_packer.rb
|
|
451
|
+
- lib/evilution/runner/mutation_executor/strategy.rb
|
|
441
452
|
- lib/evilution/runner/mutation_executor/strategy/parallel.rb
|
|
442
453
|
- lib/evilution/runner/mutation_executor/strategy/sequential.rb
|
|
443
454
|
- lib/evilution/runner/mutation_planner.rb
|