henitai 0.4.0 → 0.5.1

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +97 -1
  3. data/README.md +1 -1
  4. data/lib/henitai/cli.rb +1 -1
  5. data/lib/henitai/configuration.rb +9 -2
  6. data/lib/henitai/dirty_source_detector.rb +53 -0
  7. data/lib/henitai/equivalence_detector/operand_predicates.rb +49 -0
  8. data/lib/henitai/equivalence_detector.rb +6 -23
  9. data/lib/henitai/excluded_test_filter.rb +47 -0
  10. data/lib/henitai/execution_engine.rb +5 -11
  11. data/lib/henitai/inherited_fd_registry.rb +66 -0
  12. data/lib/henitai/integration/base.rb +7 -2
  13. data/lib/henitai/integration/child_bootstrap.rb +27 -0
  14. data/lib/henitai/integration/child_debug_log.rb +135 -0
  15. data/lib/henitai/integration/child_runtime_control.rb +6 -18
  16. data/lib/henitai/integration/loaded_features.rb +38 -0
  17. data/lib/henitai/integration/mutant_run_support.rb +5 -5
  18. data/lib/henitai/integration/rspec_child_runner.rb +16 -15
  19. data/lib/henitai/integration/rspec_process_runner.rb +7 -2
  20. data/lib/henitai/integration.rb +10 -7
  21. data/lib/henitai/mutation_skip_directives.rb +7 -1
  22. data/lib/henitai/operators/return_value.rb +1 -1
  23. data/lib/henitai/orphan_watchdog.rb +93 -0
  24. data/lib/henitai/process_liveness.rb +41 -0
  25. data/lib/henitai/reports_directory_lock.rb +12 -11
  26. data/lib/henitai/result.rb +30 -3
  27. data/lib/henitai/runner.rb +41 -123
  28. data/lib/henitai/runner_dependencies.rb +75 -0
  29. data/lib/henitai/slot_scheduler/drain_verdict.rb +29 -0
  30. data/lib/henitai/slot_scheduler/draining.rb +7 -17
  31. data/lib/henitai/slot_scheduler/retry_policy.rb +21 -0
  32. data/lib/henitai/slot_scheduler/slot_deadline.rb +37 -0
  33. data/lib/henitai/slot_scheduler/slot_table.rb +75 -0
  34. data/lib/henitai/slot_scheduler/test_file_selection.rb +40 -0
  35. data/lib/henitai/slot_scheduler.rb +68 -80
  36. data/lib/henitai/source_file_selection.rb +76 -0
  37. data/lib/henitai/subject_selection.rb +33 -0
  38. data/lib/henitai/survivor_rerun_strategy.rb +7 -19
  39. data/lib/henitai/version.rb +1 -1
  40. data/lib/henitai.rb +8 -0
  41. data/sig/henitai.rbs +92 -38
  42. metadata +39 -11
  43. data/lib/henitai/integration/child_debug_support.rb +0 -119
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.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Otten
@@ -13,16 +13,22 @@ dependencies:
13
13
  name: minitest
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
17
  - !ruby/object:Gem::Version
18
18
  version: '5.25'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '7'
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
22
25
  requirements:
23
- - - "~>"
26
+ - - ">="
24
27
  - !ruby/object:Gem::Version
25
28
  version: '5.25'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '7'
26
32
  - !ruby/object:Gem::Dependency
27
33
  name: prism
28
34
  requirement: !ruby/object:Gem::Requirement
@@ -55,16 +61,22 @@ dependencies:
55
61
  name: sqlite3
56
62
  requirement: !ruby/object:Gem::Requirement
57
63
  requirements:
58
- - - "~>"
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 2.9.5
67
+ - - "<"
59
68
  - !ruby/object:Gem::Version
60
- version: '1.7'
69
+ version: '3'
61
70
  type: :runtime
62
71
  prerelease: false
63
72
  version_requirements: !ruby/object:Gem::Requirement
64
73
  requirements:
65
- - - "~>"
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 2.9.5
77
+ - - "<"
66
78
  - !ruby/object:Gem::Version
67
- version: '1.7'
79
+ version: '3'
68
80
  - !ruby/object:Gem::Dependency
69
81
  name: unparser
70
82
  requirement: !ruby/object:Gem::Requirement
@@ -80,7 +92,7 @@ dependencies:
80
92
  - !ruby/object:Gem::Version
81
93
  version: '0.6'
82
94
  description: |
83
- Hen'i-tai (変異体) is a mutation testing framework for Ruby 4+.
95
+ Hen'i-tai (変異体) is a mutation testing framework for Ruby 3.3.6+.
84
96
  It produces Stryker-compatible mutation-testing-report-schema JSON,
85
97
  integrates with the Stryker Dashboard, and ships with a standalone
86
98
  HTML report powered by mutation-testing-elements.
@@ -122,18 +134,24 @@ files:
122
134
  - lib/henitai/coverage_bootstrapper.rb
123
135
  - lib/henitai/coverage_formatter.rb
124
136
  - lib/henitai/coverage_report_reader.rb
137
+ - lib/henitai/dirty_source_detector.rb
125
138
  - lib/henitai/eager_load.rb
126
139
  - lib/henitai/equivalence_detector.rb
140
+ - lib/henitai/equivalence_detector/operand_predicates.rb
141
+ - lib/henitai/excluded_test_filter.rb
127
142
  - lib/henitai/execution_engine.rb
128
143
  - lib/henitai/execution_engine/env_scope.rb
129
144
  - lib/henitai/generated_artifacts.rb
130
145
  - lib/henitai/git_diff_analyzer.rb
131
146
  - lib/henitai/incremental_filter.rb
147
+ - lib/henitai/inherited_fd_registry.rb
132
148
  - lib/henitai/integration.rb
133
149
  - lib/henitai/integration/base.rb
134
- - lib/henitai/integration/child_debug_support.rb
150
+ - lib/henitai/integration/child_bootstrap.rb
151
+ - lib/henitai/integration/child_debug_log.rb
135
152
  - lib/henitai/integration/child_runtime_control.rb
136
153
  - lib/henitai/integration/coverage_suppression.rb
154
+ - lib/henitai/integration/loaded_features.rb
137
155
  - lib/henitai/integration/minitest.rb
138
156
  - lib/henitai/integration/minitest_load_path.rb
139
157
  - lib/henitai/integration/minitest_suite_command.rb
@@ -179,10 +197,12 @@ files:
179
197
  - lib/henitai/operators/string_literal.rb
180
198
  - lib/henitai/operators/unary_operator.rb
181
199
  - lib/henitai/operators/update_operator.rb
200
+ - lib/henitai/orphan_watchdog.rb
182
201
  - lib/henitai/parser_current.rb
183
202
  - lib/henitai/per_test_coverage.rb
184
203
  - lib/henitai/per_test_coverage_collector.rb
185
204
  - lib/henitai/per_test_coverage_selector.rb
205
+ - lib/henitai/process_liveness.rb
186
206
  - lib/henitai/process_wakeup.rb
187
207
  - lib/henitai/process_worker_runner.rb
188
208
  - lib/henitai/reporter.rb
@@ -191,16 +211,24 @@ files:
191
211
  - lib/henitai/result.rb
192
212
  - lib/henitai/rspec_coverage_formatter.rb
193
213
  - lib/henitai/runner.rb
214
+ - lib/henitai/runner_dependencies.rb
194
215
  - lib/henitai/sampling_strategy.rb
195
216
  - lib/henitai/scenario_execution_result.rb
196
217
  - lib/henitai/slot_scheduler.rb
218
+ - lib/henitai/slot_scheduler/drain_verdict.rb
197
219
  - lib/henitai/slot_scheduler/draining.rb
198
220
  - lib/henitai/slot_scheduler/process_control.rb
221
+ - lib/henitai/slot_scheduler/retry_policy.rb
222
+ - lib/henitai/slot_scheduler/slot_deadline.rb
223
+ - lib/henitai/slot_scheduler/slot_table.rb
224
+ - lib/henitai/slot_scheduler/test_file_selection.rb
225
+ - lib/henitai/source_file_selection.rb
199
226
  - lib/henitai/source_parser.rb
200
227
  - lib/henitai/static_filter.rb
201
228
  - lib/henitai/stillborn_filter.rb
202
229
  - lib/henitai/subject.rb
203
230
  - lib/henitai/subject_resolver.rb
231
+ - lib/henitai/subject_selection.rb
204
232
  - lib/henitai/survivor_activation_cache.rb
205
233
  - lib/henitai/survivor_loader.rb
206
234
  - lib/henitai/survivor_rerun_strategy.rb
@@ -224,7 +252,7 @@ metadata:
224
252
  changelog_uri: https://github.com/martinotten/henitai/blob/main/CHANGELOG.md
225
253
  documentation_uri: https://github.com/martinotten/henitai/blob/main/README.md
226
254
  homepage_uri: https://github.com/martinotten/henitai
227
- source_code_uri: https://github.com/martinotten/henitai/tree/v0.4.0
255
+ source_code_uri: https://github.com/martinotten/henitai/tree/v0.5.1
228
256
  rubygems_mfa_required: 'true'
229
257
  rdoc_options: []
230
258
  require_paths:
@@ -233,7 +261,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
233
261
  requirements:
234
262
  - - ">="
235
263
  - !ruby/object:Gem::Version
236
- version: 4.0.0
264
+ version: 3.3.6
237
265
  required_rubygems_version: !ruby/object:Gem::Requirement
238
266
  requirements:
239
267
  - - ">="
@@ -1,119 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Henitai
4
- module Integration
5
- # Shared debug helpers for child-run diagnostics.
6
- # Debug helpers are intentionally grouped here so the child-run diagnostics
7
- # stay isolated from the main integration flow.
8
- module ChildDebugSupport
9
- private
10
-
11
- def debug_child? = ENV["HENITAI_DEBUG_CHILD"] == "1"
12
-
13
- # Gated here (not only at call sites) so no unguarded caller can leak
14
- # debug lines into every child log by default.
15
- def debug_child_puts(message)
16
- return unless debug_child?
17
-
18
- $stdout.puts(message)
19
- $stdout.flush
20
- end
21
-
22
- def debug_child_rspec_trace(test_files:, rspec_options:, rspec_argv:)
23
- return unless debug_child?
24
-
25
- files_exist = test_files.map { |f| [f, File.exist?(f)] }.inspect
26
- loaded_features = loaded_feature_map(test_files).inspect # steep:ignore Ruby::NoMethod
27
-
28
- debug_child_puts(
29
- "[henitai-debug-child] cwd=#{Dir.pwd}\n" \
30
- "[henitai-debug-child] files_exist=#{files_exist}\n" \
31
- "[henitai-debug-child] loaded_features_check=#{loaded_features}\n" \
32
- "[henitai-debug-child] test_files=#{test_files.inspect}\n" \
33
- "[henitai-debug-child] rspec_options=#{rspec_options.inspect}\n" \
34
- "[henitai-debug-child] rspec_argv=#{rspec_argv.inspect}"
35
- )
36
- end
37
-
38
- def debug_child_rspec_exit(status)
39
- return unless debug_child?
40
-
41
- debug_child_puts("[henitai-debug-child] RSpec result=#{status.inspect}")
42
- end
43
-
44
- def debug_child_example_count(stage) # steep:ignore Ruby::UndeclaredMethodDefinition
45
- return unless debug_child?
46
-
47
- count = rspec_world_example_count
48
- debug_child_puts(
49
- "[henitai-debug-child] rspec_world_example_count_#{stage}=#{count.inspect}"
50
- )
51
- end
52
-
53
- def debug_child_activation_start(mutant_id)
54
- return unless debug_child?
55
-
56
- debug_child_puts("[henitai-debug-child] activate_start mutant=#{mutant_id}")
57
- end
58
-
59
- def debug_child_activation_end(activation_result, test_files:)
60
- return unless debug_child?
61
-
62
- debug_child_puts(
63
- "[henitai-debug-child] activate_end result=#{activation_result.inspect}\n" \
64
- "[henitai-debug-child] run_tests_start test_files=#{test_files.inspect}"
65
- )
66
- end
67
-
68
- def debug_child_mutant_meta(mutant)
69
- stable_id = mutant.respond_to?(:stable_id) ? mutant.stable_id : nil
70
- operator = mutant.respond_to?(:operator) ? mutant.operator : nil
71
- has_subject_expression =
72
- mutant.respond_to?(:subject) && mutant.subject.respond_to?(:expression)
73
- subject_expression = has_subject_expression ? mutant.subject.expression : nil
74
- location = mutant.respond_to?(:location) ? mutant.location.inspect : nil
75
-
76
- debug_child_puts(
77
- "[henitai-debug-child] mutant_meta stableId=#{stable_id}\n" \
78
- "[henitai-debug-child] mutant_meta operator=#{operator}\n" \
79
- "[henitai-debug-child] mutant_meta subject=#{subject_expression}\n" \
80
- "[henitai-debug-child] mutant_meta location=#{location}\n"
81
- )
82
- end
83
-
84
- def debug_child_activation_check
85
- location = begin
86
- Henitai::Runner.instance_method(:resolve_subjects).source_location&.join(":") # henitai:disable
87
- rescue StandardError
88
- nil
89
- end
90
-
91
- debug_child_puts(
92
- "[henitai-debug-child] activation_check resolve_subjects_location=#{location}\n"
93
- )
94
- end
95
-
96
- def loaded_feature_map(test_files) = test_files.map { |file| [file, loaded_feature?(file)] } # steep:ignore Ruby::UndeclaredMethodDefinition
97
-
98
- def loaded_feature?(file) # steep:ignore Ruby::UndeclaredMethodDefinition
99
- expanded = File.expand_path(file)
100
- candidates = [expanded, "#{expanded}.rb", file, "#{file}.rb"].uniq
101
- $LOADED_FEATURES.any? do |feature|
102
- normalized = begin
103
- File.expand_path(feature)
104
- rescue StandardError
105
- feature
106
- end
107
- candidates.include?(feature) || candidates.include?(normalized)
108
- end
109
- end
110
-
111
- def rspec_world_example_count # steep:ignore Ruby::UndeclaredMethodDefinition
112
- world = ::RSpec.world
113
- world.example_count
114
- rescue StandardError
115
- nil
116
- end
117
- end
118
- end
119
- end