Class: RSpec::MultiprocessRunner::Worker
- Inherits:
-
Object
- Object
- RSpec::MultiprocessRunner::Worker
- Defined in:
- lib/rspec/multiprocess_runner/worker.rb
Overview
This object has several roles:
-
It forks the worker process
-
In the coordinator process, it is used to send messages to the worker and track the worker’s status, completed specs, and example results.
-
In the worker process, it is used to send messages to the coordinator and actually run specs.
Constant Summary collapse
- COMMAND_QUIT =
"quit"- COMMAND_RUN_FILE =
"run_file"- STATUS_EXAMPLE_COMPLETE =
"example_complete"- STATUS_RUN_COMPLETE =
"run_complete"
Instance Attribute Summary collapse
-
#current_file ⇒ Object
readonly
Returns the value of attribute current_file.
-
#deactivation_reason ⇒ Object
Returns the value of attribute deactivation_reason.
-
#environment_number ⇒ Object
readonly
Returns the value of attribute environment_number.
-
#example_results ⇒ Object
readonly
Returns the value of attribute example_results.
-
#pid ⇒ Object
readonly
Returns the value of attribute pid.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Workers can be found in the coordinator process by their coordinator socket.
-
#initialize(environment_number, options) ⇒ Worker
constructor
A new instance of Worker.
- #kill_now ⇒ Object
- #quit_when_idle_and_wait_for_quit ⇒ Object
- #reap ⇒ Object
- #receive_and_act_on_message_from_worker ⇒ Object
- #report_example_result(example_status, description, line_number, details) ⇒ Object
- #run_file(filename) ⇒ Object
- #shutdown_now ⇒ Object
- #socket ⇒ Object
- #stalled? ⇒ Boolean
-
#start ⇒ Object
Forks the worker process.
- #test_env_number ⇒ Object
- #to_json(options = nil) ⇒ Object
- #working? ⇒ Boolean
Constructor Details
#initialize(environment_number, options) ⇒ Worker
Returns a new instance of Worker.
33 34 35 36 37 38 39 40 41 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 33 def initialize(environment_number, ) @environment_number = environment_number @worker_socket, @coordinator_socket = Socket.pair(:UNIX, :STREAM) @rspec_arguments = ([:rspec_options] || []) + ["--format", ReportingFormatter.to_s] @example_timeout_seconds = [:example_timeout_seconds] @file_timeout_seconds = [:file_timeout_seconds] @test_env_number_first_is_1 = [:test_env_number_first_is_1] @example_results = [] end |
Instance Attribute Details
#current_file ⇒ Object (readonly)
Returns the value of attribute current_file.
24 25 26 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 24 def current_file @current_file end |
#deactivation_reason ⇒ Object
Returns the value of attribute deactivation_reason.
25 26 27 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 25 def deactivation_reason @deactivation_reason end |
#environment_number ⇒ Object (readonly)
Returns the value of attribute environment_number.
24 25 26 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 24 def environment_number @environment_number end |
#example_results ⇒ Object (readonly)
Returns the value of attribute example_results.
24 25 26 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 24 def example_results @example_results end |
#pid ⇒ Object (readonly)
Returns the value of attribute pid.
24 25 26 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 24 def pid @pid end |
Instance Method Details
#==(other) ⇒ Object
Workers can be found in the coordinator process by their coordinator socket.
45 46 47 48 49 50 51 52 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 45 def ==(other) case other when Socket other == @coordinator_socket else super end end |
#kill_now ⇒ Object
137 138 139 140 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 137 def kill_now Process.kill(:KILL, pid) Process.detach(pid) end |
#quit_when_idle_and_wait_for_quit ⇒ Object
106 107 108 109 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 106 def quit_when_idle_and_wait_for_quit (command: COMMAND_QUIT) Process.wait(self.pid) end |
#reap ⇒ Object
142 143 144 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 142 def reap terminate_then_kill(3, "Reaping troubled process #{environment_number} (#{pid}; #{@current_file})") end |
#receive_and_act_on_message_from_worker ⇒ Object
146 147 148 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 146 def () end |
#report_example_result(example_status, description, line_number, details) ⇒ Object
217 218 219 220 221 222 223 224 225 226 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 217 def report_example_result(example_status, description, line_number, details) ( status: STATUS_EXAMPLE_COMPLETE, example_status: example_status, description: description, line_number: line_number, details: details, filename: @current_file ) end |
#run_file(filename) ⇒ Object
111 112 113 114 115 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 111 def run_file(filename) (command: COMMAND_RUN_FILE, filename: filename) @current_file = filename @current_file_started_at = @current_example_started_at = Time.now end |
#shutdown_now ⇒ Object
133 134 135 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 133 def shutdown_now terminate_then_kill(5) end |
#socket ⇒ Object
92 93 94 95 96 97 98 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 92 def socket if self.pid == Process.pid @worker_socket else @coordinator_socket end end |
#stalled? ⇒ Boolean
121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 121 def stalled? file_stalled = if @file_timeout_seconds working? && (Time.now - @current_file_started_at > @file_timeout_seconds) end example_stalled = if @example_timeout_seconds working? && (Time.now - @current_example_started_at > @example_timeout_seconds) end file_stalled || example_stalled end |
#start ⇒ Object
Forks the worker process. In the parent, returns the PID.
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 64 def start pid = fork if pid @worker_socket.close @pid = pid else @coordinator_socket.close @pid = Process.pid ENV["TEST_ENV_NUMBER"] = test_env_number # reset TERM handler so that # - the coordinator's version (if any) is not executed twice # - it actually terminates the process, instead of doing the ruby # default (throw an exception, which gets caught by RSpec) Kernel.trap("TERM", "SYSTEM_DEFAULT") # rely on the coordinator to handle INT Kernel.trap("INT", "IGNORE") # prevent RSpec from trapping INT, also ::RSpec::Core::Runner.instance_eval { def self.trap_interrupt; end } # Disable RSpec's at_exit hook that would try to run whatever is in ARGV ::RSpec::Core::Runner.disable_autorun! set_process_name run_loop end end |
#test_env_number ⇒ Object
54 55 56 57 58 59 60 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 54 def test_env_number if environment_number == 1 && !@test_env_number_first_is_1 "" else environment_number.to_s end end |
#to_json(options = nil) ⇒ Object
150 151 152 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 150 def to_json( = nil) { "pid" => @pid, "environment_number" => @environment_number, "current_file" => @current_file, "deactivation_reason" => @deactivation_reason }.to_json end |
#working? ⇒ Boolean
117 118 119 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 117 def working? @current_file end |