Class: Test::Unit::TestSuiteProcessRunner

Inherits:
TestSuiteRunner show all
Defined in:
lib/test/unit/test-suite-process-runner.rb

Defined Under Namespace

Classes: Worker

Constant Summary collapse

MAIN_TO_WORKER_INPUT_FILENO =
3
WORKER_TO_MAIN_OUTPUT_FILENO =
4

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from TestSuiteRunner

default=, #initialize, n_workers, n_workers=, run

Constructor Details

This class inherits a constructor from Test::Unit::TestSuiteRunner

Class Method Details

.run_all_tests(result, options) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/test/unit/test-suite-process-runner.rb', line 51

def run_all_tests(result, options)
  n_workers = TestSuiteRunner.n_workers
  test_suite = options[:test_suite]

  start_tcp_server do |tcp_server|
    workers = []
    begin
      n_workers.times do |i|
        load_paths = options[:load_paths]
        base_directory = options[:base_directory]
        test_paths = options[:test_paths]
        command_line = [Gem.ruby, File.join(__dir__, "process-worker.rb")]
        load_paths.each do |load_path|
          command_line << "--load-path" << load_path
        end
        unless base_directory.nil?
          command_line << "--base-directory" << base_directory
        end
        command_line << "--worker-id" << (i + 1).to_s
        if Gem.win_platform?
          local_address = tcp_server.local_address
          command_line << "--ip-address" << local_address.ip_address
          command_line << "--ip-port" << local_address.ip_port.to_s
        end
        command_line.concat(test_paths)
        if Gem.win_platform?
          # On Windows, file descriptors 3 and above cannot be passed to
          # child processes.
          pid = spawn(*command_line)
          data_socket = tcp_server.accept
          workers << Worker.new(pid, data_socket, data_socket)
        else
          main_to_worker_input, main_to_worker_output = IO.pipe
          worker_to_main_input, worker_to_main_output = IO.pipe
          pid = spawn(*command_line, {MAIN_TO_WORKER_INPUT_FILENO => main_to_worker_input,
                                      WORKER_TO_MAIN_OUTPUT_FILENO => worker_to_main_output})
          main_to_worker_input.close
          worker_to_main_output.close
          workers << Worker.new(pid, main_to_worker_output, worker_to_main_input)
        end
      end

      run_context = TestProcessRunContext.new(self)
      yield(run_context)
      run_context.progress_block.call(TestSuite::STARTED, test_suite.name)
      run_context.progress_block.call(TestSuite::STARTED_OBJECT, test_suite)

      worker_inputs = workers.collect(&:worker_to_main_input)
      until run_context.test_names.empty? do
        select_each_worker(worker_inputs, workers) do |_, worker, data|
          case data[:status]
          when :ready
            test_name = run_context.test_names.shift
            break if test_name.nil?
            worker.send(test_name)
          when :result
            add_result(result, data)
          when :event
            emit_event(options[:event_listener], data)
          end
        end
      end
      workers.each do |worker|
        worker.send(nil)
      end
      until worker_inputs.empty? do
        select_each_worker(worker_inputs, workers) do |worker_to_main_input, worker, data|
          case data[:status]
          when :result
            add_result(result, data)
          when :event
            emit_event(options[:event_listener], data)
          when :done
            worker_inputs.delete(worker_to_main_input)
            worker.send(nil)
          end
        end
      end
    ensure
      workers.each do |worker|
        worker.wait
      end
    end

    run_context.progress_block.call(TestSuite::FINISHED, test_suite.name)
    run_context.progress_block.call(TestSuite::FINISHED_OBJECT, test_suite)
  end
end

Instance Method Details

#run(worker_context, &progress_block) ⇒ Object



175
176
177
178
# File 'lib/test/unit/test-suite-process-runner.rb', line 175

def run(worker_context, &progress_block)
  worker_context.run_context.progress_block = progress_block
  run_tests_recursive(@test_suite, worker_context, &progress_block)
end