henitai 0.5.3 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +222 -1
- data/README.md +100 -13
- data/assets/schema/henitai.schema.json +20 -0
- data/lib/henitai/arid_node_filter.rb +4 -19
- data/lib/henitai/bootstrap_error_message.rb +20 -0
- data/lib/henitai/canonical_report_merger.rb +23 -2
- data/lib/henitai/cli/run_command.rb +25 -7
- data/lib/henitai/cli/run_options.rb +1 -1
- data/lib/henitai/cli.rb +4 -1
- data/lib/henitai/configuration.rb +4 -1
- data/lib/henitai/configuration_validator/rules.rb +8 -0
- data/lib/henitai/configuration_validator/scalars.rb +9 -0
- data/lib/henitai/configuration_validator.rb +2 -1
- data/lib/henitai/constant_path.rb +48 -0
- data/lib/henitai/control_run.rb +73 -0
- data/lib/henitai/coverage_bootstrapper.rb +36 -10
- data/lib/henitai/coverage_formatter.rb +26 -3
- data/lib/henitai/coverage_report_reader.rb +21 -0
- data/lib/henitai/equivalence_detector/operand_predicates.rb +16 -0
- data/lib/henitai/equivalence_detector.rb +46 -38
- data/lib/henitai/example_summary.rb +24 -0
- data/lib/henitai/execution_engine/fork_server_scope.rb +57 -0
- data/lib/henitai/execution_engine.rb +75 -60
- data/lib/henitai/fidelity_check.rb +173 -0
- data/lib/henitai/flaky_detection_baseline.rb +61 -0
- data/lib/henitai/flaky_mutant_retrier.rb +43 -0
- data/lib/henitai/flaky_retry_decision.rb +23 -0
- data/lib/henitai/flaky_test_registry.rb +63 -0
- data/lib/henitai/fork_server/client.rb +231 -0
- data/lib/henitai/fork_server/group_killer.rb +48 -0
- data/lib/henitai/fork_server/group_terminator.rb +47 -0
- data/lib/henitai/fork_server/launcher.rb +38 -0
- data/lib/henitai/fork_server/mutant_runner.rb +141 -0
- data/lib/henitai/fork_server/protocol.rb +73 -0
- data/lib/henitai/fork_server/reaper.rb +24 -0
- data/lib/henitai/fork_server/runtime.rb +109 -0
- data/lib/henitai/fork_server/server.rb +108 -0
- data/lib/henitai/fork_server/server_process.rb +73 -0
- data/lib/henitai/fork_server/status.rb +52 -0
- data/lib/henitai/fork_server.rb +43 -0
- data/lib/henitai/generated_artifacts.rb +3 -0
- data/lib/henitai/git_diff_analyzer.rb +28 -11
- data/lib/henitai/incremental_filter.rb +20 -10
- data/lib/henitai/integration/base.rb +72 -5
- data/lib/henitai/integration/capped_log_sink.rb +34 -0
- data/lib/henitai/integration/child_bootstrap.rb +7 -0
- data/lib/henitai/integration/child_report_store.rb +36 -0
- data/lib/henitai/integration/minitest.rb +7 -5
- data/lib/henitai/integration/minitest_autorun.rb +20 -0
- data/lib/henitai/integration/minitest_outcome_reporter.rb +28 -0
- data/lib/henitai/integration/minitest_preload.rb +30 -0
- data/lib/henitai/integration/minitest_runnable_filter.rb +61 -0
- data/lib/henitai/integration/minitest_test_runner.rb +32 -15
- data/lib/henitai/integration/mutant_run_support.rb +73 -13
- data/lib/henitai/integration/rspec_child_runner.rb +44 -9
- data/lib/henitai/integration/rspec_preload.rb +35 -0
- data/lib/henitai/integration/rspec_process_runner.rb +4 -1
- data/lib/henitai/integration/scenario_log_support.rb +31 -18
- data/lib/henitai/integration.rb +16 -3
- data/lib/henitai/minitest_coverage_reporter.rb +22 -6
- data/lib/henitai/minitest_result_file.rb +62 -0
- data/lib/henitai/mutant/activation.rb +32 -0
- data/lib/henitai/mutant/activator.rb +75 -55
- data/lib/henitai/mutant/def_injection.rb +136 -0
- data/lib/henitai/mutant/lexical_scope_check.rb +120 -0
- data/lib/henitai/mutant/lexical_target.rb +105 -0
- data/lib/henitai/mutant/replacement.rb +52 -0
- data/lib/henitai/mutant.rb +27 -8
- data/lib/henitai/mutant_generator.rb +62 -18
- data/lib/henitai/mutant_history_store/verdict_cache.rb +12 -11
- data/lib/henitai/mutant_history_store.rb +14 -4
- data/lib/henitai/mutant_identity.rb +5 -1
- data/lib/henitai/mutant_verdict.rb +71 -0
- data/lib/henitai/operators/array_declaration.rb +4 -0
- data/lib/henitai/operators/assignment_expression.rb +2 -0
- data/lib/henitai/operators/conditional_expression.rb +21 -1
- data/lib/henitai/operators/hash_literal.rb +7 -4
- data/lib/henitai/operators/method_expression.rb +14 -3
- data/lib/henitai/operators/regex_metacharacters.rb +89 -0
- data/lib/henitai/operators/regex_mutator.rb +23 -28
- data/lib/henitai/operators/return_value.rb +1 -1
- data/lib/henitai/operators.rb +1 -0
- data/lib/henitai/per_test_coverage.rb +11 -7
- data/lib/henitai/per_test_coverage_collector.rb +30 -31
- data/lib/henitai/per_test_coverage_delta.rb +60 -0
- data/lib/henitai/per_test_coverage_selector.rb +26 -13
- data/lib/henitai/process_wakeup.rb +8 -3
- data/lib/henitai/process_worker_runner.rb +19 -5
- data/lib/henitai/reporter.rb +15 -8
- data/lib/henitai/result.rb +32 -16
- data/lib/henitai/reuse_context.rb +50 -0
- data/lib/henitai/rspec_coverage_formatter.rb +4 -0
- data/lib/henitai/rspec_outcomes.rb +72 -0
- data/lib/henitai/runner.rb +58 -19
- data/lib/henitai/runner_dependencies.rb +22 -1
- data/lib/henitai/sampling_strategy.rb +36 -6
- data/lib/henitai/scenario_execution_result.rb +28 -5
- data/lib/henitai/signature_line.rb +21 -0
- data/lib/henitai/slot_scheduler/draining.rb +12 -2
- data/lib/henitai/slot_scheduler/process_control.rb +33 -0
- data/lib/henitai/slot_scheduler/retry_policy.rb +8 -6
- data/lib/henitai/slot_scheduler.rb +47 -8
- data/lib/henitai/source_file_selection.rb +1 -1
- data/lib/henitai/source_parser.rb +29 -9
- data/lib/henitai/static_filter.rb +45 -14
- data/lib/henitai/stillborn_filter.rb +70 -2
- data/lib/henitai/subject.rb +8 -3
- data/lib/henitai/subject_resolver.rb +65 -31
- data/lib/henitai/suite_boot_clock.rb +48 -0
- data/lib/henitai/survivor_activation_cache.rb +18 -11
- data/lib/henitai/survivor_rerun_strategy.rb +47 -43
- data/lib/henitai/test_file_outcomes.rb +79 -0
- data/lib/henitai/timeout_calibrator.rb +31 -9
- data/lib/henitai/timeout_ceiling.rb +37 -0
- data/lib/henitai/verdict_fingerprint.rb +29 -30
- data/lib/henitai/version.rb +1 -1
- data/lib/henitai.rb +17 -1
- data/sig/configuration_validator.rbs +1 -0
- data/sig/henitai.rbs +225 -45
- metadata +46 -3
- 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
|
|
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
|
|
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?, ?
|
|
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
|
|
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?, ?
|
|
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
|
|
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,
|
|
675
|
-
def self?.survivor_fingerprint_current?: (String?, live_paths: Array[String],
|
|
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
|
|
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
|
|
1186
|
-
def recipe_fast_path_safe?: (SurvivorLoader::Report
|
|
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
|
|
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]
|
|
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,8 @@ 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
|
|
1214
1339
|
def resolve_test_files: (Integration::Base, Array[String]?, Configuration) -> Array[String]
|
|
1215
1340
|
def configured_test_excludes: (Configuration) -> Array[String]?
|
|
1216
1341
|
def source_file_paths: (Array[String]) -> Array[String]
|
|
@@ -1237,5 +1362,60 @@ module RSpec
|
|
|
1237
1362
|
class Runner
|
|
1238
1363
|
def self.run: (Array[String]) -> Integer
|
|
1239
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
|
|
1240
1420
|
end
|
|
1241
1421
|
end
|