henitai 0.2.0 → 0.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/CHANGELOG.md +105 -1
- data/README.md +138 -5
- data/assets/schema/henitai.schema.json +41 -0
- data/lib/henitai/available_cpu_count.rb +16 -23
- data/lib/henitai/canonical_report_merger.rb +107 -0
- data/lib/henitai/canonical_report_writer.rb +22 -0
- data/lib/henitai/checkpoint_reporter.rb +79 -0
- data/lib/henitai/cli/clean_command.rb +54 -0
- data/lib/henitai/cli/command_support.rb +52 -0
- data/lib/henitai/cli/init_command.rb +64 -0
- data/lib/henitai/cli/operator_command.rb +96 -0
- data/lib/henitai/cli/options.rb +84 -0
- data/lib/henitai/cli/run_command.rb +136 -0
- data/lib/henitai/cli/run_options.rb +108 -0
- data/lib/henitai/cli.rb +27 -407
- data/lib/henitai/composite_progress_reporter.rb +42 -0
- data/lib/henitai/configuration.rb +42 -9
- data/lib/henitai/configuration_validator/rules.rb +161 -0
- data/lib/henitai/configuration_validator/scalars.rb +169 -0
- data/lib/henitai/configuration_validator.rb +20 -240
- data/lib/henitai/coverage_bootstrapper.rb +54 -5
- data/lib/henitai/coverage_formatter.rb +5 -1
- data/lib/henitai/coverage_report_reader.rb +28 -5
- data/lib/henitai/eager_load.rb +36 -5
- data/lib/henitai/execution_engine/env_scope.rb +67 -0
- data/lib/henitai/execution_engine.rb +115 -53
- data/lib/henitai/generated_artifacts.rb +58 -0
- data/lib/henitai/incremental_filter.rb +100 -0
- data/lib/henitai/integration/base.rb +171 -0
- data/lib/henitai/integration/child_debug_support.rb +119 -0
- data/lib/henitai/integration/child_runtime_control.rb +50 -0
- data/lib/henitai/integration/coverage_suppression.rb +52 -0
- data/lib/henitai/integration/minitest.rb +101 -0
- data/lib/henitai/integration/minitest_load_path.rb +14 -0
- data/lib/henitai/integration/minitest_suite_command.rb +17 -0
- data/lib/henitai/integration/minitest_test_runner.rb +39 -0
- data/lib/henitai/integration/mutant_run_support.rb +77 -0
- data/lib/henitai/integration/rails_environment_preloader.rb +14 -0
- data/lib/henitai/integration/rspec_child_runner.rb +61 -0
- data/lib/henitai/integration/rspec_test_selection.rb +138 -0
- data/lib/henitai/integration/scenario_log_support.rb +160 -0
- data/lib/henitai/integration.rb +22 -846
- data/lib/henitai/minitest_coverage_reporter.rb +4 -1
- data/lib/henitai/mutant/activator.rb +15 -79
- data/lib/henitai/mutant/parameter_source.rb +98 -0
- data/lib/henitai/mutant.rb +14 -6
- data/lib/henitai/mutant_history_store/sql.rb +90 -0
- data/lib/henitai/mutant_history_store/verdict_cache.rb +84 -0
- data/lib/henitai/mutant_history_store.rb +67 -81
- data/lib/henitai/mutant_identity.rb +33 -2
- data/lib/henitai/mutation_skip_directives.rb +227 -0
- data/lib/henitai/operator.rb +3 -1
- data/lib/henitai/operators/equality_identity_operator.rb +51 -0
- data/lib/henitai/operators/equality_operator.rb +8 -3
- data/lib/henitai/operators.rb +1 -0
- data/lib/henitai/per_test_coverage.rb +66 -0
- data/lib/henitai/per_test_coverage_collector.rb +23 -6
- data/lib/henitai/per_test_coverage_selector.rb +11 -33
- data/lib/henitai/process_worker_runner.rb +48 -334
- data/lib/henitai/reporter/dashboard_metadata_provider.rb +113 -0
- data/lib/henitai/reporter.rb +258 -125
- data/lib/henitai/reports_directory_lock.rb +76 -0
- data/lib/henitai/result.rb +88 -23
- data/lib/henitai/runner.rb +137 -218
- data/lib/henitai/scenario_execution_result.rb +12 -0
- data/lib/henitai/slot_scheduler/draining.rb +146 -0
- data/lib/henitai/slot_scheduler/process_control.rb +43 -0
- data/lib/henitai/slot_scheduler.rb +272 -0
- data/lib/henitai/static_filter.rb +16 -6
- data/lib/henitai/survivor_rerun_strategy.rb +195 -0
- data/lib/henitai/survivor_test_filter.rb +1 -1
- data/lib/henitai/test_prioritizer.rb +28 -2
- data/lib/henitai/timeout_calibrator.rb +44 -0
- data/lib/henitai/unparse_helper.rb +5 -2
- data/lib/henitai/verdict_fingerprint.rb +155 -0
- data/lib/henitai/version.rb +1 -1
- data/lib/henitai.rb +16 -1
- data/sig/configuration_validator.rbs +46 -22
- data/sig/henitai.rbs +386 -96
- metadata +45 -3
- data/lib/henitai/parallel_execution_runner.rb +0 -153
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: henitai
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Martin Otten
|
|
@@ -103,26 +103,59 @@ files:
|
|
|
103
103
|
- lib/henitai.rb
|
|
104
104
|
- lib/henitai/arid_node_filter.rb
|
|
105
105
|
- lib/henitai/available_cpu_count.rb
|
|
106
|
+
- lib/henitai/canonical_report_merger.rb
|
|
107
|
+
- lib/henitai/canonical_report_writer.rb
|
|
108
|
+
- lib/henitai/checkpoint_reporter.rb
|
|
106
109
|
- lib/henitai/cli.rb
|
|
110
|
+
- lib/henitai/cli/clean_command.rb
|
|
111
|
+
- lib/henitai/cli/command_support.rb
|
|
112
|
+
- lib/henitai/cli/init_command.rb
|
|
113
|
+
- lib/henitai/cli/operator_command.rb
|
|
114
|
+
- lib/henitai/cli/options.rb
|
|
115
|
+
- lib/henitai/cli/run_command.rb
|
|
116
|
+
- lib/henitai/cli/run_options.rb
|
|
117
|
+
- lib/henitai/composite_progress_reporter.rb
|
|
107
118
|
- lib/henitai/configuration.rb
|
|
108
119
|
- lib/henitai/configuration_validator.rb
|
|
120
|
+
- lib/henitai/configuration_validator/rules.rb
|
|
121
|
+
- lib/henitai/configuration_validator/scalars.rb
|
|
109
122
|
- lib/henitai/coverage_bootstrapper.rb
|
|
110
123
|
- lib/henitai/coverage_formatter.rb
|
|
111
124
|
- lib/henitai/coverage_report_reader.rb
|
|
112
125
|
- lib/henitai/eager_load.rb
|
|
113
126
|
- lib/henitai/equivalence_detector.rb
|
|
114
127
|
- lib/henitai/execution_engine.rb
|
|
128
|
+
- lib/henitai/execution_engine/env_scope.rb
|
|
129
|
+
- lib/henitai/generated_artifacts.rb
|
|
115
130
|
- lib/henitai/git_diff_analyzer.rb
|
|
131
|
+
- lib/henitai/incremental_filter.rb
|
|
116
132
|
- lib/henitai/integration.rb
|
|
133
|
+
- lib/henitai/integration/base.rb
|
|
134
|
+
- lib/henitai/integration/child_debug_support.rb
|
|
135
|
+
- lib/henitai/integration/child_runtime_control.rb
|
|
136
|
+
- lib/henitai/integration/coverage_suppression.rb
|
|
137
|
+
- lib/henitai/integration/minitest.rb
|
|
138
|
+
- lib/henitai/integration/minitest_load_path.rb
|
|
139
|
+
- lib/henitai/integration/minitest_suite_command.rb
|
|
140
|
+
- lib/henitai/integration/minitest_test_runner.rb
|
|
141
|
+
- lib/henitai/integration/mutant_run_support.rb
|
|
142
|
+
- lib/henitai/integration/rails_environment_preloader.rb
|
|
143
|
+
- lib/henitai/integration/rspec_child_runner.rb
|
|
117
144
|
- lib/henitai/integration/rspec_process_runner.rb
|
|
145
|
+
- lib/henitai/integration/rspec_test_selection.rb
|
|
146
|
+
- lib/henitai/integration/scenario_log_support.rb
|
|
118
147
|
- lib/henitai/minitest_coverage_hook.rb
|
|
119
148
|
- lib/henitai/minitest_coverage_reporter.rb
|
|
120
149
|
- lib/henitai/minitest_simplecov.rb
|
|
121
150
|
- lib/henitai/mutant.rb
|
|
122
151
|
- lib/henitai/mutant/activator.rb
|
|
152
|
+
- lib/henitai/mutant/parameter_source.rb
|
|
123
153
|
- lib/henitai/mutant_generator.rb
|
|
124
154
|
- lib/henitai/mutant_history_store.rb
|
|
155
|
+
- lib/henitai/mutant_history_store/sql.rb
|
|
156
|
+
- lib/henitai/mutant_history_store/verdict_cache.rb
|
|
125
157
|
- lib/henitai/mutant_identity.rb
|
|
158
|
+
- lib/henitai/mutation_skip_directives.rb
|
|
126
159
|
- lib/henitai/operator.rb
|
|
127
160
|
- lib/henitai/operators.rb
|
|
128
161
|
- lib/henitai/operators/arithmetic_operator.rb
|
|
@@ -131,6 +164,7 @@ files:
|
|
|
131
164
|
- lib/henitai/operators/block_statement.rb
|
|
132
165
|
- lib/henitai/operators/boolean_literal.rb
|
|
133
166
|
- lib/henitai/operators/conditional_expression.rb
|
|
167
|
+
- lib/henitai/operators/equality_identity_operator.rb
|
|
134
168
|
- lib/henitai/operators/equality_operator.rb
|
|
135
169
|
- lib/henitai/operators/hash_literal.rb
|
|
136
170
|
- lib/henitai/operators/logical_operator.rb
|
|
@@ -144,18 +178,23 @@ files:
|
|
|
144
178
|
- lib/henitai/operators/string_literal.rb
|
|
145
179
|
- lib/henitai/operators/unary_operator.rb
|
|
146
180
|
- lib/henitai/operators/update_operator.rb
|
|
147
|
-
- lib/henitai/parallel_execution_runner.rb
|
|
148
181
|
- lib/henitai/parser_current.rb
|
|
182
|
+
- lib/henitai/per_test_coverage.rb
|
|
149
183
|
- lib/henitai/per_test_coverage_collector.rb
|
|
150
184
|
- lib/henitai/per_test_coverage_selector.rb
|
|
151
185
|
- lib/henitai/process_wakeup.rb
|
|
152
186
|
- lib/henitai/process_worker_runner.rb
|
|
153
187
|
- lib/henitai/reporter.rb
|
|
188
|
+
- lib/henitai/reporter/dashboard_metadata_provider.rb
|
|
189
|
+
- lib/henitai/reports_directory_lock.rb
|
|
154
190
|
- lib/henitai/result.rb
|
|
155
191
|
- lib/henitai/rspec_coverage_formatter.rb
|
|
156
192
|
- lib/henitai/runner.rb
|
|
157
193
|
- lib/henitai/sampling_strategy.rb
|
|
158
194
|
- lib/henitai/scenario_execution_result.rb
|
|
195
|
+
- lib/henitai/slot_scheduler.rb
|
|
196
|
+
- lib/henitai/slot_scheduler/draining.rb
|
|
197
|
+
- lib/henitai/slot_scheduler/process_control.rb
|
|
159
198
|
- lib/henitai/source_parser.rb
|
|
160
199
|
- lib/henitai/static_filter.rb
|
|
161
200
|
- lib/henitai/stillborn_filter.rb
|
|
@@ -163,11 +202,14 @@ files:
|
|
|
163
202
|
- lib/henitai/subject_resolver.rb
|
|
164
203
|
- lib/henitai/survivor_activation_cache.rb
|
|
165
204
|
- lib/henitai/survivor_loader.rb
|
|
205
|
+
- lib/henitai/survivor_rerun_strategy.rb
|
|
166
206
|
- lib/henitai/survivor_selector.rb
|
|
167
207
|
- lib/henitai/survivor_test_filter.rb
|
|
168
208
|
- lib/henitai/syntax_validator.rb
|
|
169
209
|
- lib/henitai/test_prioritizer.rb
|
|
210
|
+
- lib/henitai/timeout_calibrator.rb
|
|
170
211
|
- lib/henitai/unparse_helper.rb
|
|
212
|
+
- lib/henitai/verdict_fingerprint.rb
|
|
171
213
|
- lib/henitai/version.rb
|
|
172
214
|
- lib/henitai/warning_silencer.rb
|
|
173
215
|
- sig/configuration_validator.rbs
|
|
@@ -181,7 +223,7 @@ metadata:
|
|
|
181
223
|
changelog_uri: https://github.com/martinotten/henitai/blob/main/CHANGELOG.md
|
|
182
224
|
documentation_uri: https://github.com/martinotten/henitai/blob/main/README.md
|
|
183
225
|
homepage_uri: https://github.com/martinotten/henitai
|
|
184
|
-
source_code_uri: https://github.com/martinotten/henitai/tree/v0.
|
|
226
|
+
source_code_uri: https://github.com/martinotten/henitai/tree/v0.3.0
|
|
185
227
|
rubygems_mfa_required: 'true'
|
|
186
228
|
rdoc_options: []
|
|
187
229
|
require_paths:
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Henitai
|
|
4
|
-
# Runs pending mutants across worker threads with signal and stdin handling.
|
|
5
|
-
class ParallelExecutionRunner
|
|
6
|
-
ParallelExecutionContext = Struct.new(
|
|
7
|
-
:queue, :integration, :config, :progress_reporter,
|
|
8
|
-
:mutex, :state, :old_handlers, :stdin_watcher
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
def initialize(worker_count:)
|
|
12
|
-
@worker_count = worker_count
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def run(mutants, integration, config, progress_reporter, options = {})
|
|
16
|
-
context = build_parallel_context(
|
|
17
|
-
mutants,
|
|
18
|
-
integration,
|
|
19
|
-
config,
|
|
20
|
-
progress_reporter
|
|
21
|
-
)
|
|
22
|
-
execute_parallel_execution(
|
|
23
|
-
context,
|
|
24
|
-
stdin_pipe: options.fetch(:stdin_pipe, false),
|
|
25
|
-
process_mutant: options.fetch(:process_mutant)
|
|
26
|
-
)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def execute_parallel_execution(context, stdin_pipe:, process_mutant:)
|
|
30
|
-
install_parallel_signal_traps(context)
|
|
31
|
-
start_parallel_stdin_watcher(context, stdin_pipe)
|
|
32
|
-
parallel_workers(context, process_mutant).each(&:join)
|
|
33
|
-
ensure
|
|
34
|
-
teardown_parallel_execution(context)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
attr_reader :worker_count
|
|
40
|
-
|
|
41
|
-
def teardown_parallel_execution(context)
|
|
42
|
-
stop_parallel_stdin_watcher(context)
|
|
43
|
-
restore_parallel_signal_traps(context)
|
|
44
|
-
emit_scheduler_diagnostics if Integration::SchedulerDiagnostics.enabled?
|
|
45
|
-
raise context.state[:error] if context&.state&.fetch(:error, nil)
|
|
46
|
-
raise Interrupt if context&.state&.fetch(:stopping, false)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def emit_scheduler_diagnostics
|
|
50
|
-
summary = Integration::SchedulerDiagnostics.summary
|
|
51
|
-
warn "[henitai-scheduler] max_concurrent_children=#{summary[:max_concurrent]}"
|
|
52
|
-
warn "[henitai-scheduler] child_intervals=#{summary[:intervals].inspect}"
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def build_parallel_queue(mutants)
|
|
56
|
-
Queue.new.tap { |queue| mutants.each { |mutant| queue << mutant } }
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def build_parallel_context(mutants, integration, config, progress_reporter)
|
|
60
|
-
ParallelExecutionContext.new(
|
|
61
|
-
build_parallel_queue(mutants),
|
|
62
|
-
integration,
|
|
63
|
-
config,
|
|
64
|
-
progress_reporter,
|
|
65
|
-
Mutex.new,
|
|
66
|
-
{ stopping: false }
|
|
67
|
-
)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def install_parallel_signal_traps(context)
|
|
71
|
-
context.old_handlers = {
|
|
72
|
-
int: trap(:INT) { stop_parallel_execution(context) },
|
|
73
|
-
term: trap(:TERM) { stop_parallel_execution(context) },
|
|
74
|
-
hup: trap(:HUP) { stop_parallel_execution(context) }
|
|
75
|
-
}
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def stop_parallel_execution(context)
|
|
79
|
-
context.state[:stopping] = true
|
|
80
|
-
context.queue.clear
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def start_parallel_stdin_watcher(context, stdin_pipe)
|
|
84
|
-
return unless stdin_pipe
|
|
85
|
-
# CI runners expose stdin as a non-interactive pipe, so EOF there should
|
|
86
|
-
# not be treated as a user disconnect.
|
|
87
|
-
return if ci_environment?
|
|
88
|
-
|
|
89
|
-
context.stdin_watcher = Thread.new do
|
|
90
|
-
$stdin.read
|
|
91
|
-
stop_parallel_execution(context)
|
|
92
|
-
rescue IOError, Errno::EBADF
|
|
93
|
-
nil
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def parallel_workers(context, process_mutant)
|
|
98
|
-
Array.new(worker_count) do
|
|
99
|
-
Thread.new { process_parallel_worker(context, process_mutant) }
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
def process_parallel_worker(context, process_mutant)
|
|
104
|
-
loop do
|
|
105
|
-
break if context.state[:stopping]
|
|
106
|
-
|
|
107
|
-
run_one_mutant(context, process_mutant)
|
|
108
|
-
rescue ThreadError
|
|
109
|
-
break
|
|
110
|
-
rescue StandardError => e
|
|
111
|
-
record_parallel_error(context, e)
|
|
112
|
-
break
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def run_one_mutant(context, process_mutant)
|
|
117
|
-
mutant = context.queue.pop(true)
|
|
118
|
-
process_mutant.call(
|
|
119
|
-
mutant,
|
|
120
|
-
context.integration,
|
|
121
|
-
context.config,
|
|
122
|
-
context.progress_reporter,
|
|
123
|
-
context.mutex
|
|
124
|
-
)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def stop_parallel_stdin_watcher(context)
|
|
128
|
-
context&.stdin_watcher&.kill
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def restore_parallel_signal_traps(context)
|
|
132
|
-
handlers = context&.old_handlers
|
|
133
|
-
return unless handlers
|
|
134
|
-
|
|
135
|
-
trap(:INT, handlers[:int] || "DEFAULT")
|
|
136
|
-
trap(:TERM, handlers[:term] || "DEFAULT")
|
|
137
|
-
trap(:HUP, handlers[:hup] || "DEFAULT")
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def record_parallel_error(context, error)
|
|
141
|
-
context.mutex.synchronize do
|
|
142
|
-
context.state[:error] ||= error
|
|
143
|
-
context.state[:stopping] = true
|
|
144
|
-
context.queue.clear
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def ci_environment?
|
|
149
|
-
value = ENV.fetch("CI", nil)
|
|
150
|
-
value && !%w[0 false].include?(value.downcase)
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
end
|