unicorn-simon 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.CHANGELOG.old +25 -0
- data/.document +28 -0
- data/.gitattributes +5 -0
- data/.gitignore +25 -0
- data/.mailmap +26 -0
- data/.manifest +156 -0
- data/.olddoc.yml +18 -0
- data/Application_Timeouts +77 -0
- data/CONTRIBUTORS +35 -0
- data/COPYING +674 -0
- data/DESIGN +95 -0
- data/Documentation/.gitignore +5 -0
- data/Documentation/GNUmakefile +30 -0
- data/Documentation/unicorn.1.txt +187 -0
- data/Documentation/unicorn_rails.1.txt +175 -0
- data/FAQ +70 -0
- data/GIT-VERSION-FILE +1 -0
- data/GIT-VERSION-GEN +39 -0
- data/GNUmakefile +253 -0
- data/HACKING +120 -0
- data/ISSUES +90 -0
- data/KNOWN_ISSUES +79 -0
- data/LATEST +30 -0
- data/LICENSE +67 -0
- data/Links +56 -0
- data/NEWS +2465 -0
- data/PHILOSOPHY +139 -0
- data/README +138 -0
- data/Rakefile +16 -0
- data/SIGNALS +123 -0
- data/Sandbox +104 -0
- data/TODO +3 -0
- data/TUNING +119 -0
- data/archive/.gitignore +3 -0
- data/archive/slrnpull.conf +4 -0
- data/bin/unicorn +126 -0
- data/bin/unicorn_rails +209 -0
- data/examples/big_app_gc.rb +2 -0
- data/examples/echo.ru +27 -0
- data/examples/init.sh +102 -0
- data/examples/logger_mp_safe.rb +25 -0
- data/examples/logrotate.conf +44 -0
- data/examples/nginx.conf +155 -0
- data/examples/unicorn.conf.minimal.rb +13 -0
- data/examples/unicorn.conf.rb +110 -0
- data/examples/unicorn.socket +11 -0
- data/examples/unicorn@.service +33 -0
- data/ext/unicorn_http/CFLAGS +13 -0
- data/ext/unicorn_http/c_util.h +124 -0
- data/ext/unicorn_http/common_field_optimization.h +111 -0
- data/ext/unicorn_http/ext_help.h +62 -0
- data/ext/unicorn_http/extconf.rb +11 -0
- data/ext/unicorn_http/global_variables.h +97 -0
- data/ext/unicorn_http/httpdate.c +78 -0
- data/ext/unicorn_http/unicorn_http.c +4274 -0
- data/ext/unicorn_http/unicorn_http.rl +980 -0
- data/ext/unicorn_http/unicorn_http_common.rl +76 -0
- data/lib/unicorn/app/old_rails/static.rb +59 -0
- data/lib/unicorn/app/old_rails.rb +35 -0
- data/lib/unicorn/cgi_wrapper.rb +147 -0
- data/lib/unicorn/configurator.rb +664 -0
- data/lib/unicorn/const.rb +21 -0
- data/lib/unicorn/http_request.rb +122 -0
- data/lib/unicorn/http_response.rb +60 -0
- data/lib/unicorn/http_server.rb +824 -0
- data/lib/unicorn/launcher.rb +62 -0
- data/lib/unicorn/oob_gc.rb +82 -0
- data/lib/unicorn/preread_input.rb +33 -0
- data/lib/unicorn/socket_helper.rb +195 -0
- data/lib/unicorn/stream_input.rb +146 -0
- data/lib/unicorn/tee_input.rb +133 -0
- data/lib/unicorn/tmpio.rb +27 -0
- data/lib/unicorn/util.rb +90 -0
- data/lib/unicorn/version.rb +1 -0
- data/lib/unicorn/worker.rb +140 -0
- data/lib/unicorn.rb +123 -0
- data/man/man1/unicorn.1 +221 -0
- data/man/man1/unicorn_rails.1 +212 -0
- data/setup.rb +1586 -0
- data/t/.gitignore +4 -0
- data/t/GNUmakefile +74 -0
- data/t/README +42 -0
- data/t/bin/content-md5-put +36 -0
- data/t/bin/sha1sum.rb +17 -0
- data/t/bin/unused_listen +40 -0
- data/t/broken-app.ru +12 -0
- data/t/detach.ru +11 -0
- data/t/env.ru +3 -0
- data/t/fails-rack-lint.ru +5 -0
- data/t/heartbeat-timeout.ru +12 -0
- data/t/hijack.ru +43 -0
- data/t/listener_names.ru +4 -0
- data/t/my-tap-lib.sh +201 -0
- data/t/oob_gc.ru +20 -0
- data/t/oob_gc_path.ru +20 -0
- data/t/pid.ru +3 -0
- data/t/preread_input.ru +17 -0
- data/t/rack-input-tests.ru +21 -0
- data/t/t0000-http-basic.sh +50 -0
- data/t/t0001-reload-bad-config.sh +53 -0
- data/t/t0002-config-conflict.sh +49 -0
- data/t/t0002-parser-error.sh +94 -0
- data/t/t0003-working_directory.sh +51 -0
- data/t/t0004-heartbeat-timeout.sh +69 -0
- data/t/t0004-working_directory_broken.sh +24 -0
- data/t/t0005-working_directory_app.rb.sh +40 -0
- data/t/t0006-reopen-logs.sh +83 -0
- data/t/t0006.ru +13 -0
- data/t/t0007-working_directory_no_embed_cli.sh +44 -0
- data/t/t0008-back_out_of_upgrade.sh +110 -0
- data/t/t0009-broken-app.sh +56 -0
- data/t/t0009-winch_ttin.sh +59 -0
- data/t/t0010-reap-logging.sh +55 -0
- data/t/t0011-active-unix-socket.sh +79 -0
- data/t/t0012-reload-empty-config.sh +85 -0
- data/t/t0013-rewindable-input-false.sh +24 -0
- data/t/t0013.ru +12 -0
- data/t/t0014-rewindable-input-true.sh +24 -0
- data/t/t0014.ru +12 -0
- data/t/t0015-configurator-internals.sh +25 -0
- data/t/t0018-write-on-close.sh +23 -0
- data/t/t0019-max_header_len.sh +49 -0
- data/t/t0020-at_exit-handler.sh +49 -0
- data/t/t0021-process_detach.sh +29 -0
- data/t/t0022-listener_names-preload_app.sh +32 -0
- data/t/t0100-rack-input-tests.sh +124 -0
- data/t/t0116-client_body_buffer_size.sh +80 -0
- data/t/t0116.ru +16 -0
- data/t/t0200-rack-hijack.sh +30 -0
- data/t/t0300-no-default-middleware.sh +20 -0
- data/t/t9000-preread-input.sh +48 -0
- data/t/t9001-oob_gc.sh +47 -0
- data/t/t9002-oob_gc-path.sh +75 -0
- data/t/test-lib.sh +128 -0
- data/t/write-on-close.ru +11 -0
- data/test/aggregate.rb +15 -0
- data/test/benchmark/README +50 -0
- data/test/benchmark/dd.ru +18 -0
- data/test/benchmark/stack.ru +8 -0
- data/test/exec/README +5 -0
- data/test/exec/test_exec.rb +1099 -0
- data/test/test_helper.rb +298 -0
- data/test/unit/test_configurator.rb +175 -0
- data/test/unit/test_droplet.rb +28 -0
- data/test/unit/test_http_parser.rb +886 -0
- data/test/unit/test_http_parser_ng.rb +633 -0
- data/test/unit/test_request.rb +182 -0
- data/test/unit/test_response.rb +111 -0
- data/test/unit/test_server.rb +268 -0
- data/test/unit/test_signals.rb +188 -0
- data/test/unit/test_socket_helper.rb +197 -0
- data/test/unit/test_stream_input.rb +203 -0
- data/test/unit/test_tee_input.rb +304 -0
- data/test/unit/test_upload.rb +306 -0
- data/test/unit/test_util.rb +105 -0
- data/unicorn.gemspec +50 -0
- metadata +310 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
t_plan 7 "reload config.ru error with preload_app true"
|
|
4
|
+
|
|
5
|
+
t_begin "setup and start" && {
|
|
6
|
+
unicorn_setup
|
|
7
|
+
rtmpfiles ru
|
|
8
|
+
|
|
9
|
+
cat > $ru <<\EOF
|
|
10
|
+
use Rack::ContentLength
|
|
11
|
+
use Rack::ContentType, "text/plain"
|
|
12
|
+
x = { "hello" => "world" }
|
|
13
|
+
run lambda { |env| [ 200, {}, [ x.inspect << "\n" ] ] }
|
|
14
|
+
EOF
|
|
15
|
+
echo 'preload_app true' >> $unicorn_config
|
|
16
|
+
unicorn -D -c $unicorn_config $ru
|
|
17
|
+
unicorn_wait_start
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
t_begin "hit with curl" && {
|
|
21
|
+
out=$(curl -sSf http://$listen/)
|
|
22
|
+
test x"$out" = x'{"hello"=>"world"}'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
t_begin "introduce syntax error in rackup file" && {
|
|
26
|
+
echo '...' >> $ru
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
t_begin "reload signal succeeds" && {
|
|
30
|
+
kill -HUP $unicorn_pid
|
|
31
|
+
while ! egrep '(done|error) reloading' $r_err >/dev/null
|
|
32
|
+
do
|
|
33
|
+
sleep 1
|
|
34
|
+
done
|
|
35
|
+
|
|
36
|
+
grep 'error reloading' $r_err >/dev/null
|
|
37
|
+
> $r_err
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
t_begin "hit with curl" && {
|
|
41
|
+
out=$(curl -sSf http://$listen/)
|
|
42
|
+
test x"$out" = x'{"hello"=>"world"}'
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
t_begin "killing succeeds" && {
|
|
46
|
+
kill $unicorn_pid
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
t_begin "check stderr" && {
|
|
50
|
+
check_stderr
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
t_done
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
t_plan 6 "config variables conflict with preload_app"
|
|
4
|
+
|
|
5
|
+
t_begin "setup and start" && {
|
|
6
|
+
unicorn_setup
|
|
7
|
+
rtmpfiles ru rutmp
|
|
8
|
+
|
|
9
|
+
cat > $ru <<\EOF
|
|
10
|
+
use Rack::ContentLength
|
|
11
|
+
use Rack::ContentType, "text/plain"
|
|
12
|
+
config = ru = { "hello" => "world" }
|
|
13
|
+
run lambda { |env| [ 200, {}, [ ru.inspect << "\n" ] ] }
|
|
14
|
+
EOF
|
|
15
|
+
echo 'preload_app true' >> $unicorn_config
|
|
16
|
+
unicorn -D -c $unicorn_config $ru
|
|
17
|
+
unicorn_wait_start
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
t_begin "hit with curl" && {
|
|
21
|
+
out=$(curl -sSf http://$listen/)
|
|
22
|
+
test x"$out" = x'{"hello"=>"world"}'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
t_begin "modify rackup file" && {
|
|
26
|
+
sed -e 's/world/WORLD/' < $ru > $rutmp
|
|
27
|
+
mv $rutmp $ru
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
t_begin "reload signal succeeds" && {
|
|
31
|
+
kill -HUP $unicorn_pid
|
|
32
|
+
while ! egrep '(done|error) reloading' < $r_err >/dev/null
|
|
33
|
+
do
|
|
34
|
+
sleep 1
|
|
35
|
+
done
|
|
36
|
+
|
|
37
|
+
grep 'done reloading' $r_err >/dev/null
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
t_begin "hit with curl" && {
|
|
41
|
+
out=$(curl -sSf http://$listen/)
|
|
42
|
+
test x"$out" = x'{"hello"=>"WORLD"}'
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
t_begin "killing succeeds" && {
|
|
46
|
+
kill $unicorn_pid
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
t_done
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
t_plan 11 "parser error test"
|
|
4
|
+
|
|
5
|
+
t_begin "setup and startup" && {
|
|
6
|
+
unicorn_setup
|
|
7
|
+
unicorn -D env.ru -c $unicorn_config
|
|
8
|
+
unicorn_wait_start
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
t_begin "send a bad request" && {
|
|
12
|
+
(
|
|
13
|
+
printf 'GET / HTTP/1/1\r\nHost: example.com\r\n\r\n'
|
|
14
|
+
cat $fifo > $tmp &
|
|
15
|
+
wait
|
|
16
|
+
echo ok > $ok
|
|
17
|
+
) | socat - TCP:$listen > $fifo
|
|
18
|
+
test xok = x$(cat $ok)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
dbgcat tmp
|
|
22
|
+
|
|
23
|
+
t_begin "response should be a 400" && {
|
|
24
|
+
grep -F 'HTTP/1.1 400 Bad Request' $tmp
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
t_begin "send a huge Request URI (REQUEST_PATH > (12 * 1024))" && {
|
|
28
|
+
rm -f $tmp
|
|
29
|
+
cat $fifo > $tmp &
|
|
30
|
+
(
|
|
31
|
+
set -e
|
|
32
|
+
trap 'echo ok > $ok' EXIT
|
|
33
|
+
printf 'GET /'
|
|
34
|
+
for i in $(awk </dev/null 'BEGIN{for(i=0;i<1024;i++) print i}')
|
|
35
|
+
do
|
|
36
|
+
printf '0123456789ab'
|
|
37
|
+
done
|
|
38
|
+
printf ' HTTP/1.1\r\nHost: example.com\r\n\r\n'
|
|
39
|
+
) | socat - TCP:$listen > $fifo || :
|
|
40
|
+
test xok = x$(cat $ok)
|
|
41
|
+
wait
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
t_begin "response should be a 414 (REQUEST_PATH)" && {
|
|
45
|
+
grep -F 'HTTP/1.1 414 ' $tmp
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
t_begin "send a huge Request URI (QUERY_STRING > (10 * 1024))" && {
|
|
49
|
+
rm -f $tmp
|
|
50
|
+
cat $fifo > $tmp &
|
|
51
|
+
(
|
|
52
|
+
set -e
|
|
53
|
+
trap 'echo ok > $ok' EXIT
|
|
54
|
+
printf 'GET /hello-world?a'
|
|
55
|
+
for i in $(awk </dev/null 'BEGIN{for(i=0;i<1024;i++) print i}')
|
|
56
|
+
do
|
|
57
|
+
printf '0123456789'
|
|
58
|
+
done
|
|
59
|
+
printf ' HTTP/1.1\r\nHost: example.com\r\n\r\n'
|
|
60
|
+
) | socat - TCP:$listen > $fifo || :
|
|
61
|
+
test xok = x$(cat $ok)
|
|
62
|
+
wait
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
t_begin "response should be a 414 (QUERY_STRING)" && {
|
|
66
|
+
grep -F 'HTTP/1.1 414 ' $tmp
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
t_begin "send a huge Request URI (FRAGMENT > 1024)" && {
|
|
70
|
+
rm -f $tmp
|
|
71
|
+
cat $fifo > $tmp &
|
|
72
|
+
(
|
|
73
|
+
set -e
|
|
74
|
+
trap 'echo ok > $ok' EXIT
|
|
75
|
+
printf 'GET /hello-world#a'
|
|
76
|
+
for i in $(awk </dev/null 'BEGIN{for(i=0;i<64;i++) print i}')
|
|
77
|
+
do
|
|
78
|
+
printf '0123456789abcdef'
|
|
79
|
+
done
|
|
80
|
+
printf ' HTTP/1.1\r\nHost: example.com\r\n\r\n'
|
|
81
|
+
) | socat - TCP:$listen > $fifo || :
|
|
82
|
+
test xok = x$(cat $ok)
|
|
83
|
+
wait
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
t_begin "response should be a 414 (FRAGMENT)" && {
|
|
87
|
+
grep -F 'HTTP/1.1 414 ' $tmp
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
t_begin "server stderr should be clean" && check_stderr
|
|
91
|
+
|
|
92
|
+
t_begin "term signal sent" && kill $unicorn_pid
|
|
93
|
+
|
|
94
|
+
t_done
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
|
|
4
|
+
t_plan 4 "config.ru inside alt working_directory"
|
|
5
|
+
|
|
6
|
+
t_begin "setup and start" && {
|
|
7
|
+
unicorn_setup
|
|
8
|
+
rtmpfiles unicorn_config_tmp
|
|
9
|
+
rm -rf $t_pfx.app
|
|
10
|
+
mkdir $t_pfx.app
|
|
11
|
+
|
|
12
|
+
cat > $t_pfx.app/config.ru <<EOF
|
|
13
|
+
#\--daemonize --host $host --port $port
|
|
14
|
+
use Rack::ContentLength
|
|
15
|
+
use Rack::ContentType, "text/plain"
|
|
16
|
+
run lambda { |env| [ 200, {}, [ "#{\$master_ppid}\\n" ] ] }
|
|
17
|
+
EOF
|
|
18
|
+
# we have --host/--port in config.ru instead
|
|
19
|
+
grep -v ^listen $unicorn_config > $unicorn_config_tmp
|
|
20
|
+
|
|
21
|
+
# the whole point of this exercise
|
|
22
|
+
echo "working_directory '$t_pfx.app'" >> $unicorn_config_tmp
|
|
23
|
+
|
|
24
|
+
# allows ppid to be 1 in before_fork
|
|
25
|
+
echo "preload_app true" >> $unicorn_config_tmp
|
|
26
|
+
cat >> $unicorn_config_tmp <<\EOF
|
|
27
|
+
before_fork do |server,worker|
|
|
28
|
+
$master_ppid = Process.ppid # should be zero to detect daemonization
|
|
29
|
+
end
|
|
30
|
+
EOF
|
|
31
|
+
|
|
32
|
+
mv $unicorn_config_tmp $unicorn_config
|
|
33
|
+
|
|
34
|
+
# rely on --daemonize switch, no & or -D
|
|
35
|
+
unicorn -c $unicorn_config
|
|
36
|
+
unicorn_wait_start
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
t_begin "hit with curl" && {
|
|
40
|
+
body=$(curl -sSf http://$listen/)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
t_begin "killing succeeds" && {
|
|
44
|
+
kill $unicorn_pid
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
t_begin "response body ppid == 1 (daemonized)" && {
|
|
48
|
+
test "$body" -eq 1
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
t_done
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
|
|
4
|
+
t_plan 11 "heartbeat/timeout test"
|
|
5
|
+
|
|
6
|
+
t_begin "setup and startup" && {
|
|
7
|
+
unicorn_setup
|
|
8
|
+
echo timeout 3 >> $unicorn_config
|
|
9
|
+
echo preload_app true >> $unicorn_config
|
|
10
|
+
unicorn -D heartbeat-timeout.ru -c $unicorn_config
|
|
11
|
+
unicorn_wait_start
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
t_begin "read worker PID" && {
|
|
15
|
+
worker_pid=$(curl -sSf http://$listen/)
|
|
16
|
+
t_info "worker_pid=$worker_pid"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
t_begin "sleep for a bit, ensure worker PID does not change" && {
|
|
20
|
+
sleep 4
|
|
21
|
+
test $(curl -sSf http://$listen/) -eq $worker_pid
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
t_begin "block the worker process to force it to die" && {
|
|
25
|
+
rm $ok
|
|
26
|
+
t0=$(unix_time)
|
|
27
|
+
err="$(curl -sSf http://$listen/block-forever 2>&1 || > $ok)"
|
|
28
|
+
t1=$(unix_time)
|
|
29
|
+
elapsed=$(($t1 - $t0))
|
|
30
|
+
t_info "elapsed=$elapsed err=$err"
|
|
31
|
+
test x"$err" != x"Should never get here"
|
|
32
|
+
test x"$err" != x"$worker_pid"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
t_begin "ensure worker was killed" && {
|
|
36
|
+
test -e $ok
|
|
37
|
+
test 1 -eq $(grep timeout $r_err | grep killing | count_lines)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
t_begin "ensure timeout took at least 3 seconds" && {
|
|
41
|
+
test $elapsed -ge 3
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
t_begin "we get a fresh new worker process" && {
|
|
45
|
+
new_worker_pid=$(curl -sSf http://$listen/)
|
|
46
|
+
test $new_worker_pid -ne $worker_pid
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
t_begin "truncate the server error log" && {
|
|
50
|
+
> $r_err
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
t_begin "SIGSTOP and SIGCONT on unicorn master does not kill worker" && {
|
|
54
|
+
kill -STOP $unicorn_pid
|
|
55
|
+
sleep 4
|
|
56
|
+
kill -CONT $unicorn_pid
|
|
57
|
+
sleep 2
|
|
58
|
+
test $new_worker_pid -eq $(curl -sSf http://$listen/)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
t_begin "stop server" && {
|
|
62
|
+
kill -QUIT $unicorn_pid
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
t_begin "check stderr" && check_stderr
|
|
66
|
+
|
|
67
|
+
dbgcat r_err
|
|
68
|
+
|
|
69
|
+
t_done
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
|
|
4
|
+
t_plan 3 "config.ru is missing inside alt working_directory"
|
|
5
|
+
|
|
6
|
+
t_begin "setup" && {
|
|
7
|
+
unicorn_setup
|
|
8
|
+
rtmpfiles unicorn_config_tmp ok
|
|
9
|
+
rm -rf $t_pfx.app
|
|
10
|
+
mkdir $t_pfx.app
|
|
11
|
+
|
|
12
|
+
# the whole point of this exercise
|
|
13
|
+
echo "working_directory '$t_pfx.app'" >> $unicorn_config_tmp
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
t_begin "fails to start up w/o config.ru" && {
|
|
17
|
+
unicorn -c $unicorn_config_tmp || echo ok > $ok
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
t_begin "fallback code was run" && {
|
|
21
|
+
test x"$(cat $ok)" = xok
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
t_done
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
|
|
4
|
+
t_plan 4 "fooapp.rb inside alt working_directory"
|
|
5
|
+
|
|
6
|
+
t_begin "setup and start" && {
|
|
7
|
+
unicorn_setup
|
|
8
|
+
rm -rf $t_pfx.app
|
|
9
|
+
mkdir $t_pfx.app
|
|
10
|
+
|
|
11
|
+
cat > $t_pfx.app/fooapp.rb <<\EOF
|
|
12
|
+
class Fooapp
|
|
13
|
+
def self.call(env)
|
|
14
|
+
# Rack::Lint in 1.5.0 requires headers to be a hash
|
|
15
|
+
h = [%w(Content-Type text/plain), %w(Content-Length 2)]
|
|
16
|
+
h = Rack::Utils::HeaderHash.new(h)
|
|
17
|
+
[ 200, h, %w(HI) ]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
EOF
|
|
21
|
+
# the whole point of this exercise
|
|
22
|
+
echo "working_directory '$t_pfx.app'" >> $unicorn_config
|
|
23
|
+
cd /
|
|
24
|
+
unicorn -D -c $unicorn_config -I. fooapp.rb
|
|
25
|
+
unicorn_wait_start
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
t_begin "hit with curl" && {
|
|
29
|
+
body=$(curl -sSf http://$listen/)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
t_begin "killing succeeds" && {
|
|
33
|
+
kill $unicorn_pid
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
t_begin "response body expected" && {
|
|
37
|
+
test x"$body" = xHI
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
t_done
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
|
|
4
|
+
t_plan 15 "reopen rotated logs"
|
|
5
|
+
|
|
6
|
+
t_begin "setup and startup" && {
|
|
7
|
+
rtmpfiles curl_out curl_err r_rot
|
|
8
|
+
unicorn_setup
|
|
9
|
+
unicorn -D t0006.ru -c $unicorn_config
|
|
10
|
+
unicorn_wait_start
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
t_begin "ensure server is responsive" && {
|
|
14
|
+
test xtrue = x$(curl -sSf http://$listen/ 2> $curl_err)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
t_begin "ensure stderr log is clean" && check_stderr
|
|
18
|
+
|
|
19
|
+
t_begin "external log rotation" && {
|
|
20
|
+
rm -f $r_rot
|
|
21
|
+
mv $r_err $r_rot
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
t_begin "send reopen log signal (USR1)" && {
|
|
25
|
+
kill -USR1 $unicorn_pid
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
t_begin "wait for rotated log to reappear" && {
|
|
29
|
+
nr=60
|
|
30
|
+
while ! test -f $r_err && test $nr -ge 0
|
|
31
|
+
do
|
|
32
|
+
sleep 1
|
|
33
|
+
nr=$(( $nr - 1 ))
|
|
34
|
+
done
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
t_begin "ensure server is still responsive" && {
|
|
38
|
+
test xtrue = x$(curl -sSf http://$listen/ 2> $curl_err)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
t_begin "wait for worker to reopen logs" && {
|
|
42
|
+
nr=60
|
|
43
|
+
re="worker=.* done reopening logs"
|
|
44
|
+
while ! grep "$re" < $r_err >/dev/null && test $nr -ge 0
|
|
45
|
+
do
|
|
46
|
+
sleep 1
|
|
47
|
+
nr=$(( $nr - 1 ))
|
|
48
|
+
done
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
dbgcat r_rot
|
|
52
|
+
dbgcat r_err
|
|
53
|
+
|
|
54
|
+
t_begin "ensure no errors from curl" && {
|
|
55
|
+
test ! -s $curl_err
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
t_begin "current server stderr is clean" && check_stderr
|
|
59
|
+
|
|
60
|
+
t_begin "rotated stderr is clean" && {
|
|
61
|
+
check_stderr $r_rot
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
t_begin "server is now writing logs to new stderr" && {
|
|
65
|
+
before_rot=$(count_bytes < $r_rot)
|
|
66
|
+
before_err=$(count_bytes < $r_err)
|
|
67
|
+
test xtrue = x$(curl -sSf http://$listen/ 2> $curl_err)
|
|
68
|
+
after_rot=$(count_bytes < $r_rot)
|
|
69
|
+
after_err=$(count_bytes < $r_err)
|
|
70
|
+
test $after_rot -eq $before_rot
|
|
71
|
+
test $after_err -gt $before_err
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
t_begin "stop server" && {
|
|
75
|
+
kill $unicorn_pid
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
dbgcat r_err
|
|
79
|
+
|
|
80
|
+
t_begin "current server stderr is clean" && check_stderr
|
|
81
|
+
t_begin "rotated stderr is clean" && check_stderr $r_rot
|
|
82
|
+
|
|
83
|
+
t_done
|
data/t/t0006.ru
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
use Rack::ContentLength
|
|
2
|
+
use Rack::ContentType, "text/plain"
|
|
3
|
+
run lambda { |env|
|
|
4
|
+
|
|
5
|
+
# our File objects for stderr/stdout should always have #path
|
|
6
|
+
# and be sync=true
|
|
7
|
+
ok = $stderr.sync &&
|
|
8
|
+
$stdout.sync &&
|
|
9
|
+
String === $stderr.path &&
|
|
10
|
+
String === $stdout.path
|
|
11
|
+
|
|
12
|
+
[ 200, {}, [ "#{ok}\n" ] ]
|
|
13
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
|
|
4
|
+
t_plan 4 "config.ru inside alt working_directory (no embedded switches)"
|
|
5
|
+
|
|
6
|
+
t_begin "setup and start" && {
|
|
7
|
+
unicorn_setup
|
|
8
|
+
rm -rf $t_pfx.app
|
|
9
|
+
mkdir $t_pfx.app
|
|
10
|
+
|
|
11
|
+
cat > $t_pfx.app/config.ru <<EOF
|
|
12
|
+
use Rack::ContentLength
|
|
13
|
+
use Rack::ContentType, "text/plain"
|
|
14
|
+
run lambda { |env| [ 200, {}, [ "#{\$master_ppid}\\n" ] ] }
|
|
15
|
+
EOF
|
|
16
|
+
# the whole point of this exercise
|
|
17
|
+
echo "working_directory '$t_pfx.app'" >> $unicorn_config
|
|
18
|
+
|
|
19
|
+
# allows ppid to be 1 in before_fork
|
|
20
|
+
echo "preload_app true" >> $unicorn_config
|
|
21
|
+
cat >> $unicorn_config <<\EOF
|
|
22
|
+
before_fork do |server,worker|
|
|
23
|
+
$master_ppid = Process.ppid # should be zero to detect daemonization
|
|
24
|
+
end
|
|
25
|
+
EOF
|
|
26
|
+
|
|
27
|
+
cd /
|
|
28
|
+
unicorn -D -c $unicorn_config
|
|
29
|
+
unicorn_wait_start
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
t_begin "hit with curl" && {
|
|
33
|
+
body=$(curl -sSf http://$listen/)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
t_begin "killing succeeds" && {
|
|
37
|
+
kill $unicorn_pid
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
t_begin "response body ppid == 1 (daemonized)" && {
|
|
41
|
+
test "$body" -eq 1
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
t_done
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
t_plan 13 "backout of USR2 upgrade"
|
|
4
|
+
|
|
5
|
+
worker_wait_start () {
|
|
6
|
+
test xSTART = x"$(cat $fifo)"
|
|
7
|
+
unicorn_pid=$(cat $pid)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
t_begin "setup and start" && {
|
|
11
|
+
unicorn_setup
|
|
12
|
+
rm -f $pid.oldbin
|
|
13
|
+
|
|
14
|
+
cat >> $unicorn_config <<EOF
|
|
15
|
+
after_fork do |server, worker|
|
|
16
|
+
# test script will block while reading from $fifo,
|
|
17
|
+
# so notify the script on the first worker we spawn
|
|
18
|
+
# by opening the FIFO
|
|
19
|
+
if worker.nr == 0
|
|
20
|
+
File.open("$fifo", "wb") { |fp| fp.syswrite "START" }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
EOF
|
|
24
|
+
unicorn -D -c $unicorn_config pid.ru
|
|
25
|
+
worker_wait_start
|
|
26
|
+
orig_master_pid=$unicorn_pid
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
t_begin "read original worker pid" && {
|
|
30
|
+
orig_worker_pid=$(curl -sSf http://$listen/)
|
|
31
|
+
test -n "$orig_worker_pid" && kill -0 $orig_worker_pid
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
t_begin "upgrade to new master" && {
|
|
35
|
+
kill -USR2 $orig_master_pid
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
t_begin "kill old worker" && {
|
|
39
|
+
kill -WINCH $orig_master_pid
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
t_begin "wait for new worker to start" && {
|
|
43
|
+
worker_wait_start
|
|
44
|
+
test $unicorn_pid -ne $orig_master_pid
|
|
45
|
+
new_master_pid=$unicorn_pid
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
t_begin "old master pid is stashed in $pid.oldbin" && {
|
|
49
|
+
test -s "$pid.oldbin"
|
|
50
|
+
test $orig_master_pid -eq $(cat $pid.oldbin)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
t_begin "ensure old worker is no longer running" && {
|
|
54
|
+
i=0
|
|
55
|
+
while kill -0 $orig_worker_pid 2>/dev/null
|
|
56
|
+
do
|
|
57
|
+
i=$(( $i + 1 ))
|
|
58
|
+
test $i -lt 600 || die "timed out"
|
|
59
|
+
sleep 1
|
|
60
|
+
done
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
t_begin "capture pid of new worker" && {
|
|
64
|
+
new_worker_pid=$(curl -sSf http://$listen/)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
t_begin "reload old master process" && {
|
|
68
|
+
kill -HUP $orig_master_pid
|
|
69
|
+
worker_wait_start
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
t_begin "gracefully kill new master and ensure it dies" && {
|
|
73
|
+
kill -QUIT $new_master_pid
|
|
74
|
+
i=0
|
|
75
|
+
while kill -0 $new_worker_pid 2>/dev/null
|
|
76
|
+
do
|
|
77
|
+
i=$(( $i + 1 ))
|
|
78
|
+
test $i -lt 600 || die "timed out"
|
|
79
|
+
sleep 1
|
|
80
|
+
done
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
t_begin "ensure $pid.oldbin does not exist" && {
|
|
84
|
+
i=0
|
|
85
|
+
while test -s $pid.oldbin
|
|
86
|
+
do
|
|
87
|
+
i=$(( $i + 1 ))
|
|
88
|
+
test $i -lt 600 || die "timed out"
|
|
89
|
+
sleep 1
|
|
90
|
+
done
|
|
91
|
+
while ! test -s $pid
|
|
92
|
+
do
|
|
93
|
+
i=$(( $i + 1 ))
|
|
94
|
+
test $i -lt 600 || die "timed out"
|
|
95
|
+
sleep 1
|
|
96
|
+
done
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
t_begin "ensure $pid is correct" && {
|
|
100
|
+
cur_master_pid=$(cat $pid)
|
|
101
|
+
test $orig_master_pid -eq $cur_master_pid
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
t_begin "killing succeeds" && {
|
|
105
|
+
kill $orig_master_pid
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
dbgcat r_err
|
|
109
|
+
|
|
110
|
+
t_done
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
|
|
4
|
+
t_plan 9 "graceful handling of broken apps"
|
|
5
|
+
|
|
6
|
+
t_begin "setup and start" && {
|
|
7
|
+
unicorn_setup
|
|
8
|
+
unicorn -E none -D broken-app.ru -c $unicorn_config
|
|
9
|
+
unicorn_wait_start
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
t_begin "normal response is alright" && {
|
|
13
|
+
test xOK = x"$(curl -sSf http://$listen/)"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
t_begin "app raised exception" && {
|
|
17
|
+
curl -sSf http://$listen/raise 2> $tmp || :
|
|
18
|
+
grep -F 500 $tmp
|
|
19
|
+
> $tmp
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
t_begin "app exception logged and backtrace not swallowed" && {
|
|
23
|
+
grep -F 'app error' $r_err
|
|
24
|
+
grep -A1 -F 'app error' $r_err | tail -1 | grep broken-app.ru:
|
|
25
|
+
dbgcat r_err
|
|
26
|
+
> $r_err
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
t_begin "trigger bad response" && {
|
|
30
|
+
curl -sSf http://$listen/nil 2> $tmp || :
|
|
31
|
+
grep -F 500 $tmp
|
|
32
|
+
> $tmp
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
t_begin "app exception logged" && {
|
|
36
|
+
grep -F 'app error' $r_err
|
|
37
|
+
> $r_err
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
t_begin "normal responses alright afterwards" && {
|
|
41
|
+
> $tmp
|
|
42
|
+
curl -sSf http://$listen/ >> $tmp &
|
|
43
|
+
curl -sSf http://$listen/ >> $tmp &
|
|
44
|
+
curl -sSf http://$listen/ >> $tmp &
|
|
45
|
+
curl -sSf http://$listen/ >> $tmp &
|
|
46
|
+
wait
|
|
47
|
+
test xOK = x$(sort < $tmp | uniq)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
t_begin "teardown" && {
|
|
51
|
+
kill $unicorn_pid
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
t_begin "check stderr" && check_stderr
|
|
55
|
+
|
|
56
|
+
t_done
|