Class: ActiveMutator::Runner
- Inherits:
-
Object
- Object
- ActiveMutator::Runner
- Defined in:
- lib/active_mutator/runner.rb
Instance Method Summary collapse
- #call ⇒ Object
- #exit_code(results) ⇒ Object
-
#initialize(config, reporter: nil) ⇒ Runner
constructor
A new instance of Runner.
-
#plan_work(mutations, map, ledger: nil, fingerprints: {}) ⇒ Object
Returns [work_items, pre_results].
Constructor Details
#initialize(config, reporter: nil) ⇒ Runner
Returns a new instance of Runner.
5 6 7 8 |
# File 'lib/active_mutator/runner.rb', line 5 def initialize(config, reporter: nil) @config = config @reporter = reporter || build_reporter end |
Instance Method Details
#call ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/active_mutator/runner.rb', line 10 def call ENV["ACTIVE_MUTATOR"] = "1" load_operators preload! preload_spec_helper! map = Baseline.new(root: @config.root).coverage_map(force: @config.force_baseline) @reporter.coverage_map = map if @reporter.respond_to?(:coverage_map=) subjects = discover_subjects analyses = subjects.map { |s| Engine.new.analyze(s) } mutations = analyses.flat_map(&:mutations) mutations = mutations.first(@config.max_mutants) if @config.max_mutants invalid_count = analyses.sum(&:invalid_count) fingerprints = Fingerprint.for_mutations(mutations, root: @config.root) ledger = AcceptedLedger.load(@config.root) scanned_files = prune_scope(subjects) warn_stale(ledger, fingerprints.values, scanned_files) items, pre_results = plan_work(mutations, map, ledger: ledger, fingerprints: fingerprints) return debug_plan(items, pre_results) if @config.debug_plan pre_results.each { |r| @reporter.on_result(r) } calibrators = if @config.adaptive_timeout { parallel: TimeoutCalibrator.new, serial: TimeoutCalibrator.new } end scheduler = Scheduler.new(jobs: @config.jobs, on_result: @reporter.method(:on_result), calibrators: calibrators) results = scheduler.run(items) + pre_results accept_survivors!(ledger, results, fingerprints, scanned_files) if @config.accept_survivors @reporter.summary(results, invalid_count: invalid_count) exit_code(results) end |
#exit_code(results) ⇒ Object
69 70 71 72 73 74 75 76 77 |
# File 'lib/active_mutator/runner.rb', line 69 def exit_code(results) survived = results.count { |r| r.status == :survived } return 0 if survived.zero? return 1 unless @config.fail_at detected = results.count { |r| %i[killed timeout].include?(r.status) } score = detected * 100.0 / (detected + survived) score >= @config.fail_at ? 0 : 1 end |
#plan_work(mutations, map, ledger: nil, fingerprints: {}) ⇒ Object
Returns [work_items, pre_results]. Public for unit testing.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/active_mutator/runner.rb', line 46 def plan_work(mutations, map, ledger: nil, fingerprints: {}) items = [] pre_results = [] mutations.each do |mutation| if ledger&.accepted?(fingerprints[mutation]) pre_results << Result.new(mutation: mutation, status: :accepted, details: nil) next end example_ids = map.examples_for(mutation.subject.file, coverage_lines(mutation)) if example_ids.empty? pre_results << Result.new(mutation: mutation, status: :uncovered, details: nil) else lane = example_ids.any? { |id| serial_example?(id) } ? :serial : :parallel variable = map.time_for(example_ids) * @config.timeout_factor boot_extra = lane == :serial ? @config.browser_boot_seconds : 0.0 timeout = variable + @config.timeout_floor + boot_extra items << WorkItem.new(mutation: mutation, example_ids: example_ids, timeout: timeout, lane: lane, variable: variable) end end [items, pre_results] end |