Class: Henitai::Configuration
- Inherits:
-
Object
- Object
- Henitai::Configuration
- Defined in:
- lib/henitai/configuration.rb,
sig/henitai.rbs
Overview
Loads and validates .henitai.yml configuration.
Configuration is resolved from built-in defaults and the project-root
.henitai.yml file.
Constant Summary collapse
- DEFAULT_TIMEOUT =
10.0- DEFAULT_TIMEOUT_MULTIPLIER =
3.0- DEFAULT_OPERATORS =
:light- DEFAULT_JOBS =
1- DEFAULT_MAX_FLAKY_RETRIES =
3- DEFAULT_MAX_LOG_BYTES =
Cap on captured child stdout/stderr per stream (bytes). A runaway mutant (e.g. one that puts henitai's own suite into a spewing recursion) can otherwise write hundreds of MB per child; overflow is discarded.
5_000_000- DEFAULT_MAX_TIMEOUT =
Ceiling for the per-mutant auto-calibrated timeout (seconds). Keeps a runaway from running for minutes when the calibrated value is large.
30.0- DEFAULT_CHECKPOINT_EVERY =
Incremental report checkpoint cadence for long full runs.
200- DEFAULT_CHECKPOINT_INTERVAL =
30.0- DEFAULT_REPORTS_DIR =
"reports"- DEFAULT_COVERAGE_CRITERIA =
All three default to true because Result's MS numerator has always counted killed + timeout + runtime_error unconditionally. Until 0.5.0 this block was validated but never read, so the shipped
falsedefaults described behavior the scorer did not have. Wiring it up with those defaults intact would have silently dropped timeouts and aborts out of every user's score; flipping them keeps the numerator exactly as it was and makes the knob mean what it says. See Result::CRITERION_STATUSES for the mapping. { test_result: true, timeout: true, process_abort: true }.freeze
- DEFAULT_THRESHOLDS =
{ high: 80, low: 60 }.freeze
- CONFIG_FILE =
".henitai.yml"- DEFAULT_MAX_MUTANTS_PER_LINE =
Instance Attribute Summary collapse
-
#all_logs ⇒ Boolean
readonly
Returns the value of attribute all_logs.
-
#checkpoint_enabled ⇒ Boolean
readonly
Returns the value of attribute checkpoint_enabled.
-
#checkpoint_every ⇒ Integer
readonly
Returns the value of attribute checkpoint_every.
-
#checkpoint_interval ⇒ Float
readonly
Returns the value of attribute checkpoint_interval.
-
#coverage_criteria ⇒ Hash[Symbol, untyped]
readonly
Returns the value of attribute coverage_criteria.
-
#dashboard ⇒ Hash[Symbol, untyped]
readonly
Returns the value of attribute dashboard.
-
#excludes ⇒ Array[String]
readonly
Returns the value of attribute excludes.
-
#ignore_patterns ⇒ Array[untyped]
readonly
Returns the value of attribute ignore_patterns.
-
#includes ⇒ Array[String]
readonly
Returns the value of attribute includes.
-
#integration ⇒ Object
readonly
Returns the value of attribute integration.
-
#jobs ⇒ Object
readonly
Returns the value of attribute jobs.
-
#max_flaky_retries ⇒ Integer
readonly
Returns the value of attribute max_flaky_retries.
-
#max_log_bytes ⇒ Integer
readonly
Returns the value of attribute max_log_bytes.
-
#max_mutants_per_line ⇒ Integer
readonly
Returns the value of attribute max_mutants_per_line.
-
#max_timeout ⇒ Float
readonly
Returns the value of attribute max_timeout.
-
#operators ⇒ Symbol
readonly
Returns the value of attribute operators.
-
#reporters ⇒ Array[String]
readonly
Returns the value of attribute reporters.
-
#reports_dir ⇒ String
readonly
Returns the value of attribute reports_dir.
-
#sampling ⇒ Object
readonly
Returns the value of attribute sampling.
-
#test_excludes ⇒ Array[String]
readonly
Returns the value of attribute test_excludes.
-
#thresholds ⇒ Hash[Symbol, Integer]
readonly
Returns the value of attribute thresholds.
-
#timeout ⇒ Float
readonly
Returns the value of attribute timeout.
-
#timeout_multiplier ⇒ Float
readonly
Returns the value of attribute timeout_multiplier.
Class Method Summary collapse
Instance Method Summary collapse
- #apply_analysis_defaults(raw) ⇒ void
- #apply_defaults(raw) ⇒ void
- #apply_general_defaults(raw) ⇒ void
- #apply_mutation_defaults(raw) ⇒ void
- #apply_mutation_limit_defaults(mutation) ⇒ void
- #apply_reports_defaults(raw) ⇒ void
- #default_dashboard(overrides) ⇒ Hash[Symbol, untyped]
- #detect_integration ⇒ String
-
#initialize(path: CONFIG_FILE, overrides: {}) ⇒ Configuration
constructor
A new instance of Configuration.
- #load_raw_configuration(path) ⇒ Hash[Symbol, untyped]
- #merge_defaults(defaults, overrides) ⇒ Hash[Symbol, untyped]
- #resolve_integration_default(integration) ⇒ Object
- #symbolize_keys(value) ⇒ Object
-
#timeout_configured? ⇒ Boolean
True when mutation.timeout was set explicitly (file or CLI override); a fixed timeout disables per-mutant auto-calibration.
Constructor Details
#initialize(path: CONFIG_FILE, overrides: {}) ⇒ Configuration
Returns a new instance of Configuration.
63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/henitai/configuration.rb', line 63 def initialize(path: CONFIG_FILE, overrides: {}) @config_dir = File.dirname(File.(path)) raw = load_raw_configuration(path) unless raw.is_a?(Hash) raise Henitai::ConfigurationError, "Invalid configuration value for configuration: expected Hash, got #{raw.class}" end merged = merge_defaults(raw, symbolize_keys(overrides)) ConfigurationValidator.validate!(merged) apply_defaults(merged) end |
Instance Attribute Details
#all_logs ⇒ Boolean (readonly)
Returns the value of attribute all_logs.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def all_logs @all_logs end |
#checkpoint_enabled ⇒ Boolean (readonly)
Returns the value of attribute checkpoint_enabled.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def checkpoint_enabled @checkpoint_enabled end |
#checkpoint_every ⇒ Integer (readonly)
Returns the value of attribute checkpoint_every.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def checkpoint_every @checkpoint_every end |
#checkpoint_interval ⇒ Float (readonly)
Returns the value of attribute checkpoint_interval.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def checkpoint_interval @checkpoint_interval end |
#coverage_criteria ⇒ Hash[Symbol, untyped] (readonly)
Returns the value of attribute coverage_criteria.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def coverage_criteria @coverage_criteria end |
#dashboard ⇒ Hash[Symbol, untyped] (readonly)
Returns the value of attribute dashboard.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def dashboard @dashboard end |
#excludes ⇒ Array[String] (readonly)
Returns the value of attribute excludes.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def excludes @excludes end |
#ignore_patterns ⇒ Array[untyped] (readonly)
Returns the value of attribute ignore_patterns.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def ignore_patterns @ignore_patterns end |
#includes ⇒ Array[String] (readonly)
Returns the value of attribute includes.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def includes @includes end |
#integration ⇒ Object (readonly)
Returns the value of attribute integration.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def integration @integration end |
#jobs ⇒ Object (readonly)
Returns the value of attribute jobs.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def jobs @jobs end |
#max_flaky_retries ⇒ Integer (readonly)
Returns the value of attribute max_flaky_retries.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def max_flaky_retries @max_flaky_retries end |
#max_log_bytes ⇒ Integer (readonly)
Returns the value of attribute max_log_bytes.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def max_log_bytes @max_log_bytes end |
#max_mutants_per_line ⇒ Integer (readonly)
Returns the value of attribute max_mutants_per_line.
188 189 190 |
# File 'sig/henitai.rbs', line 188 def max_mutants_per_line @max_mutants_per_line end |
#max_timeout ⇒ Float (readonly)
Returns the value of attribute max_timeout.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def max_timeout @max_timeout end |
#operators ⇒ Symbol (readonly)
Returns the value of attribute operators.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def operators @operators end |
#reporters ⇒ Array[String] (readonly)
Returns the value of attribute reporters.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def reporters @reporters end |
#reports_dir ⇒ String (readonly)
Returns the value of attribute reports_dir.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def reports_dir @reports_dir end |
#sampling ⇒ Object (readonly)
Returns the value of attribute sampling.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def sampling @sampling end |
#test_excludes ⇒ Array[String] (readonly)
Returns the value of attribute test_excludes.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def test_excludes @test_excludes end |
#thresholds ⇒ Hash[Symbol, Integer] (readonly)
Returns the value of attribute thresholds.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def thresholds @thresholds end |
#timeout ⇒ Float (readonly)
Returns the value of attribute timeout.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def timeout @timeout end |
#timeout_multiplier ⇒ Float (readonly)
Returns the value of attribute timeout_multiplier.
44 45 46 |
# File 'lib/henitai/configuration.rb', line 44 def timeout_multiplier @timeout_multiplier end |
Class Method Details
.load(path: CONFIG_FILE, overrides: {}) ⇒ Configuration
59 60 61 |
# File 'lib/henitai/configuration.rb', line 59 def self.load(path: CONFIG_FILE, overrides: {}) new(path:, overrides:) end |
Instance Method Details
#apply_analysis_defaults(raw) ⇒ void
This method returns an undefined value.
136 137 138 139 140 |
# File 'lib/henitai/configuration.rb', line 136 def apply_analysis_defaults(raw) @coverage_criteria = merge_defaults(DEFAULT_COVERAGE_CRITERIA, raw[:coverage_criteria]) @thresholds = merge_defaults(DEFAULT_THRESHOLDS, raw[:thresholds]) end |
#apply_defaults(raw) ⇒ void
This method returns an undefined value.
92 93 94 95 96 97 |
# File 'lib/henitai/configuration.rb', line 92 def apply_defaults(raw) apply_general_defaults(raw) apply_mutation_defaults(raw) apply_reports_defaults(raw) apply_analysis_defaults(raw) end |
#apply_general_defaults(raw) ⇒ void
This method returns an undefined value.
99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/henitai/configuration.rb', line 99 def apply_general_defaults(raw) @integration = resolve_integration_default(raw[:integration]) @includes = raw[:includes] || ["lib"] @excludes = raw[:excludes] || [] @test_excludes = raw[:test_excludes] || [] @jobs = raw.fetch(:jobs, DEFAULT_JOBS) @reporters = raw[:reporters] || ["terminal"] @reports_dir = raw[:reports_dir] || DEFAULT_REPORTS_DIR @all_logs = raw[:all_logs] == true @dashboard = default_dashboard(raw[:dashboard]) end |
#apply_mutation_defaults(raw) ⇒ void
This method returns an undefined value.
111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/henitai/configuration.rb', line 111 def apply_mutation_defaults(raw) mutation = raw[:mutation] || {} @operators = (mutation[:operators] || DEFAULT_OPERATORS).to_sym @timeout_configured = !mutation[:timeout].nil? @timeout = mutation[:timeout] || DEFAULT_TIMEOUT @timeout_multiplier = mutation[:timeout_multiplier] || DEFAULT_TIMEOUT_MULTIPLIER @ignore_patterns = mutation[:ignore_patterns] || [] @sampling = mutation[:sampling] apply_mutation_limit_defaults(mutation) end |
#apply_mutation_limit_defaults(mutation) ⇒ void
This method returns an undefined value.
123 124 125 126 127 |
# File 'lib/henitai/configuration.rb', line 123 def apply_mutation_limit_defaults(mutation) @max_flaky_retries = mutation.fetch(:max_flaky_retries, DEFAULT_MAX_FLAKY_RETRIES) @max_log_bytes = mutation[:max_log_bytes] || DEFAULT_MAX_LOG_BYTES @max_timeout = mutation[:max_timeout] || DEFAULT_MAX_TIMEOUT end |
#apply_reports_defaults(raw) ⇒ void
This method returns an undefined value.
129 130 131 132 133 134 |
# File 'lib/henitai/configuration.rb', line 129 def apply_reports_defaults(raw) reports = raw[:reports] || {} @checkpoint_enabled = reports.fetch(:checkpoint, true) @checkpoint_every = reports[:checkpoint_every] || DEFAULT_CHECKPOINT_EVERY @checkpoint_interval = reports[:checkpoint_interval] || DEFAULT_CHECKPOINT_INTERVAL end |
#default_dashboard(overrides) ⇒ Hash[Symbol, untyped]
161 162 163 164 165 |
# File 'lib/henitai/configuration.rb', line 161 def default_dashboard(overrides) # @type var empty_dashboard: Hash[Symbol, untyped] empty_dashboard = {} merge_defaults(empty_dashboard, overrides) end |
#detect_integration ⇒ String
84 85 86 87 88 89 90 |
# File 'lib/henitai/configuration.rb', line 84 def detect_integration return "rspec" if File.exist?(File.join(@config_dir, ".rspec")) return "minitest" if File.directory?(File.join(@config_dir, "test")) return "rspec" if File.directory?(File.join(@config_dir, "spec")) "rspec" end |
#load_raw_configuration(path) ⇒ Hash[Symbol, untyped]
77 78 79 80 81 82 |
# File 'lib/henitai/configuration.rb', line 77 def load_raw_configuration(path) return {} unless File.exist?(path) raw = Psych.safe_load(File.read(path), symbolize_names: true) raw || {} end |
#merge_defaults(defaults, overrides) ⇒ Hash[Symbol, untyped]
142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/henitai/configuration.rb', line 142 def merge_defaults(defaults, overrides) return defaults.dup if overrides.nil? defaults.merge(overrides) do |_key, default_value, override_value| if default_value.is_a?(Hash) && override_value.is_a?(Hash) merge_defaults(default_value, override_value) else override_value end end end |
#resolve_integration_default(integration) ⇒ Object
154 155 156 157 158 159 |
# File 'lib/henitai/configuration.rb', line 154 def resolve_integration_default(integration) return integration[:name] || detect_integration if integration.is_a?(Hash) return detect_integration if integration.nil? integration end |
#symbolize_keys(value) ⇒ Object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/henitai/configuration.rb', line 167 def symbolize_keys(value) case value when Hash # @type var result: Hash[Symbol, untyped] result = {} value.each do |key, val| result[key.to_sym] = symbolize_keys(val) end result when Array value.map { |item| symbolize_keys(item) } else value end end |
#timeout_configured? ⇒ Boolean
True when mutation.timeout was set explicitly (file or CLI override); a fixed timeout disables per-mutant auto-calibration.
54 55 56 |
# File 'lib/henitai/configuration.rb', line 54 def timeout_configured? @timeout_configured end |