henitai 0.5.1 → 0.6.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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +296 -1
  3. data/README.md +109 -16
  4. data/assets/schema/henitai.schema.json +20 -0
  5. data/lib/henitai/arid_node_filter.rb +4 -19
  6. data/lib/henitai/bootstrap_error_message.rb +20 -0
  7. data/lib/henitai/canonical_report_merger.rb +23 -2
  8. data/lib/henitai/cli/run_command.rb +25 -7
  9. data/lib/henitai/cli/run_options.rb +1 -1
  10. data/lib/henitai/cli.rb +4 -1
  11. data/lib/henitai/configuration.rb +4 -1
  12. data/lib/henitai/configuration_validator/rules.rb +8 -0
  13. data/lib/henitai/configuration_validator/scalars.rb +9 -0
  14. data/lib/henitai/configuration_validator.rb +2 -1
  15. data/lib/henitai/constant_path.rb +48 -0
  16. data/lib/henitai/control_run.rb +73 -0
  17. data/lib/henitai/coverage_bootstrapper.rb +57 -15
  18. data/lib/henitai/coverage_formatter.rb +26 -3
  19. data/lib/henitai/coverage_report_reader.rb +21 -0
  20. data/lib/henitai/equivalence_detector/operand_predicates.rb +16 -0
  21. data/lib/henitai/equivalence_detector.rb +46 -38
  22. data/lib/henitai/example_summary.rb +24 -0
  23. data/lib/henitai/execution_engine/fork_server_scope.rb +57 -0
  24. data/lib/henitai/execution_engine.rb +75 -60
  25. data/lib/henitai/fidelity_check.rb +173 -0
  26. data/lib/henitai/flaky_detection_baseline.rb +61 -0
  27. data/lib/henitai/flaky_mutant_retrier.rb +43 -0
  28. data/lib/henitai/flaky_retry_decision.rb +23 -0
  29. data/lib/henitai/flaky_test_registry.rb +63 -0
  30. data/lib/henitai/fork_server/client.rb +231 -0
  31. data/lib/henitai/fork_server/group_killer.rb +48 -0
  32. data/lib/henitai/fork_server/group_terminator.rb +47 -0
  33. data/lib/henitai/fork_server/launcher.rb +38 -0
  34. data/lib/henitai/fork_server/mutant_runner.rb +141 -0
  35. data/lib/henitai/fork_server/protocol.rb +73 -0
  36. data/lib/henitai/fork_server/reaper.rb +24 -0
  37. data/lib/henitai/fork_server/runtime.rb +109 -0
  38. data/lib/henitai/fork_server/server.rb +108 -0
  39. data/lib/henitai/fork_server/server_process.rb +73 -0
  40. data/lib/henitai/fork_server/status.rb +52 -0
  41. data/lib/henitai/fork_server.rb +43 -0
  42. data/lib/henitai/generated_artifacts.rb +3 -0
  43. data/lib/henitai/git_diff_analyzer.rb +28 -11
  44. data/lib/henitai/incremental_filter.rb +20 -10
  45. data/lib/henitai/integration/base.rb +72 -5
  46. data/lib/henitai/integration/capped_log_sink.rb +34 -0
  47. data/lib/henitai/integration/child_bootstrap.rb +7 -0
  48. data/lib/henitai/integration/child_report_store.rb +36 -0
  49. data/lib/henitai/integration/minitest.rb +17 -7
  50. data/lib/henitai/integration/minitest_autorun.rb +20 -0
  51. data/lib/henitai/integration/minitest_outcome_reporter.rb +28 -0
  52. data/lib/henitai/integration/minitest_preload.rb +30 -0
  53. data/lib/henitai/integration/minitest_runnable_filter.rb +61 -0
  54. data/lib/henitai/integration/minitest_test_runner.rb +32 -15
  55. data/lib/henitai/integration/mutant_run_support.rb +73 -13
  56. data/lib/henitai/integration/rspec_child_runner.rb +44 -9
  57. data/lib/henitai/integration/rspec_preload.rb +35 -0
  58. data/lib/henitai/integration/rspec_process_runner.rb +4 -1
  59. data/lib/henitai/integration/scenario_log_support.rb +31 -18
  60. data/lib/henitai/integration.rb +16 -3
  61. data/lib/henitai/minitest_coverage_reporter.rb +22 -6
  62. data/lib/henitai/minitest_result_file.rb +62 -0
  63. data/lib/henitai/mutant/activation.rb +32 -0
  64. data/lib/henitai/mutant/activator.rb +75 -55
  65. data/lib/henitai/mutant/def_injection.rb +136 -0
  66. data/lib/henitai/mutant/lexical_scope_check.rb +120 -0
  67. data/lib/henitai/mutant/lexical_target.rb +105 -0
  68. data/lib/henitai/mutant/replacement.rb +52 -0
  69. data/lib/henitai/mutant.rb +27 -8
  70. data/lib/henitai/mutant_generator.rb +62 -18
  71. data/lib/henitai/mutant_history_store/verdict_cache.rb +12 -11
  72. data/lib/henitai/mutant_history_store.rb +14 -4
  73. data/lib/henitai/mutant_identity.rb +5 -1
  74. data/lib/henitai/mutant_verdict.rb +71 -0
  75. data/lib/henitai/operators/array_declaration.rb +4 -0
  76. data/lib/henitai/operators/assignment_expression.rb +2 -0
  77. data/lib/henitai/operators/conditional_expression.rb +21 -1
  78. data/lib/henitai/operators/hash_literal.rb +7 -4
  79. data/lib/henitai/operators/method_expression.rb +14 -3
  80. data/lib/henitai/operators/regex_metacharacters.rb +89 -0
  81. data/lib/henitai/operators/regex_mutator.rb +23 -28
  82. data/lib/henitai/operators/return_value.rb +1 -1
  83. data/lib/henitai/operators.rb +1 -0
  84. data/lib/henitai/per_test_coverage.rb +11 -7
  85. data/lib/henitai/per_test_coverage_collector.rb +30 -31
  86. data/lib/henitai/per_test_coverage_delta.rb +60 -0
  87. data/lib/henitai/per_test_coverage_selector.rb +26 -13
  88. data/lib/henitai/process_wakeup.rb +8 -3
  89. data/lib/henitai/process_worker_runner.rb +19 -5
  90. data/lib/henitai/reporter.rb +15 -8
  91. data/lib/henitai/result.rb +32 -16
  92. data/lib/henitai/reuse_context.rb +50 -0
  93. data/lib/henitai/rspec_coverage_formatter.rb +4 -0
  94. data/lib/henitai/rspec_outcomes.rb +72 -0
  95. data/lib/henitai/runner.rb +58 -19
  96. data/lib/henitai/runner_dependencies.rb +22 -1
  97. data/lib/henitai/sampling_strategy.rb +36 -6
  98. data/lib/henitai/scenario_execution_result.rb +28 -5
  99. data/lib/henitai/signature_line.rb +21 -0
  100. data/lib/henitai/slot_scheduler/draining.rb +12 -2
  101. data/lib/henitai/slot_scheduler/process_control.rb +33 -0
  102. data/lib/henitai/slot_scheduler/retry_policy.rb +8 -6
  103. data/lib/henitai/slot_scheduler.rb +47 -8
  104. data/lib/henitai/source_file_selection.rb +1 -1
  105. data/lib/henitai/source_parser.rb +29 -9
  106. data/lib/henitai/static_filter.rb +45 -14
  107. data/lib/henitai/stillborn_filter.rb +70 -2
  108. data/lib/henitai/subject.rb +8 -3
  109. data/lib/henitai/subject_resolver.rb +65 -31
  110. data/lib/henitai/suite_boot_clock.rb +48 -0
  111. data/lib/henitai/survivor_activation_cache.rb +18 -11
  112. data/lib/henitai/survivor_rerun_strategy.rb +47 -43
  113. data/lib/henitai/test_file_outcomes.rb +79 -0
  114. data/lib/henitai/timeout_calibrator.rb +31 -9
  115. data/lib/henitai/timeout_ceiling.rb +37 -0
  116. data/lib/henitai/verdict_fingerprint.rb +29 -30
  117. data/lib/henitai/version.rb +1 -1
  118. data/lib/henitai.rb +17 -1
  119. data/sig/configuration_validator.rbs +1 -0
  120. data/sig/henitai.rbs +227 -45
  121. metadata +46 -3
  122. data/lib/henitai/survivor_test_filter.rb +0 -72
data/sig/henitai.rbs CHANGED
@@ -128,14 +128,42 @@ module Henitai
128
128
  def pause: (Float) -> void
129
129
  end
130
130
 
131
+ module Integration::RspecPreload
132
+ def fork_server_supported?: () -> bool
133
+ def preload_environment: (Array[String]) -> untyped
134
+ end
135
+
136
+ module Integration::MinitestPreload
137
+ def fork_server_supported?: () -> bool
138
+ def preload_environment: (Array[String]) -> untyped
139
+ end
140
+
131
141
  module Integration::RspecChildRunner
132
142
  private
133
143
 
134
- def run_rspec_runner: (Array[String]) -> untyped
144
+ def run_rspec_runner: (Array[String]) ?{ () -> untyped } -> untyped
135
145
  def build_rspec_runner: () -> untyped
136
146
  def configure_rspec_runner: (untyped) -> void
137
147
  def load_rspec_spec_files: (Array[String]) -> void
138
- def run_rspec_specs: (untyped) -> untyped
148
+ def run_rspec_specs: (untyped, untyped) -> untyped
149
+ end
150
+
151
+ module RspecOutcomes
152
+ EVENTS: Array[Symbol]
153
+ HOOK_ERROR: String
154
+
155
+ def self.record: (TestFileOutcomes, untyped) -> void
156
+ def self.register: (TestFileOutcomes, untyped) -> void
157
+ def self.group_file: (untyped) -> String
158
+ end
159
+
160
+ class RspecOutcomes::Listener
161
+ def initialize: (TestFileOutcomes) -> void
162
+ def example_finished: (untyped) -> void
163
+ def example_group_started: (untyped) -> void
164
+ def example_group_finished: (untyped) -> void
165
+ def message: (untyped) -> void
166
+ def dump_summary: (untyped) -> void
139
167
  end
140
168
 
141
169
  module Integration::RspecTestSelection
@@ -187,6 +215,9 @@ module Henitai
187
215
  attr_reader ignore_patterns: Array[untyped]
188
216
  attr_reader max_mutants_per_line: Integer
189
217
  attr_reader max_flaky_retries: Integer
218
+ attr_reader control_runs: bool
219
+ attr_reader flaky_detection: bool
220
+ attr_reader fork_server: bool
190
221
  attr_reader max_log_bytes: Integer
191
222
  attr_reader max_timeout: Float
192
223
  attr_reader sampling: untyped
@@ -227,9 +258,14 @@ module Henitai
227
258
  attr_reader stderr: String
228
259
  attr_reader exit_status: Integer?
229
260
  attr_reader log_path: String
261
+ attr_reader status_reason: String?
262
+ attr_reader killing_tests: Array[String]
230
263
 
231
264
  def self.build: (wait_result: untyped, stdout: String?, stderr: String?, log_path: String) -> ScenarioExecutionResult
232
- def initialize: (status: Symbol, stdout: String?, stderr: String?, log_path: String, ?exit_status: Integer?) -> void
265
+ def self.build_for_mutant: (wait_result: untyped, report: untyped, stdout: String?, stderr: String?, log_path: String) -> ScenarioExecutionResult
266
+ def self.copy_reason: (untyped, untyped) -> String?
267
+ def initialize: (status: Symbol, stdout: String?, stderr: String?, log_path: String, ?exit_status: Integer?, ?status_reason: String?, ?killing_tests: Array[String]) -> void
268
+ def release_output!: () -> self
233
269
  def survived?: () -> bool
234
270
  def killed?: () -> bool
235
271
  def timeout?: () -> bool
@@ -251,9 +287,10 @@ module Henitai
251
287
  attr_reader method_type: Symbol
252
288
  attr_reader source_file: String?
253
289
  attr_reader source_range: Range[Integer]?
290
+ attr_reader lexical_scope: Array[String]?
254
291
 
255
292
  def self.parse: (String) -> Subject
256
- def initialize: (?expression: String, ?namespace: String, ?method_name: String, ?method_type: Symbol, ?source_location: Hash[Symbol, untyped], ?ast_node: untyped) -> void
293
+ def initialize: (?expression: String, ?namespace: String, ?method_name: String, ?method_type: Symbol, ?source_location: Hash[Symbol, untyped], ?ast_node: untyped, ?lexical_scope: Array[String]?) -> void
257
294
  def expression: () -> String
258
295
  def wildcard?: () -> bool
259
296
 
@@ -281,11 +318,14 @@ module Henitai
281
318
  attr_accessor covered_by: Array[String]?
282
319
  attr_accessor tests_completed: Integer?
283
320
  attr_accessor ignore_reason: String?
321
+ attr_accessor status_reason: String?
322
+ attr_accessor identity_discriminator: String?
284
323
  attr_accessor from_cache: bool
285
324
  attr_reader precomputed_stable_id: String?
286
- attr_reader precomputed_activation_source: String?
325
+ attr_reader precomputed_activation: untyped
326
+ attr_reader precomputed_replacement: String?
287
327
 
288
- 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
328
+ def initialize: (subject: Subject, operator: String, nodes: Hash[Symbol, untyped], description: String, location: Hash[Symbol, untyped], ?precomputed_stable_id: String?, ?precomputed_activation: untyped, ?precomputed_replacement: String?) -> void
289
329
  def stable_id: () -> String
290
330
  def mutated_source: () -> String
291
331
  def from_cache?: () -> bool
@@ -295,6 +335,10 @@ module Henitai
295
335
  def ignored?: () -> bool
296
336
  def equivalent?: () -> bool
297
337
  def to_s: () -> String
338
+
339
+ private
340
+
341
+ def reset_outcome: () -> void
298
342
  end
299
343
 
300
344
  class SyntaxValidator
@@ -317,13 +361,22 @@ module Henitai
317
361
  def current_snapshot: () -> untyped
318
362
  def warn_missing_coverage: () -> void
319
363
  def new_lines: (untyped) -> Hash[String, Array[Integer]]
320
- def new_line_numbers: (untyped, untyped) -> Array[Integer]
321
- def previous_line_counts: (String) -> Array[untyped]
322
- def line_counts_for: (untyped) -> Array[untyped]
323
364
  def source_file?: (String) -> bool
324
365
  def serializable_report: () -> Hash[String, Hash[String, Array[Integer]]]
325
366
  end
326
367
 
368
+ class PerTestCoverageDelta
369
+ def executed_lines: (untyped, untyped) -> Array[Integer]
370
+
371
+ private
372
+
373
+ def counted_lines: (untyped, untyped) -> Array[Integer]
374
+ def called_method_lines: (untyped, untyped) -> Array[Integer]
375
+ def untracked_method_lines: (Array[untyped], Array[untyped]) -> Array[Integer]
376
+ def line_counts: (untyped) -> Array[untyped]
377
+ def method_counts: (untyped) -> Hash[untyped, untyped]
378
+ end
379
+
327
380
  class CoverageFormatter
328
381
  REPORT_DIR_ENV: String
329
382
  REPORT_FILE_NAME: String
@@ -344,22 +397,54 @@ module Henitai
344
397
  end
345
398
 
346
399
  class SamplingStrategy
400
+ DEFAULT_SEED: Integer
401
+
347
402
  def initialize: () -> void
348
- def sample: (Array[Mutant], ratio: Float, ?strategy: Symbol) -> Array[Mutant]
403
+ def sample: (Array[Mutant], ratio: Float, ?strategy: Symbol, ?seed: Integer) -> Array[Mutant]
349
404
  end
350
405
 
351
406
  class TimeoutCalibrator
352
407
  FLOOR_SECONDS: Float
353
408
 
354
- def initialize: (timing_source: untyped, multiplier: untyped) -> void
409
+ def initialize: (timing_source: untyped, multiplier: untyped, ?boot_seconds: ^() -> Float, ?include_boot: bool) -> void
355
410
  def timeout_for: (untyped) -> Float?
356
411
 
357
412
  private
358
413
 
414
+ def boot_component: () -> Float
359
415
  def durations: () -> Hash[String, untyped]
360
416
  def normalize: (untyped) -> String
361
417
  end
362
418
 
419
+ class TimeoutCeiling
420
+ def initialize: (ceiling: Float?, warner: untyped) -> void
421
+ def cap: (Float, Float) -> Float
422
+
423
+ private
424
+
425
+ def warn_baseline_exceeds_ceiling: (Float) -> void
426
+ end
427
+
428
+ class SuiteBootClock
429
+ STARTED_AT_ENV: String
430
+
431
+ def self.from_env: (Hash[String, String], ?clock: ^() -> Float) -> SuiteBootClock
432
+ def self.parse_timestamp: (untyped) -> Float?
433
+ def initialize: (started_at: Float?, ?clock: ^() -> Float) -> void
434
+ def mark_first_test_started: () -> void
435
+ def boot_seconds: () -> Float
436
+ def measured?: () -> bool
437
+ end
438
+
439
+ class ProcessWakeup
440
+ def initialize: (?signal_name: String) -> void
441
+ def install: () -> self
442
+ def watch: () { () -> Array[untyped] } -> void
443
+ def wait: (Float?) -> void
444
+ def drain: () -> void
445
+ def close: () -> void
446
+ end
447
+
363
448
  class TestPrioritizer
364
449
  def initialize: (?timing_source: untyped?) -> void
365
450
  def sort: (Array[String], untyped, Hash[untyped, untyped]) -> Array[String]
@@ -432,6 +517,11 @@ module Henitai
432
517
  def run_child_activation_and_tests: (mutant: Mutant, test_files: Array[String], log_paths: Hash[Symbol, String]) -> Integer
433
518
  end
434
519
 
520
+ class CappedLogSink
521
+ def initialize: (untyped, Integer) -> void
522
+ def write: (String) -> void
523
+ end
524
+
435
525
  class ScenarioLogSupport
436
526
  def capture_child_output: (Hash[Symbol, String]) { () -> untyped } -> untyped
437
527
  def with_coverage_dir: (String) { () -> untyped } -> untyped
@@ -465,8 +555,9 @@ module Henitai
465
555
  class ChildHandle
466
556
  attr_accessor pid: Integer?
467
557
  attr_accessor log_paths: Hash[Symbol, String]
558
+ attr_accessor timeout: Float?
468
559
 
469
- def initialize: (pid: Integer?, log_paths: Hash[Symbol, String]) -> void
560
+ def initialize: (pid: Integer?, log_paths: Hash[Symbol, String], ?timeout: Float?) -> void
470
561
  end
471
562
 
472
563
  class RspecProcessRunner
@@ -478,6 +569,7 @@ module Henitai
478
569
  class Rspec < Base
479
570
  include MutantRunSupport
480
571
  include RspecChildRunner
572
+ include RspecPreload
481
573
  include RspecTestSelection
482
574
 
483
575
  DEFAULT_SUITE_TIMEOUT: Float
@@ -491,7 +583,8 @@ module Henitai
491
583
 
492
584
  private
493
585
 
494
- def run_tests: (Array[String]) -> Integer
586
+ def outcome_recording_hook: (TestFileOutcomes, (^() -> untyped)?) -> (^() -> untyped)
587
+ def run_tests: (Array[String], TestFileOutcomes) ?{ () -> untyped } -> Integer
495
588
  end
496
589
 
497
590
  module CoverageRuntimeSuppressors
@@ -522,7 +615,7 @@ module Henitai
522
615
 
523
616
  private
524
617
 
525
- def run_tests: (Array[String]) -> Integer
618
+ def run_tests: (Array[String], TestFileOutcomes) ?{ () -> untyped } -> Integer
526
619
  def preload_environment: () -> void
527
620
  def setup_load_path: () -> void
528
621
  def suppress_minitest_autorun!: () -> nil
@@ -541,12 +634,13 @@ module Henitai
541
634
 
542
635
  class GitDiffAnalyzer
543
636
  def changed_files: (from: String, to: String, ?dir: String) -> Array[String]
637
+ def changed_files_since: (String, ?dir: String) -> Array[String]
544
638
  def working_tree_changed_files: (?dir: String) -> Array[String]
545
639
  def head_sha: (?dir: String) -> String?
546
640
  end
547
641
 
548
642
  class MutantGenerator
549
- def generate: (Array[Subject], Array[untyped], ?config: untyped) -> Array[Mutant]
643
+ def generate: (Array[Subject], Array[untyped], ?config: untyped, ?sample: bool) -> Array[Mutant]
550
644
  end
551
645
 
552
646
  module MutantIdentity
@@ -557,7 +651,7 @@ module Henitai
557
651
  class MutantHistoryStore
558
652
  attr_reader path: String
559
653
 
560
- def initialize: (path: String, ?per_test_coverage: PerTestCoverage?) -> void
654
+ def initialize: (path: String, ?per_test_coverage: PerTestCoverage?, ?reuse_context: ReuseContext?) -> void
561
655
  def record: (untyped, version: String, ?recorded_at: Time) -> void
562
656
  def verdict_for: (String) -> Hash[Symbol, untyped]?
563
657
  def killed_verdict_for: (String) -> Hash[Symbol, untyped]?
@@ -607,6 +701,7 @@ module Henitai
607
701
  def coverage_lines_by_file: (?String) -> Hash[String, Array[Integer]]
608
702
  def test_lines_by_file: (?String) -> Hash[String, Hash[String, Array[Integer]]]
609
703
  def durations_by_test: (?String) -> Hash[String, Float]
704
+ def boot_seconds: (?String) -> Float
610
705
  end
611
706
 
612
707
  class ProcessWorkerRunner
@@ -649,14 +744,15 @@ module Henitai
649
744
  end
650
745
 
651
746
  class IncrementalFilter
652
- def initialize: (history_store: untyped, ?per_test_coverage: PerTestCoverage?, ?dependency_fingerprint: String?) -> void
747
+ def initialize: (history_store: untyped, ?per_test_coverage: PerTestCoverage?, ?reuse_context: ReuseContext?) -> void
653
748
  def apply: (Array[Mutant]) -> Array[Mutant]
654
749
 
655
750
  private
656
751
 
657
752
  def history_store: () -> untyped
658
753
  def per_test_coverage: () -> PerTestCoverage?
659
- def dependency_fingerprint: () -> String?
754
+ def reuse_context: () -> ReuseContext?
755
+ def context_sha: () -> String?
660
756
  def ambiguous_stable_ids: (Array[Mutant]) -> Set[String]
661
757
  def reusable_status: (Mutant) -> Symbol?
662
758
  def killed_reusable?: (Mutant, Hash[Symbol, untyped]) -> bool
@@ -664,15 +760,25 @@ module Henitai
664
760
  def subject_source_unchanged?: (Mutant, Hash[Symbol, untyped]) -> bool
665
761
  end
666
762
 
763
+ class ReuseContext
764
+ def initialize: (config: untyped, ?version: String, ?root: String) -> void
765
+ def fingerprint: () -> String?
766
+
767
+ private
768
+
769
+ def compute: () -> String?
770
+ def components: (String) -> Hash[String, untyped]
771
+ end
772
+
667
773
  module VerdictFingerprint
668
774
  DEPENDENCY_GLOBS: Array[String]
669
775
 
670
776
  def self?.subject_source_hash: (untyped) -> String?
671
- def self?.tests_fingerprint: (untyped) -> String?
672
- def self?.tests_fingerprint_current?: (String?) -> bool
777
+ def self?.tests_fingerprint: (untyped, context_sha: String?) -> String?
778
+ def self?.tests_fingerprint_current?: (String?, context_sha: String?) -> bool
673
779
  def self?.dependency_fingerprint: (?String) -> String?
674
- def self?.survivor_tests_fingerprint: (untyped, dependency_sha: String?) -> String?
675
- def self?.survivor_fingerprint_current?: (String?, live_paths: Array[String], dependency_sha: String?) -> bool
780
+ def self?.survivor_tests_fingerprint: (untyped, context_sha: String?) -> String?
781
+ def self?.survivor_fingerprint_current?: (String?, live_paths: Array[String], context_sha: String?) -> bool
676
782
  def self?.survivor_fingerprint_matches?: (untyped, Array[String], String?) -> bool
677
783
  def self?.combined_content_sha: (untyped) -> String?
678
784
  end
@@ -741,9 +847,13 @@ module Henitai
741
847
  def map: () -> Hash[String, Hash[String, Array[Integer]]]
742
848
  end
743
849
 
850
+ module SignatureLine
851
+ def self.on?: (untyped) -> bool
852
+ end
853
+
744
854
  class PerTestCoverageSelector
745
855
  def initialize: (?coverage_report_reader: CoverageReportReader) -> void
746
- def filter: (Array[String], Mutant, reports_dir: String) -> Array[String]
856
+ def select: (Mutant, reports_dir: String, test_files: ^() -> Array[String], fallback: ^() -> Array[String]) -> Array[String]
747
857
 
748
858
  private
749
859
 
@@ -767,7 +877,6 @@ module Henitai
767
877
  def test_prioritizer: (untyped) -> TestPrioritizer
768
878
  def timing_source: (untyped) -> untyped
769
879
  def test_history: (untyped) -> Hash[untyped, untyped]
770
- def run_with_flaky_retry: (Mutant, untyped, untyped, Array[String], ?untyped) -> ScenarioExecutionResult
771
880
  def warn_flaky_mutants: (Integer) -> void
772
881
  def with_reports_dir: (untyped) { () -> untyped } -> untyped
773
882
  end
@@ -780,8 +889,6 @@ module Henitai
780
889
 
781
890
  private
782
891
 
783
- def load_target: (Subject) -> untyped
784
- def load_source_file: (Subject) -> void
785
892
  def target_for: (Subject) -> untyped
786
893
  def method_source: (Mutant) -> String
787
894
  def body_source: (Mutant) -> String
@@ -790,11 +897,28 @@ module Henitai
790
897
  def same_node?: (untyped, untyped) -> bool
791
898
  def replace_child: (untyped, untyped, untyped) -> untyped
792
899
  def method_body: (untyped) -> untyped
793
- def source_file_from_ast: (Subject) -> String?
794
900
  def node_location_signature: (untyped) -> Array[untyped]?
795
901
  def compile_safe_unparse: (untyped) -> String
796
902
  end
797
903
 
904
+ class Mutant::LexicalTarget
905
+ class SubjectNotLoadedError < StandardError
906
+ end
907
+
908
+ def self.resolve: (Subject, untyped) -> untyped
909
+ def self.load_target: (Subject) -> untyped
910
+ def resolve: (Subject, untyped) -> untyped
911
+ def load_target: (Subject) -> untyped
912
+
913
+ private
914
+
915
+ def ensure_loaded: (Subject, Array[String]) -> void
916
+ def load_toplevel_source: (Subject) -> untyped
917
+ def load_subject_source: (Subject) -> void
918
+ def load_source_file: (Subject) -> void
919
+ def source_file_from_ast: (Subject) -> String?
920
+ end
921
+
798
922
  class Mutant::ParameterSource
799
923
  SERIALIZER_METHODS: Hash[Symbol, Symbol]
800
924
 
@@ -830,6 +954,7 @@ module Henitai
830
954
  def history_store: () -> MutantHistoryStore?
831
955
  def authoritative?: (untyped) -> bool
832
956
  def canonical_path: () -> String
957
+ def merged_schema_for: (untyped) -> untyped
833
958
  end
834
959
 
835
960
  class Terminal < Base
@@ -991,10 +1116,12 @@ module Henitai
991
1116
  attr_reader survivor_stats: Hash[Symbol, untyped]?
992
1117
  attr_reader session_id: String
993
1118
  attr_reader git_sha: String?
1119
+ attr_reader complete_files: Array[String]
994
1120
  attr_reader since: String?
995
1121
  attr_reader coverage_criteria: Hash[Symbol, bool]
1122
+ attr_reader sampling: Hash[Symbol, untyped]?
996
1123
 
997
- 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, ?since: String?, ?coverage_criteria: Hash[Symbol, bool]?) -> void
1124
+ 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, ?since: String?, ?coverage_criteria: Hash[Symbol, bool]?, ?complete_files: Array[String]?, ?sampling: Hash[Symbol, untyped]?) -> void
998
1125
  def partial_rerun?: () -> bool
999
1126
  def authoritative?: () -> bool
1000
1127
  def killed: () -> Integer
@@ -1017,6 +1144,7 @@ module Henitai
1017
1144
  def base_schema: () -> Hash[Symbol, untyped]
1018
1145
  def unmatched_survivor_ids: () -> Array[String]
1019
1146
  def build_files_section: () -> Hash[Symbol, untyped]
1147
+ def file_provenance: () -> Hash[Symbol, String]
1020
1148
  def mutant_to_schema: (Mutant) -> Hash[Symbol, untyped]
1021
1149
  def coverage_schema: (Mutant) -> Hash[Symbol, untyped]
1022
1150
  def replacement_for: (Mutant) -> String
@@ -1047,17 +1175,6 @@ module Henitai
1047
1175
  def load: () -> Report
1048
1176
  end
1049
1177
 
1050
- class SurvivorTestFilter
1051
- def initialize: (
1052
- coverage_map: Hash[String, Array[String]],
1053
- git_sha: String?,
1054
- ?dirty_source_files: bool,
1055
- ?worktree_changed_files: Array[String],
1056
- ?diff_analyzer: GitDiffAnalyzer
1057
- ) -> void
1058
- def apply: (Array[Mutant]) -> Hash[Symbol, Array[Mutant]]
1059
- end
1060
-
1061
1178
  class SurvivorSelector
1062
1179
  DRIFT_THRESHOLD: Float
1063
1180
 
@@ -1086,6 +1203,9 @@ module Henitai
1086
1203
  def integration: () -> untyped
1087
1204
  def operators: () -> Array[Operator]
1088
1205
  def per_test_coverage: () -> PerTestCoverage
1206
+ def source_selection_coverage: () -> PerTestCoverage
1207
+ def reuse_context: () -> ReuseContext
1208
+ def reuse_filter: () -> IncrementalFilter
1089
1209
  def history_store: () -> untyped
1090
1210
  def progress_reporter: (full_run: bool) -> untyped
1091
1211
  def source_provider: () -> ^(String) -> String
@@ -1144,6 +1264,8 @@ module Henitai
1144
1264
  def progress_reporter: () -> untyped?
1145
1265
  def history_store: () -> untyped
1146
1266
  def per_test_coverage: () -> PerTestCoverage
1267
+ def reuse_filter: () -> IncrementalFilter
1268
+ def source_selection_coverage: () -> PerTestCoverage
1147
1269
  def history_store_path: () -> String
1148
1270
  def source_files: () -> Array[String]
1149
1271
  def source_file_selection: () -> SourceFileSelection
@@ -1164,9 +1286,11 @@ module Henitai
1164
1286
  def with_reports_dir: () { () -> untyped } -> untyped
1165
1287
  def result_thresholds: () -> Hash[Symbol, Integer]?
1166
1288
  def result_coverage_criteria: () -> Hash[Symbol, bool]?
1289
+ def result_sampling: () -> Hash[Symbol, untyped]?
1167
1290
  def optional_config: (Symbol) -> untyped
1168
1291
  def survivor_rerun?: () -> bool
1169
1292
  def full_run?: () -> bool
1293
+ def complete_files: () -> Array[String]
1170
1294
  def survivor_strategy: () -> SurvivorRerunStrategy
1171
1295
  def safe_head_sha: () -> String?
1172
1296
  end
@@ -1177,27 +1301,26 @@ module Henitai
1177
1301
  def initialize: (survivors_from: String?, config: Configuration, git_diff_analyzer: untyped) -> void
1178
1302
  def active?: () -> bool
1179
1303
  def try_recipe_run: () -> Array[Mutant]?
1180
- def apply_selection: (Array[Mutant]) -> Array[Mutant]
1304
+ def apply_selection: (Array[Mutant], ?reuse_filter: IncrementalFilter?) -> Array[Mutant]
1181
1305
 
1182
1306
  private
1183
1307
 
1184
1308
  def load_survivor_report: () -> SurvivorLoader::Report
1185
- def run_from_recipes: (SurvivorLoader::Report, Array[String]?) -> Array[Mutant]?
1186
- def recipe_fast_path_safe?: (SurvivorLoader::Report, Array[String]?) -> bool
1309
+ def run_from_recipes: (SurvivorLoader::Report) -> Array[Mutant]?
1310
+ def recipe_fast_path_safe?: (SurvivorLoader::Report) -> bool
1187
1311
  def recipe_selector_and_stubs: (Array[String], Hash[String, Hash[String, untyped]]) -> [SurvivorSelector, Array[Mutant]]
1188
1312
  def load_activation_recipes: (Array[String]) -> Hash[String, Hash[String, untyped]]?
1189
1313
  def build_stub_mutant: (String, Hash[String, untyped]) -> Mutant
1190
1314
  def stub_subject_from_recipe: (Hash[String, untyped]) -> Subject
1191
1315
  def recipe_location: (Hash[String, untyped]?) -> Hash[Symbol, untyped]
1192
- def finalize_survivor_split: (SurvivorSelector, Array[Mutant], Hash[Symbol, Array[Mutant]]) -> Array[Mutant]
1316
+ def finalize_selection: (SurvivorSelector, Array[Mutant]) -> Array[Mutant]
1193
1317
  def dirty_worktree_changed_files: () -> Array[String]?
1194
1318
  def dirty_source_files?: (Array[String]?, ?git_sha: String?) -> bool
1195
1319
  def committed_changed_files: (String?) -> Array[String]
1196
1320
  def in_include_root?: (String, Array[String]) -> bool
1197
1321
  def normalize_path: (String) -> String
1198
1322
  def warn_survivor_drift: (SurvivorSelector) -> void
1199
- def build_survivor_stats: (SurvivorSelector, Array[Mutant], Hash[Symbol, Array[Mutant]]) -> Hash[Symbol, untyped]
1200
- def test_filter: (SurvivorLoader::Report, ?dirty_source_files: bool) -> SurvivorTestFilter
1323
+ def build_survivor_stats: (SurvivorSelector, Array[Mutant]) -> Hash[Symbol, untyped]
1201
1324
  end
1202
1325
 
1203
1326
  class CoverageBootstrapper
@@ -1211,6 +1334,10 @@ module Henitai
1211
1334
  def coverage_fresh?: (Array[String], Configuration, Integration::Base, Array[String]?) -> bool
1212
1335
  def coverage_report_path: (Configuration) -> String
1213
1336
  def bootstrap_coverage: (Integration::Base, Configuration, ?Array[String]?) -> void
1337
+ def flaky_detection?: (Configuration) -> bool
1338
+ def run_flaky_baseline: (Integration::Base, Configuration, Array[String]) -> void
1339
+ def resolve_test_files: (Integration::Base, Array[String]?, Configuration) -> Array[String]
1340
+ def configured_test_excludes: (Configuration) -> Array[String]?
1214
1341
  def source_file_paths: (Array[String]) -> Array[String]
1215
1342
  end
1216
1343
 
@@ -1235,5 +1362,60 @@ module RSpec
1235
1362
  class Runner
1236
1363
  def self.run: (Array[String]) -> Integer
1237
1364
  end
1365
+
1366
+ end
1367
+ end
1368
+
1369
+ module Henitai
1370
+ class TestFileOutcomes
1371
+ REPORT_FILE_NAME: String
1372
+
1373
+ def self.report_path: (String) -> String
1374
+ def self.default_report_path: () -> String
1375
+ def self.load: (String) -> TestFileOutcomes
1376
+ def initialize: () -> void
1377
+ def record: (String, failed: bool) -> void
1378
+ def record_unattributed_failure: () -> void
1379
+ def unattributed_failures?: () -> bool
1380
+ def failed_files: () -> Array[String]
1381
+ def outcomes: () -> Hash[String, String]
1382
+ def write: (String) -> void
1383
+ end
1384
+
1385
+ class FlakyTestRegistry
1386
+ FILE_NAME: String
1387
+
1388
+ def self.from_outcomes: (Hash[String, String], Hash[String, String]) -> FlakyTestRegistry
1389
+ def self.load: (String) -> FlakyTestRegistry
1390
+ def self.for_config: (untyped) -> FlakyTestRegistry
1391
+ def self.for_reports_dir: (String?) -> FlakyTestRegistry
1392
+ def initialize: (Array[String]) -> void
1393
+ def all: () -> Array[String]
1394
+ def flaky?: (String) -> bool
1395
+ def empty?: () -> bool
1396
+ def write: (String) -> void
1397
+ end
1398
+
1399
+ class FlakyDetectionBaseline
1400
+ def initialize: (reports_dir: String) -> void
1401
+ def run: (integration: untyped, test_files: Array[String]) -> FlakyTestRegistry
1402
+ end
1403
+
1404
+ module BootstrapErrorMessage
1405
+ GENERIC: String
1406
+
1407
+ def self.build: (untyped) -> String
1408
+ end
1409
+
1410
+ class FlakyRetryDecision
1411
+ def initialize: (flaky_tests: FlakyTestRegistry, max_retries: Integer) -> void
1412
+ def retry?: (status: Symbol, killing_tests: Array[String], attempts: Integer) -> bool
1413
+ end
1414
+
1415
+ class FlakyMutantRetrier
1416
+ attr_reader retried_count: Integer
1417
+
1418
+ def initialize: (flaky_tests: FlakyTestRegistry, max_retries: Integer) -> void
1419
+ def run: (mutant: Mutant, integration: untyped, test_files: Array[String], timeout: Float) -> untyped
1238
1420
  end
1239
1421
  end