Class: Evilution::Baseline Private

Inherits:
Object
  • Object
show all
Defined in:
lib/evilution/baseline.rb

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Defined Under Namespace

Classes: Result

Constant Summary collapse

GRACE_PERIOD =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

0.5

Instance Method Summary collapse

Constructor Details

#initialize(spec_resolver: Evilution::SpecResolver.new, timeout: 30, runner: nil, fallback_dir: "spec", test_files: nil) ⇒ Baseline

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Baseline.



18
19
20
21
22
23
24
25
# File 'lib/evilution/baseline.rb', line 18

def initialize(spec_resolver: Evilution::SpecResolver.new, timeout: 30, runner: nil,
               fallback_dir: "spec", test_files: nil)
  @spec_resolver = spec_resolver
  @timeout = timeout
  @runner = runner
  @fallback_dir = fallback_dir
  @test_files = test_files
end

Instance Method Details

#call(subjects) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/evilution/baseline.rb', line 27

def call(subjects)
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  spec_files = baseline_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

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/evilution/baseline.rb', line 56

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

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/evilution/baseline.rb', line 72

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)
    result[:passed]
  else
    terminate_child(pid)
    false
  end
end

#run_spec_file(spec_file) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/evilution/baseline.rb', line 40

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

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/evilution/baseline.rb', line 86

def terminate_child(pid)
  Evilution::ProcessCleanup.safe_kill("TERM", pid)
  _, status = Process.waitpid2(pid, Process::WNOHANG)
  return if status

  sleep(GRACE_PERIOD)
  _, status = Process.waitpid2(pid, Process::WNOHANG)
  return if status

  Evilution::ProcessCleanup.safe_kill("KILL", pid)
  Evilution::ProcessCleanup.safe_wait(pid)
end