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: SpecResolver.new, timeout: 30) ⇒ 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: SpecResolver.new, timeout: 30) ⇒ Baseline
Returns a new instance of Baseline.
18 19 20 21 |
# File 'lib/evilution/baseline.rb', line 18 def initialize(spec_resolver: SpecResolver.new, timeout: 30) @spec_resolver = spec_resolver @timeout = timeout end |
Instance Method Details
#call(subjects) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/evilution/baseline.rb', line 23 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
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/evilution/baseline.rb', line 48 def fork_spec_runner(spec_file, read_io, write_io) Process.fork do read_io.close $stdout.reopen(File::NULL, "w") $stderr.reopen(File::NULL, "w") require "rspec/core" ::RSpec.reset status = ::RSpec::Core::Runner.run( ["--format", "progress", "--no-color", "--order", "defined", spec_file] ) Marshal.dump({ passed: status.zero? }, write_io) write_io.close exit!(status.zero? ? 0 : 1) end end |
#read_result(read_io, pid) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/evilution/baseline.rb', line 67 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
36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/evilution/baseline.rb', line 36 def run_spec_file(spec_file) 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 StandardError false ensure read_io&.close write_io&.close end |
#terminate_child(pid) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/evilution/baseline.rb', line 81 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 |