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.
- #working? ⇒ Boolean
Constructor Details
#initialize(environment_number, options) ⇒ Worker
Returns a new instance of Worker.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 32 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] @example_results = [] # Use a single configuration and world across all individual runs # This will not be necessary to do manually in RSpec 3 — it does not # reset the globals after each run. @rspec_configuration = RSpec.configuration @rspec_world = RSpec.world end |
Instance Attribute Details
#current_file ⇒ Object (readonly)
Returns the value of attribute current_file.
23 24 25 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 23 def current_file @current_file end |
#deactivation_reason ⇒ Object
Returns the value of attribute deactivation_reason.
24 25 26 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 24 def deactivation_reason @deactivation_reason end |
#environment_number ⇒ Object (readonly)
Returns the value of attribute environment_number.
23 24 25 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 23 def environment_number @environment_number end |
#example_results ⇒ Object (readonly)
Returns the value of attribute example_results.
23 24 25 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 23 def example_results @example_results end |
#pid ⇒ Object (readonly)
Returns the value of attribute pid.
23 24 25 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 23 def pid @pid end |
Instance Method Details
#==(other) ⇒ Object
Workers can be found in the coordinator process by their coordinator socket.
49 50 51 52 53 54 55 56 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 49 def ==(other) case other when Socket other == @coordinator_socket else super end end |
#kill_now ⇒ Object
130 131 132 133 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 130 def kill_now Process.kill(:KILL, pid) Process.detach(pid) end |
#quit_when_idle_and_wait_for_quit ⇒ Object
99 100 101 102 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 99 def quit_when_idle_and_wait_for_quit (command: COMMAND_QUIT) Process.wait(self.pid) end |
#reap ⇒ Object
135 136 137 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 135 def reap terminate_then_kill(3, "Reaping troubled process #{environment_number} (#{pid}; #{@current_file})") end |
#receive_and_act_on_message_from_worker ⇒ Object
139 140 141 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 139 def () end |
#report_example_result(example_status, description, line_number, details) ⇒ Object
203 204 205 206 207 208 209 210 211 212 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 203 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, file_path: @current_file ) end |
#run_file(filename) ⇒ Object
104 105 106 107 108 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 104 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
126 127 128 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 126 def shutdown_now terminate_then_kill(5) end |
#socket ⇒ Object
85 86 87 88 89 90 91 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 85 def socket if self.pid == Process.pid @worker_socket else @coordinator_socket end end |
#stalled? ⇒ Boolean
114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 114 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.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 60 def start pid = fork if pid @worker_socket.close @pid = pid else @coordinator_socket.close @pid = Process.pid ENV["TEST_ENV_NUMBER"] = environment_number.to_s # 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 } set_process_name run_loop end end |
#working? ⇒ Boolean
110 111 112 |
# File 'lib/rspec/multiprocess_runner/worker.rb', line 110 def working? @current_file end |