mega-max-tool 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/mega-max-tool.gemspec +12 -0
- data/unicorn-6.1.0/Application_Timeouts +77 -0
- data/unicorn-6.1.0/CONTRIBUTORS +39 -0
- data/unicorn-6.1.0/COPYING +674 -0
- data/unicorn-6.1.0/DESIGN +95 -0
- data/unicorn-6.1.0/Documentation/unicorn.1 +222 -0
- data/unicorn-6.1.0/Documentation/unicorn_rails.1 +207 -0
- data/unicorn-6.1.0/FAQ +70 -0
- data/unicorn-6.1.0/GIT-VERSION-FILE +1 -0
- data/unicorn-6.1.0/GIT-VERSION-GEN +39 -0
- data/unicorn-6.1.0/GNUmakefile +313 -0
- data/unicorn-6.1.0/HACKING +112 -0
- data/unicorn-6.1.0/ISSUES +97 -0
- data/unicorn-6.1.0/KNOWN_ISSUES +79 -0
- data/unicorn-6.1.0/LATEST +24 -0
- data/unicorn-6.1.0/LICENSE +67 -0
- data/unicorn-6.1.0/Links +58 -0
- data/unicorn-6.1.0/NEWS +2890 -0
- data/unicorn-6.1.0/PHILOSOPHY +139 -0
- data/unicorn-6.1.0/README +151 -0
- data/unicorn-6.1.0/Rakefile +16 -0
- data/unicorn-6.1.0/SIGNALS +123 -0
- data/unicorn-6.1.0/Sandbox +104 -0
- data/unicorn-6.1.0/TODO +3 -0
- data/unicorn-6.1.0/TUNING +119 -0
- data/unicorn-6.1.0/archive/slrnpull.conf +4 -0
- data/unicorn-6.1.0/bin/unicorn +128 -0
- data/unicorn-6.1.0/bin/unicorn_rails +209 -0
- data/unicorn-6.1.0/examples/big_app_gc.rb +2 -0
- data/unicorn-6.1.0/examples/echo.ru +27 -0
- data/unicorn-6.1.0/examples/init.sh +102 -0
- data/unicorn-6.1.0/examples/logger_mp_safe.rb +25 -0
- data/unicorn-6.1.0/examples/logrotate.conf +44 -0
- data/unicorn-6.1.0/examples/nginx.conf +156 -0
- data/unicorn-6.1.0/examples/unicorn.conf.minimal.rb +13 -0
- data/unicorn-6.1.0/examples/unicorn.conf.rb +110 -0
- data/unicorn-6.1.0/examples/unicorn.socket +11 -0
- data/unicorn-6.1.0/examples/unicorn@.service +40 -0
- data/unicorn-6.1.0/ext/unicorn_http/CFLAGS +13 -0
- data/unicorn-6.1.0/ext/unicorn_http/c_util.h +116 -0
- data/unicorn-6.1.0/ext/unicorn_http/common_field_optimization.h +128 -0
- data/unicorn-6.1.0/ext/unicorn_http/epollexclusive.h +124 -0
- data/unicorn-6.1.0/ext/unicorn_http/ext_help.h +38 -0
- data/unicorn-6.1.0/ext/unicorn_http/extconf.rb +37 -0
- data/unicorn-6.1.0/ext/unicorn_http/global_variables.h +97 -0
- data/unicorn-6.1.0/ext/unicorn_http/httpdate.c +79 -0
- data/unicorn-6.1.0/ext/unicorn_http/unicorn_http.c +4319 -0
- data/unicorn-6.1.0/ext/unicorn_http/unicorn_http.rl +1025 -0
- data/unicorn-6.1.0/ext/unicorn_http/unicorn_http_common.rl +76 -0
- data/unicorn-6.1.0/lib/unicorn/app/old_rails/static.rb +59 -0
- data/unicorn-6.1.0/lib/unicorn/app/old_rails.rb +35 -0
- data/unicorn-6.1.0/lib/unicorn/cgi_wrapper.rb +147 -0
- data/unicorn-6.1.0/lib/unicorn/configurator.rb +743 -0
- data/unicorn-6.1.0/lib/unicorn/const.rb +21 -0
- data/unicorn-6.1.0/lib/unicorn/http_request.rb +201 -0
- data/unicorn-6.1.0/lib/unicorn/http_response.rb +61 -0
- data/unicorn-6.1.0/lib/unicorn/http_server.rb +893 -0
- data/unicorn-6.1.0/lib/unicorn/launcher.rb +62 -0
- data/unicorn-6.1.0/lib/unicorn/oob_gc.rb +81 -0
- data/unicorn-6.1.0/lib/unicorn/preread_input.rb +33 -0
- data/unicorn-6.1.0/lib/unicorn/select_waiter.rb +6 -0
- data/unicorn-6.1.0/lib/unicorn/socket_helper.rb +211 -0
- data/unicorn-6.1.0/lib/unicorn/stream_input.rb +147 -0
- data/unicorn-6.1.0/lib/unicorn/tee_input.rb +131 -0
- data/unicorn-6.1.0/lib/unicorn/tmpio.rb +33 -0
- data/unicorn-6.1.0/lib/unicorn/util.rb +90 -0
- data/unicorn-6.1.0/lib/unicorn/version.rb +1 -0
- data/unicorn-6.1.0/lib/unicorn/worker.rb +165 -0
- data/unicorn-6.1.0/lib/unicorn.rb +138 -0
- data/unicorn-6.1.0/man/man1/unicorn.1 +222 -0
- data/unicorn-6.1.0/man/man1/unicorn_rails.1 +207 -0
- data/unicorn-6.1.0/setup.rb +1586 -0
- data/unicorn-6.1.0/t/GNUmakefile +5 -0
- data/unicorn-6.1.0/t/README +42 -0
- data/unicorn-6.1.0/t/bin/content-md5-put +36 -0
- data/unicorn-6.1.0/t/bin/sha1sum.rb +17 -0
- data/unicorn-6.1.0/t/bin/unused_listen +40 -0
- data/unicorn-6.1.0/t/broken-app.ru +12 -0
- data/unicorn-6.1.0/t/detach.ru +11 -0
- data/unicorn-6.1.0/t/env.ru +3 -0
- data/unicorn-6.1.0/t/fails-rack-lint.ru +5 -0
- data/unicorn-6.1.0/t/heartbeat-timeout.ru +12 -0
- data/unicorn-6.1.0/t/listener_names.ru +4 -0
- data/unicorn-6.1.0/t/my-tap-lib.sh +201 -0
- data/unicorn-6.1.0/t/oob_gc.ru +20 -0
- data/unicorn-6.1.0/t/oob_gc_path.ru +20 -0
- data/unicorn-6.1.0/t/pid.ru +3 -0
- data/unicorn-6.1.0/t/preread_input.ru +17 -0
- data/unicorn-6.1.0/t/rack-input-tests.ru +21 -0
- data/unicorn-6.1.0/t/t0000-http-basic.sh +50 -0
- data/unicorn-6.1.0/t/t0001-reload-bad-config.sh +53 -0
- data/unicorn-6.1.0/t/t0002-config-conflict.sh +49 -0
- data/unicorn-6.1.0/t/t0002-parser-error.sh +94 -0
- data/unicorn-6.1.0/t/t0003-working_directory.sh +51 -0
- data/unicorn-6.1.0/t/t0004-heartbeat-timeout.sh +69 -0
- data/unicorn-6.1.0/t/t0004-working_directory_broken.sh +24 -0
- data/unicorn-6.1.0/t/t0005-working_directory_app.rb.sh +40 -0
- data/unicorn-6.1.0/t/t0006-reopen-logs.sh +83 -0
- data/unicorn-6.1.0/t/t0006.ru +13 -0
- data/unicorn-6.1.0/t/t0007-working_directory_no_embed_cli.sh +44 -0
- data/unicorn-6.1.0/t/t0008-back_out_of_upgrade.sh +110 -0
- data/unicorn-6.1.0/t/t0009-broken-app.sh +56 -0
- data/unicorn-6.1.0/t/t0009-winch_ttin.sh +59 -0
- data/unicorn-6.1.0/t/t0010-reap-logging.sh +55 -0
- data/unicorn-6.1.0/t/t0011-active-unix-socket.sh +79 -0
- data/unicorn-6.1.0/t/t0012-reload-empty-config.sh +86 -0
- data/unicorn-6.1.0/t/t0013-rewindable-input-false.sh +24 -0
- data/unicorn-6.1.0/t/t0013.ru +12 -0
- data/unicorn-6.1.0/t/t0014-rewindable-input-true.sh +24 -0
- data/unicorn-6.1.0/t/t0014.ru +12 -0
- data/unicorn-6.1.0/t/t0015-configurator-internals.sh +25 -0
- data/unicorn-6.1.0/t/t0018-write-on-close.sh +23 -0
- data/unicorn-6.1.0/t/t0019-max_header_len.sh +49 -0
- data/unicorn-6.1.0/t/t0020-at_exit-handler.sh +49 -0
- data/unicorn-6.1.0/t/t0021-process_detach.sh +29 -0
- data/unicorn-6.1.0/t/t0022-listener_names-preload_app.sh +32 -0
- data/unicorn-6.1.0/t/t0100-rack-input-tests.sh +124 -0
- data/unicorn-6.1.0/t/t0116-client_body_buffer_size.sh +80 -0
- data/unicorn-6.1.0/t/t0116.ru +16 -0
- data/unicorn-6.1.0/t/t0300-no-default-middleware.sh +20 -0
- data/unicorn-6.1.0/t/t0301-no-default-middleware-ignored-in-config.sh +25 -0
- data/unicorn-6.1.0/t/t0301.ru +13 -0
- data/unicorn-6.1.0/t/t9000-preread-input.sh +48 -0
- data/unicorn-6.1.0/t/t9001-oob_gc.sh +47 -0
- data/unicorn-6.1.0/t/t9002-oob_gc-path.sh +75 -0
- data/unicorn-6.1.0/t/test-lib.sh +129 -0
- data/unicorn-6.1.0/t/write-on-close.ru +11 -0
- data/unicorn-6.1.0/test/aggregate.rb +15 -0
- data/unicorn-6.1.0/test/benchmark/README +60 -0
- data/unicorn-6.1.0/test/benchmark/dd.ru +18 -0
- data/unicorn-6.1.0/test/benchmark/ddstream.ru +50 -0
- data/unicorn-6.1.0/test/benchmark/readinput.ru +40 -0
- data/unicorn-6.1.0/test/benchmark/stack.ru +8 -0
- data/unicorn-6.1.0/test/benchmark/uconnect.perl +66 -0
- data/unicorn-6.1.0/test/exec/README +5 -0
- data/unicorn-6.1.0/test/exec/test_exec.rb +1101 -0
- data/unicorn-6.1.0/test/test_helper.rb +306 -0
- data/unicorn-6.1.0/test/unit/test_ccc.rb +91 -0
- data/unicorn-6.1.0/test/unit/test_configurator.rb +175 -0
- data/unicorn-6.1.0/test/unit/test_droplet.rb +28 -0
- data/unicorn-6.1.0/test/unit/test_http_parser.rb +884 -0
- data/unicorn-6.1.0/test/unit/test_http_parser_ng.rb +714 -0
- data/unicorn-6.1.0/test/unit/test_request.rb +182 -0
- data/unicorn-6.1.0/test/unit/test_response.rb +111 -0
- data/unicorn-6.1.0/test/unit/test_server.rb +342 -0
- data/unicorn-6.1.0/test/unit/test_signals.rb +188 -0
- data/unicorn-6.1.0/test/unit/test_socket_helper.rb +201 -0
- data/unicorn-6.1.0/test/unit/test_stream_input.rb +203 -0
- data/unicorn-6.1.0/test/unit/test_tee_input.rb +304 -0
- data/unicorn-6.1.0/test/unit/test_upload.rb +301 -0
- data/unicorn-6.1.0/test/unit/test_util.rb +131 -0
- data/unicorn-6.1.0/test/unit/test_waiter.rb +34 -0
- data/unicorn-6.1.0/unicorn.gemspec +49 -0
- data/unicorn-6.1.0/unicorn_1 +1 -0
- data/unicorn-6.1.0/unicorn_rails_1 +1 -0
- metadata +196 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
t_plan 3 "-N / --no-default-middleware option not supported in config.ru"
|
|
4
|
+
|
|
5
|
+
t_begin "setup and start" && {
|
|
6
|
+
unicorn_setup
|
|
7
|
+
RACK_ENV=development unicorn -D -c $unicorn_config t0301.ru
|
|
8
|
+
unicorn_wait_start
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
t_begin "check switches parsed as expected and -N ignored for Rack::Lint" && {
|
|
12
|
+
debug=false
|
|
13
|
+
lint=
|
|
14
|
+
eval "$(curl -sf http://$listen/vars)"
|
|
15
|
+
test x"$debug" = xtrue
|
|
16
|
+
test x"$lint" != x
|
|
17
|
+
test -f "$lint"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
t_begin "killing succeeds" && {
|
|
21
|
+
kill $unicorn_pid
|
|
22
|
+
check_stderr
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
t_done
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#\-N --debug
|
|
2
|
+
run(lambda do |env|
|
|
3
|
+
case env['PATH_INFO']
|
|
4
|
+
when '/vars'
|
|
5
|
+
b = "debug=#{$DEBUG.inspect}\n" \
|
|
6
|
+
"lint=#{caller.grep(%r{rack/lint\.rb})[0].split(':')[0]}\n"
|
|
7
|
+
end
|
|
8
|
+
h = {
|
|
9
|
+
'Content-Length' => b.size.to_s,
|
|
10
|
+
'Content-Type' => 'text/plain',
|
|
11
|
+
}
|
|
12
|
+
[ 200, h, [ b ] ]
|
|
13
|
+
end)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
t_plan 9 "PrereadInput middleware tests"
|
|
4
|
+
|
|
5
|
+
t_begin "setup and start" && {
|
|
6
|
+
random_blob_sha1=$(rsha1 < random_blob)
|
|
7
|
+
unicorn_setup
|
|
8
|
+
unicorn -D -c $unicorn_config preread_input.ru
|
|
9
|
+
unicorn_wait_start
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
t_begin "single identity request" && {
|
|
13
|
+
curl -sSf -T random_blob http://$listen/ > $tmp
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
t_begin "sha1 matches" && {
|
|
17
|
+
test x"$(cat $tmp)" = x"$random_blob_sha1"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
t_begin "single chunked request" && {
|
|
21
|
+
curl -sSf -T- < random_blob http://$listen/ > $tmp
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
t_begin "sha1 matches" && {
|
|
25
|
+
test x"$(cat $tmp)" = x"$random_blob_sha1"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
t_begin "app only dispatched twice" && {
|
|
29
|
+
test 2 -eq "$(grep 'app dispatch:' < $r_err | count_lines )"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
t_begin "aborted chunked request" && {
|
|
33
|
+
rm -f $tmp
|
|
34
|
+
curl -sSf -T- < $fifo http://$listen/ > $tmp &
|
|
35
|
+
curl_pid=$!
|
|
36
|
+
kill -9 $curl_pid
|
|
37
|
+
wait
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
t_begin "app only dispatched twice" && {
|
|
41
|
+
test 2 -eq "$(grep 'app dispatch:' < $r_err | count_lines )"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
t_begin "killing succeeds" && {
|
|
45
|
+
kill -QUIT $unicorn_pid
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
t_done
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
t_plan 9 "OobGC test"
|
|
4
|
+
|
|
5
|
+
t_begin "setup and start" && {
|
|
6
|
+
unicorn_setup
|
|
7
|
+
unicorn -D -c $unicorn_config oob_gc.ru
|
|
8
|
+
unicorn_wait_start
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
t_begin "test default interval (4 requests)" && {
|
|
12
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
13
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
14
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
15
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
t_begin "GC starting-request returns immediately" && {
|
|
19
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
t_begin "GC is started after 5 requests" && {
|
|
23
|
+
test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
t_begin "reset GC" && {
|
|
27
|
+
test xfalse = x$(curl -vsSf -X POST http://$listen/gc_reset 2>> $tmp)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
t_begin "test default interval again (3 requests)" && {
|
|
31
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
32
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
33
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
t_begin "GC is started after 5 requests" && {
|
|
37
|
+
test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
t_begin "killing succeeds" && {
|
|
41
|
+
kill -QUIT $unicorn_pid
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
t_begin "check_stderr" && check_stderr
|
|
45
|
+
dbgcat r_err
|
|
46
|
+
|
|
47
|
+
t_done
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
. ./test-lib.sh
|
|
3
|
+
t_plan 12 "OobGC test with limited path"
|
|
4
|
+
|
|
5
|
+
t_begin "setup and start" && {
|
|
6
|
+
unicorn_setup
|
|
7
|
+
unicorn -D -c $unicorn_config oob_gc_path.ru
|
|
8
|
+
unicorn_wait_start
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
t_begin "test default is noop" && {
|
|
12
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
13
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
14
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
15
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
16
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
17
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
18
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
19
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
20
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
t_begin "4 bad requests to bump counter" && {
|
|
24
|
+
test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
|
|
25
|
+
test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
|
|
26
|
+
test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
|
|
27
|
+
test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
t_begin "GC-starting request returns immediately" && {
|
|
31
|
+
test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
t_begin "GC was started after 5 requests" && {
|
|
35
|
+
test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
t_begin "reset GC" && {
|
|
39
|
+
test xfalse = x$(curl -vsSf -X POST http://$listen/gc_reset 2>> $tmp)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
t_begin "test default is noop" && {
|
|
43
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
44
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
45
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
46
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
47
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
48
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
49
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
50
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
51
|
+
test xfalse = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
t_begin "4 bad requests to bump counter" && {
|
|
55
|
+
test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
|
|
56
|
+
test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
|
|
57
|
+
test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
|
|
58
|
+
test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
t_begin "GC-starting request returns immediately" && {
|
|
62
|
+
test xfalse = x$(curl -vsSf http://$listen/BAD 2>> $tmp)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
t_begin "GC was started after 5 requests" && {
|
|
66
|
+
test xtrue = x$(curl -vsSf http://$listen/ 2>> $tmp)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
t_begin "killing succeeds" && {
|
|
70
|
+
kill -QUIT $unicorn_pid
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
t_begin "check_stderr" && check_stderr
|
|
74
|
+
|
|
75
|
+
t_done
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Copyright (c) 2009 Rainbows! hackers
|
|
3
|
+
# Copyright (c) 2010 Unicorn hackers
|
|
4
|
+
. ./my-tap-lib.sh
|
|
5
|
+
|
|
6
|
+
set +u
|
|
7
|
+
|
|
8
|
+
# sometimes we rely on http_proxy to avoid wasting bandwidth with Isolate
|
|
9
|
+
# and multiple Ruby versions
|
|
10
|
+
NO_PROXY=${UNICORN_TEST_ADDR-127.0.0.1}
|
|
11
|
+
export NO_PROXY
|
|
12
|
+
|
|
13
|
+
set -e
|
|
14
|
+
RUBY="${RUBY-ruby}"
|
|
15
|
+
RUBY_VERSION=${RUBY_VERSION-$($RUBY -e 'puts RUBY_VERSION')}
|
|
16
|
+
RUBY_ENGINE=${RUBY_ENGINE-$($RUBY -e 'puts((RUBY_ENGINE rescue "ruby"))')}
|
|
17
|
+
t_pfx=$PWD/trash/$T-$RUBY_ENGINE-$RUBY_VERSION
|
|
18
|
+
set -u
|
|
19
|
+
|
|
20
|
+
PATH=$PWD/bin:$PATH
|
|
21
|
+
export PATH
|
|
22
|
+
|
|
23
|
+
test -x $PWD/bin/unused_listen || die "must be run in 't' directory"
|
|
24
|
+
|
|
25
|
+
wait_for_pid () {
|
|
26
|
+
path="$1"
|
|
27
|
+
nr=30
|
|
28
|
+
while ! test -s "$path" && test $nr -gt 0
|
|
29
|
+
do
|
|
30
|
+
nr=$(($nr - 1))
|
|
31
|
+
sleep 1
|
|
32
|
+
done
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# "unix_time" is not in POSIX, but in GNU, and FreeBSD 9.0 (possibly earlier)
|
|
36
|
+
unix_time () {
|
|
37
|
+
$RUBY -e 'puts Time.now.to_i'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# "wc -l" outputs leading whitespace on *BSDs, filter it out for portability
|
|
41
|
+
count_lines () {
|
|
42
|
+
wc -l | tr -d '[:space:]'
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# "wc -c" outputs leading whitespace on *BSDs, filter it out for portability
|
|
46
|
+
count_bytes () {
|
|
47
|
+
wc -c | tr -d '[:space:]'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# given a list of variable names, create temporary files and assign
|
|
51
|
+
# the pathnames to those variables
|
|
52
|
+
rtmpfiles () {
|
|
53
|
+
for id in "$@"
|
|
54
|
+
do
|
|
55
|
+
name=$id
|
|
56
|
+
|
|
57
|
+
case $name in
|
|
58
|
+
*fifo)
|
|
59
|
+
_tmp=$t_pfx.$id
|
|
60
|
+
eval "$id=$_tmp"
|
|
61
|
+
rm -f $_tmp
|
|
62
|
+
mkfifo $_tmp
|
|
63
|
+
T_RM_LIST="$T_RM_LIST $_tmp"
|
|
64
|
+
;;
|
|
65
|
+
*socket)
|
|
66
|
+
_tmp="$(mktemp -t $id.$$.XXXXXXXX)"
|
|
67
|
+
if test $(printf "$_tmp" |count_bytes) -gt 108
|
|
68
|
+
then
|
|
69
|
+
echo >&2 "$_tmp too long, tests may fail"
|
|
70
|
+
echo >&2 "Try to set TMPDIR to a shorter path"
|
|
71
|
+
fi
|
|
72
|
+
eval "$id=$_tmp"
|
|
73
|
+
rm -f $_tmp
|
|
74
|
+
T_RM_LIST="$T_RM_LIST $_tmp"
|
|
75
|
+
;;
|
|
76
|
+
*)
|
|
77
|
+
_tmp=$t_pfx.$id
|
|
78
|
+
eval "$id=$_tmp"
|
|
79
|
+
> $_tmp
|
|
80
|
+
T_OK_RM_LIST="$T_OK_RM_LIST $_tmp"
|
|
81
|
+
;;
|
|
82
|
+
esac
|
|
83
|
+
done
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
dbgcat () {
|
|
87
|
+
id=$1
|
|
88
|
+
eval '_file=$'$id
|
|
89
|
+
echo "==> $id <=="
|
|
90
|
+
sed -e "s/^/$id:/" < $_file
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
check_stderr () {
|
|
94
|
+
set +u
|
|
95
|
+
_r_err=${1-${r_err}}
|
|
96
|
+
set -u
|
|
97
|
+
if grep -v $T $_r_err | grep -i Error | \
|
|
98
|
+
grep -v NameError.*Unicorn::Waiter
|
|
99
|
+
then
|
|
100
|
+
die "Errors found in $_r_err"
|
|
101
|
+
elif grep SIGKILL $_r_err
|
|
102
|
+
then
|
|
103
|
+
die "SIGKILL found in $_r_err"
|
|
104
|
+
fi
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
# unicorn_setup
|
|
108
|
+
unicorn_setup () {
|
|
109
|
+
eval $(unused_listen)
|
|
110
|
+
port=$(expr $listen : '[^:]*:\([0-9]*\)')
|
|
111
|
+
host=$(expr $listen : '\([^:][^:]*\):[0-9][0-9]*')
|
|
112
|
+
|
|
113
|
+
rtmpfiles unicorn_config pid r_err r_out fifo tmp ok
|
|
114
|
+
cat > $unicorn_config <<EOF
|
|
115
|
+
listen "$listen"
|
|
116
|
+
pid "$pid"
|
|
117
|
+
stderr_path "$r_err"
|
|
118
|
+
stdout_path "$r_out"
|
|
119
|
+
EOF
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
unicorn_wait_start () {
|
|
123
|
+
# no need to play tricks with FIFOs since we got "ready_pipe" now
|
|
124
|
+
unicorn_pid=$(cat $pid)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
rsha1 () {
|
|
128
|
+
sha1sum.rb
|
|
129
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/ruby -n
|
|
2
|
+
# -*- encoding: binary -*-
|
|
3
|
+
|
|
4
|
+
BEGIN { $tests = $assertions = $failures = $errors = 0 }
|
|
5
|
+
|
|
6
|
+
$_ =~ /(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/ or next
|
|
7
|
+
$tests += $1.to_i
|
|
8
|
+
$assertions += $2.to_i
|
|
9
|
+
$failures += $3.to_i
|
|
10
|
+
$errors += $4.to_i
|
|
11
|
+
|
|
12
|
+
END {
|
|
13
|
+
printf("\n%d tests, %d assertions, %d failures, %d errors\n",
|
|
14
|
+
$tests, $assertions, $failures, $errors)
|
|
15
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
= Performance
|
|
2
|
+
|
|
3
|
+
Unicorn is pretty fast, and we want it to get faster. Unicorn strives
|
|
4
|
+
to get HTTP requests to your application and write HTTP responses back
|
|
5
|
+
as quickly as possible. Unicorn does not do any background processing
|
|
6
|
+
while your app runs, so your app will get all the CPU time provided to
|
|
7
|
+
it by your OS kernel.
|
|
8
|
+
|
|
9
|
+
A gentle reminder: Unicorn is NOT for serving clients over slow network
|
|
10
|
+
connections. Use nginx (or something similar) to complement Unicorn if
|
|
11
|
+
you have slow clients.
|
|
12
|
+
|
|
13
|
+
== dd.ru
|
|
14
|
+
|
|
15
|
+
This is a pure I/O benchmark. In the context of Unicorn, this is the
|
|
16
|
+
only one that matters. It is a standard rackup-compatible .ru file and
|
|
17
|
+
may be used with other Rack-compatible servers.
|
|
18
|
+
|
|
19
|
+
unicorn -E none dd.ru
|
|
20
|
+
|
|
21
|
+
You can change the size and number of chunks in the response with
|
|
22
|
+
the "bs" and "count" environment variables. The following command
|
|
23
|
+
will cause dd.ru to return 4 chunks of 16384 bytes each, leading to
|
|
24
|
+
65536 byte response:
|
|
25
|
+
|
|
26
|
+
bs=16384 count=4 unicorn -E none dd.ru
|
|
27
|
+
|
|
28
|
+
Or if you want to add logging (small performance impact):
|
|
29
|
+
|
|
30
|
+
unicorn -E deployment dd.ru
|
|
31
|
+
|
|
32
|
+
Eric runs then runs clients on a LAN it in several different ways:
|
|
33
|
+
|
|
34
|
+
client@host1 -> unicorn@host1(tcp)
|
|
35
|
+
client@host2 -> unicorn@host1(tcp)
|
|
36
|
+
client@host3 -> nginx@host1 -> unicorn@host1(tcp)
|
|
37
|
+
client@host3 -> nginx@host1 -> unicorn@host1(unix)
|
|
38
|
+
client@host3 -> nginx@host2 -> unicorn@host1(tcp)
|
|
39
|
+
|
|
40
|
+
The benchmark client is usually httperf.
|
|
41
|
+
|
|
42
|
+
Another gentle reminder: performance with slow networks/clients
|
|
43
|
+
is NOT our problem. That is the job of nginx (or similar).
|
|
44
|
+
|
|
45
|
+
== ddstream.ru
|
|
46
|
+
|
|
47
|
+
Standalone Rack app intended to show how BAD we are at slow clients.
|
|
48
|
+
See usage in comments.
|
|
49
|
+
|
|
50
|
+
== readinput.ru
|
|
51
|
+
|
|
52
|
+
Standalone Rack app intended to show how bad we are with slow uploaders.
|
|
53
|
+
See usage in comments.
|
|
54
|
+
|
|
55
|
+
== Contributors
|
|
56
|
+
|
|
57
|
+
This directory is intended to remain stable. Do not make changes
|
|
58
|
+
to benchmarking code which can change performance and invalidate
|
|
59
|
+
results across revisions. Instead, write new benchmarks and update
|
|
60
|
+
coments/documentation as necessary.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# This benchmark is the simplest test of the I/O facilities in
|
|
2
|
+
# unicorn. It is meant to return a fixed-sized blob to test
|
|
3
|
+
# the performance of things in Unicorn, _NOT_ the app.
|
|
4
|
+
#
|
|
5
|
+
# Adjusting this benchmark is done via the "bs" (byte size) and "count"
|
|
6
|
+
# environment variables. "count" designates the count of elements of
|
|
7
|
+
# "bs" length in the Rack response body. The defaults are bs=4096, count=1
|
|
8
|
+
# to return one 4096-byte chunk.
|
|
9
|
+
bs = ENV['bs'] ? ENV['bs'].to_i : 4096
|
|
10
|
+
count = ENV['count'] ? ENV['count'].to_i : 1
|
|
11
|
+
slice = (' ' * bs).freeze
|
|
12
|
+
body = (1..count).map { slice }.freeze
|
|
13
|
+
hdr = {
|
|
14
|
+
'Content-Length' => (bs * count).to_s.freeze,
|
|
15
|
+
'Content-Type' => 'text/plain'.freeze
|
|
16
|
+
}.freeze
|
|
17
|
+
response = [ 200, hdr, body ].freeze
|
|
18
|
+
run(lambda { |env| response })
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# This app is intended to test large HTTP responses with or without
|
|
2
|
+
# a fully-buffering reverse proxy such as nginx. Without a fully-buffering
|
|
3
|
+
# reverse proxy, unicorn will be unresponsive when client count exceeds
|
|
4
|
+
# worker_processes.
|
|
5
|
+
#
|
|
6
|
+
# To demonstrate how bad unicorn is at slowly reading clients:
|
|
7
|
+
#
|
|
8
|
+
# # in one terminal, start unicorn with one worker:
|
|
9
|
+
# unicorn -E none -l 127.0.0.1:8080 test/benchmark/ddstream.ru
|
|
10
|
+
#
|
|
11
|
+
# # in a different terminal, start more slow curl processes than
|
|
12
|
+
# # unicorn workers and watch time outputs
|
|
13
|
+
# curl --limit-rate 8K --trace-time -vsN http://127.0.0.1:8080/ >/dev/null &
|
|
14
|
+
# curl --limit-rate 8K --trace-time -vsN http://127.0.0.1:8080/ >/dev/null &
|
|
15
|
+
# wait
|
|
16
|
+
#
|
|
17
|
+
# The last client won't see a response until the first one is done reading
|
|
18
|
+
#
|
|
19
|
+
# nginx note: do not change the default "proxy_buffering" behavior.
|
|
20
|
+
# Setting "proxy_buffering off" prevents nginx from protecting unicorn.
|
|
21
|
+
|
|
22
|
+
# totally standalone rack app to stream a giant response
|
|
23
|
+
class BigResponse
|
|
24
|
+
def initialize(bs, count)
|
|
25
|
+
@buf = "#{bs.to_s(16)}\r\n#{' ' * bs}\r\n"
|
|
26
|
+
@count = count
|
|
27
|
+
@res = [ 200,
|
|
28
|
+
{ 'Transfer-Encoding' => -'chunked', 'Content-Type' => 'text/plain' },
|
|
29
|
+
self
|
|
30
|
+
]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# rack response body iterator
|
|
34
|
+
def each
|
|
35
|
+
(1..@count).each { yield @buf }
|
|
36
|
+
yield -"0\r\n\r\n"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# rack app entry endpoint
|
|
40
|
+
def call(_env)
|
|
41
|
+
@res
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# default to a giant (128M) response because kernel socket buffers
|
|
46
|
+
# can be ridiculously large on some systems
|
|
47
|
+
bs = ENV['bs'] ? ENV['bs'].to_i : 65536
|
|
48
|
+
count = ENV['count'] ? ENV['count'].to_i : 2048
|
|
49
|
+
warn "serving response with bs=#{bs} count=#{count} (#{bs*count} bytes)"
|
|
50
|
+
run BigResponse.new(bs, count)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# This app is intended to test large HTTP requests with or without
|
|
2
|
+
# a fully-buffering reverse proxy such as nginx. Without a fully-buffering
|
|
3
|
+
# reverse proxy, unicorn will be unresponsive when client count exceeds
|
|
4
|
+
# worker_processes.
|
|
5
|
+
|
|
6
|
+
DOC = <<DOC
|
|
7
|
+
To demonstrate how bad unicorn is at slowly uploading clients:
|
|
8
|
+
|
|
9
|
+
# in one terminal, start unicorn with one worker:
|
|
10
|
+
unicorn -E none -l 127.0.0.1:8080 test/benchmark/readinput.ru
|
|
11
|
+
|
|
12
|
+
# in a different terminal, upload 45M from multiple curl processes:
|
|
13
|
+
dd if=/dev/zero bs=45M count=1 | curl -T- -HExpect: --limit-rate 1M \
|
|
14
|
+
--trace-time -v http://127.0.0.1:8080/ &
|
|
15
|
+
dd if=/dev/zero bs=45M count=1 | curl -T- -HExpect: --limit-rate 1M \
|
|
16
|
+
--trace-time -v http://127.0.0.1:8080/ &
|
|
17
|
+
wait
|
|
18
|
+
|
|
19
|
+
# The last client won't see a response until the first one is done uploading
|
|
20
|
+
# You also won't be able to make GET requests to view this documentation
|
|
21
|
+
# while clients are uploading. You can also view the stderr debug output
|
|
22
|
+
# of unicorn (see logging code in #{__FILE__}).
|
|
23
|
+
DOC
|
|
24
|
+
|
|
25
|
+
run(lambda do |env|
|
|
26
|
+
input = env['rack.input']
|
|
27
|
+
buf = ''.b
|
|
28
|
+
|
|
29
|
+
# default logger contains timestamps, rely on that so users can
|
|
30
|
+
# see what the server is doing
|
|
31
|
+
l = env['rack.logger']
|
|
32
|
+
|
|
33
|
+
l.debug('BEGIN reading input ...') if l
|
|
34
|
+
:nop while input.read(16384, buf)
|
|
35
|
+
l.debug('DONE reading input ...') if l
|
|
36
|
+
|
|
37
|
+
buf.clear
|
|
38
|
+
[ 200, [ %W(Content-Length #{DOC.size}), %w(Content-Type text/plain) ],
|
|
39
|
+
[ DOC ] ]
|
|
40
|
+
end)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/perl -w
|
|
2
|
+
# Benchmark script to spawn some processes and hammer a local unicorn
|
|
3
|
+
# to test accept loop performance. This only does Unix sockets.
|
|
4
|
+
# There's plenty of TCP benchmarking tools out there, and TCP port reuse
|
|
5
|
+
# has predictability problems since unicorn can't do persistent connections.
|
|
6
|
+
# Written in Perl for the same reason: predictability.
|
|
7
|
+
# Ruby GC is not as predictable as Perl refcounting.
|
|
8
|
+
use strict;
|
|
9
|
+
use Socket qw(AF_UNIX SOCK_STREAM sockaddr_un);
|
|
10
|
+
use POSIX qw(:sys_wait_h);
|
|
11
|
+
use Getopt::Std;
|
|
12
|
+
# -c / -n switches stolen from ab(1)
|
|
13
|
+
my $usage = "$0 [-c CONCURRENCY] [-n NUM_REQUESTS] SOCKET_PATH\n";
|
|
14
|
+
our $opt_c = 2;
|
|
15
|
+
our $opt_n = 1000;
|
|
16
|
+
getopts('c:n:') or die $usage;
|
|
17
|
+
my $unix_path = shift or die $usage;
|
|
18
|
+
use constant REQ => "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
|
|
19
|
+
use constant REQ_LEN => length(REQ);
|
|
20
|
+
use constant BUFSIZ => 8192;
|
|
21
|
+
$^F = 99; # don't waste syscall time with FD_CLOEXEC
|
|
22
|
+
|
|
23
|
+
my %workers; # pid => worker num
|
|
24
|
+
die "-n $opt_n not evenly divisible by -c $opt_c\n" if $opt_n % $opt_c;
|
|
25
|
+
my $n_per_worker = $opt_n / $opt_c;
|
|
26
|
+
my $addr = sockaddr_un($unix_path);
|
|
27
|
+
|
|
28
|
+
for my $num (1..$opt_c) {
|
|
29
|
+
defined(my $pid = fork) or die "fork failed: $!\n";
|
|
30
|
+
if ($pid) {
|
|
31
|
+
$workers{$pid} = $num;
|
|
32
|
+
} else {
|
|
33
|
+
work($n_per_worker);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
reap_worker(0) while scalar keys %workers;
|
|
38
|
+
exit;
|
|
39
|
+
|
|
40
|
+
sub work {
|
|
41
|
+
my ($n) = @_;
|
|
42
|
+
my ($buf, $x);
|
|
43
|
+
for (1..$n) {
|
|
44
|
+
socket(S, AF_UNIX, SOCK_STREAM, 0) or die "socket: $!";
|
|
45
|
+
connect(S, $addr) or die "connect: $!";
|
|
46
|
+
defined($x = syswrite(S, REQ)) or die "write: $!";
|
|
47
|
+
$x == REQ_LEN or die "short write: $x != ".REQ_LEN."\n";
|
|
48
|
+
do {
|
|
49
|
+
$x = sysread(S, $buf, BUFSIZ);
|
|
50
|
+
unless (defined $x) {
|
|
51
|
+
next if $!{EINTR};
|
|
52
|
+
die "sysread: $!\n";
|
|
53
|
+
}
|
|
54
|
+
} until ($x == 0);
|
|
55
|
+
}
|
|
56
|
+
exit 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
sub reap_worker {
|
|
60
|
+
my ($flags) = @_;
|
|
61
|
+
my $pid = waitpid(-1, $flags);
|
|
62
|
+
return if !defined $pid || $pid <= 0;
|
|
63
|
+
my $p = delete $workers{$pid} || '(unknown)';
|
|
64
|
+
warn("$pid [$p] exited with $?\n") if $?;
|
|
65
|
+
$p;
|
|
66
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
These tests require the "unicorn" executable script to be installed in
|
|
2
|
+
PATH and rack being directly "require"-able ("rubygems" will not be
|
|
3
|
+
loaded for you). The tester is responsible for setting up RUBYLIB and
|
|
4
|
+
PATH environment variables (or running tests via GNU Make instead of
|
|
5
|
+
Rake).
|