1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
unless defined?(JRUBY_VERSION)
require 'coveralls'
Coveralls.wear!
end
require 'childprocess'
require 'rspec'
require 'tempfile'
require 'socket'
require 'stringio'
module ChildProcessSpecHelper
RUBY = defined?(Gem) ? Gem.ruby : 'ruby'
CapturedOutput = Struct.new(:stdout, :stderr)
def ruby_process(*args)
@process = ChildProcess.build(RUBY , *args)
end
def windows_process(*args)
@process = ChildProcess.build("powershell", *args)
end
def sleeping_ruby(seconds = nil)
if seconds
ruby_process("-e", "sleep #{seconds}")
else
ruby_process("-e", "sleep")
end
end
def invalid_process
@process = ChildProcess.build("unlikelytoexist")
end
def ignored(signal)
code = <<-RUBY
trap(#{signal.inspect}, "IGNORE")
sleep
RUBY
ruby_process tmp_script(code)
end
def write_env(path)
if ChildProcess.os == :windows
ps_env_file_path = File.expand_path(File.dirname(__FILE__))
args = ['-File', "#{ps_env_file_path}/get_env.ps1", path]
windows_process(*args)
else
code = <<-RUBY
File.open(#{path.inspect}, "w") { |f| f << ENV.inspect }
RUBY
ruby_process tmp_script(code)
end
end
def write_argv(path, *args)
code = <<-RUBY
File.open(#{path.inspect}, "w") { |f| f << ARGV.inspect }
RUBY
ruby_process(tmp_script(code), *args)
end
def write_pid(path)
code = <<-RUBY
File.open(#{path.inspect}, "w") { |f| f << Process.pid }
RUBY
ruby_process tmp_script(code)
end
def write_pid_in_sleepy_grand_child(path)
code = <<-RUBY
system "ruby", "-e", 'File.open(#{path.inspect}, "w") { |f| f << Process.pid; f.flush }; sleep'
RUBY
ruby_process tmp_script(code)
end
def exit_with(exit_code)
ruby_process(tmp_script("exit(#{exit_code})"))
end
def with_env(hash)
hash.each { |k,v| ENV[k] = v }
begin
yield
ensure
hash.each_key { |k| ENV[k] = nil }
end
end
def tmp_script(code)
# use an ivar to avoid GC
@tf = Tempfile.new("childprocess-temp")
@tf << code
@tf.close
puts code if $DEBUG
@tf.path
end
def cat
if ChildProcess.os == :windows
ruby(<<-CODE)
STDIN.sync = STDOUT.sync = true
IO.copy_stream(STDIN, STDOUT)
CODE
else
ChildProcess.build("cat")
end
end
def echo
if ChildProcess.os == :windows
ruby(<<-CODE)
STDIN.sync = true
STDOUT.sync = true
puts "hello"
CODE
else
ChildProcess.build("echo", "hello")
end
end
def ruby(code)
ruby_process(tmp_script(code))
end
def with_executable_at(path, &blk)
if ChildProcess.os == :windows
path << ".cmd"
content = "#{RUBY} -e 'sleep 10' \n @echo foo"
else
content = "#!/bin/sh\nsleep 10\necho foo"
end
File.open(path, 'w', 0744) { |io| io << content }
proc = ChildProcess.build(path)
begin
yield proc
ensure
proc.stop if proc.alive?
File.delete path
end
end
def exit_timeout
10
end
def random_free_port
server = TCPServer.new('127.0.0.1', 0)
port = server.addr[1]
server.close
port
end
def with_tmpdir(&blk)
name = "#{Time.now.strftime("%Y%m%d")}-#{$$}-#{rand(0x100000000).to_s(36)}"
FileUtils.mkdir_p(name)
begin
yield File.expand_path(name)
ensure
FileUtils.rm_rf name
end
end
def wait_until(timeout = 10, &blk)
end_time = Time.now + timeout
last_exception = nil
until Time.now >= end_time
begin
result = yield
return result if result
rescue RSpec::Expectations::ExpectationNotMetError => ex
last_exception = ex
end
sleep 0.01
end
msg = "timed out after #{timeout} seconds"
msg << ":\n#{last_exception.message}" if last_exception
raise msg
end
def can_bind?(host, port)
TCPServer.new(host, port).close
true
rescue
false
end
def rewind_and_read(io)
io.rewind
io.read
end
def alive?(pid)
!!Process.kill(0, pid)
rescue Errno::ESRCH
false
end
def capture_std
orig_out = STDOUT.clone
orig_err = STDERR.clone
out = Tempfile.new 'captured-stdout'
err = Tempfile.new 'captured-stderr'
out.sync = true
err.sync = true
STDOUT.reopen out
STDERR.reopen err
yield
CapturedOutput.new rewind_and_read(out), rewind_and_read(err)
ensure
STDOUT.reopen orig_out
STDERR.reopen orig_err
end
def generate_log_messages
ChildProcess.logger.level = Logger::DEBUG
process = exit_with(0).start
process.wait
process.poll_for_exit(0.1)
end
end # ChildProcessSpecHelper
Thread.abort_on_exception = true
RSpec.configure do |c|
c.include(ChildProcessSpecHelper)
c.after(:each) {
defined?(@process) && @process.alive? && @process.stop
}
end
|