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.
Files changed (158) hide show
  1. checksums.yaml +7 -0
  2. data/.CHANGELOG.old +25 -0
  3. data/.document +28 -0
  4. data/.gitattributes +5 -0
  5. data/.gitignore +25 -0
  6. data/.mailmap +26 -0
  7. data/.manifest +156 -0
  8. data/.olddoc.yml +18 -0
  9. data/Application_Timeouts +77 -0
  10. data/CONTRIBUTORS +35 -0
  11. data/COPYING +674 -0
  12. data/DESIGN +95 -0
  13. data/Documentation/.gitignore +5 -0
  14. data/Documentation/GNUmakefile +30 -0
  15. data/Documentation/unicorn.1.txt +187 -0
  16. data/Documentation/unicorn_rails.1.txt +175 -0
  17. data/FAQ +70 -0
  18. data/GIT-VERSION-FILE +1 -0
  19. data/GIT-VERSION-GEN +39 -0
  20. data/GNUmakefile +253 -0
  21. data/HACKING +120 -0
  22. data/ISSUES +90 -0
  23. data/KNOWN_ISSUES +79 -0
  24. data/LATEST +30 -0
  25. data/LICENSE +67 -0
  26. data/Links +56 -0
  27. data/NEWS +2465 -0
  28. data/PHILOSOPHY +139 -0
  29. data/README +138 -0
  30. data/Rakefile +16 -0
  31. data/SIGNALS +123 -0
  32. data/Sandbox +104 -0
  33. data/TODO +3 -0
  34. data/TUNING +119 -0
  35. data/archive/.gitignore +3 -0
  36. data/archive/slrnpull.conf +4 -0
  37. data/bin/unicorn +126 -0
  38. data/bin/unicorn_rails +209 -0
  39. data/examples/big_app_gc.rb +2 -0
  40. data/examples/echo.ru +27 -0
  41. data/examples/init.sh +102 -0
  42. data/examples/logger_mp_safe.rb +25 -0
  43. data/examples/logrotate.conf +44 -0
  44. data/examples/nginx.conf +155 -0
  45. data/examples/unicorn.conf.minimal.rb +13 -0
  46. data/examples/unicorn.conf.rb +110 -0
  47. data/examples/unicorn.socket +11 -0
  48. data/examples/unicorn@.service +33 -0
  49. data/ext/unicorn_http/CFLAGS +13 -0
  50. data/ext/unicorn_http/c_util.h +124 -0
  51. data/ext/unicorn_http/common_field_optimization.h +111 -0
  52. data/ext/unicorn_http/ext_help.h +62 -0
  53. data/ext/unicorn_http/extconf.rb +11 -0
  54. data/ext/unicorn_http/global_variables.h +97 -0
  55. data/ext/unicorn_http/httpdate.c +78 -0
  56. data/ext/unicorn_http/unicorn_http.c +4274 -0
  57. data/ext/unicorn_http/unicorn_http.rl +980 -0
  58. data/ext/unicorn_http/unicorn_http_common.rl +76 -0
  59. data/lib/unicorn/app/old_rails/static.rb +59 -0
  60. data/lib/unicorn/app/old_rails.rb +35 -0
  61. data/lib/unicorn/cgi_wrapper.rb +147 -0
  62. data/lib/unicorn/configurator.rb +664 -0
  63. data/lib/unicorn/const.rb +21 -0
  64. data/lib/unicorn/http_request.rb +122 -0
  65. data/lib/unicorn/http_response.rb +60 -0
  66. data/lib/unicorn/http_server.rb +824 -0
  67. data/lib/unicorn/launcher.rb +62 -0
  68. data/lib/unicorn/oob_gc.rb +82 -0
  69. data/lib/unicorn/preread_input.rb +33 -0
  70. data/lib/unicorn/socket_helper.rb +195 -0
  71. data/lib/unicorn/stream_input.rb +146 -0
  72. data/lib/unicorn/tee_input.rb +133 -0
  73. data/lib/unicorn/tmpio.rb +27 -0
  74. data/lib/unicorn/util.rb +90 -0
  75. data/lib/unicorn/version.rb +1 -0
  76. data/lib/unicorn/worker.rb +140 -0
  77. data/lib/unicorn.rb +123 -0
  78. data/man/man1/unicorn.1 +221 -0
  79. data/man/man1/unicorn_rails.1 +212 -0
  80. data/setup.rb +1586 -0
  81. data/t/.gitignore +4 -0
  82. data/t/GNUmakefile +74 -0
  83. data/t/README +42 -0
  84. data/t/bin/content-md5-put +36 -0
  85. data/t/bin/sha1sum.rb +17 -0
  86. data/t/bin/unused_listen +40 -0
  87. data/t/broken-app.ru +12 -0
  88. data/t/detach.ru +11 -0
  89. data/t/env.ru +3 -0
  90. data/t/fails-rack-lint.ru +5 -0
  91. data/t/heartbeat-timeout.ru +12 -0
  92. data/t/hijack.ru +43 -0
  93. data/t/listener_names.ru +4 -0
  94. data/t/my-tap-lib.sh +201 -0
  95. data/t/oob_gc.ru +20 -0
  96. data/t/oob_gc_path.ru +20 -0
  97. data/t/pid.ru +3 -0
  98. data/t/preread_input.ru +17 -0
  99. data/t/rack-input-tests.ru +21 -0
  100. data/t/t0000-http-basic.sh +50 -0
  101. data/t/t0001-reload-bad-config.sh +53 -0
  102. data/t/t0002-config-conflict.sh +49 -0
  103. data/t/t0002-parser-error.sh +94 -0
  104. data/t/t0003-working_directory.sh +51 -0
  105. data/t/t0004-heartbeat-timeout.sh +69 -0
  106. data/t/t0004-working_directory_broken.sh +24 -0
  107. data/t/t0005-working_directory_app.rb.sh +40 -0
  108. data/t/t0006-reopen-logs.sh +83 -0
  109. data/t/t0006.ru +13 -0
  110. data/t/t0007-working_directory_no_embed_cli.sh +44 -0
  111. data/t/t0008-back_out_of_upgrade.sh +110 -0
  112. data/t/t0009-broken-app.sh +56 -0
  113. data/t/t0009-winch_ttin.sh +59 -0
  114. data/t/t0010-reap-logging.sh +55 -0
  115. data/t/t0011-active-unix-socket.sh +79 -0
  116. data/t/t0012-reload-empty-config.sh +85 -0
  117. data/t/t0013-rewindable-input-false.sh +24 -0
  118. data/t/t0013.ru +12 -0
  119. data/t/t0014-rewindable-input-true.sh +24 -0
  120. data/t/t0014.ru +12 -0
  121. data/t/t0015-configurator-internals.sh +25 -0
  122. data/t/t0018-write-on-close.sh +23 -0
  123. data/t/t0019-max_header_len.sh +49 -0
  124. data/t/t0020-at_exit-handler.sh +49 -0
  125. data/t/t0021-process_detach.sh +29 -0
  126. data/t/t0022-listener_names-preload_app.sh +32 -0
  127. data/t/t0100-rack-input-tests.sh +124 -0
  128. data/t/t0116-client_body_buffer_size.sh +80 -0
  129. data/t/t0116.ru +16 -0
  130. data/t/t0200-rack-hijack.sh +30 -0
  131. data/t/t0300-no-default-middleware.sh +20 -0
  132. data/t/t9000-preread-input.sh +48 -0
  133. data/t/t9001-oob_gc.sh +47 -0
  134. data/t/t9002-oob_gc-path.sh +75 -0
  135. data/t/test-lib.sh +128 -0
  136. data/t/write-on-close.ru +11 -0
  137. data/test/aggregate.rb +15 -0
  138. data/test/benchmark/README +50 -0
  139. data/test/benchmark/dd.ru +18 -0
  140. data/test/benchmark/stack.ru +8 -0
  141. data/test/exec/README +5 -0
  142. data/test/exec/test_exec.rb +1099 -0
  143. data/test/test_helper.rb +298 -0
  144. data/test/unit/test_configurator.rb +175 -0
  145. data/test/unit/test_droplet.rb +28 -0
  146. data/test/unit/test_http_parser.rb +886 -0
  147. data/test/unit/test_http_parser_ng.rb +633 -0
  148. data/test/unit/test_request.rb +182 -0
  149. data/test/unit/test_response.rb +111 -0
  150. data/test/unit/test_server.rb +268 -0
  151. data/test/unit/test_signals.rb +188 -0
  152. data/test/unit/test_socket_helper.rb +197 -0
  153. data/test/unit/test_stream_input.rb +203 -0
  154. data/test/unit/test_tee_input.rb +304 -0
  155. data/test/unit/test_upload.rb +306 -0
  156. data/test/unit/test_util.rb +105 -0
  157. data/unicorn.gemspec +50 -0
  158. metadata +310 -0
@@ -0,0 +1,80 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 12 "client_body_buffer_size settings"
4
+
5
+ t_begin "setup and start" && {
6
+ unicorn_setup
7
+ rtmpfiles unicorn_config_tmp one_meg
8
+ dd if=/dev/zero bs=1M count=1 of=$one_meg
9
+ cat >> $unicorn_config <<EOF
10
+ after_fork do |server, worker|
11
+ File.open("$fifo", "wb") { |fp| fp.syswrite "START" }
12
+ end
13
+ EOF
14
+ cat $unicorn_config > $unicorn_config_tmp
15
+ echo client_body_buffer_size 0 >> $unicorn_config
16
+ unicorn -D -c $unicorn_config t0116.ru
17
+ unicorn_wait_start
18
+ fs_class=Unicorn::TmpIO
19
+ mem_class=StringIO
20
+
21
+ test x"$(cat $fifo)" = xSTART
22
+ }
23
+
24
+ t_begin "class for a zero-byte file should be StringIO" && {
25
+ > $tmp
26
+ test xStringIO = x"$(curl -T $tmp -sSf http://$listen/input_class)"
27
+ }
28
+
29
+ t_begin "class for a 1 byte file should be filesystem-backed" && {
30
+ echo > $tmp
31
+ test x$fs_class = x"$(curl -T $tmp -sSf http://$listen/tmp_class)"
32
+ }
33
+
34
+ t_begin "reload with default client_body_buffer_size" && {
35
+ mv $unicorn_config_tmp $unicorn_config
36
+ kill -HUP $unicorn_pid
37
+ test x"$(cat $fifo)" = xSTART
38
+ }
39
+
40
+ t_begin "class for a 1 byte file should be memory-backed" && {
41
+ echo > $tmp
42
+ test x$mem_class = x"$(curl -T $tmp -sSf http://$listen/tmp_class)"
43
+ }
44
+
45
+ t_begin "class for a random blob file should be filesystem-backed" && {
46
+ resp="$(curl -T random_blob -sSf http://$listen/tmp_class)"
47
+ test x$fs_class = x"$resp"
48
+ }
49
+
50
+ t_begin "one megabyte file should be filesystem-backed" && {
51
+ resp="$(curl -T $one_meg -sSf http://$listen/tmp_class)"
52
+ test x$fs_class = x"$resp"
53
+ }
54
+
55
+ t_begin "reload with a big client_body_buffer_size" && {
56
+ echo "client_body_buffer_size(1024 * 1024)" >> $unicorn_config
57
+ kill -HUP $unicorn_pid
58
+ test x"$(cat $fifo)" = xSTART
59
+ }
60
+
61
+ t_begin "one megabyte file should be memory-backed" && {
62
+ resp="$(curl -T $one_meg -sSf http://$listen/tmp_class)"
63
+ test x$mem_class = x"$resp"
64
+ }
65
+
66
+ t_begin "one megabyte + 1 byte file should be filesystem-backed" && {
67
+ echo >> $one_meg
68
+ resp="$(curl -T $one_meg -sSf http://$listen/tmp_class)"
69
+ test x$fs_class = x"$resp"
70
+ }
71
+
72
+ t_begin "killing succeeds" && {
73
+ kill $unicorn_pid
74
+ }
75
+
76
+ t_begin "check stderr" && {
77
+ check_stderr
78
+ }
79
+
80
+ t_done
data/t/t0116.ru ADDED
@@ -0,0 +1,16 @@
1
+ #\ -E none
2
+ use Rack::ContentLength
3
+ use Rack::ContentType, 'text/plain'
4
+ app = lambda do |env|
5
+ input = env['rack.input']
6
+ case env["PATH_INFO"]
7
+ when "/tmp_class"
8
+ body = input.instance_variable_get(:@tmp).class.name
9
+ when "/input_class"
10
+ body = input.class.name
11
+ else
12
+ return [ 500, {}, [] ]
13
+ end
14
+ [ 200, {}, [ body ] ]
15
+ end
16
+ run app
@@ -0,0 +1,30 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 5 "rack.hijack tests (Rack 1.5+ (Rack::VERSION >= [ 1,2]))"
4
+
5
+ t_begin "setup and start" && {
6
+ unicorn_setup
7
+ unicorn -D -c $unicorn_config hijack.ru
8
+ unicorn_wait_start
9
+ }
10
+
11
+ t_begin "check request hijack" && {
12
+ test "xrequest.hijacked" = x"$(curl -sSfv http://$listen/hijack_req)"
13
+ }
14
+
15
+ t_begin "check response hijack" && {
16
+ test "xresponse.hijacked" = x"$(curl -sSfv http://$listen/hijack_res)"
17
+ }
18
+
19
+ t_begin "killing succeeds after hijack" && {
20
+ kill $unicorn_pid
21
+ }
22
+
23
+ t_begin "check stderr for hijacked body close" && {
24
+ check_stderr
25
+ grep 'closed DieIfUsed 1\>' $r_err
26
+ grep 'closed DieIfUsed 2\>' $r_err
27
+ ! grep 'closed DieIfUsed 3\>' $r_err
28
+ }
29
+
30
+ t_done
@@ -0,0 +1,20 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 3 "test the -N / --no-default-middleware option"
4
+
5
+ t_begin "setup and start" && {
6
+ unicorn_setup
7
+ unicorn -N -D -c $unicorn_config fails-rack-lint.ru
8
+ unicorn_wait_start
9
+ }
10
+
11
+ t_begin "check exit status with Rack::Lint not present" && {
12
+ test 42 -eq "$(curl -sf -o/dev/null -w'%{http_code}' http://$listen/)"
13
+ }
14
+
15
+ t_begin "killing succeeds" && {
16
+ kill $unicorn_pid
17
+ check_stderr
18
+ }
19
+
20
+ t_done
@@ -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
data/t/t9001-oob_gc.sh ADDED
@@ -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
data/t/test-lib.sh ADDED
@@ -0,0 +1,128 @@
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
+ then
99
+ die "Errors found in $_r_err"
100
+ elif grep SIGKILL $_r_err
101
+ then
102
+ die "SIGKILL found in $_r_err"
103
+ fi
104
+ }
105
+
106
+ # unicorn_setup
107
+ unicorn_setup () {
108
+ eval $(unused_listen)
109
+ port=$(expr $listen : '[^:]*:\([0-9]\+\)')
110
+ host=$(expr $listen : '\([^:]*\):[0-9]\+')
111
+
112
+ rtmpfiles unicorn_config pid r_err r_out fifo tmp ok
113
+ cat > $unicorn_config <<EOF
114
+ listen "$listen"
115
+ pid "$pid"
116
+ stderr_path "$r_err"
117
+ stdout_path "$r_out"
118
+ EOF
119
+ }
120
+
121
+ unicorn_wait_start () {
122
+ # no need to play tricks with FIFOs since we got "ready_pipe" now
123
+ unicorn_pid=$(cat $pid)
124
+ }
125
+
126
+ rsha1 () {
127
+ sha1sum.rb
128
+ }
@@ -0,0 +1,11 @@
1
+ class WriteOnClose
2
+ def each(&block)
3
+ @callback = block
4
+ end
5
+
6
+ def close
7
+ @callback.call "7\r\nGoodbye\r\n0\r\n\r\n"
8
+ end
9
+ end
10
+ use Rack::ContentType, "text/plain"
11
+ run(lambda { |_| [ 200, [%w(Transfer-Encoding chunked)], WriteOnClose.new ] })
data/test/aggregate.rb ADDED
@@ -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,50 @@
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
+ == Contributors
46
+
47
+ This directory is maintained independently in the "benchmark" branch
48
+ based against v0.1.0. Only changes to this directory (test/benchmarks)
49
+ are committed to this branch although the master branch may merge this
50
+ branch occassionaly.
@@ -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,8 @@
1
+ run(lambda { |env|
2
+ body = "#{caller.size}\n"
3
+ h = {
4
+ "Content-Length" => body.size.to_s,
5
+ "Content-Type" => "text/plain",
6
+ }
7
+ [ 200, h, [ body ] ]
8
+ })
data/test/exec/README ADDED
@@ -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).