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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +105 -1
  3. data/README.md +138 -5
  4. data/assets/schema/henitai.schema.json +41 -0
  5. data/lib/henitai/available_cpu_count.rb +16 -23
  6. data/lib/henitai/canonical_report_merger.rb +107 -0
  7. data/lib/henitai/canonical_report_writer.rb +22 -0
  8. data/lib/henitai/checkpoint_reporter.rb +79 -0
  9. data/lib/henitai/cli/clean_command.rb +54 -0
  10. data/lib/henitai/cli/command_support.rb +52 -0
  11. data/lib/henitai/cli/init_command.rb +64 -0
  12. data/lib/henitai/cli/operator_command.rb +96 -0
  13. data/lib/henitai/cli/options.rb +84 -0
  14. data/lib/henitai/cli/run_command.rb +136 -0
  15. data/lib/henitai/cli/run_options.rb +108 -0
  16. data/lib/henitai/cli.rb +27 -407
  17. data/lib/henitai/composite_progress_reporter.rb +42 -0
  18. data/lib/henitai/configuration.rb +42 -9
  19. data/lib/henitai/configuration_validator/rules.rb +161 -0
  20. data/lib/henitai/configuration_validator/scalars.rb +169 -0
  21. data/lib/henitai/configuration_validator.rb +20 -240
  22. data/lib/henitai/coverage_bootstrapper.rb +54 -5
  23. data/lib/henitai/coverage_formatter.rb +5 -1
  24. data/lib/henitai/coverage_report_reader.rb +28 -5
  25. data/lib/henitai/eager_load.rb +36 -5
  26. data/lib/henitai/execution_engine/env_scope.rb +67 -0
  27. data/lib/henitai/execution_engine.rb +115 -53
  28. data/lib/henitai/generated_artifacts.rb +58 -0
  29. data/lib/henitai/incremental_filter.rb +100 -0
  30. data/lib/henitai/integration/base.rb +171 -0
  31. data/lib/henitai/integration/child_debug_support.rb +119 -0
  32. data/lib/henitai/integration/child_runtime_control.rb +50 -0
  33. data/lib/henitai/integration/coverage_suppression.rb +52 -0
  34. data/lib/henitai/integration/minitest.rb +101 -0
  35. data/lib/henitai/integration/minitest_load_path.rb +14 -0
  36. data/lib/henitai/integration/minitest_suite_command.rb +17 -0
  37. data/lib/henitai/integration/minitest_test_runner.rb +39 -0
  38. data/lib/henitai/integration/mutant_run_support.rb +77 -0
  39. data/lib/henitai/integration/rails_environment_preloader.rb +14 -0
  40. data/lib/henitai/integration/rspec_child_runner.rb +61 -0
  41. data/lib/henitai/integration/rspec_test_selection.rb +138 -0
  42. data/lib/henitai/integration/scenario_log_support.rb +160 -0
  43. data/lib/henitai/integration.rb +22 -846
  44. data/lib/henitai/minitest_coverage_reporter.rb +4 -1
  45. data/lib/henitai/mutant/activator.rb +15 -79
  46. data/lib/henitai/mutant/parameter_source.rb +98 -0
  47. data/lib/henitai/mutant.rb +14 -6
  48. data/lib/henitai/mutant_history_store/sql.rb +90 -0
  49. data/lib/henitai/mutant_history_store/verdict_cache.rb +84 -0
  50. data/lib/henitai/mutant_history_store.rb +67 -81
  51. data/lib/henitai/mutant_identity.rb +33 -2
  52. data/lib/henitai/mutation_skip_directives.rb +227 -0
  53. data/lib/henitai/operator.rb +3 -1
  54. data/lib/henitai/operators/equality_identity_operator.rb +51 -0
  55. data/lib/henitai/operators/equality_operator.rb +8 -3
  56. data/lib/henitai/operators.rb +1 -0
  57. data/lib/henitai/per_test_coverage.rb +66 -0
  58. data/lib/henitai/per_test_coverage_collector.rb +23 -6
  59. data/lib/henitai/per_test_coverage_selector.rb +11 -33
  60. data/lib/henitai/process_worker_runner.rb +48 -334
  61. data/lib/henitai/reporter/dashboard_metadata_provider.rb +113 -0
  62. data/lib/henitai/reporter.rb +258 -125
  63. data/lib/henitai/reports_directory_lock.rb +76 -0
  64. data/lib/henitai/result.rb +88 -23
  65. data/lib/henitai/runner.rb +137 -218
  66. data/lib/henitai/scenario_execution_result.rb +12 -0
  67. data/lib/henitai/slot_scheduler/draining.rb +146 -0
  68. data/lib/henitai/slot_scheduler/process_control.rb +43 -0
  69. data/lib/henitai/slot_scheduler.rb +272 -0
  70. data/lib/henitai/static_filter.rb +16 -6
  71. data/lib/henitai/survivor_rerun_strategy.rb +195 -0
  72. data/lib/henitai/survivor_test_filter.rb +1 -1
  73. data/lib/henitai/test_prioritizer.rb +28 -2
  74. data/lib/henitai/timeout_calibrator.rb +44 -0
  75. data/lib/henitai/unparse_helper.rb +5 -2
  76. data/lib/henitai/verdict_fingerprint.rb +155 -0
  77. data/lib/henitai/version.rb +1 -1
  78. data/lib/henitai.rb +16 -1
  79. data/sig/configuration_validator.rbs +46 -22
  80. data/sig/henitai.rbs +386 -96
  81. metadata +45 -3
  82. data/lib/henitai/parallel_execution_runner.rb +0 -153
data/sig/henitai.rbs CHANGED
@@ -67,6 +67,9 @@ module Henitai
67
67
  class CoverageError < StandardError
68
68
  end
69
69
 
70
+ class ConcurrentRunError < StandardError
71
+ end
72
+
70
73
  class GitDiffError < StandardError
71
74
  end
72
75
 
@@ -76,14 +79,6 @@ module Henitai
76
79
  module Integration::ChildDebugSupport
77
80
  private
78
81
 
79
- def run_rspec_runner: (Array[String]) -> untyped
80
- def build_rspec_runner: () -> untyped
81
- def configure_rspec_runner: (untyped) -> void
82
- def load_rspec_spec_files: (Array[String]) -> void
83
- def run_rspec_specs: (untyped) -> untyped
84
- def debug_child_timeout_dump: (Integer) -> void
85
- def install_debug_timeout_trap: () -> void
86
- def debug_child_thread_dump: (String) -> void
87
82
  def debug_child_puts: (String) -> void
88
83
  def debug_child?: () -> bool
89
84
  def debug_child_rspec_trace: (
@@ -97,20 +92,66 @@ module Henitai
97
92
  def debug_child_activation_end: (untyped, test_files: Array[String]) -> void
98
93
  def debug_child_mutant_meta: (Mutant) -> void
99
94
  def debug_child_activation_check: () -> void
100
- def suppress_simplecov!: () -> void
101
- def suppress_coverage!: () -> void
102
95
  def loaded_feature_map: (Array[String]) -> Array[[String, bool]]
103
96
  def loaded_feature?: (String) -> bool
104
97
  def rspec_world_example_count: () -> Integer?
105
98
  def pause: (Float) -> void
106
99
  end
107
100
 
101
+ module Integration::ChildRuntimeControl
102
+ private
103
+
104
+ def suppress_simplecov!: () -> void
105
+ def suppress_coverage!: () -> void
106
+ def debug_child_timeout_dump: (Integer) -> void
107
+ def install_debug_timeout_trap: () -> void
108
+ def debug_child_thread_dump: (String) -> void
109
+ end
110
+
111
+ module Integration::RspecChildRunner
112
+ private
113
+
114
+ def run_rspec_runner: (Array[String]) -> untyped
115
+ def build_rspec_runner: () -> untyped
116
+ def configure_rspec_runner: (untyped) -> void
117
+ def load_rspec_spec_files: (Array[String]) -> void
118
+ def run_rspec_specs: (untyped) -> untyped
119
+ end
120
+
121
+ module Integration::RspecTestSelection
122
+ REQUIRE_DIRECTIVE_PATTERN: Regexp
123
+
124
+ def select_tests: (Subject) -> Array[String]
125
+
126
+ private
127
+
128
+ def spec_files: () -> Array[String]
129
+ def fallback_spec_files: (Subject) -> Array[String]
130
+ def excluded_spec_files: () -> Array[String]
131
+ def rspec_exclude_patterns: () -> Array[String]
132
+ def rspec_config_lines: () -> Array[String]
133
+ def rspec_config_path: () -> String
134
+ def selection_patterns: (Subject) -> Array[String]
135
+ def requires_source_file?: (String, String) -> bool
136
+ def requires_source_file_transitively?: (String, String, ?Array[String]) -> bool
137
+ def required_files: (String) -> Array[String]
138
+ def resolve_required_file: (String, String, String) -> String?
139
+ def relative_candidates: (String, String) -> Array[String]
140
+ def require_candidates: (String, String) -> Array[String]
141
+ def expand_candidates: (String, String) -> Array[String]
142
+ end
143
+
108
144
  class Configuration
109
145
  DEFAULT_TIMEOUT: Float
146
+ DEFAULT_TIMEOUT_MULTIPLIER: Float
110
147
  DEFAULT_OPERATORS: Symbol
111
148
  DEFAULT_JOBS: untyped
112
149
  DEFAULT_MAX_MUTANTS_PER_LINE: Integer
113
150
  DEFAULT_MAX_FLAKY_RETRIES: Integer
151
+ DEFAULT_MAX_LOG_BYTES: Integer
152
+ DEFAULT_MAX_TIMEOUT: Float
153
+ DEFAULT_CHECKPOINT_EVERY: Integer
154
+ DEFAULT_CHECKPOINT_INTERVAL: Float
114
155
  DEFAULT_REPORTS_DIR: String
115
156
  DEFAULT_COVERAGE_CRITERIA: Hash[Symbol, bool]
116
157
  DEFAULT_THRESHOLDS: Hash[Symbol, Integer]
@@ -118,22 +159,31 @@ module Henitai
118
159
 
119
160
  attr_reader integration: untyped
120
161
  attr_reader includes: Array[String]
162
+ attr_reader excludes: Array[String]
163
+ attr_reader test_excludes: Array[String]
121
164
  attr_reader operators: Symbol
122
165
  attr_reader timeout: Float
166
+ attr_reader timeout_multiplier: Float
123
167
  attr_reader ignore_patterns: Array[untyped]
124
168
  attr_reader max_mutants_per_line: Integer
125
169
  attr_reader max_flaky_retries: Integer
170
+ attr_reader max_log_bytes: Integer
171
+ attr_reader max_timeout: Float
126
172
  attr_reader sampling: untyped
127
173
  attr_reader jobs: untyped
128
174
  attr_reader coverage_criteria: Hash[Symbol, untyped]
129
175
  attr_reader thresholds: Hash[Symbol, Integer]
130
176
  attr_reader reporters: Array[String]
131
177
  attr_reader reports_dir: String
178
+ attr_reader checkpoint_enabled: bool
179
+ attr_reader checkpoint_every: Integer
180
+ attr_reader checkpoint_interval: Float
132
181
  attr_reader dashboard: Hash[Symbol, untyped]
133
182
  attr_reader all_logs: bool
134
183
 
135
184
  def self.load: (?path: String, ?overrides: Hash[Symbol, untyped]) -> Configuration
136
185
  def initialize: (?path: String, ?overrides: Hash[Symbol, untyped]) -> void
186
+ def timeout_configured?: () -> bool
137
187
 
138
188
  private
139
189
 
@@ -142,6 +192,8 @@ module Henitai
142
192
  def apply_defaults: (Hash[Symbol, untyped]) -> void
143
193
  def apply_general_defaults: (Hash[Symbol, untyped]) -> void
144
194
  def apply_mutation_defaults: (Hash[Symbol, untyped]) -> void
195
+ def apply_mutation_limit_defaults: (Hash[Symbol, untyped]) -> void
196
+ def apply_reports_defaults: (Hash[Symbol, untyped]) -> void
145
197
  def apply_analysis_defaults: (Hash[Symbol, untyped]) -> void
146
198
  def merge_defaults: (Hash[Symbol, untyped], Hash[Symbol, untyped]?) -> Hash[Symbol, untyped]
147
199
  def resolve_integration_default: (untyped) -> untyped
@@ -191,6 +243,8 @@ module Henitai
191
243
  end
192
244
 
193
245
  class Mutant
246
+ include UnparseHelper
247
+
194
248
  STATUSES: Array[Symbol]
195
249
 
196
250
  attr_reader id: String
@@ -206,11 +260,15 @@ module Henitai
206
260
  attr_accessor duration: Float?
207
261
  attr_accessor covered_by: Array[String]?
208
262
  attr_accessor tests_completed: Integer?
263
+ attr_accessor ignore_reason: String?
264
+ attr_accessor from_cache: bool
209
265
  attr_reader precomputed_stable_id: String?
210
266
  attr_reader precomputed_activation_source: String?
211
267
 
212
268
  def initialize: (subject: Subject, operator: String, nodes: Hash[Symbol, untyped], description: String, location: Hash[Symbol, untyped], ?precomputed_stable_id: String?, ?precomputed_activation_source: String?) -> void
213
269
  def stable_id: () -> String
270
+ def mutated_source: () -> String
271
+ def from_cache?: () -> bool
214
272
  def killed?: () -> bool
215
273
  def survived?: () -> bool
216
274
  def pending?: () -> bool
@@ -229,7 +287,7 @@ module Henitai
229
287
  REPORT_FILE_NAME: String
230
288
 
231
289
  def initialize: () -> void
232
- def record_test: (String) -> void
290
+ def record_test: (String, ?duration: Float?) -> void
233
291
  def write_report: () -> void
234
292
 
235
293
  private
@@ -270,9 +328,26 @@ module Henitai
270
328
  def sample: (Array[Mutant], ratio: Float, ?strategy: Symbol) -> Array[Mutant]
271
329
  end
272
330
 
331
+ class TimeoutCalibrator
332
+ FLOOR_SECONDS: Float
333
+
334
+ def initialize: (timing_source: untyped, multiplier: untyped) -> void
335
+ def timeout_for: (untyped) -> Float?
336
+
337
+ private
338
+
339
+ def durations: () -> Hash[String, untyped]
340
+ def normalize: (untyped) -> String
341
+ end
342
+
273
343
  class TestPrioritizer
274
- def initialize: () -> void
344
+ def initialize: (?timing_source: untyped?) -> void
275
345
  def sort: (Array[String], untyped, Hash[untyped, untyped]) -> Array[String]
346
+
347
+ private
348
+
349
+ def runtime: (untyped) -> Float
350
+ def timing_durations: () -> Hash[String, untyped]
276
351
  end
277
352
 
278
353
  class Operator
@@ -295,6 +370,7 @@ module Henitai
295
370
 
296
371
  class Base
297
372
  include ChildDebugSupport
373
+ include ChildRuntimeControl
298
374
 
299
375
  def select_tests: (Subject) -> Array[String]
300
376
  def test_files: () -> Array[String]
@@ -314,7 +390,6 @@ module Henitai
314
390
  def cleanup_child_process: (Integer) -> void
315
391
  def suppress_simplecov!: () -> void
316
392
  def suppress_coverage!: () -> void
317
- def run_tests: (Array[String]) -> Integer
318
393
  def debug_child?: () -> bool
319
394
  def debug_child_puts: (String) -> void
320
395
  def debug_child_rspec_trace: (test_files: Array[String], rspec_options: Array[String], rspec_argv: Array[String]) -> void
@@ -327,13 +402,24 @@ module Henitai
327
402
  def loaded_feature_map: (Array[String]) -> Array[[String, bool]]
328
403
  def loaded_feature?: (String) -> bool
329
404
  def rspec_world_example_count: () -> Integer?
330
- def run_child_activation_and_tests: (mutant: Mutant, test_files: Array[String], log_paths: Hash[Symbol, String]) -> Integer
331
405
  def with_non_interactive_stdin: () { () -> untyped } -> untyped
332
406
  def subprocess_env: () -> Hash[String, String]
333
407
  def scenario_log_support: () -> ScenarioLogSupport
334
408
  def with_subprocess_env: () { () -> untyped } -> untyped
335
409
  def restore_subprocess_env: (Hash[String, String?]) -> void
336
- def spawn_suite_process: (Array[String], Hash[Symbol, String]) -> Integer
410
+ end
411
+
412
+ module MutantRunSupport
413
+ def spawn_mutant: (mutant: Mutant, test_files: Array[String]) -> ChildHandle
414
+ def run_mutant: (mutant: Mutant, test_files: Array[String], timeout: Float) -> ScenarioExecutionResult
415
+ def scenario_log_paths: (String) -> Hash[Symbol, String]
416
+ def build_result: (untyped, Hash[Symbol, String]) -> ScenarioExecutionResult
417
+ def run_in_child: (mutant: Mutant, test_files: Array[String], log_paths: Hash[Symbol, String]) -> Integer
418
+ def mutant_log_name: (Mutant) -> String
419
+
420
+ private
421
+
422
+ def run_child_activation_and_tests: (mutant: Mutant, test_files: Array[String], log_paths: Hash[Symbol, String]) -> Integer
337
423
  end
338
424
 
339
425
  class ScenarioLogSupport
@@ -374,58 +460,28 @@ module Henitai
374
460
  end
375
461
 
376
462
  class RspecProcessRunner
377
- def run_mutant: (Rspec, mutant: Mutant, test_files: Array[String], timeout: Float) -> ScenarioExecutionResult
378
- def run_suite: (Rspec, Array[String], timeout: Float) -> ScenarioExecutionResult
379
- def spawn_mutant: (Rspec, mutant: Mutant, test_files: Array[String], log_paths: Hash[Symbol, String]) -> ChildHandle
463
+ def run_mutant: (Base, mutant: Mutant, test_files: Array[String], timeout: Float) -> ScenarioExecutionResult
464
+ def run_suite: (Base, Array[String], timeout: Float) -> ScenarioExecutionResult
465
+ def spawn_mutant: (Base, mutant: Mutant, test_files: Array[String], log_paths: Hash[Symbol, String]) -> ChildHandle
380
466
  end
381
467
 
382
468
  class Rspec < Base
383
- REQUIRE_DIRECTIVE_PATTERN: Regexp
469
+ include MutantRunSupport
470
+ include RspecChildRunner
471
+ include RspecTestSelection
472
+
384
473
  DEFAULT_SUITE_TIMEOUT: Float
385
474
 
386
- def select_tests: (Subject) -> Array[String]
387
475
  def test_files: () -> Array[String]
388
- def run_mutant: (mutant: Mutant, test_files: Array[String], timeout: Float) -> ScenarioExecutionResult
389
- def spawn_mutant: (mutant: Mutant, test_files: Array[String]) -> ChildHandle
390
476
  def run_suite: (Array[String], ?timeout: Float) -> ScenarioExecutionResult
391
477
  def per_test_coverage_supported?: () -> bool
478
+ def suite_command: (Array[String]) -> Array[String]
479
+ def rspec_suite_runner_script: () -> String
480
+ def spawn_suite_process: (Array[String], Hash[Symbol, String]) -> Integer
392
481
 
393
482
  private
394
483
 
395
- def mutant_log_name: (Mutant) -> String
396
- def run_in_child: (mutant: Mutant, test_files: Array[String], log_paths: Hash[Symbol, String]) -> Integer
397
- def suppress_simplecov!: () -> void
398
- def suppress_coverage!: () -> void
399
- def install_debug_timeout_trap: () -> void
400
- def debug_child_thread_dump: (String) -> void
401
- def debug_child_example_count: (String) -> void
402
- def suite_command: (Array[String]) -> Array[String]
403
- def rspec_suite_runner_script: () -> String
404
- def build_result: (untyped, Hash[Symbol, String]) -> ScenarioExecutionResult
405
- def scenario_status: (untyped) -> Symbol
406
- def exit_status_for: (untyped) -> Integer?
407
- def read_log_file: (String) -> String
408
- def write_combined_log: (String, String, String) -> void
409
- def combined_log: (String, String) -> String
410
- def scenario_log_paths: (String) -> Hash[Symbol, String]
411
484
  def run_tests: (Array[String]) -> Integer
412
- def with_subprocess_env: () { () -> untyped } -> untyped
413
- def spec_files: () -> Array[String]
414
- def fallback_spec_files: (Subject) -> Array[String]
415
- def excluded_spec_files: () -> Array[String]
416
- def rspec_exclude_patterns: () -> Array[String]
417
- def rspec_config_lines: () -> Array[String]
418
- def rspec_config_path: () -> String
419
- def selection_patterns: (Subject) -> Array[String]
420
- def requires_source_file?: (String, String) -> bool
421
- def requires_source_file_transitively?: (String, String, ?Array[String]) -> bool
422
- def required_files: (String) -> Array[String]
423
- def resolve_required_file: (String, String, String) -> String?
424
- def loaded_feature_map: (Array[String]) -> Array[[String, bool]]
425
- def loaded_feature?: (String) -> bool
426
- def relative_candidates: (String, String) -> Array[String]
427
- def require_candidates: (String, String) -> Array[String]
428
- def expand_candidates: (String, String) -> Array[String]
429
485
  end
430
486
 
431
487
  module CoverageRuntimeSuppressors
@@ -441,20 +497,28 @@ module Henitai
441
497
  def start: (*untyped) -> nil
442
498
  end
443
499
 
444
- class Minitest < Rspec
500
+ class Minitest < Base
501
+ include MutantRunSupport
502
+ include RspecTestSelection
503
+
504
+ DEFAULT_SUITE_TIMEOUT: Float
505
+
506
+ def test_files: () -> Array[String]
507
+ def per_test_coverage_supported?: () -> bool
445
508
  def run_mutant: (mutant: Mutant, test_files: Array[String], timeout: Float) -> ScenarioExecutionResult
446
509
  def spawn_mutant: (mutant: Mutant, test_files: Array[String]) -> ChildHandle
510
+ def run_in_child: (mutant: Mutant, test_files: Array[String], log_paths: Hash[Symbol, String]) -> Integer
447
511
  def run_suite: (Array[String], ?timeout: Float) -> ScenarioExecutionResult
448
512
 
449
513
  private
450
514
 
451
- def run_in_child: (mutant: Mutant, test_files: Array[String], log_paths: Hash[Symbol, String]) -> Integer
452
515
  def run_tests: (Array[String]) -> Integer
453
516
  def preload_environment: () -> void
454
517
  def setup_load_path: () -> void
455
518
  def suppress_minitest_autorun!: () -> nil
456
519
  def suppress_simplecov!: () -> void
457
520
  def subprocess_env: () -> Hash[String, String]
521
+ def spawn_suite_process: (Array[String], Hash[Symbol, String]) -> Integer
458
522
  def cleanup_suite_process: (Integer?, untyped) -> void
459
523
  def spec_files: () -> Array[String]
460
524
  end
@@ -477,12 +541,30 @@ module Henitai
477
541
 
478
542
  module MutantIdentity
479
543
  def self.stable_id: (Mutant) -> String
544
+ def self.legacy_stable_id: (Mutant) -> String
480
545
  end
481
546
 
482
547
  class MutantHistoryStore
483
- def initialize: (path: String) -> void
548
+ attr_reader path: String
549
+
550
+ def initialize: (path: String, ?per_test_coverage: PerTestCoverage?) -> void
484
551
  def record: (untyped, version: String, ?recorded_at: Time) -> void
552
+ def verdict_for: (String) -> Hash[Symbol, untyped]?
553
+ def killed_verdict_for: (String) -> Hash[Symbol, untyped]?
485
554
  def trend_report: () -> Hash[Symbol, untyped]
555
+
556
+ module Sql
557
+ RUNS_TABLE: String
558
+ MUTANTS_TABLE: String
559
+ MIGRATION_COLUMNS: Hash[String, String]
560
+ INSERT_RUN: String
561
+ UPSERT_MUTANT: String
562
+ VERDICT_LOOKUP: String
563
+ end
564
+
565
+ module VerdictCache
566
+ CACHEABLE_STATUSES: Array[String]
567
+ end
486
568
  end
487
569
 
488
570
  class EquivalenceDetector
@@ -514,34 +596,148 @@ module Henitai
514
596
  class CoverageReportReader
515
597
  def coverage_lines_by_file: (?String) -> Hash[String, Array[Integer]]
516
598
  def test_lines_by_file: (?String) -> Hash[String, Hash[String, Array[Integer]]]
599
+ def durations_by_test: (?String) -> Hash[String, Float]
517
600
  end
518
601
 
519
- class ParallelExecutionRunner
520
- def initialize: (worker_count: Integer) -> void
521
- def run: (Array[Mutant], untyped, untyped, untyped, ?Hash[Symbol, untyped]) -> void
602
+ class ProcessWorkerRunner
603
+ attr_reader worker_count: Integer
604
+ attr_reader runtime: untyped
605
+ attr_reader wakeup: untyped
606
+
607
+ def initialize: (worker_count: Integer, ?runtime: untyped, ?wakeup: untyped) -> void
608
+ def flaky_retry_count: () -> Integer
609
+ def shutdown_requested?: () -> bool
610
+ def request_shutdown: () -> void
611
+ def run: (Array[Mutant], untyped, untyped, untyped?, ?Hash[Symbol, untyped]) -> Array[ScenarioExecutionResult]
522
612
  end
523
613
 
524
- class ProcessWorkerRunner
525
- SCHEDULER_POLL_INTERVAL: Float
614
+ class SlotScheduler
526
615
  PROCESS_DRAIN_WINDOW: Float
616
+ WORKER_SLOT_ENV: String
527
617
 
528
618
  Slot: untyped
529
619
 
530
- def initialize: (worker_count: Integer) -> void
531
- def run: (Array[Mutant], untyped, untyped, untyped?, ?Hash[Symbol, untyped]) -> Array[ScenarioExecutionResult]
620
+ attr_reader flaky_retry_count: Integer
621
+ attr_reader results: Array[ScenarioExecutionResult]
622
+
623
+ def initialize: (
624
+ integration: untyped,
625
+ config: untyped,
626
+ progress_reporter: untyped?,
627
+ options: Hash[Symbol, untyped],
628
+ host: untyped
629
+ ) -> void
630
+ def enqueue: (Array[Mutant]) -> Array[Mutant]
631
+ def done?: () -> bool
632
+ def fill_idle_slots: () -> void
633
+ def reap_all_completed_children: () -> void
634
+ def next_event_timeout: () -> Float?
635
+ def check_timeouts: () -> void
636
+ def draining_slots?: () -> bool
637
+ def drain_draining_slots: () -> void
638
+ def interrupt_active_slots: () -> void
639
+ end
640
+
641
+ class IncrementalFilter
642
+ def initialize: (history_store: untyped, ?per_test_coverage: PerTestCoverage?, ?dependency_fingerprint: String?) -> void
643
+ def apply: (Array[Mutant]) -> Array[Mutant]
644
+
645
+ private
646
+
647
+ def history_store: () -> untyped
648
+ def per_test_coverage: () -> PerTestCoverage?
649
+ def dependency_fingerprint: () -> String?
650
+ def ambiguous_stable_ids: (Array[Mutant]) -> Set[String]
651
+ def reusable_status: (Mutant) -> Symbol?
652
+ def killed_reusable?: (Mutant, Hash[Symbol, untyped]) -> bool
653
+ def survived_reusable?: (Mutant, Hash[Symbol, untyped]) -> bool
654
+ def subject_source_unchanged?: (Mutant, Hash[Symbol, untyped]) -> bool
655
+ end
656
+
657
+ module VerdictFingerprint
658
+ DEPENDENCY_GLOBS: Array[String]
659
+
660
+ def self?.subject_source_hash: (untyped) -> String?
661
+ def self?.tests_fingerprint: (untyped) -> String?
662
+ def self?.tests_fingerprint_current?: (String?) -> bool
663
+ def self?.dependency_fingerprint: (?String) -> String?
664
+ def self?.survivor_tests_fingerprint: (untyped, dependency_sha: String?) -> String?
665
+ def self?.survivor_fingerprint_current?: (String?, live_paths: Array[String], dependency_sha: String?) -> bool
666
+ def self?.survivor_fingerprint_matches?: (untyped, Array[String], String?) -> bool
667
+ def self?.combined_content_sha: (untyped) -> String?
668
+ end
669
+
670
+ module CanonicalReportMerger
671
+ def self.merge: (Hash[Symbol, untyped], String, ?prune_missing: bool) -> Hash[String, untyped]
672
+ end
673
+
674
+ module CanonicalReportWriter
675
+ def self.write: (Hash[Symbol, untyped], path: String, authoritative: bool) -> Hash[untyped, untyped]
676
+ end
677
+
678
+ class ReportsDirectoryLock
679
+ LOCK_FILENAME: String
680
+
681
+ def initialize: (reports_dir: String) -> void
682
+ def synchronize: () { () -> untyped } -> untyped
683
+
684
+ private
685
+
686
+ def lock_path: () -> String
687
+ def acquire: (File) -> void
688
+ def owner_pid: (File) -> (Integer | String)
689
+ def contention_message: (Integer | String) -> String
690
+ def write_owner: (File) -> untyped
691
+ end
692
+
693
+ class CheckpointReporter
694
+ def initialize: (config: untyped, source_provider: untyped, authoritative: bool, ?started_at: untyped, ?clock: untyped) -> void
695
+ def progress: (untyped, ?scenario_result: untyped) -> void
696
+ end
697
+
698
+ class CompositeProgressReporter
699
+ def self.for: (config: untyped, source_provider: untyped, full_run: bool) -> untyped?
700
+ def initialize: (Array[untyped]) -> void
701
+ def progress: (untyped, ?scenario_result: untyped) -> void
702
+ end
703
+
704
+ class MutationSkipDirectives
705
+ def skip?: (Mutant) -> bool
706
+ def directive_for: (Mutant) -> untyped
532
707
  end
533
708
 
534
709
  class StaticFilter
535
- def initialize: (?coverage_report_reader: CoverageReportReader) -> void
710
+ def initialize: (?coverage_report_reader: CoverageReportReader, ?skip_directives: MutationSkipDirectives) -> void
536
711
  def apply: (Array[Mutant], untyped) -> Array[Mutant]
537
712
  def coverage_lines_for: (untyped) -> Hash[String, Array[Integer]]
538
713
  def coverage_lines_by_file: (?String) -> Hash[String, Array[Integer]]
539
714
  def test_lines_by_file: (?String) -> Hash[String, Hash[String, Array[Integer]]]
540
715
  end
541
716
 
717
+ class PerTestCoverage
718
+ def initialize: (reports_dir: String, ?coverage_report_reader: CoverageReportReader) -> void
719
+ def available?: () -> bool
720
+ def tests_covering: (untyped) -> Array[String]
721
+ def covers?: (String, untyped) -> bool
722
+
723
+ private
724
+
725
+ def reports_dir: () -> String
726
+ def coverage_report_reader: () -> CoverageReportReader
727
+ def location_available?: (untyped) -> bool
728
+ def coverage_lines_for: (String, untyped) -> Array[Integer]
729
+ def mutant_lines: (untyped) -> Array[Integer]
730
+ def map: () -> Hash[String, Hash[String, Array[Integer]]]
731
+ end
732
+
542
733
  class PerTestCoverageSelector
543
734
  def initialize: (?coverage_report_reader: CoverageReportReader) -> void
544
735
  def filter: (Array[String], Mutant, reports_dir: String) -> Array[String]
736
+
737
+ private
738
+
739
+ def per_test_coverage: (String) -> PerTestCoverage
740
+ def coverage_report_reader: () -> CoverageReportReader
545
741
  end
546
742
 
547
743
  class ExecutionEngine
@@ -549,13 +745,16 @@ module Henitai
549
745
 
550
746
  private
551
747
 
748
+ def execute: (Array[Mutant], untyped, untyped, untyped?) -> Array[Mutant]
749
+ def with_worker_slot: () { () -> untyped } -> untyped
552
750
  def parallel_execution?: (untyped, Array[Mutant]) -> bool
553
751
  def worker_count: (untyped) -> Integer
554
752
  def run_linear: (Array[Mutant], untyped, untyped, untyped?, untyped) -> void
555
753
  def run_parallel: (Array[Mutant], untyped, untyped, untyped?) -> void
556
754
  def process_mutant: (Mutant, untyped, untyped, untyped?, ?untyped) -> void
557
755
  def prioritized_tests_for: (Mutant, untyped, untyped) -> Array[String]
558
- def test_prioritizer: () -> TestPrioritizer
756
+ def test_prioritizer: (untyped) -> TestPrioritizer
757
+ def timing_source: (untyped) -> untyped
559
758
  def test_history: (untyped) -> Hash[untyped, untyped]
560
759
  def run_with_flaky_retry: (Mutant, untyped, untyped, Array[String], ?untyped) -> ScenarioExecutionResult
561
760
  def warn_flaky_mutants: (Integer) -> void
@@ -563,8 +762,6 @@ module Henitai
563
762
  end
564
763
 
565
764
  class Mutant::Activator
566
- SERIALIZER_METHODS: Hash[Symbol, Symbol]
567
-
568
765
  def self.activate!: (untyped) -> Symbol?
569
766
  def self.activation_source_for: (Mutant) -> String?
570
767
  def initialize: () -> void
@@ -578,6 +775,22 @@ module Henitai
578
775
  def method_source: (Mutant) -> String
579
776
  def body_source: (Mutant) -> String
580
777
  def parameter_source: (Mutant) -> String
778
+ def replace_node: (untyped, untyped, untyped) -> untyped
779
+ def same_node?: (untyped, untyped) -> bool
780
+ def replace_child: (untyped, untyped, untyped) -> untyped
781
+ def method_body: (untyped) -> untyped
782
+ def source_file_from_ast: (Subject) -> String?
783
+ def node_location_signature: (untyped) -> Array[untyped]?
784
+ def compile_safe_unparse: (untyped) -> String
785
+ end
786
+
787
+ class Mutant::ParameterSource
788
+ SERIALIZER_METHODS: Hash[Symbol, Symbol]
789
+
790
+ def build: (untyped) -> String
791
+
792
+ private
793
+
581
794
  def method_arguments: (untyped) -> untyped
582
795
  def parameter_fragment: (untyped) -> String?
583
796
  def argument_parameter_fragment: (untyped) -> String
@@ -589,26 +802,23 @@ module Henitai
589
802
  def block_parameter_fragment: (untyped) -> String
590
803
  def forward_parameter_fragment: (untyped) -> String
591
804
  def prefixed_parameter: (untyped, String) -> String
592
- def replace_node: (untyped, untyped, untyped) -> untyped
593
- def same_node?: (untyped, untyped) -> bool
594
- def replace_child: (untyped, untyped, untyped) -> untyped
595
- def method_body: (untyped) -> untyped
596
- def source_file_from_ast: (Subject) -> String?
597
- def node_location_signature: (untyped) -> Array[untyped]?
598
805
  def compile_safe_unparse: (untyped) -> String
599
806
  end
600
807
 
601
808
  module Reporter
602
- def self.run_all: (names: Array[String], result: Result, config: Configuration) -> void
809
+ def self.run_all: (names: Array[String], result: Result, config: Configuration, ?history_store: MutantHistoryStore?) -> void
603
810
  def self.reporter_class: (String) -> untyped
604
811
 
605
812
  class Base
606
- def initialize: (config: Configuration) -> void
813
+ def initialize: (config: Configuration, ?history_store: MutantHistoryStore?) -> void
607
814
  def report: (Result) -> void
608
815
 
609
816
  private
610
817
 
611
818
  def config: () -> Configuration
819
+ def history_store: () -> MutantHistoryStore?
820
+ def authoritative?: (untyped) -> bool
821
+ def canonical_path: () -> String
612
822
  end
613
823
 
614
824
  class Terminal < Base
@@ -616,11 +826,13 @@ module Henitai
616
826
 
617
827
  PROGRESS_GLYPHS: Hash[Symbol, String]
618
828
 
829
+ def initialize: (config: Configuration, ?history_store: MutantHistoryStore?, ?color_enabled: bool) -> void
619
830
  def report: (Result) -> void
620
831
  def progress: (untyped, ?scenario_result: ScenarioExecutionResult) -> void
621
832
 
622
833
  private
623
834
 
835
+ def color_enabled: () -> bool
624
836
  def report_lines: (Result) -> Array[String]
625
837
  def summary_lines: (untyped) -> Array[String]
626
838
  def full_summary_lines: (untyped) -> Array[String]
@@ -632,8 +844,14 @@ module Henitai
632
844
  def original_line: (Mutant) -> String
633
845
  def mutated_line: (Mutant) -> String
634
846
  def display_unparse: (untyped) -> String
847
+ def display_mutated_source: (untyped) -> String
848
+ def str_node?: (untyped) -> bool
849
+ def source_slice: (untyped) -> String?
635
850
  def score_line: (Result) -> String
636
851
  def format_row: (String, untyped) -> String
852
+ def reused_verdicts_line: (Result) -> String?
853
+ def reused_mutants: (Result) -> Array[Mutant]
854
+ def executed_only_score_line: (Result) -> String?
637
855
  def count_status: (Result, Symbol) -> Integer
638
856
  def format_duration: (Float) -> String
639
857
  def format_percent: (Float?) -> String
@@ -649,37 +867,87 @@ module Henitai
649
867
 
650
868
  private
651
869
 
652
- def write_canonical: (Hash[Symbol, untyped]) -> void
870
+ def write_canonical: (Hash[Symbol, untyped], authoritative: bool) -> void
653
871
  def write_session_snapshot: (Hash[Symbol, untyped]) -> void
654
872
  def write_activation_recipes: (untyped) -> void
655
873
  def survived_mutants_for: (untyped) -> Array[Mutant]
656
874
  def session_snapshot_path: (String) -> String
657
875
  def session_recipe_path: (String) -> String
658
- def canonical_path: () -> String
659
- def report_path: () -> String
660
876
  def write_history_report: () -> void
661
- def history_store_path: () -> String
877
+ def default_history_store: () -> MutantHistoryStore
662
878
  def history_report_path: () -> String
663
879
  end
664
880
 
665
881
  class Html < Base
666
882
  def report: (Result) -> void
883
+ def report_schema: (Hash[untyped, untyped]) -> void
667
884
 
668
885
  private
669
886
 
670
887
  def report_path: () -> String
671
- def html_document: (Result) -> String
672
- def escaped_report_json: (Result) -> String
888
+ def html_document: (Hash[untyped, untyped]) -> String
889
+ def schema_for: (Result) -> Hash[untyped, untyped]
890
+ def escaped_report_json: (Hash[untyped, untyped]) -> String
891
+ end
892
+
893
+ class DryRun < Base
894
+ def initialize: (config: Configuration, ?history_store: MutantHistoryStore?, ?io: untyped) -> void
895
+ def report: (untyped) -> void
896
+
897
+ private
898
+
899
+ def io: () -> untyped
900
+ def listing_lines: (untyped) -> Array[String]
901
+ def grouped_lines: (untyped) -> Array[String]
902
+ def subject_label: (untyped) -> String
903
+ def mutant_line: (untyped) -> String
904
+ def ignore_reason_for: (untyped) -> String?
905
+ def summary_line: (untyped) -> String
906
+ end
907
+
908
+ class Github < Base
909
+ def initialize: (config: Configuration, ?history_store: MutantHistoryStore?, ?io: untyped) -> void
910
+ def report: (Result) -> void
911
+
912
+ private
913
+
914
+ def io: () -> untyped
915
+ def annotation_line: (Mutant) -> String
916
+ def relative_path: (String) -> String
917
+ def escape_message: (String) -> String
918
+ end
919
+
920
+ class DashboardMetadataProvider
921
+ def initialize: (dashboard_config: Hash[Symbol, untyped]?, ?env: untyped, ?git_executor: untyped) -> void
922
+ def project: () -> String?
923
+ def version: () -> String?
924
+ def api_key: () -> String?
925
+
926
+ private
927
+
928
+ def env_version: () -> String?
929
+ def ref_without_prefix: (String?) -> String?
930
+ def project_from_git_remote: () -> String?
931
+ def blank?: (String?) -> bool
932
+ def git_remote_url: () -> String?
933
+ def git_branch_name: () -> String?
934
+
935
+ def self.project_from_git_url: (String?) -> String?
936
+ def self.normalize_git_url: (String?) -> String?
937
+ def self.project_from_uri_url: (String) -> String?
938
+ def self.project_from_ssh_url: (String) -> String?
673
939
  end
674
940
 
675
941
  class Dashboard < Base
676
942
  DEFAULT_BASE_URL: String
677
943
  HTTP_TIMEOUT_SECONDS: Integer
678
944
 
945
+ def initialize: (config: Configuration, ?history_store: MutantHistoryStore?, ?metadata_provider: DashboardMetadataProvider?) -> void
679
946
  def report: (Result) -> void
680
947
 
681
948
  private
682
949
 
950
+ def metadata_provider: () -> DashboardMetadataProvider
683
951
  def ready?: () -> bool
684
952
  def build_request: (Result, untyped) -> untyped
685
953
  def request_headers: () -> Hash[String, String]
@@ -688,20 +956,11 @@ module Henitai
688
956
  def base_url: () -> String
689
957
  def project: () -> String?
690
958
  def version: () -> String?
691
- def env_version: () -> String?
692
- def ref_without_prefix: (String?) -> String?
693
- def project_from_git_remote: () -> String?
694
959
  def api_key: () -> String?
695
960
  def project_path: () -> String
696
961
  def encoded_version: () -> String
697
- def blank?: (String?) -> bool
698
- def git_remote_url: () -> String?
699
- def git_branch_name: () -> String?
700
962
 
701
963
  def self.project_from_git_url: (String?) -> String?
702
- def self.normalize_git_url: (String?) -> String?
703
- def self.project_from_uri_url: (String) -> String?
704
- def self.project_from_ssh_url: (String) -> String?
705
964
  end
706
965
  end
707
966
 
@@ -719,20 +978,25 @@ module Henitai
719
978
  attr_reader session_id: String
720
979
  attr_reader git_sha: String?
721
980
 
722
- def initialize: (mutants: Array[Mutant], started_at: Time, finished_at: Time, ?thresholds: Hash[Symbol, Integer]?, ?partial_rerun: bool, ?survivor_stats: Hash[Symbol, untyped]?, ?session_id: String, ?git_sha: String?) -> void
981
+ def initialize: (mutants: Array[Mutant], started_at: Time, finished_at: Time, ?thresholds: Hash[Symbol, Integer]?, ?partial_rerun: bool, ?survivor_stats: Hash[Symbol, untyped]?, ?session_id: String, ?git_sha: String?, ?source_provider: ^(String) -> String, ?authoritative: bool) -> void
723
982
  def partial_rerun?: () -> bool
983
+ def authoritative?: () -> bool
724
984
  def killed: () -> Integer
725
985
  def survived: () -> Integer
726
986
  def equivalent: () -> Integer
727
987
  def detected: () -> Integer
728
988
  def mutation_score: () -> Float?
729
989
  def mutation_score_indicator: () -> Float?
990
+ def executed_scoring_summary: () -> Hash[Symbol, untyped]?
730
991
  def scoring_summary: () -> Hash[Symbol, untyped]
731
992
  def duration: () -> Float
732
993
  def to_stryker_schema: () -> Hash[Symbol, untyped]
733
994
 
734
995
  private
735
996
 
997
+ def detected_in: (Array[Mutant]) -> Integer
998
+ def mutation_score_for: (Array[Mutant]) -> Float?
999
+ def mutation_score_indicator_for: (Array[Mutant]) -> Float?
736
1000
  def base_schema: () -> Hash[Symbol, untyped]
737
1001
  def unmatched_survivor_ids: () -> Array[String]
738
1002
  def build_files_section: () -> Hash[Symbol, untyped]
@@ -742,6 +1006,9 @@ module Henitai
742
1006
  def location_for: (Mutant) -> Hash[Symbol, untyped]
743
1007
  def line_column: (Mutant, Symbol) -> Hash[Symbol, Integer]
744
1008
  def duration_for: (Mutant) -> Integer?
1009
+ def status_reason_for: (Mutant) -> String?
1010
+ def from_cache_for: (Mutant) -> bool?
1011
+ def legacy_stable_id_for: (Mutant) -> String?
745
1012
  def equivalence_uncertainty: () -> String?
746
1013
  def stryker_status: (Symbol) -> String
747
1014
  end
@@ -795,7 +1062,7 @@ module Henitai
795
1062
  attr_reader config: Configuration
796
1063
  attr_reader result: untyped
797
1064
 
798
- def initialize: (?config: Configuration, ?subjects: Array[Subject], ?since: String, ?survivors_from: String?) -> void
1065
+ def initialize: (?config: Configuration, ?subjects: Array[Subject], ?since: String, ?survivors_from: String?, ?mode: Hash[Symbol, bool]) -> void
799
1066
  def run: () -> Result
800
1067
  def resolve_subjects: (?Array[String]) -> untyped
801
1068
  def generate_mutants: (untyped) -> untyped
@@ -812,8 +1079,13 @@ module Henitai
812
1079
  def operators: () -> untyped
813
1080
  def progress_reporter: () -> untyped?
814
1081
  def history_store: () -> untyped
1082
+ def per_test_coverage: () -> PerTestCoverage
815
1083
  def history_store_path: () -> String
816
1084
  def source_files: () -> Array[String]
1085
+ def included_source_files: () -> Array[String]
1086
+ def reject_excluded: (Array[String]) -> Array[String]
1087
+ def excluded_source_files: () -> Array[String]
1088
+ def filter_changed: (Array[String]) -> Array[String]
817
1089
  def pattern_subjects: () -> Array[Subject]
818
1090
  def unique_subjects: (Array[Subject]) -> Array[Subject]
819
1091
  def normalize_path: (String) -> String
@@ -821,6 +1093,11 @@ module Henitai
821
1093
  private
822
1094
 
823
1095
  def build_result: (Array[Mutant], Time, Time) -> Result
1096
+ def build_result_object: (Array[Mutant], Time, Time) -> Result
1097
+ def pipeline_mutants: () -> Array[Mutant]
1098
+ def apply_incremental_filter: (Array[Mutant]) -> Array[Mutant]
1099
+ def dry_run_result: (Array[Mutant], Time, Time) -> Result
1100
+ def source_provider: () -> ^(String) -> String
824
1101
  def persist_history: (Result, Time) -> void
825
1102
  def bootstrap_coverage: (Array[String], ?Array[String]?) -> void
826
1103
  def bootstrap_mutants: (Array[String]) -> Thread
@@ -828,8 +1105,21 @@ module Henitai
828
1105
  def with_reports_dir: () { () -> untyped } -> untyped
829
1106
  def result_thresholds: () -> Hash[Symbol, Integer]?
830
1107
  def survivor_rerun?: () -> bool
831
- def apply_survivor_selection: (Array[Mutant]) -> Array[Mutant]
1108
+ def full_run?: () -> bool
1109
+ def survivor_strategy: () -> SurvivorRerunStrategy
1110
+ def safe_head_sha: () -> String?
1111
+ end
1112
+
1113
+ class SurvivorRerunStrategy
1114
+ attr_reader survivor_stats: Hash[Symbol, untyped]?
1115
+
1116
+ def initialize: (survivors_from: String?, config: Configuration, git_diff_analyzer: untyped) -> void
1117
+ def active?: () -> bool
832
1118
  def try_recipe_run: () -> Array[Mutant]?
1119
+ def apply_selection: (Array[Mutant]) -> Array[Mutant]
1120
+
1121
+ private
1122
+
833
1123
  def load_survivor_report: () -> SurvivorLoader::Report
834
1124
  def run_from_recipes: (SurvivorLoader::Report, Array[String]?) -> Array[Mutant]?
835
1125
  def recipe_fast_path_safe?: (SurvivorLoader::Report, Array[String]?) -> bool
@@ -843,10 +1133,10 @@ module Henitai
843
1133
  def dirty_source_files?: (Array[String]?, ?git_sha: String?) -> bool
844
1134
  def committed_changed_files: (String?) -> Array[String]
845
1135
  def in_include_root?: (String, Array[String]) -> bool
1136
+ def normalize_path: (String) -> String
846
1137
  def warn_survivor_drift: (SurvivorSelector) -> void
847
1138
  def build_survivor_stats: (SurvivorSelector, Array[Mutant], Hash[Symbol, Array[Mutant]]) -> Hash[Symbol, untyped]
848
1139
  def test_filter: (SurvivorLoader::Report, ?dirty_source_files: bool) -> SurvivorTestFilter
849
- def safe_head_sha: () -> String?
850
1140
  end
851
1141
 
852
1142
  class CoverageBootstrapper