$curl_out 2> $curl_err
dbgcat curl_err
dbgcat curl_out
test x"$(cat $curl_out)" = x$empty_sha1
}
t_begin "chunked request" && {
curl -vsSf -T- < /dev/null -H Expect: \
http://$listen/ > $curl_out 2> $curl_err
dbgcat curl_err
dbgcat curl_out
test x"$(cat $curl_out)" = x$empty_sha1
}
t_begin "small input chunked" && {
rm -f $ok
echo | \
curl -vsSf -T- -H Expect: \
http://$listen/ > $curl_out 2> $curl_err || > $ok
dbgcat curl_err
dbgcat curl_out
fgrep 413 $curl_err
test -e $ok
}
t_begin "small input content-length" && {
rm -f $ok
echo > $tmp
curl -vsSf -T $tmp -H Expect: \
http://$listen/ > $curl_out 2> $curl_err || > $ok
fgrep 413 $curl_err
dbgcat curl_err
dbgcat curl_out
test -e $ok
}
t_begin "shutdown" && {
kill $rainbows_pid
}
t_done
rainbows-5.2.1/t/t0002-graceful.sh 0000755 0000041 0000041 00000001224 13635276123 016537 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
t_plan 4 "graceful exit test for $model"
t_begin "setup and startup" && {
rtmpfiles curl_out
rainbows_setup $model
rainbows -D sleep.ru -c $unicorn_config
rainbows_wait_start
}
t_begin "send a request and SIGQUIT while request is processing" && {
curl -sSfv -T- $curl_out 2> $fifo &
awk -v rainbows_pid=$rainbows_pid '
{ print $0 }
/100 Continue/ {
print "awk: sending SIGQUIT to", rainbows_pid
system("kill -QUIT "rainbows_pid)
}' $fifo
wait
}
dbgcat r_err
t_begin 'response returned "Hello"' && {
test x$(cat $curl_out) = xHello
}
t_begin 'stderr has no errors' && check_stderr
t_done
rainbows-5.2.1/t/t0016.rb 0000644 0000041 0000041 00000000554 13635276123 014751 0 ustar www-data www-data # -*- encoding: utf-8 -*-
module T0016
CHUNK = '©' * 1024 * 1024
BODY = (1..50).map { CHUNK }
HEADER = {
# BODY.inject(0) { |m,c| m += c.bytesize }.to_s,
'Content-Length' => '104857600',
'Content-Type' => 'text/plain',
}
def self.call(env)
[ 200, HEADER, BODY ]
end
end
$0 == __FILE__ and T0016::BODY.each { |x| $stdout.syswrite(x) }
rainbows-5.2.1/t/sleep.ru 0000644 0000041 0000041 00000000442 13635276123 015326 0 ustar www-data www-data use Rack::ContentLength
run lambda { |env|
/\A100-continue\z/i =~ env['HTTP_EXPECT'] and return [ 100, {}, [] ]
env['rack.input'].read
nr = 1
env["PATH_INFO"] =~ %r{/([\d\.]+)\z} and nr = $1.to_f
Rainbows.sleep(nr)
[ 200, {'Content-Type' => 'text/plain'}, [ "Hello\n" ] ]
}
rainbows-5.2.1/t/t0400-em-async-app.sh 0000755 0000041 0000041 00000002201 13635276123 017237 0 ustar www-data www-data #!/bin/sh
nr=${nr-5}
. ./test-lib.sh
case $model in
NeverBlock|EventMachine) ;;
*)
t_info "skipping $T since it's not compatible with $model"
exit 0
;;
esac
t_plan 7 "async_app test for test for EM"
CONFIG_RU=async_examples/async_app.ru
t_begin "setup and start" && {
rainbows_setup
rtmpfiles a b c curl_err expect
# this does not does not support Rack::Lint
rainbows -E deployment -D $CONFIG_RU -c $unicorn_config
rainbows_wait_start
}
t_begin "send async requests off in parallel" && {
t0=$(unix_time)
curl --no-buffer -sSf http://$listen/ > $a 2>> $curl_err &
curl --no-buffer -sSf http://$listen/ > $b 2>> $curl_err &
curl --no-buffer -sSf http://$listen/ > $c 2>> $curl_err &
}
t_begin "wait for curl terminations" && {
wait
t1=$(unix_time)
elapsed=$(( $t1 - $t0 ))
t_info "elapsed=$elapsed"
}
t_begin "termination signal sent" && {
kill $rainbows_pid
}
t_begin "no errors from curl" && {
test ! -s $curl_err
}
t_begin "no errors in stderr" && check_stderr
t_begin "responses match expected" && {
echo 'Woah, async!' > $expect
printf 'Cheers then!' >> $expect
cmp $expect $a
cmp $expect $b
cmp $expect $c
}
t_done
rainbows-5.2.1/t/t0035-kgio-pipe-response.sh 0000755 0000041 0000041 00000002735 13635276123 020505 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
skip_models StreamResponseEpoll
test -r random_blob || die "random_blob required, run with 'make $0'"
t_plan 10 "fast Kgio pipe response for $model"
t_begin "setup and startup" && {
rtmpfiles err out
rainbows_setup $model
rainbows -E none -D kgio-pipe-response.ru -c $unicorn_config
rainbows_wait_start
}
t_begin "read random blob sha1" && {
random_blob_sha1=$(rsha1 < random_blob)
three_sha1=$(cat random_blob random_blob random_blob | rsha1)
}
t_begin "single request matches" && {
sha1=$(curl -sSfv 2> $err http://$listen/ | rsha1)
test -n "$sha1"
test x"$sha1" = x"$random_blob_sha1"
}
t_begin "Content-Length header preserved in response" && {
grep "^< Content-Length:" $err
}
t_begin "send three keep-alive requests" && {
sha1=$(curl -vsSf 2> $err \
http://$listen/ http://$listen/ http://$listen/ | rsha1)
test -n "$sha1"
test x"$sha1" = x"$three_sha1"
}
t_begin "ensure responses were all keep-alive" && {
test 3 -eq $(grep '< Connection: keep-alive' < $err | count_lines)
}
t_begin "HTTP/1.0 test" && {
sha1=$(curl -0 -v 2> $err -sSf http://$listen/ | rsha1)
test $sha1 = $random_blob_sha1
grep '< Connection: close' < $err
}
t_begin "HTTP/0.9 test" && {
(
printf 'GET /\r\n'
rsha1 < $fifo > $tmp &
wait
echo ok > $ok
) | socat - TCP:$listen > $fifo
test $(cat $tmp) = $random_blob_sha1
test xok = x$(cat $ok)
}
t_begin "shutdown server" && {
kill -QUIT $rainbows_pid
}
t_begin "check stderr" && check_stderr
t_done
rainbows-5.2.1/t/t0401-em-async-tailer.sh 0000755 0000041 0000041 00000002710 13635276123 017745 0 ustar www-data www-data #!/bin/sh
nr=${nr-5}
. ./test-lib.sh
case $model in
NeverBlock|EventMachine) ;;
*)
t_info "skipping $T since it's not compatible with $model"
exit 0
;;
esac
t_plan 8 "async_tailer test for test for EM"
CONFIG_RU=async_examples/async_tailer.ru
t_begin "setup and start" && {
rainbows_setup
rtmpfiles a b c curl_err TAIL_LOG_FILE expect
printf 'Async Tailer
' >> $expect
export TAIL_LOG_FILE
# this does not does not support Rack::Lint
rainbows -E deployment -D $CONFIG_RU -c $unicorn_config
rainbows_wait_start
}
t_begin "send async requests off in parallel" && {
t0=$(unix_time)
curl --no-buffer -sSf http://$listen/ > $a 2>> $curl_err &
curl_a=$!
curl --no-buffer -sSf http://$listen/ > $b 2>> $curl_err &
curl_b=$!
curl --no-buffer -sSf http://$listen/ > $c 2>> $curl_err &
curl_c=$!
}
t_begin "generate log output" && {
for i in $(awk "BEGIN {for(i=0;i<$nr;i++) print i}" < /dev/null)
do
date >> $TAIL_LOG_FILE
sleep 1
done
# sometimes tail(1) can be slow
sleep 2
}
t_begin "kill curls and wait for termination" && {
kill $curl_a $curl_b $curl_c
wait
t1=$(unix_time)
elapsed=$(( $t1 - $t0 ))
t_info "elapsed=$elapsed"
}
t_begin "termination signal sent" && {
kill -QUIT $rainbows_pid
}
t_begin "no errors from curl" && {
test ! -s $curl_err
}
t_begin "no errors in stderr" && check_stderr
t_begin "responses match expected" && {
cat $TAIL_LOG_FILE >> $expect
cmp $expect $a
cmp $expect $b
cmp $expect $c
}
t_done
rainbows-5.2.1/t/t0045-client_max_header_size.sh 0000755 0000041 0000041 00000004055 13635276123 021450 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
skip_models StreamResponseEpoll
t_plan 11 "client_max_header_size tests for $model"
t_begin "setup Rainbows!" && {
rainbows_setup $model
}
t_begin "fails with zero size" && {
ed -s $unicorn_config < $tmp &
printf 'GET /\r\n'
wait
echo ok > $ok
) | socat - TCP:$listen > $fifo
wait
test xok = x"$(cat $ok)"
test 1 -eq $(count_lines < $tmp)
grep HTTP_VERSION $tmp && die "unexpected HTTP_VERSION in HTTP/0.9 request"
}
t_begin "HTTP/1.1 request fails" && {
curl -vsSf http://$listen/ > $tmp 2>&1 && die "unexpected curl success"
grep '400\( Bad Request\)\?$' $tmp
}
t_begin "increase client_max_header_size on reload" && {
ed -s $unicorn_config < $tmp
test 1 -eq $(count_lines < $tmp)
dbgcat tmp
}
t_begin "no errors in stderr" && {
check_stderr
}
t_begin "shutdown" && {
kill $rainbows_pid
}
t_done
rainbows-5.2.1/t/simple-http_CoolioThreadPool.ru 0000644 0000041 0000041 00000000352 13635276123 021752 0 ustar www-data www-data use Rack::ContentLength
use Rack::ContentType
run lambda { |env|
if env['rack.multithread'] && env['rainbows.model'] == :CoolioThreadPool
[ 200, {}, [ env.inspect << "\n" ] ]
else
raise "rack.multithread is false"
end
}
rainbows-5.2.1/t/t0032-close-pipe-to_path-response.sh 0000755 0000041 0000041 00000004351 13635276123 022306 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
skip_models StreamResponseEpoll
if ! test -d /dev/fd
then
t_info "skipping $T since /dev/fd is required"
exit 0
fi
t_plan 16 "close pipe to_path response for $model"
t_begin "setup and startup" && {
rtmpfiles err out http_fifo sub_ok
rainbows_setup $model
export fifo
rainbows -E none -D close-pipe-to_path-response.ru -c $unicorn_config
rainbows_wait_start
}
t_begin "read random blob sha1" && {
random_blob_sha1=$(rsha1 < random_blob)
}
t_begin "start FIFO reader" && {
cat $fifo > $out &
}
t_begin "single request matches" && {
sha1=$(curl -sSfv 2> $err http://$listen/ | rsha1)
test -n "$sha1"
test x"$sha1" = x"$random_blob_sha1"
}
t_begin "body.close called" && {
wait # for cat $fifo
grep CLOSING $out || die "body.close not logged"
}
t_begin "start FIFO reader for abortive HTTP/1.1 request" && {
cat $fifo > $out &
}
t_begin "send abortive HTTP/1.1 request" && {
rm -f $ok
(
printf 'GET /random_blob HTTP/1.1\r\nHost: example.com\r\n\r\n'
dd bs=4096 count=1 < $http_fifo >/dev/null
echo ok > $ok
) | socat - TCP:$listen > $http_fifo || :
test xok = x$(cat $ok)
}
t_begin "body.close called for aborted HTTP/1.1 request" && {
wait # for cat $fifo
grep CLOSING $out || die "body.close not logged"
}
t_begin "start FIFO reader for abortive HTTP/1.0 request" && {
cat $fifo > $out &
}
t_begin "send abortive HTTP/1.0 request" && {
rm -f $ok
(
printf 'GET /random_blob HTTP/1.0\r\n\r\n'
dd bs=4096 count=1 < $http_fifo >/dev/null
echo ok > $ok
) | socat - TCP:$listen > $http_fifo || :
test xok = x$(cat $ok)
}
t_begin "body.close called for aborted HTTP/1.0 request" && {
wait # for cat $fifo
grep CLOSING $out || die "body.close not logged"
}
t_begin "start FIFO reader for abortive HTTP/0.9 request" && {
cat $fifo > $out &
}
t_begin "send abortive HTTP/0.9 request" && {
rm -f $ok
(
printf 'GET /random_blob\r\n'
dd bs=4096 count=1 < $http_fifo >/dev/null
echo ok > $ok
) | socat - TCP:$listen > $http_fifo || :
test xok = x$(cat $ok)
}
t_begin "body.close called for aborted HTTP/0.9 request" && {
wait # for cat $fifo
grep CLOSING $out || die "body.close not logged"
}
t_begin "shutdown server" && {
kill -QUIT $rainbows_pid
}
t_begin "check stderr" && check_stderr
t_done
rainbows-5.2.1/t/t9101.ru 0000644 0000041 0000041 00000000364 13635276123 014777 0 ustar www-data www-data use Rack::ContentLength
use Rack::ContentType, 'text/plain'
use Rainbows::ThreadTimeout, :timeout => 1, :threshold => -1
run lambda { |env|
if env["PATH_INFO"] =~ %r{/([\d\.]+)\z}
Rainbows.sleep($1.to_f)
end
[ 200, [], [ "HI\n" ] ]
}
rainbows-5.2.1/t/async_chunk_app.ru 0000644 0000041 0000041 00000003154 13635276123 017366 0 ustar www-data www-data # based on async_examples/async_app.ru by James Tucker
class DeferrableChunkBody
include EventMachine::Deferrable
def call(*body)
body.each do |chunk|
@body_callback.call("#{chunk.size.to_s(16)}\r\n")
@body_callback.call(chunk)
@body_callback.call("\r\n")
end
end
def each(&block)
@body_callback = block
end
def finish
@body_callback.call("0\r\n\r\n")
end
end if defined?(EventMachine)
class AsyncChunkApp
def call(env)
headers = {
'Content-Type' => 'text/plain',
'Transfer-Encoding' => 'chunked',
}
delay = env["HTTP_X_DELAY"].to_i
case env["rainbows.model"]
when :EventMachine, :NeverBlock
body = DeferrableChunkBody.new
body.callback { body.finish }
task = lambda {
env['async.callback'].call([ 200, headers, body ])
EM.add_timer(1) {
body.call "Hello "
EM.add_timer(1) {
body.call "World #{env['PATH_INFO']}\n"
body.succeed
}
}
}
delay == 0 ? EM.next_tick(&task) : EM.add_timer(delay, &task)
when :Coolio
# Cool.io only does one-shot responses due to the lack of the
# equivalent of EM::Deferrables
body = [ "Hello ", "World #{env['PATH_INFO']}\n", '' ].map do |chunk|
"#{chunk.size.to_s(16)}\r\n#{chunk}\r\n"
end
next_tick = Coolio::TimerWatcher.new(delay, false)
next_tick.on_timer { env['async.callback'].call([ 200, headers, body ]) }
next_tick.attach(Coolio::Loop.default)
else
raise "Not supported: #{env['rainbows.model']}"
end
nil
end
end
run AsyncChunkApp.new
rainbows-5.2.1/t/t0800-rack-hijack.sh 0000755 0000041 0000041 00000001027 13635276123 017125 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
t_plan 5 "rack.hijack tests (Rack 1.5+ (Rack::VERSION >= [1,2]))"
t_begin "setup and start" && {
rainbows_setup
rainbows -D -c $unicorn_config hijack.ru
rainbows_wait_start
}
t_begin "check request hijack" && {
test "xrequest.hijacked" = x"$(curl -sSfv http://$listen/hijack_req)"
}
t_begin "check response hijack" && {
test "xresponse.hijacked" = x"$(curl -sSfv http://$listen/hijack_res)"
}
t_begin "killing succeeds" && {
kill $rainbows_pid
}
t_begin "check stderr" && {
check_stderr
}
t_done
rainbows-5.2.1/t/t0019-keepalive-cpu-usage.sh 0000644 0000041 0000041 00000002614 13635276123 020614 0 ustar www-data www-data #!/bin/sh
if test -z "$V" || test 0 -eq "$V"
then
exit 0
fi
. ./test-lib.sh
skip_models WriterThreadSpawn WriterThreadPool Base
skip_models StreamResponseEpoll
t_plan 6 "keepalive_timeout CPU usage tests for $model"
t_begin "setup and start" && {
rainbows_setup $model 50 666
grep 'worker_connections 50' $unicorn_config
grep 'keepalive_timeout 666' $unicorn_config
rainbows -E deployment -D times.ru -c $unicorn_config
rainbows_wait_start
}
t_begin 'read current times' && {
eval "$(curl -sSf http://$listen/)"
before_utime=$utime
before_stime=$stime
echo "utime=$utime stime=$stime"
}
t_begin 'keepalive connections' && {
listen=$listen $RUBY -rsocket -e '
host, port = ENV["listen"].split(/:/)
port = port.to_i
socks = (1..49).map do |i|
s = TCPSocket.new(host, port)
# need to write something to get around deferred accepts
s.write "GET /#{i} HTTP/1.1\r\nHost: example.com\r\n\r\n"
s.readpartial 16384
s
end
sleep
' &
ruby_pid=$!
for i in $(awk 'BEGIN { for(i=0;i<60;++i) print i }' $utime" \
"stime[$i] $before_stime => $stime"
done
kill $ruby_pid
}
t_begin "times not unreasonable" && {
echo "utime: $before_utime => $utime" \
"stime: $before_stime => $stime"
}
t_begin "killing succeeds" && {
kill $rainbows_pid
}
t_begin "check stderr" && {
check_stderr
}
t_done
rainbows-5.2.1/t/t0018-reload-restore-settings.sh 0000644 0000041 0000041 00000002137 13635276123 021544 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
t_plan 8 "reload restore settings for $model"
t_begin "setup and start" && {
rtmpfiles orig_config
rainbows_setup
cat $unicorn_config > $orig_config
rainbows -D -c $unicorn_config -l $listen env.ru
rainbows_wait_start
}
t_begin "HTTP request confirms we're running the correct model" && {
curl -sSfv http://$listen/ | grep "\"rainbows.model\"=>:$model"
}
t_begin "clobber config and reload" && {
cat > $unicorn_config <:Base" >/dev/null
}
t_begin "restore config and reload" && {
cat $orig_config > $unicorn_config
> $r_err
kill -HUP $rainbows_pid
rainbows_wait_start
wait_for_reload
wait_for_reap
}
t_begin "HTTP request confirms we're back on the correct model" && {
curl -sSfv http://$listen/ | \
grep "\"rainbows.model\"=>:$model" >/dev/null
}
t_begin "killing succeeds" && {
kill $rainbows_pid
}
t_begin "check stderr" && {
check_stderr
}
t_done
rainbows-5.2.1/t/t0044-autopush.sh 0000644 0000041 0000041 00000005046 13635276123 016630 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
STRACE=$(which strace 2>/dev/null || :)
if ! test -x "$STRACE"
then
t_info "strace not found, skipping $T"
exit 0
fi
if test x"$(uname -s)" != xLinux
then
t_info "Linux is the only supported OS for $T"
exit 0
fi
# these buffer internally in external libraries, so we can't detect when
# to use TCP_CORK
skip_models EventMachine NeverBlock
skip_models StreamResponseEpoll
skip_models Coolio CoolioThreadPool CoolioThreadSpawn
skip_models Revactor Rev RevThreadPool RevThreadSpawn
# not sure why, but we don't have time to care about Ruby 1.8 too much
case $RUBY_VERSION in
1.8.*) skip_models WriterThreadSpawn WriterThreadPool ;;
esac
t_plan 13 "Kgio autopush tests"
start_strace () {
# dbgcat strace_out
> $strace_out
sleep 1
strace -p $worker_pid -e '!futex' -f -o $strace_out &
strace_pid=$!
while ! test -s $strace_out; do sleep 1; done
}
check_TCP_CORK () {
nr=0
while test 2 -gt $(grep TCP_CORK $strace_out | count_lines)
do
nr=$(( $nr + 1 ))
if test $nr -gt 30
then
dbgcat strace_out
die "waited too long ($nr seconds) for TCP_CORK"
fi
sleep 1
done
test 2 -eq $(grep TCP_CORK $strace_out | count_lines)
fgrep 'SOL_TCP, TCP_CORK, [0],' $strace_out
fgrep 'SOL_TCP, TCP_CORK, [1],' $strace_out
}
t_begin "setup and start" && {
rainbows_setup $model 1 1
rtmpfiles strace_out
ed -s $unicorn_config < true, :tcp_nopush => true/
w
EOF
rainbows -D large-file-response.ru -c $unicorn_config -E none
rainbows_wait_start
}
t_begin "read worker pid" && {
worker_pid=$(curl -sSf http://$listen/pid)
kill -0 $worker_pid
}
t_begin "start strace on worker" && start_strace
t_begin "reading RSS uncorks" && {
curl -sSf http://$listen/rss >/dev/null
}
t_begin "restart strace on worker" && {
kill $strace_pid
wait
start_strace
}
t_begin "reading static file uncorks" && {
curl -sSf http://$listen/random_blob >/dev/null
check_TCP_CORK
}
t_begin "stop strace on worker" && {
kill $strace_pid
wait
}
t_begin "enable sendfile" && {
echo >> $unicorn_config 'require "sendfile"'
kill -HUP $rainbows_pid
test xSTART = x"$(cat $fifo)"
}
t_begin "reread worker pid" && {
worker_pid=$(curl -sSf http://$listen/pid)
kill -0 $worker_pid
}
t_begin "restart strace on the worker" && start_strace
t_begin "HTTP/1.x GET on static file with sendfile uncorks" && {
curl -sSf http://$listen/random_blob >/dev/null
check_TCP_CORK
}
t_begin "killing succeeds" && {
kill $strace_pid
wait
# dbgcat strace_out
kill $rainbows_pid
}
t_begin "check stderr" && check_stderr
t_done
rainbows-5.2.1/t/t9100.ru 0000644 0000041 0000041 00000000342 13635276123 014772 0 ustar www-data www-data use Rack::ContentLength
use Rack::ContentType, 'text/plain'
use Rainbows::ThreadTimeout, :timeout => 1
run lambda { |env|
if env["PATH_INFO"] =~ %r{/([\d\.]+)\z}
Rainbows.sleep($1.to_f)
end
[ 200, [], [ "HI\n" ] ]
}
rainbows-5.2.1/t/file-wrap-to_path.ru 0000644 0000041 0000041 00000001000 13635276123 017527 0 ustar www-data www-data # must be run without Rack::Lint since that clobbers to_path
class Wrapper < Struct.new(:app)
def call(env)
status, headers, body = app.call(env)
body = Body.new(body) if body.respond_to?(:to_path)
[ status, headers, body ]
end
class Body < Struct.new(:body)
def to_path
body.to_path
end
def each(&block)
body.each(&block)
end
def close
::File.open(ENV['fifo'], 'wb') { |fp| fp.puts "CLOSING" }
end
end
end
use Wrapper
run Rack::File.new(Dir.pwd)
rainbows-5.2.1/t/t0004-heartbeat-timeout.sh 0000755 0000041 0000041 00000003116 13635276123 020376 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
t_plan 12 "heartbeat/timeout test for $model"
t_begin "setup and startup" && {
rainbows_setup $model
echo timeout 3 >> $unicorn_config
echo preload_app true >> $unicorn_config
rainbows -D heartbeat-timeout.ru -c $unicorn_config
rainbows_wait_start
}
t_begin "read worker PID" && {
worker_pid=$(curl -sSf http://$listen/)
t_info "worker_pid=$worker_pid"
}
t_begin "sleep for a bit, ensure worker PID does not change" && {
sleep 4
test $(curl -sSf http://$listen/) -eq $worker_pid
}
t_begin "block the worker process to force it to die" && {
rm $ok
t0=$(unix_time)
err="$(curl -sSf http://$listen/block-forever 2>&1 || > $ok)"
t1=$(unix_time)
elapsed=$(($t1 - $t0))
t_info "elapsed=$elapsed err=$err"
test x"$err" != x"Should never get here"
test x"$err" != x"$worker_pid"
}
t_begin "ensure worker was killed" && {
test -e $ok
test 1 -eq $(grep timeout $r_err | grep killing | count_lines)
}
t_begin "ensure timeout took at least 3 seconds" && {
test $elapsed -ge 3
}
t_begin "wait for new worker to start up" && {
test xSTART = x"$(cat $fifo)"
}
t_begin "we get a fresh new worker process" && {
new_worker_pid=$(curl -sSf http://$listen/)
test $new_worker_pid -ne $worker_pid
}
t_begin "truncate the server error log" && {
> $r_err
}
t_begin "SIGSTOP and SIGCONT on rainbows master does not kill worker" && {
kill -STOP $rainbows_pid
sleep 4
kill -CONT $rainbows_pid
sleep 2
test $new_worker_pid -eq $(curl -sSf http://$listen/)
}
t_begin "stop server" && {
kill -QUIT $rainbows_pid
}
t_begin "check stderr" && check_stderr
dbgcat r_err
t_done
rainbows-5.2.1/t/simple-http_RevThreadPool.ru 0000644 0000041 0000041 00000000347 13635276123 021266 0 ustar www-data www-data use Rack::ContentLength
use Rack::ContentType
run lambda { |env|
if env['rack.multithread'] && env['rainbows.model'] == :RevThreadPool
[ 200, {}, [ env.inspect << "\n" ] ]
else
raise "rack.multithread is false"
end
}
rainbows-5.2.1/t/simple-http_WriterThreadPool.ru 0000644 0000041 0000041 00000000365 13635276123 022006 0 ustar www-data www-data use Rack::ContentLength
use Rack::ContentType
run lambda { |env|
if env['rack.multithread'] && env['rainbows.model'] == :WriterThreadPool
[ 200, {}, [ Thread.current.inspect << "\n" ] ]
else
raise "rack.multithread is false"
end
}
rainbows-5.2.1/t/sha1.ru 0000644 0000041 0000041 00000000705 13635276123 015054 0 ustar www-data www-data # SHA1 checksum generator
bs = ENV['bs'] ? ENV['bs'].to_i : 16384
require 'digest/sha1'
use Rack::ContentLength
app = lambda do |env|
/\A100-continue\z/i =~ env['HTTP_EXPECT'] and
return [ 100, {}, [] ]
digest = Digest::SHA1.new
input = env['rack.input']
if buf = input.read(bs)
begin
digest.update(buf)
end while input.read(bs, buf)
end
[ 200, {'Content-Type' => 'text/plain'}, [ digest.hexdigest << "\n" ] ]
end
run app
rainbows-5.2.1/t/t0013-reload-bad-config.sh 0000755 0000041 0000041 00000001662 13635276123 020214 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
t_plan 7 "reload config.ru error with preload_app true"
t_begin "setup and start" && {
rainbows_setup
rtmpfiles ru
cat > $ru <<\EOF
use Rack::ContentLength
use Rack::ContentType, "text/plain"
x = { "hello" => "world" }
run lambda { |env| [ 200, {}, [ x.inspect << "\n" ] ] }
EOF
echo 'preload_app true' >> $unicorn_config
rainbows -D -c $unicorn_config $ru
rainbows_wait_start
}
t_begin "hit with curl" && {
out=$(curl -sSf http://$listen/)
test x"$out" = x'{"hello"=>"world"}'
}
t_begin "introduce syntax error in rackup file" && {
echo '...' >> $ru
}
t_begin "reload signal succeeds" && {
kill -HUP $rainbows_pid
rainbows_wait_start
wait_for_reload $r_err error
wait_for_reap
> $r_err
}
t_begin "hit with curl" && {
out=$(curl -sSf http://$listen/)
test x"$out" = x'{"hello"=>"world"}'
}
t_begin "killing succeeds" && {
kill $rainbows_pid
}
t_begin "check stderr" && {
check_stderr
}
t_done
rainbows-5.2.1/t/t0020-large-sendfile-response.sh 0000755 0000041 0000041 00000006164 13635276123 021474 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
skip_models StreamResponseEpoll
test -r random_blob || die "random_blob required, run with 'make $0'"
case $RUBY_ENGINE in
ruby) ;;
*)
t_info "skipping $T since it can't load the sendfile gem, yet"
exit 0
;;
esac
t_plan 12 "large sendfile response for $model"
t_begin "setup and startup" && {
rtmpfiles curl_out a b c slow_a slow_b
rainbows_setup $model
echo 'require "sendfile"' >> $unicorn_config
echo 'def (::IO).copy_stream(*x); abort "NO"; end' >> $unicorn_config
# can't load Rack::Lint here since it clobbers body#to_path
rainbows -E none -D large-file-response.ru -c $unicorn_config
rainbows_wait_start
}
t_begin "read random blob sha1" && {
random_blob_sha1=$(rsha1 < random_blob)
three_sha1=$(cat random_blob random_blob random_blob | rsha1)
}
t_begin "send keepalive HTTP/1.1 requests in parallel" && {
for i in $a $b $c $slow_a $slow_b
do
curl -sSf http://$listen/random_blob \
http://$listen/random_blob \
http://$listen/random_blob | rsha1 > $i &
done
wait
for i in $a $b $c $slow_a $slow_b
do
test x$(cat $i) = x$three_sha1
done
}
t_begin "send a batch of abortive HTTP/1.1 requests in parallel" && {
for i in $a $b $c $slow_a $slow_b
do
rm -f $i
(
curl -sSf --max-time 2 --limit-rate 1K \
http://$listen/random_blob >/dev/null || echo ok > $i
) &
done
wait
}
t_begin "all requests timed out" && {
for i in $a $b $c $slow_a $slow_b
do
test x$(cat $i) = xok
done
}
s='$NF ~ /worker_connections=[0-9]+/{gsub(/[^0-9]/,"",$3); print $3; exit}'
t_begin "check proc to ensure file is closed properly (Linux only)" && {
worker_pid=$(awk "$s" < $r_err)
test -n "$worker_pid"
if test -d /proc/$worker_pid/fd
then
if ls -l /proc/$worker_pid/fd | grep random_blob
then
t_info "random_blob file is open ($model)"
fi
else
t_info "/proc/$worker_pid/fd not found"
fi
}
t_begin "send a bunch of HTTP/1.1 requests in parallel" && {
(
curl -sSf --limit-rate 5M http://$listen/random_blob | \
rsha1 > $slow_a
) &
(
curl -sSf --limit-rate 6M http://$listen/random_blob | \
rsha1 > $slow_b
) &
for i in $a $b $c
do
(
curl -sSf http://$listen/random_blob | rsha1 > $i
) &
done
wait
for i in $a $b $c $slow_a $slow_b
do
test x$(cat $i) = x$random_blob_sha1
done
}
# this was a problem during development
t_begin "HTTP/1.0 test" && {
sha1=$( (curl -0 -sSf http://$listen/random_blob &&
echo ok >$ok) | rsha1)
test $sha1 = $random_blob_sha1
test xok = x$(cat $ok)
}
t_begin "HTTP/0.9 test" && {
(
printf 'GET /random_blob\r\n'
rsha1 < $fifo > $tmp &
wait
echo ok > $ok
) | socat - TCP:$listen > $fifo
test $(cat $tmp) = $random_blob_sha1
test xok = x$(cat $ok)
}
t_begin "check proc to ensure file is closed properly (Linux only)" && {
worker_pid=$(awk "$s" < $r_err)
test -n "$worker_pid"
if test -d /proc/$worker_pid/fd
then
if ls -l /proc/$worker_pid/fd | grep random_blob
then
t_info "random_blob file is open ($model)"
fi
else
t_info "/proc/$worker_pid/fd not found"
fi
}
t_begin "shutdown server" && {
kill -QUIT $rainbows_pid
}
dbgcat r_err
t_begin "check stderr" && check_stderr
t_done
rainbows-5.2.1/t/t0003-reopen-logs.sh 0000755 0000041 0000041 00000004255 13635276123 017211 0 ustar www-data www-data #!/bin/sh
# don't set nr_client for Rev, only _one_ app running at once :x
nr_client=${nr_client-2}
. ./test-lib.sh
t_plan 19 "reopen rotated logs"
t_begin "setup and startup" && {
rtmpfiles curl_out curl_err r_rot
rainbows_setup $model
rainbows -D sleep.ru -c $unicorn_config
rainbows_wait_start
}
t_begin "ensure server is responsive" && {
curl -sSf http://$listen/ >/dev/null
}
t_begin "start $nr_client concurrent requests" && {
start=$(unix_time)
for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" > $curl_out 2>> $curl_err ) &
done
}
t_begin "ensure stderr log is clean" && check_stderr
t_begin "external log rotation" && {
rm -f $r_rot
mv $r_err $r_rot
}
t_begin "send reopen log signal (USR1)" && {
kill -USR1 $rainbows_pid
}
t_begin "wait for rotated log to reappear" && {
nr=60
while ! test -f $r_err && test $nr -ge 0
do
sleep 1
nr=$(( $nr - 1 ))
done
}
t_begin "wait for worker to reopen logs" && {
nr=60
re="worker=.* done reopening logs"
while ! grep "$re" < $r_err >/dev/null && test $nr -ge 0
do
sleep 1
nr=$(( $nr - 1 ))
done
}
dbgcat r_rot
dbgcat r_err
t_begin "wait curl requests to finish" && {
wait
t_info elapsed=$(( $(unix_time) - $start ))
}
t_begin "ensure no errors from curl" && {
test ! -s $curl_err
}
t_begin "curl got $nr_client responses" && {
test "$(count_lines < $curl_out)" -eq $nr_client
}
t_begin "all responses were identical" && {
nr=$(sort < $curl_out | uniq | count_lines)
test "$nr" -eq 1
}
t_begin 'response was "Hello"' && {
test x$(sort < $curl_out | uniq) = xHello
}
t_begin "current server stderr is clean" && check_stderr
t_begin "rotated stderr is clean" && {
check_stderr $r_rot
}
t_begin "server is now writing logs to new stderr" && {
before_rot=$(count_bytes < $r_rot)
before_err=$(count_bytes < $r_err)
curl -sSfv http://$listen/
after_rot=$(count_bytes < $r_rot)
after_err=$(count_bytes < $r_err)
test $after_rot -eq $before_rot
test $after_err -gt $before_err
}
t_begin "stop server" && {
kill $rainbows_pid
}
dbgcat r_err
t_begin "current server stderr is clean" && check_stderr
t_begin "rotated stderr is clean" && check_stderr $r_rot
t_done
rainbows-5.2.1/t/t0103-rack-input-limit.sh 0000755 0000041 0000041 00000002716 13635276123 020151 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
skip_models StreamResponseEpoll
test -r random_blob || die "random_blob required, run with 'make $0'"
req_curl_chunked_upload_err_check
t_plan 6 "rack.input client_max_body_size default"
t_begin "setup and startup" && {
rtmpfiles curl_out curl_err cmbs_config
rainbows_setup $model
grep -v client_max_body_size < $unicorn_config > $cmbs_config
rainbows -D sha1-random-size.ru -c $cmbs_config
rainbows_wait_start
}
t_begin "regular request" && {
rm -f $ok
curl -vsSf -T random_blob -H Expect: \
http://$listen/ > $curl_out 2> $curl_err || > $ok
dbgcat curl_err
dbgcat curl_out
test -e $ok
}
t_begin "chunked request" && {
rm -f $ok
curl -vsSf -T- < random_blob -H Expect: \
http://$listen/ > $curl_out 2> $curl_err || > $ok
dbgcat curl_err
dbgcat curl_out
test -e $ok
}
t_begin "default size sha1 chunked" && {
blob_sha1=3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
rm -f $ok
> $r_err
dd if=/dev/zero bs=1048576 count=1 | \
curl -vsSf -T- -H Expect: \
http://$listen/ > $curl_out 2> $curl_err
test "$(cat $curl_out)" = $blob_sha1
dbgcat curl_err
dbgcat curl_out
}
t_begin "default size sha1 content-length" && {
blob_sha1=3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
rm -f $ok
dd if=/dev/zero bs=1048576 count=1 of=$tmp
curl -vsSf -T $tmp -H Expect: \
http://$listen/ > $curl_out 2> $curl_err
test "$(cat $curl_out)" = $blob_sha1
dbgcat curl_err
dbgcat curl_out
}
t_begin "shutdown" && {
kill $rainbows_pid
}
t_done
rainbows-5.2.1/t/large-file-response.ru 0000644 0000041 0000041 00000000713 13635276123 020062 0 ustar www-data www-data # lib-large-file-response will stop running if we're not on Linux here
use Rack::ContentLength
use Rack::ContentType
map "/rss" do
run lambda { |env|
# on Linux, this is in kilobytes
GC.start if GC.respond_to?(:start)
::File.read("/proc/self/status") =~ /^VmRSS:\s+(\d+)/
[ 200, {}, [ ($1.to_i * 1024).to_s ] ]
}
end
map "/pid" do
run lambda { |env| [ 200, {}, [ "#{Process.pid}\n" ] ] }
end
map "/" do
run Rack::File.new(Dir.pwd)
end
rainbows-5.2.1/t/t9100-thread-timeout.sh 0000755 0000041 0000041 00000002154 13635276123 017715 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
check_threaded_app_dispatch
t_plan 6 "ThreadTimeout Rack middleware test for $model"
t_begin "configure and start" && {
rtmpfiles curl_err
rainbows_setup
rainbows -D t9100.ru -c $unicorn_config
rainbows_wait_start
}
t_begin "normal request should not timeout" && {
test x"HI" = x"$(curl -sSf http://$listen/ 2>> $curl_err)"
}
t_begin "sleepy request times out with 408" && {
rm -f $ok
curl -sSf http://$listen/2 2>> $curl_err || > $ok
test -e $ok
grep 408 $curl_err
}
t_begin "short requests do not timeout while making a long one" && {
rm -f $ok $curl_err
> $ok
curl -sSf http://$listen/2 2>$curl_err >/dev/null &
(
for i in $(awk =0;)print i}')
do
curl -sSf http://$listen/0.1 >> $ok 2>&1 &
test x"HI" = x"$(curl -sSf http://$listen/0.05)"
done
wait
)
test x"HI" = x"$(curl -sSf http://$listen/)"
wait
test -f $ok
test 20 -eq $(grep '^HI$' $ok | count_lines)
test x = x"$(grep -v '^HI$' $ok)"
grep 408 $curl_err
}
t_begin "kill server" && {
kill $rainbows_pid
}
t_begin "no errors in Rainbows! stderr" && {
check_stderr
}
t_done
rainbows-5.2.1/t/close-has-env.ru 0000644 0000041 0000041 00000002355 13635276123 016667 0 ustar www-data www-data #\ -E none
use Rainbows::DevFdResponse
class ClosablePipe < ::IO
attr_accessor :env
def self.new(env)
rv = popen "echo hello", "rb"
rv.env = env
rv
end
def close
return if closed? # idempotent for Ruby 2.3.0 compatibility
super
$stdout.syswrite "path_info=#{@env['PATH_INFO']}\n"
end
end
class ClosableFile < ::File
attr_accessor :env
alias to_path path
def close
super
$stdout.syswrite "path_info=#{@env['PATH_INFO']}\n"
end
end
class Blob
def initialize(env)
@env = env
end
def each(&block)
yield "BLOB\n"
end
def close
$stdout.syswrite "path_info=#{@env['PATH_INFO']}\n"
end
end
run(lambda { |env|
case env["PATH_INFO"]
when %r{\A/pipe/}
[ 200,
[ %w(Content-Length 6), %w(Content-Type text/plain)],
ClosablePipe.new(env)
]
when %r{\A/file/}
f = ClosableFile.open("env.ru", "rb")
f.env = env
[ 200, {
'X-Req-Path' => env["PATH_INFO"],
'Content-Length' => f.stat.size.to_s,
'Content-Type' => 'text/plain' },
f
]
when %r{\A/blob/}
[ 200,
[%w(Content-Length 5), %w(Content-Type text/plain)],
Blob.new(env)
]
else
[ 404, [%w(Content-Length 0), %w(Content-Type text/plain)], [] ]
end
})
rainbows-5.2.1/t/t0042-client_header_buffer_size.sh 0000644 0000041 0000041 00000003041 13635276123 022120 0 ustar www-data www-data #!/bin/sh
. ./test-lib.sh
t_plan 8 "client_header_buffer_size tests for $model"
t_begin "setup and startup" && {
rainbows_setup $model
}
t_begin "fails with zero buffer size" && {
ed -s $unicorn_config < $ok
test x"$(cat $ok)" = "xerr=1"
}
t_begin "fails with negative value" && {
ed -s $unicorn_config < $ok
test x"$(cat $ok)" = "xerr=1"
}
t_begin "fails with negative value" && {
ed -s $unicorn_config < $ok
test x"$(cat $ok)" = "xerr=1"
}
t_begin "starts with correct value" && {
ed -s $unicorn_config <