evilution 1.1.0 → 1.3.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 +58 -0
- data/.rubocop_todo.yml +9 -0
- data/CHANGELOG.md +86 -0
- data/README.md +202 -14
- data/docs/architecture.md +54 -5
- data/docs/isolation.md +3 -4
- data/exe/evil +8 -1
- data/exe/evilution +8 -1
- data/lib/evilution/ast/local_reads.rb +43 -0
- data/lib/evilution/ast/parser.rb +1 -0
- data/lib/evilution/ast/pattern/filter.rb +1 -0
- data/lib/evilution/ast/pattern/parser.rb +1 -0
- data/lib/evilution/ast/pattern.rb +2 -0
- data/lib/evilution/ast/sorbet_sig_detector.rb +1 -0
- data/lib/evilution/baseline.rb +37 -15
- data/lib/evilution/child_output.rb +1 -1
- data/lib/evilution/cli/command.rb +1 -0
- data/lib/evilution/cli/commands/tests_list.rb +4 -3
- data/lib/evilution/cli/commands.rb +2 -0
- data/lib/evilution/cli/dispatcher.rb +2 -0
- data/lib/evilution/cli/exit_guard.rb +61 -0
- data/lib/evilution/cli/parsed_args.rb +2 -0
- data/lib/evilution/cli/parser/command_extractor.rb +2 -0
- data/lib/evilution/cli/parser/file_args.rb +2 -0
- data/lib/evilution/cli/parser/options_builder.rb +4 -0
- data/lib/evilution/cli/parser/stdin_reader.rb +1 -0
- data/lib/evilution/cli/parser.rb +1 -0
- data/lib/evilution/cli/printers/tests_list.rb +5 -4
- data/lib/evilution/cli/printers.rb +2 -0
- data/lib/evilution/cli/result.rb +2 -0
- data/lib/evilution/cli.rb +6 -0
- data/lib/evilution/config/builders.rb +2 -0
- data/lib/evilution/config/env_loader.rb +2 -0
- data/lib/evilution/config/file_loader.rb +1 -0
- data/lib/evilution/config/sources.rb +1 -0
- data/lib/evilution/config/validators/example_targeting_cache.rb +1 -0
- data/lib/evilution/config/validators/example_targeting_fallback.rb +1 -0
- data/lib/evilution/config/validators/example_targeting_strategy.rb +1 -0
- data/lib/evilution/config/validators/fail_fast.rb +1 -0
- data/lib/evilution/config/validators/hooks.rb +1 -0
- data/lib/evilution/config/validators/ignore_patterns.rb +1 -0
- data/lib/evilution/config/validators/integration.rb +1 -0
- data/lib/evilution/config/validators/isolation.rb +1 -0
- data/lib/evilution/config/validators/jobs.rb +1 -0
- data/lib/evilution/config/validators/preload.rb +1 -0
- data/lib/evilution/config/validators/profile.rb +1 -0
- data/lib/evilution/config/validators/spec_mappings.rb +1 -0
- data/lib/evilution/config/validators/spec_pattern.rb +1 -0
- data/lib/evilution/config/validators/warmup.rb +17 -0
- data/lib/evilution/config/validators.rb +2 -0
- data/lib/evilution/config.rb +7 -5
- data/lib/evilution/coverage.rb +1 -1
- data/lib/evilution/coverage_example_filter.rb +1 -1
- data/lib/evilution/diagnostic.rb +22 -0
- data/lib/evilution/example_filter.rb +1 -1
- data/lib/evilution/integration/loading/body_call_neutralizer.rb +10 -2
- data/lib/evilution/integration/loading/concern_state_cleaner.rb +20 -4
- data/lib/evilution/integration/loading/reeval_warning_filter.rb +72 -0
- data/lib/evilution/integration/loading/source_evaluator.rb +4 -1
- data/lib/evilution/integration/loading/test_load_path.rb +21 -13
- data/lib/evilution/integration/minitest.rb +2 -1
- data/lib/evilution/integration/rspec/crash_detector_lifecycle.rb +9 -1
- data/lib/evilution/integration/rspec/state_guard/configuration_state.rb +1 -0
- data/lib/evilution/integration/rspec/state_guard/configuration_streams.rb +5 -1
- data/lib/evilution/integration/rspec/state_guard/example_groups_constants.rb +1 -2
- data/lib/evilution/integration/rspec/state_guard/internals.rb +1 -2
- data/lib/evilution/integration/rspec/state_guard/object_space_example_groups.rb +1 -2
- data/lib/evilution/integration/rspec/state_guard/reporter_arrays.rb +1 -0
- data/lib/evilution/integration/rspec/state_guard/world_example_groups.rb +1 -0
- data/lib/evilution/integration/rspec/state_guard/world_filtered_examples.rb +1 -0
- data/lib/evilution/integration/rspec/state_guard/world_sources_by_path.rb +1 -0
- data/lib/evilution/integration/rspec/state_guard.rb +6 -0
- data/lib/evilution/integration/rspec/unresolved_spec_warner.rb +2 -1
- data/lib/evilution/integration/rspec.rb +48 -2
- data/lib/evilution/integration/test_unit/test_file_resolver.rb +2 -1
- data/lib/evilution/isolation/fork.rb +29 -8
- data/lib/evilution/mcp/info_tool/actions/environment.rb +1 -0
- data/lib/evilution/mcp/info_tool/actions/feedback.rb +1 -0
- data/lib/evilution/mcp/info_tool/actions/statuses.rb +1 -0
- data/lib/evilution/mcp/info_tool/actions/subjects.rb +1 -0
- data/lib/evilution/mcp/info_tool/actions/tests.rb +1 -0
- data/lib/evilution/mutation.rb +1 -1
- data/lib/evilution/mutator/operator/argument_list_removal.rb +52 -0
- data/lib/evilution/mutator/operator/argument_propagation.rb +54 -0
- data/lib/evilution/mutator/operator/array_coercion_to_literal.rb +34 -0
- data/lib/evilution/mutator/operator/attribute_write_to_read.rb +34 -0
- data/lib/evilution/mutator/operator/bang_method.rb +11 -3
- data/lib/evilution/mutator/operator/binary_operand_promotion.rb +63 -0
- data/lib/evilution/mutator/operator/block_body_promotion.rb +45 -0
- data/lib/evilution/mutator/operator/block_body_to_nil.rb +52 -0
- data/lib/evilution/mutator/operator/block_body_to_raise.rb +34 -0
- data/lib/evilution/mutator/operator/block_destructuring_expansion.rb +85 -0
- data/lib/evilution/mutator/operator/block_parameter_drop.rb +96 -0
- data/lib/evilution/mutator/operator/call_to_nil.rb +34 -0
- data/lib/evilution/mutator/operator/coercion_emptying.rb +60 -0
- data/lib/evilution/mutator/operator/collection_replacement.rb +19 -9
- data/lib/evilution/mutator/operator/comparison_replacement.rb +37 -12
- data/lib/evilution/mutator/operator/const_get_to_constant_path.rb +50 -0
- data/lib/evilution/mutator/operator/dig_to_fetch_chain.rb +45 -0
- data/lib/evilution/mutator/operator/double_negation_removal.rb +22 -0
- data/lib/evilution/mutator/operator/dynamic_dispatch_resolution.rb +79 -0
- data/lib/evilution/mutator/operator/forwarding_super_to_explicit.rb +71 -0
- data/lib/evilution/mutator/operator/inequality_to_negated_identity.rb +43 -0
- data/lib/evilution/mutator/operator/keyword_argument_removal.rb +47 -0
- data/lib/evilution/mutator/operator/method_body_replacement.rb +10 -1
- data/lib/evilution/mutator/operator/method_body_to_raise.rb +59 -0
- data/lib/evilution/mutator/operator/method_body_to_super.rb +150 -0
- data/lib/evilution/mutator/operator/optional_default_injection.rb +71 -0
- data/lib/evilution/mutator/operator/optional_parameter_to_required.rb +41 -0
- data/lib/evilution/mutator/operator/proc_to_lambda.rb +43 -0
- data/lib/evilution/mutator/operator/receiver_constructor_swap.rb +51 -0
- data/lib/evilution/mutator/operator/reduce_to_sum.rb +58 -0
- data/lib/evilution/mutator/operator/regexp_anchor_to_predicate.rb +136 -0
- data/lib/evilution/mutator/operator/safe_navigation_removal.rb +67 -0
- data/lib/evilution/mutator/operator/send_mutation.rb +42 -6
- data/lib/evilution/mutator/operator/symbol_to_proc_replacement.rb +59 -0
- data/lib/evilution/mutator/operator/to_i_to_integer.rb +38 -0
- data/lib/evilution/mutator/operator/typed_default_return.rb +84 -0
- data/lib/evilution/mutator/primitives.rb +25 -0
- data/lib/evilution/mutator/registry.rb +32 -1
- data/lib/evilution/parallel/pool.rb +1 -0
- data/lib/evilution/parallel_db_warning.rb +1 -1
- data/lib/evilution/process_supervisor.rb +20 -8
- data/lib/evilution/rails_warmup.rb +61 -0
- data/lib/evilution/reporter/cli/item_formatters/neutral_group.rb +23 -0
- data/lib/evilution/reporter/cli/item_formatters/subject_score.rb +42 -0
- data/lib/evilution/reporter/cli/item_formatters/subject_score_group.rb +16 -0
- data/lib/evilution/reporter/cli/line_formatters/infra_retry_notice.rb +19 -0
- data/lib/evilution/reporter/cli/line_formatters/result_line.rb +27 -3
- data/lib/evilution/reporter/cli/line_formatters/score.rb +19 -1
- data/lib/evilution/reporter/cli/line_formatters/unresolved_targets.rb +35 -0
- data/lib/evilution/reporter/cli/metrics_block.rb +4 -0
- data/lib/evilution/reporter/cli/trailer.rb +11 -7
- data/lib/evilution/reporter/cli.rb +20 -4
- data/lib/evilution/reporter/html/report.rb +1 -0
- data/lib/evilution/reporter/json/subjects.rb +29 -0
- data/lib/evilution/reporter/json.rb +23 -1
- data/lib/evilution/result/coverage_gap_grouper.rb +1 -0
- data/lib/evilution/result/mutation_result.rb +3 -2
- data/lib/evilution/result/neutral_reason.rb +35 -0
- data/lib/evilution/result/subject_score.rb +28 -0
- data/lib/evilution/result/subject_scorer.rb +38 -0
- data/lib/evilution/result/summary.rb +44 -2
- data/lib/evilution/runner/baseline_runner.rb +17 -7
- data/lib/evilution/runner/canary.rb +52 -5
- data/lib/evilution/runner/isolation_resolver.rb +23 -2
- data/lib/evilution/runner/mutation_executor/infra_retry.rb +54 -0
- data/lib/evilution/runner/mutation_executor/neutralizer/baseline_failed.rb +23 -10
- data/lib/evilution/runner/mutation_executor/neutralizer/infra_error.rb +18 -1
- data/lib/evilution/runner/mutation_executor/result_cache.rb +11 -0
- data/lib/evilution/runner/mutation_executor/strategy/parallel.rb +19 -1
- data/lib/evilution/runner/mutation_executor.rb +32 -4
- data/lib/evilution/runner/report_publisher.rb +31 -9
- data/lib/evilution/runner/target_spec_audit.rb +43 -0
- data/lib/evilution/runner.rb +10 -1
- data/lib/evilution/source_ast_cache.rb +1 -1
- data/lib/evilution/spec_ast_cache.rb +1 -1
- data/lib/evilution/version.rb +1 -1
- data/lib/evilution.rb +35 -0
- metadata +50 -2
|
@@ -3,13 +3,18 @@
|
|
|
3
3
|
require_relative "../runner"
|
|
4
4
|
|
|
5
5
|
class Evilution::Runner::MutationExecutor
|
|
6
|
-
ExecutionResult = Data.define(:results, :truncated)
|
|
6
|
+
ExecutionResult = Data.define(:results, :truncated, :infra_retried) do
|
|
7
|
+
def initialize(results:, truncated:, infra_retried: 0)
|
|
8
|
+
super
|
|
9
|
+
end
|
|
10
|
+
end
|
|
7
11
|
|
|
8
12
|
autoload :ResultCache, File.expand_path("mutation_executor/result_cache", __dir__)
|
|
9
13
|
autoload :ResultPacker, File.expand_path("mutation_executor/result_packer", __dir__)
|
|
10
14
|
autoload :ResultNotifier, File.expand_path("mutation_executor/result_notifier", __dir__)
|
|
11
15
|
autoload :MutationRunner, File.expand_path("mutation_executor/mutation_runner", __dir__)
|
|
12
16
|
autoload :NeutralizationPipeline, File.expand_path("mutation_executor/neutralization_pipeline", __dir__)
|
|
17
|
+
autoload :InfraRetry, File.expand_path("mutation_executor/infra_retry", __dir__)
|
|
13
18
|
autoload :Strategy, File.expand_path("mutation_executor/strategy", __dir__)
|
|
14
19
|
autoload :Neutralizer, File.expand_path("mutation_executor/neutralizer", __dir__)
|
|
15
20
|
|
|
@@ -29,13 +34,36 @@ class Evilution::Runner::MutationExecutor
|
|
|
29
34
|
spec_resolver = baseline_failed?(baseline_result) ? @baseline_runner.neutralization_resolver : nil
|
|
30
35
|
notifier = build_notifier
|
|
31
36
|
pipeline = build_pipeline(spec_resolver)
|
|
32
|
-
|
|
37
|
+
return sequential_run(notifier, pipeline, mutations, baseline_result, integration) if @config.jobs <= 1
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
parallel_run(notifier, pipeline, mutations, baseline_result, integration)
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
private
|
|
38
43
|
|
|
44
|
+
def sequential_run(notifier, pipeline, mutations, baseline_result, integration)
|
|
45
|
+
build_sequential(notifier, pipeline)
|
|
46
|
+
.call(mutations, baseline_result: baseline_result, integration: integration)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Infrastructure contention only exists while the pool is running, so the
|
|
50
|
+
# mutations it left without a verdict are re-run once it is done. Without
|
|
51
|
+
# this the neutral bucket swings with --jobs on identical input
|
|
52
|
+
# (EV-j0bv / GH #1607).
|
|
53
|
+
def parallel_run(notifier, pipeline, mutations, baseline_result, integration)
|
|
54
|
+
execution = build_parallel(notifier, pipeline)
|
|
55
|
+
.call(mutations, baseline_result: baseline_result, integration: integration)
|
|
56
|
+
retry_pass = InfraRetry.new(runner: build_mutation_runner, pipeline: pipeline)
|
|
57
|
+
results = retry_pass.call(execution.results, baseline_result: baseline_result, integration: integration)
|
|
58
|
+
|
|
59
|
+
ExecutionResult.new(results: results, truncated: execution.truncated,
|
|
60
|
+
infra_retried: retry_pass.retried_count)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def build_mutation_runner
|
|
64
|
+
MutationRunner.new(config: @config, cache: @cache, isolator: @isolator)
|
|
65
|
+
end
|
|
66
|
+
|
|
39
67
|
def baseline_failed?(baseline_result)
|
|
40
68
|
baseline_result && baseline_result.failed?
|
|
41
69
|
end
|
|
@@ -59,7 +87,7 @@ class Evilution::Runner::MutationExecutor
|
|
|
59
87
|
|
|
60
88
|
def build_sequential(notifier, pipeline)
|
|
61
89
|
Strategy::Sequential.new(
|
|
62
|
-
runner:
|
|
90
|
+
runner: build_mutation_runner,
|
|
63
91
|
pipeline: pipeline,
|
|
64
92
|
notifier: notifier
|
|
65
93
|
)
|
|
@@ -11,20 +11,42 @@ class Evilution::Runner::ReportPublisher
|
|
|
11
11
|
@config = config
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def publish(summary)
|
|
14
|
+
def publish(summary, stdout: $stdout)
|
|
15
15
|
reporter = build_reporter
|
|
16
16
|
return unless reporter
|
|
17
17
|
|
|
18
18
|
output = reporter.call(summary)
|
|
19
19
|
return if config.quiet
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
deliver(output, stdout)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def deliver(output, stdout)
|
|
25
|
+
return publish_html(output) if config.html?
|
|
26
|
+
return File.write(config.output, output) if config.output
|
|
27
|
+
|
|
28
|
+
stdout.puts(output)
|
|
29
|
+
claim_stdout(stdout) if config.json?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# `--preload` brings the project's at_exit hooks into this process, and
|
|
33
|
+
# SimpleCov's prints its coverage report on the way out. Once the document is
|
|
34
|
+
# written, stdout is pointed at stderr so nothing can append to it and leave a
|
|
35
|
+
# consumer with unparseable JSON (EV-g8ya / GH #1608). Text reports are read
|
|
36
|
+
# by people, not parsers, so they keep the stream as it was.
|
|
37
|
+
def claim_stdout(stdout)
|
|
38
|
+
stdout.flush
|
|
39
|
+
stdout.reopen($stderr)
|
|
40
|
+
rescue TypeError
|
|
41
|
+
# A harness that captures output swaps $stdout for a StringIO, which cannot
|
|
42
|
+
# be reopened onto an IO. There is no file descriptor to protect there.
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def publish_html(output)
|
|
47
|
+
path = "evilution-report.html"
|
|
48
|
+
File.write(path, output)
|
|
49
|
+
warn "HTML report written to #{path}"
|
|
28
50
|
end
|
|
29
51
|
|
|
30
52
|
def save_session(summary)
|
|
@@ -44,7 +66,7 @@ class Evilution::Runner::ReportPublisher
|
|
|
44
66
|
when :json
|
|
45
67
|
Evilution::Reporter::JSON.new(integration: config.integration)
|
|
46
68
|
when :text
|
|
47
|
-
Evilution::Reporter::CLI.new
|
|
69
|
+
Evilution::Reporter::CLI.new(min_score: config.min_score)
|
|
48
70
|
when :html
|
|
49
71
|
Evilution::Reporter::HTML.new(baseline: load_baseline_session, integration: config.integration)
|
|
50
72
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../runner"
|
|
4
|
+
|
|
5
|
+
# Answers, in the parent process and before any mutation runs, which of the
|
|
6
|
+
# files evilution was pointed at resolve to no test file at all.
|
|
7
|
+
#
|
|
8
|
+
# The integrations resolve specs per mutation inside the worker, which is what
|
|
9
|
+
# produces `:unresolved` results, but that is a per-mutation fact diluted by
|
|
10
|
+
# every other file in the run: a target with no spec at all contributes a
|
|
11
|
+
# handful of unresolved mutations and disappears behind a healthy score
|
|
12
|
+
# (EV-p4sm / GH #1603). Asking the same selector once per file, up front, keeps
|
|
13
|
+
# the stronger fact — "you named this file and it was never tested" — intact.
|
|
14
|
+
#
|
|
15
|
+
# Only files that produced a subject are audited: a file evilution found
|
|
16
|
+
# nothing to mutate in — a constants-only file, say — has no untested behaviour
|
|
17
|
+
# to report, and failing a run over one would be noise.
|
|
18
|
+
#
|
|
19
|
+
# With `fallback_to_full_suite` a file without its own spec is run against the
|
|
20
|
+
# whole suite rather than skipped, so nothing goes untested and there is
|
|
21
|
+
# nothing to report.
|
|
22
|
+
class Evilution::Runner::TargetSpecAudit
|
|
23
|
+
def initialize(config)
|
|
24
|
+
@config = config
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def call(file_paths)
|
|
28
|
+
return [] if @config.fallback_to_full_suite?
|
|
29
|
+
|
|
30
|
+
file_paths.uniq.sort.reject { |path| resolved?(path) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
# SpecSelector answers nil when nothing resolves; a custom resolver plugged
|
|
36
|
+
# in through it may answer an empty list instead.
|
|
37
|
+
def resolved?(path)
|
|
38
|
+
specs = @config.spec_selector.call(path)
|
|
39
|
+
return false if specs.nil?
|
|
40
|
+
|
|
41
|
+
!specs.empty?
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/evilution/runner.rb
CHANGED
|
@@ -46,9 +46,13 @@ class Evilution::Runner
|
|
|
46
46
|
|
|
47
47
|
duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
|
|
48
48
|
|
|
49
|
+
audited_files = subjects.map(&:file_path).uniq.sort
|
|
49
50
|
summary = Evilution::Result::Summary.new(results: results, duration: duration, truncated: execution.truncated,
|
|
50
51
|
skipped: plan.skipped_count,
|
|
51
|
-
disabled_mutations: plan.disabled_mutations
|
|
52
|
+
disabled_mutations: plan.disabled_mutations,
|
|
53
|
+
unresolved_target_files: target_spec_audit.call(audited_files),
|
|
54
|
+
target_file_count: audited_files.length,
|
|
55
|
+
infra_retried: execution.infra_retried)
|
|
52
56
|
output_report(summary)
|
|
53
57
|
save_session(summary)
|
|
54
58
|
|
|
@@ -71,6 +75,10 @@ class Evilution::Runner
|
|
|
71
75
|
@mutation_planner ||= Evilution::Runner::MutationPlanner.new(config, registry: registry)
|
|
72
76
|
end
|
|
73
77
|
|
|
78
|
+
def target_spec_audit
|
|
79
|
+
@target_spec_audit ||= Evilution::Runner::TargetSpecAudit.new(config)
|
|
80
|
+
end
|
|
81
|
+
|
|
74
82
|
def isolation_resolver
|
|
75
83
|
@isolation_resolver ||= Evilution::Runner::IsolationResolver.new(
|
|
76
84
|
config,
|
|
@@ -240,6 +248,7 @@ require_relative "rails_detector"
|
|
|
240
248
|
require_relative "parallel_db_warning"
|
|
241
249
|
require_relative "child_output"
|
|
242
250
|
require_relative "runner/subject_pipeline"
|
|
251
|
+
require_relative "runner/target_spec_audit"
|
|
243
252
|
require_relative "runner/mutation_planner"
|
|
244
253
|
require_relative "runner/isolation_resolver"
|
|
245
254
|
require_relative "runner/baseline_runner"
|
data/lib/evilution/version.rb
CHANGED
data/lib/evilution.rb
CHANGED
|
@@ -13,6 +13,7 @@ require_relative "evilution/ast/parser"
|
|
|
13
13
|
require_relative "evilution/ast/inheritance_scanner"
|
|
14
14
|
require_relative "evilution/ast/pattern"
|
|
15
15
|
require_relative "evilution/ast/sorbet_sig_detector"
|
|
16
|
+
require_relative "evilution/ast/local_reads"
|
|
16
17
|
require_relative "evilution/ast/pattern/matcher"
|
|
17
18
|
require_relative "evilution/ast/pattern/parser"
|
|
18
19
|
require_relative "evilution/hooks"
|
|
@@ -29,6 +30,29 @@ require_relative "evilution/mutator/operator/nil_replacement"
|
|
|
29
30
|
require_relative "evilution/mutator/operator/boolean_operator_replacement"
|
|
30
31
|
require_relative "evilution/mutator/operator/boolean_operand_promotion"
|
|
31
32
|
require_relative "evilution/mutator/operator/boolean_expression_to_nil"
|
|
33
|
+
require_relative "evilution/mutator/operator/call_to_nil"
|
|
34
|
+
require_relative "evilution/mutator/operator/safe_navigation_removal"
|
|
35
|
+
require_relative "evilution/mutator/operator/attribute_write_to_read"
|
|
36
|
+
require_relative "evilution/mutator/operator/argument_propagation"
|
|
37
|
+
require_relative "evilution/mutator/operator/argument_list_removal"
|
|
38
|
+
require_relative "evilution/mutator/operator/symbol_to_proc_replacement"
|
|
39
|
+
require_relative "evilution/mutator/operator/dynamic_dispatch_resolution"
|
|
40
|
+
require_relative "evilution/mutator/operator/keyword_argument_removal"
|
|
41
|
+
require_relative "evilution/mutator/operator/double_negation_removal"
|
|
42
|
+
require_relative "evilution/mutator/operator/regexp_anchor_to_predicate"
|
|
43
|
+
require_relative "evilution/mutator/operator/reduce_to_sum"
|
|
44
|
+
require_relative "evilution/mutator/operator/array_coercion_to_literal"
|
|
45
|
+
require_relative "evilution/mutator/operator/to_i_to_integer"
|
|
46
|
+
require_relative "evilution/mutator/operator/coercion_emptying"
|
|
47
|
+
require_relative "evilution/mutator/operator/const_get_to_constant_path"
|
|
48
|
+
require_relative "evilution/mutator/operator/proc_to_lambda"
|
|
49
|
+
require_relative "evilution/mutator/operator/dig_to_fetch_chain"
|
|
50
|
+
require_relative "evilution/mutator/operator/inequality_to_negated_identity"
|
|
51
|
+
require_relative "evilution/mutator/operator/binary_operand_promotion"
|
|
52
|
+
require_relative "evilution/mutator/operator/receiver_constructor_swap"
|
|
53
|
+
require_relative "evilution/mutator/operator/block_body_to_nil"
|
|
54
|
+
require_relative "evilution/mutator/operator/block_body_to_raise"
|
|
55
|
+
require_relative "evilution/mutator/operator/block_body_promotion"
|
|
32
56
|
require_relative "evilution/mutator/operator/arithmetic_replacement"
|
|
33
57
|
require_relative "evilution/mutator/operator/string_literal"
|
|
34
58
|
require_relative "evilution/mutator/operator/array_literal"
|
|
@@ -89,6 +113,14 @@ require_relative "evilution/mutator/operator/defined_check"
|
|
|
89
113
|
require_relative "evilution/mutator/operator/regex_capture"
|
|
90
114
|
require_relative "evilution/mutator/operator/loop_flip"
|
|
91
115
|
require_relative "evilution/mutator/operator/loop_body_to_raise"
|
|
116
|
+
require_relative "evilution/mutator/operator/method_body_to_raise"
|
|
117
|
+
require_relative "evilution/mutator/operator/method_body_to_super"
|
|
118
|
+
require_relative "evilution/mutator/operator/typed_default_return"
|
|
119
|
+
require_relative "evilution/mutator/operator/block_parameter_drop"
|
|
120
|
+
require_relative "evilution/mutator/operator/optional_parameter_to_required"
|
|
121
|
+
require_relative "evilution/mutator/operator/optional_default_injection"
|
|
122
|
+
require_relative "evilution/mutator/operator/block_destructuring_expansion"
|
|
123
|
+
require_relative "evilution/mutator/operator/forwarding_super_to_explicit"
|
|
92
124
|
require_relative "evilution/mutator/operator/string_interpolation"
|
|
93
125
|
require_relative "evilution/mutator/operator/retry_removal"
|
|
94
126
|
require_relative "evilution/mutator/operator/case_when"
|
|
@@ -121,6 +153,9 @@ require_relative "evilution/integration/base"
|
|
|
121
153
|
require_relative "evilution/integration/rspec"
|
|
122
154
|
require_relative "evilution/integration/minitest"
|
|
123
155
|
require_relative "evilution/result/mutation_result"
|
|
156
|
+
require_relative "evilution/result/neutral_reason"
|
|
157
|
+
require_relative "evilution/result/subject_score"
|
|
158
|
+
require_relative "evilution/result/subject_scorer"
|
|
124
159
|
require_relative "evilution/result/summary"
|
|
125
160
|
require_relative "evilution/reporter"
|
|
126
161
|
require_relative "evilution/reporter/json"
|
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: 1.
|
|
4
|
+
version: 1.3.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-09-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diff-lcs
|
|
@@ -123,6 +123,7 @@ files:
|
|
|
123
123
|
- lib/evilution/ast/constant_names.rb
|
|
124
124
|
- lib/evilution/ast/heredoc_span.rb
|
|
125
125
|
- lib/evilution/ast/inheritance_scanner.rb
|
|
126
|
+
- lib/evilution/ast/local_reads.rb
|
|
126
127
|
- lib/evilution/ast/parser.rb
|
|
127
128
|
- lib/evilution/ast/pattern.rb
|
|
128
129
|
- lib/evilution/ast/pattern/filter.rb
|
|
@@ -150,6 +151,7 @@ files:
|
|
|
150
151
|
- lib/evilution/cli/commands/util_mutation.rb
|
|
151
152
|
- lib/evilution/cli/commands/version.rb
|
|
152
153
|
- lib/evilution/cli/dispatcher.rb
|
|
154
|
+
- lib/evilution/cli/exit_guard.rb
|
|
153
155
|
- lib/evilution/cli/parsed_args.rb
|
|
154
156
|
- lib/evilution/cli/parser.rb
|
|
155
157
|
- lib/evilution/cli/parser/command_extractor.rb
|
|
@@ -199,6 +201,7 @@ files:
|
|
|
199
201
|
- lib/evilution/config/validators/profile.rb
|
|
200
202
|
- lib/evilution/config/validators/spec_mappings.rb
|
|
201
203
|
- lib/evilution/config/validators/spec_pattern.rb
|
|
204
|
+
- lib/evilution/config/validators/warmup.rb
|
|
202
205
|
- lib/evilution/coverage.rb
|
|
203
206
|
- lib/evilution/coverage/digest.rb
|
|
204
207
|
- lib/evilution/coverage/map.rb
|
|
@@ -206,6 +209,7 @@ files:
|
|
|
206
209
|
- lib/evilution/coverage/map_store.rb
|
|
207
210
|
- lib/evilution/coverage/recorder.rb
|
|
208
211
|
- lib/evilution/coverage_example_filter.rb
|
|
212
|
+
- lib/evilution/diagnostic.rb
|
|
209
213
|
- lib/evilution/disable_comment.rb
|
|
210
214
|
- lib/evilution/equivalent.rb
|
|
211
215
|
- lib/evilution/equivalent/detector.rb
|
|
@@ -237,6 +241,7 @@ files:
|
|
|
237
241
|
- lib/evilution/integration/loading/constant_pinner.rb
|
|
238
242
|
- lib/evilution/integration/loading/mutation_applier.rb
|
|
239
243
|
- lib/evilution/integration/loading/redefinition_recovery.rb
|
|
244
|
+
- lib/evilution/integration/loading/reeval_warning_filter.rb
|
|
240
245
|
- lib/evilution/integration/loading/source_evaluator.rb
|
|
241
246
|
- lib/evilution/integration/loading/syntax_validator.rb
|
|
242
247
|
- lib/evilution/integration/loading/test_load_path.rb
|
|
@@ -302,16 +307,26 @@ files:
|
|
|
302
307
|
- lib/evilution/mutator.rb
|
|
303
308
|
- lib/evilution/mutator/base.rb
|
|
304
309
|
- lib/evilution/mutator/operator.rb
|
|
310
|
+
- lib/evilution/mutator/operator/argument_list_removal.rb
|
|
305
311
|
- lib/evilution/mutator/operator/argument_method_call_replacement.rb
|
|
306
312
|
- lib/evilution/mutator/operator/argument_nil_substitution.rb
|
|
313
|
+
- lib/evilution/mutator/operator/argument_propagation.rb
|
|
307
314
|
- lib/evilution/mutator/operator/argument_removal.rb
|
|
308
315
|
- lib/evilution/mutator/operator/arithmetic_replacement.rb
|
|
316
|
+
- lib/evilution/mutator/operator/array_coercion_to_literal.rb
|
|
309
317
|
- lib/evilution/mutator/operator/array_literal.rb
|
|
318
|
+
- lib/evilution/mutator/operator/attribute_write_to_read.rb
|
|
310
319
|
- lib/evilution/mutator/operator/bang_method.rb
|
|
311
320
|
- lib/evilution/mutator/operator/begin_unwrap.rb
|
|
321
|
+
- lib/evilution/mutator/operator/binary_operand_promotion.rb
|
|
312
322
|
- lib/evilution/mutator/operator/bitwise_complement.rb
|
|
313
323
|
- lib/evilution/mutator/operator/bitwise_replacement.rb
|
|
324
|
+
- lib/evilution/mutator/operator/block_body_promotion.rb
|
|
325
|
+
- lib/evilution/mutator/operator/block_body_to_nil.rb
|
|
326
|
+
- lib/evilution/mutator/operator/block_body_to_raise.rb
|
|
327
|
+
- lib/evilution/mutator/operator/block_destructuring_expansion.rb
|
|
314
328
|
- lib/evilution/mutator/operator/block_param_removal.rb
|
|
329
|
+
- lib/evilution/mutator/operator/block_parameter_drop.rb
|
|
315
330
|
- lib/evilution/mutator/operator/block_pass_removal.rb
|
|
316
331
|
- lib/evilution/mutator/operator/block_removal.rb
|
|
317
332
|
- lib/evilution/mutator/operator/boolean_expression_to_nil.rb
|
|
@@ -319,9 +334,11 @@ files:
|
|
|
319
334
|
- lib/evilution/mutator/operator/boolean_operand_promotion.rb
|
|
320
335
|
- lib/evilution/mutator/operator/boolean_operator_replacement.rb
|
|
321
336
|
- lib/evilution/mutator/operator/break_statement.rb
|
|
337
|
+
- lib/evilution/mutator/operator/call_to_nil.rb
|
|
322
338
|
- lib/evilution/mutator/operator/case_in.rb
|
|
323
339
|
- lib/evilution/mutator/operator/case_when.rb
|
|
324
340
|
- lib/evilution/mutator/operator/class_variable_write.rb
|
|
341
|
+
- lib/evilution/mutator/operator/coercion_emptying.rb
|
|
325
342
|
- lib/evilution/mutator/operator/collection_replacement.rb
|
|
326
343
|
- lib/evilution/mutator/operator/collection_return.rb
|
|
327
344
|
- lib/evilution/mutator/operator/comparison_replacement.rb
|
|
@@ -329,11 +346,16 @@ files:
|
|
|
329
346
|
- lib/evilution/mutator/operator/conditional_branch.rb
|
|
330
347
|
- lib/evilution/mutator/operator/conditional_flip.rb
|
|
331
348
|
- lib/evilution/mutator/operator/conditional_negation.rb
|
|
349
|
+
- lib/evilution/mutator/operator/const_get_to_constant_path.rb
|
|
332
350
|
- lib/evilution/mutator/operator/defined_check.rb
|
|
351
|
+
- lib/evilution/mutator/operator/dig_to_fetch_chain.rb
|
|
352
|
+
- lib/evilution/mutator/operator/double_negation_removal.rb
|
|
353
|
+
- lib/evilution/mutator/operator/dynamic_dispatch_resolution.rb
|
|
333
354
|
- lib/evilution/mutator/operator/ensure_removal.rb
|
|
334
355
|
- lib/evilution/mutator/operator/equality_to_identity.rb
|
|
335
356
|
- lib/evilution/mutator/operator/explicit_super_mutation.rb
|
|
336
357
|
- lib/evilution/mutator/operator/float_literal.rb
|
|
358
|
+
- lib/evilution/mutator/operator/forwarding_super_to_explicit.rb
|
|
337
359
|
- lib/evilution/mutator/operator/global_variable_write.rb
|
|
338
360
|
- lib/evilution/mutator/operator/hash_literal.rb
|
|
339
361
|
- lib/evilution/mutator/operator/if_branch_swap.rb
|
|
@@ -341,38 +363,49 @@ files:
|
|
|
341
363
|
- lib/evilution/mutator/operator/index_to_at.rb
|
|
342
364
|
- lib/evilution/mutator/operator/index_to_dig.rb
|
|
343
365
|
- lib/evilution/mutator/operator/index_to_fetch.rb
|
|
366
|
+
- lib/evilution/mutator/operator/inequality_to_negated_identity.rb
|
|
344
367
|
- lib/evilution/mutator/operator/inline_rescue.rb
|
|
345
368
|
- lib/evilution/mutator/operator/instance_variable_write.rb
|
|
346
369
|
- lib/evilution/mutator/operator/integer_literal.rb
|
|
347
370
|
- lib/evilution/mutator/operator/keyword_argument.rb
|
|
371
|
+
- lib/evilution/mutator/operator/keyword_argument_removal.rb
|
|
348
372
|
- lib/evilution/mutator/operator/lambda_body.rb
|
|
349
373
|
- lib/evilution/mutator/operator/last_expression_removal.rb
|
|
350
374
|
- lib/evilution/mutator/operator/local_variable_assignment.rb
|
|
351
375
|
- lib/evilution/mutator/operator/loop_body_to_raise.rb
|
|
352
376
|
- lib/evilution/mutator/operator/loop_flip.rb
|
|
353
377
|
- lib/evilution/mutator/operator/method_body_replacement.rb
|
|
378
|
+
- lib/evilution/mutator/operator/method_body_to_raise.rb
|
|
379
|
+
- lib/evilution/mutator/operator/method_body_to_super.rb
|
|
354
380
|
- lib/evilution/mutator/operator/method_call_removal.rb
|
|
355
381
|
- lib/evilution/mutator/operator/mixin_removal.rb
|
|
356
382
|
- lib/evilution/mutator/operator/multiple_assignment.rb
|
|
357
383
|
- lib/evilution/mutator/operator/negation_insertion.rb
|
|
358
384
|
- lib/evilution/mutator/operator/next_statement.rb
|
|
359
385
|
- lib/evilution/mutator/operator/nil_replacement.rb
|
|
386
|
+
- lib/evilution/mutator/operator/optional_default_injection.rb
|
|
387
|
+
- lib/evilution/mutator/operator/optional_parameter_to_required.rb
|
|
360
388
|
- lib/evilution/mutator/operator/pattern_matching_alternative.rb
|
|
361
389
|
- lib/evilution/mutator/operator/pattern_matching_array.rb
|
|
362
390
|
- lib/evilution/mutator/operator/pattern_matching_guard.rb
|
|
363
391
|
- lib/evilution/mutator/operator/pattern_predicate.rb
|
|
364
392
|
- lib/evilution/mutator/operator/predicate_replacement.rb
|
|
365
393
|
- lib/evilution/mutator/operator/predicate_to_nil.rb
|
|
394
|
+
- lib/evilution/mutator/operator/proc_to_lambda.rb
|
|
366
395
|
- lib/evilution/mutator/operator/range_replacement.rb
|
|
396
|
+
- lib/evilution/mutator/operator/receiver_constructor_swap.rb
|
|
367
397
|
- lib/evilution/mutator/operator/receiver_replacement.rb
|
|
368
398
|
- lib/evilution/mutator/operator/redo_statement.rb
|
|
399
|
+
- lib/evilution/mutator/operator/reduce_to_sum.rb
|
|
369
400
|
- lib/evilution/mutator/operator/regex_capture.rb
|
|
370
401
|
- lib/evilution/mutator/operator/regex_simplification.rb
|
|
402
|
+
- lib/evilution/mutator/operator/regexp_anchor_to_predicate.rb
|
|
371
403
|
- lib/evilution/mutator/operator/regexp_mutation.rb
|
|
372
404
|
- lib/evilution/mutator/operator/rescue_body_replacement.rb
|
|
373
405
|
- lib/evilution/mutator/operator/rescue_removal.rb
|
|
374
406
|
- lib/evilution/mutator/operator/retry_removal.rb
|
|
375
407
|
- lib/evilution/mutator/operator/return_value_removal.rb
|
|
408
|
+
- lib/evilution/mutator/operator/safe_navigation_removal.rb
|
|
376
409
|
- lib/evilution/mutator/operator/scalar_return.rb
|
|
377
410
|
- lib/evilution/mutator/operator/send_mutation.rb
|
|
378
411
|
- lib/evilution/mutator/operator/splat_operator.rb
|
|
@@ -381,6 +414,9 @@ files:
|
|
|
381
414
|
- lib/evilution/mutator/operator/string_literal.rb
|
|
382
415
|
- lib/evilution/mutator/operator/superclass_removal.rb
|
|
383
416
|
- lib/evilution/mutator/operator/symbol_literal.rb
|
|
417
|
+
- lib/evilution/mutator/operator/symbol_to_proc_replacement.rb
|
|
418
|
+
- lib/evilution/mutator/operator/to_i_to_integer.rb
|
|
419
|
+
- lib/evilution/mutator/operator/typed_default_return.rb
|
|
384
420
|
- lib/evilution/mutator/operator/yield_statement.rb
|
|
385
421
|
- lib/evilution/mutator/operator/zsuper_removal.rb
|
|
386
422
|
- lib/evilution/mutator/primitives.rb
|
|
@@ -404,6 +440,7 @@ files:
|
|
|
404
440
|
- lib/evilution/process_cleanup.rb
|
|
405
441
|
- lib/evilution/process_supervisor.rb
|
|
406
442
|
- lib/evilution/rails_detector.rb
|
|
443
|
+
- lib/evilution/rails_warmup.rb
|
|
407
444
|
- lib/evilution/related_spec_heuristic.rb
|
|
408
445
|
- lib/evilution/reporter.rb
|
|
409
446
|
- lib/evilution/reporter/cli.rb
|
|
@@ -411,19 +448,24 @@ files:
|
|
|
411
448
|
- lib/evilution/reporter/cli/item_formatters/coverage_gap.rb
|
|
412
449
|
- lib/evilution/reporter/cli/item_formatters/disabled.rb
|
|
413
450
|
- lib/evilution/reporter/cli/item_formatters/error.rb
|
|
451
|
+
- lib/evilution/reporter/cli/item_formatters/neutral_group.rb
|
|
414
452
|
- lib/evilution/reporter/cli/item_formatters/result_location.rb
|
|
453
|
+
- lib/evilution/reporter/cli/item_formatters/subject_score.rb
|
|
454
|
+
- lib/evilution/reporter/cli/item_formatters/subject_score_group.rb
|
|
415
455
|
- lib/evilution/reporter/cli/line_formatters.rb
|
|
416
456
|
- lib/evilution/reporter/cli/line_formatters/duration.rb
|
|
417
457
|
- lib/evilution/reporter/cli/line_formatters/efficiency.rb
|
|
418
458
|
- lib/evilution/reporter/cli/line_formatters/error_rate_warning.rb
|
|
419
459
|
- lib/evilution/reporter/cli/line_formatters/feedback_footer.rb
|
|
420
460
|
- lib/evilution/reporter/cli/line_formatters/header.rb
|
|
461
|
+
- lib/evilution/reporter/cli/line_formatters/infra_retry_notice.rb
|
|
421
462
|
- lib/evilution/reporter/cli/line_formatters/mutations.rb
|
|
422
463
|
- lib/evilution/reporter/cli/line_formatters/peak_memory.rb
|
|
423
464
|
- lib/evilution/reporter/cli/line_formatters/result_line.rb
|
|
424
465
|
- lib/evilution/reporter/cli/line_formatters/score.rb
|
|
425
466
|
- lib/evilution/reporter/cli/line_formatters/truncation_notice.rb
|
|
426
467
|
- lib/evilution/reporter/cli/line_formatters/unresolved_rate_warning.rb
|
|
468
|
+
- lib/evilution/reporter/cli/line_formatters/unresolved_targets.rb
|
|
427
469
|
- lib/evilution/reporter/cli/metrics_block.rb
|
|
428
470
|
- lib/evilution/reporter/cli/pct.rb
|
|
429
471
|
- lib/evilution/reporter/cli/section.rb
|
|
@@ -466,6 +508,7 @@ files:
|
|
|
466
508
|
- lib/evilution/reporter/html/templates/unparseable_details.html.erb
|
|
467
509
|
- lib/evilution/reporter/html/templates/unresolved_details.html.erb
|
|
468
510
|
- lib/evilution/reporter/json.rb
|
|
511
|
+
- lib/evilution/reporter/json/subjects.rb
|
|
469
512
|
- lib/evilution/reporter/progress_bar.rb
|
|
470
513
|
- lib/evilution/reporter/suggestion.rb
|
|
471
514
|
- lib/evilution/reporter/suggestion/diff_helpers.rb
|
|
@@ -481,6 +524,9 @@ files:
|
|
|
481
524
|
- lib/evilution/result/error_info.rb
|
|
482
525
|
- lib/evilution/result/memory_stats.rb
|
|
483
526
|
- lib/evilution/result/mutation_result.rb
|
|
527
|
+
- lib/evilution/result/neutral_reason.rb
|
|
528
|
+
- lib/evilution/result/subject_score.rb
|
|
529
|
+
- lib/evilution/result/subject_scorer.rb
|
|
484
530
|
- lib/evilution/result/summary.rb
|
|
485
531
|
- lib/evilution/runner.rb
|
|
486
532
|
- lib/evilution/runner/baseline_runner.rb
|
|
@@ -488,6 +534,7 @@ files:
|
|
|
488
534
|
- lib/evilution/runner/diagnostics.rb
|
|
489
535
|
- lib/evilution/runner/isolation_resolver.rb
|
|
490
536
|
- lib/evilution/runner/mutation_executor.rb
|
|
537
|
+
- lib/evilution/runner/mutation_executor/infra_retry.rb
|
|
491
538
|
- lib/evilution/runner/mutation_executor/mutation_runner.rb
|
|
492
539
|
- lib/evilution/runner/mutation_executor/neutralization_pipeline.rb
|
|
493
540
|
- lib/evilution/runner/mutation_executor/neutralizer.rb
|
|
@@ -502,6 +549,7 @@ files:
|
|
|
502
549
|
- lib/evilution/runner/mutation_planner.rb
|
|
503
550
|
- lib/evilution/runner/report_publisher.rb
|
|
504
551
|
- lib/evilution/runner/subject_pipeline.rb
|
|
552
|
+
- lib/evilution/runner/target_spec_audit.rb
|
|
505
553
|
- lib/evilution/session.rb
|
|
506
554
|
- lib/evilution/session/diff.rb
|
|
507
555
|
- lib/evilution/session/schema.rb
|