Class: Evilution::Baseline
- Inherits:
-
Object
- Object
- Evilution::Baseline
- Defined in:
- lib/evilution/baseline.rb
Defined Under Namespace
Classes: Result
Constant Summary collapse
- GRACE_PERIOD =
0.5
Instance Method Summary collapse
- #call(subjects) ⇒ Object
- #fork_spec_runner(spec_file, read_io, write_io) ⇒ Object
-
#initialize(spec_resolver: Evilution::SpecResolver.new, timeout: 30, runner: nil, fallback_dir: "spec") ⇒ Baseline
constructor
A new instance of Baseline.
- #read_result(read_io, pid) ⇒ Object
- #run_spec_file(spec_file) ⇒ Object
- #terminate_child(pid) ⇒ Object
Constructor Details
#initialize(spec_resolver: Evilution::SpecResolver.new, timeout: 30, runner: nil, fallback_dir: "spec") ⇒ Baseline
Returns a new instance of Baseline.
17 18 19 20 21 22 |
# File 'lib/evilution/baseline.rb', line 17 def initialize(spec_resolver: Evilution::SpecResolver.new, timeout: 30, runner: nil, fallback_dir: "spec") @spec_resolver = spec_resolver @timeout = timeout @runner = runner @fallback_dir = fallback_dir end |
Instance Method Details
#call(subjects) ⇒ Object
24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/evilution/baseline.rb', line 24 def call(subjects) start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) spec_files = resolve_unique_spec_files(subjects) failed = Set.new spec_files.each do |spec_file| failed.add(spec_file) unless run_spec_file(spec_file) end duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time Result.new(failed_spec_files: failed, duration: duration) end |
#fork_spec_runner(spec_file, read_io, write_io) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/evilution/baseline.rb', line 53 def fork_spec_runner(spec_file, read_io, write_io) runner = @runner Process.fork do read_io.close $stdout.reopen(File::NULL, "w") $stderr.reopen(File::NULL, "w") passed = runner.call(spec_file) Marshal.dump({ passed: passed }, write_io) write_io.close exit!(passed ? 0 : 1) end end |
#read_result(read_io, pid) ⇒ Object
69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/evilution/baseline.rb', line 69 def read_result(read_io, pid) if read_io.wait_readable(@timeout) data = read_io.read Process.wait(pid) return false if data.empty? result = Marshal.load(data) # rubocop:disable Security/MarshalLoad result[:passed] else terminate_child(pid) false end end |
#run_spec_file(spec_file) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/evilution/baseline.rb', line 37 def run_spec_file(spec_file) raise Evilution::Error, "no baseline runner configured" unless @runner read_io, write_io = IO.pipe pid = fork_spec_runner(spec_file, read_io, write_io) write_io.close read_result(read_io, pid) rescue Evilution::Error raise rescue StandardError false ensure read_io&.close write_io&.close end |
#terminate_child(pid) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/evilution/baseline.rb', line 83 def terminate_child(pid) Process.kill("TERM", pid) rescue nil # rubocop:disable Style/RescueModifier _, status = Process.waitpid2(pid, Process::WNOHANG) return if status sleep(GRACE_PERIOD) _, status = Process.waitpid2(pid, Process::WNOHANG) return if status Process.kill("KILL", pid) rescue nil # rubocop:disable Style/RescueModifier Process.wait(pid) rescue nil # rubocop:disable Style/RescueModifier end |