rainbows 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/.document +1 -0
  2. data/.gitignore +1 -0
  3. data/.manifest +46 -18
  4. data/.wrongdoc.yml +8 -0
  5. data/ChangeLog +849 -374
  6. data/Documentation/comparison.haml +26 -21
  7. data/FAQ +6 -0
  8. data/GIT-VERSION-GEN +1 -1
  9. data/GNUmakefile +23 -65
  10. data/LATEST +27 -0
  11. data/NEWS +53 -26
  12. data/README +7 -7
  13. data/Rakefile +1 -98
  14. data/Summary +0 -7
  15. data/TODO +2 -2
  16. data/lib/rainbows/app_pool.rb +2 -1
  17. data/lib/rainbows/base.rb +1 -0
  18. data/lib/rainbows/configurator.rb +9 -0
  19. data/lib/rainbows/const.rb +1 -1
  20. data/lib/rainbows/coolio/client.rb +191 -0
  21. data/lib/rainbows/coolio/core.rb +25 -0
  22. data/lib/rainbows/{rev → coolio}/deferred_chunk_response.rb +3 -2
  23. data/lib/rainbows/{rev → coolio}/deferred_response.rb +3 -3
  24. data/lib/rainbows/coolio/heartbeat.rb +20 -0
  25. data/lib/rainbows/{rev → coolio}/master.rb +2 -3
  26. data/lib/rainbows/{rev → coolio}/sendfile.rb +1 -1
  27. data/lib/rainbows/coolio/server.rb +11 -0
  28. data/lib/rainbows/coolio/thread_client.rb +36 -0
  29. data/lib/rainbows/coolio.rb +45 -0
  30. data/lib/rainbows/coolio_fiber_spawn.rb +26 -0
  31. data/lib/rainbows/coolio_support.rb +9 -0
  32. data/lib/rainbows/coolio_thread_pool/client.rb +8 -0
  33. data/lib/rainbows/coolio_thread_pool/watcher.rb +14 -0
  34. data/lib/rainbows/coolio_thread_pool.rb +57 -0
  35. data/lib/rainbows/coolio_thread_spawn/client.rb +8 -0
  36. data/lib/rainbows/coolio_thread_spawn.rb +27 -0
  37. data/lib/rainbows/dev_fd_response.rb +6 -2
  38. data/lib/rainbows/ev_core/cap_input.rb +3 -2
  39. data/lib/rainbows/ev_core.rb +13 -3
  40. data/lib/rainbows/event_machine/client.rb +124 -0
  41. data/lib/rainbows/event_machine/response_pipe.rb +1 -2
  42. data/lib/rainbows/event_machine/server.rb +15 -0
  43. data/lib/rainbows/event_machine.rb +13 -137
  44. data/lib/rainbows/fiber/base.rb +6 -7
  45. data/lib/rainbows/fiber/body.rb +4 -2
  46. data/lib/rainbows/fiber/coolio/heartbeat.rb +15 -0
  47. data/lib/rainbows/fiber/{rev → coolio}/methods.rb +4 -5
  48. data/lib/rainbows/fiber/{rev → coolio}/server.rb +1 -1
  49. data/lib/rainbows/fiber/{rev → coolio}/sleeper.rb +2 -2
  50. data/lib/rainbows/fiber/coolio.rb +12 -0
  51. data/lib/rainbows/fiber/io/methods.rb +6 -0
  52. data/lib/rainbows/fiber/io.rb +8 -10
  53. data/lib/rainbows/fiber/queue.rb +24 -30
  54. data/lib/rainbows/fiber.rb +7 -4
  55. data/lib/rainbows/fiber_pool.rb +1 -1
  56. data/lib/rainbows/http_server.rb +9 -2
  57. data/lib/rainbows/max_body.rb +3 -1
  58. data/lib/rainbows/never_block/core.rb +15 -0
  59. data/lib/rainbows/never_block/event_machine.rb +8 -3
  60. data/lib/rainbows/never_block.rb +37 -70
  61. data/lib/rainbows/process_client.rb +3 -6
  62. data/lib/rainbows/rack_input.rb +17 -0
  63. data/lib/rainbows/response/body.rb +18 -19
  64. data/lib/rainbows/response.rb +1 -1
  65. data/lib/rainbows/rev.rb +21 -43
  66. data/lib/rainbows/rev_fiber_spawn.rb +4 -19
  67. data/lib/rainbows/rev_thread_pool.rb +21 -75
  68. data/lib/rainbows/rev_thread_spawn.rb +18 -36
  69. data/lib/rainbows/revactor/body.rb +4 -1
  70. data/lib/rainbows/revactor/tee_socket.rb +44 -0
  71. data/lib/rainbows/revactor.rb +13 -48
  72. data/lib/rainbows/socket_proxy.rb +24 -0
  73. data/lib/rainbows/sync_close.rb +37 -0
  74. data/lib/rainbows/thread_pool.rb +66 -70
  75. data/lib/rainbows/thread_spawn.rb +40 -50
  76. data/lib/rainbows/thread_timeout.rb +33 -27
  77. data/lib/rainbows/timed_read.rb +5 -1
  78. data/lib/rainbows/worker_yield.rb +16 -0
  79. data/lib/rainbows/writer_thread_pool/client.rb +19 -0
  80. data/lib/rainbows/writer_thread_pool.rb +60 -91
  81. data/lib/rainbows/writer_thread_spawn/client.rb +69 -0
  82. data/lib/rainbows/writer_thread_spawn.rb +37 -117
  83. data/lib/rainbows.rb +12 -4
  84. data/rainbows.gemspec +15 -19
  85. data/t/GNUmakefile +4 -4
  86. data/t/close-has-env.ru +65 -0
  87. data/t/simple-http_Coolio.ru +9 -0
  88. data/t/simple-http_CoolioFiberSpawn.ru +10 -0
  89. data/t/simple-http_CoolioThreadPool.ru +9 -0
  90. data/t/simple-http_CoolioThreadSpawn.ru +9 -0
  91. data/t/t0004-heartbeat-timeout.sh +2 -2
  92. data/t/t0007-worker-follows-master-to-death.sh +1 -1
  93. data/t/t0015-working_directory.sh +7 -1
  94. data/t/t0017-keepalive-timeout-zero.sh +1 -1
  95. data/t/t0019-keepalive-cpu-usage.sh +62 -0
  96. data/t/t0040-keepalive_requests-setting.sh +51 -0
  97. data/t/t0050-response-body-close-has-env.sh +109 -0
  98. data/t/t0102-rack-input-short.sh +6 -6
  99. data/t/t0106-rack-input-keepalive.sh +48 -2
  100. data/t/t0113-rewindable-input-false.sh +28 -0
  101. data/t/t0113.ru +12 -0
  102. data/t/t0114-rewindable-input-true.sh +28 -0
  103. data/t/t0114.ru +12 -0
  104. data/t/t9100-thread-timeout.sh +24 -2
  105. data/t/t9101-thread-timeout-threshold.sh +6 -13
  106. data/t/test-lib.sh +2 -1
  107. data/t/test_isolate.rb +9 -4
  108. data/t/times.ru +6 -0
  109. metadata +109 -42
  110. data/GIT-VERSION-FILE +0 -1
  111. data/lib/rainbows/fiber/rev/heartbeat.rb +0 -8
  112. data/lib/rainbows/fiber/rev/kato.rb +0 -22
  113. data/lib/rainbows/fiber/rev.rb +0 -13
  114. data/lib/rainbows/rev/client.rb +0 -194
  115. data/lib/rainbows/rev/core.rb +0 -41
  116. data/lib/rainbows/rev/heartbeat.rb +0 -23
  117. data/lib/rainbows/rev/thread.rb +0 -46
  118. data/man/man1/rainbows.1 +0 -193
data/t/GNUmakefile CHANGED
@@ -23,10 +23,9 @@ models += WriterThreadPool
23
23
  models += WriterThreadSpawn
24
24
  models += ThreadPool
25
25
  models += ThreadSpawn
26
- models += Rev
26
+ models += Coolio
27
27
  models += EventMachine
28
28
  models += NeverBlock
29
- models += RevThreadSpawn
30
29
 
31
30
  ifeq ($(RUBY_ENGINE),ruby)
32
31
  rp := )
@@ -34,9 +33,10 @@ ifeq ($(RUBY_ENGINE),ruby)
34
33
  ifeq ($(ONENINE),true)
35
34
  models += Revactor
36
35
  models += FiberSpawn
37
- models += RevFiberSpawn
38
36
  models += FiberPool
39
- models += RevThreadPool
37
+ models += CoolioThreadPool
38
+ models += CoolioThreadSpawn
39
+ models += CoolioFiberSpawn
40
40
  endif
41
41
  endif
42
42
 
@@ -0,0 +1,65 @@
1
+ #\ -E none
2
+ use Rainbows::DevFdResponse
3
+ class ClosablePipe < ::IO
4
+ attr_accessor :env
5
+
6
+ def self.new(env)
7
+ rv = popen "echo hello", "rb"
8
+ rv.env = env
9
+ rv
10
+ end
11
+
12
+ def close
13
+ super
14
+ $stdout.syswrite "path_info=#{@env['PATH_INFO']}\n"
15
+ end
16
+ end
17
+
18
+ class ClosableFile < ::File
19
+ attr_accessor :env
20
+ alias to_path path
21
+ def close
22
+ super
23
+ $stdout.syswrite "path_info=#{@env['PATH_INFO']}\n"
24
+ end
25
+ end
26
+
27
+ class Blob
28
+ def initialize(env)
29
+ @env = env
30
+ end
31
+
32
+ def each(&block)
33
+ yield "BLOB\n"
34
+ end
35
+
36
+ def close
37
+ $stdout.syswrite "path_info=#{@env['PATH_INFO']}\n"
38
+ end
39
+ end
40
+
41
+ run(lambda { |env|
42
+ case env["PATH_INFO"]
43
+ when %r{\A/pipe/}
44
+ [ 200,
45
+ [ %w(Content-Length 6), %w(Content-Type text/plain)],
46
+ ClosablePipe.new(env)
47
+ ]
48
+ when %r{\A/file/}
49
+ f = ClosableFile.open("env.ru", "rb")
50
+ f.env = env
51
+ [ 200, {
52
+ 'X-Req-Path' => env["PATH_INFO"],
53
+ 'Content-Length' => f.stat.size.to_s,
54
+ 'Content-Type' => 'text/plain' },
55
+ f
56
+ ]
57
+ when %r{\A/blob/}
58
+ [ 200,
59
+ [%w(Content-Length 5), %w(Content-Type text/plain)],
60
+ Blob.new(env)
61
+ ]
62
+ else
63
+ [ 404, [%w(Content-Length 0), %w(Content-Type text/plain)], [] ]
64
+ end
65
+ })
@@ -0,0 +1,9 @@
1
+ use Rack::ContentLength
2
+ use Rack::ContentType
3
+ run lambda { |env|
4
+ if env['rack.multithread'] == false && env['rainbows.model'] == :Coolio
5
+ [ 200, {}, [ env.inspect << "\n" ] ]
6
+ else
7
+ raise "rack.multithread is true"
8
+ end
9
+ }
@@ -0,0 +1,10 @@
1
+ use Rack::ContentLength
2
+ use Rack::ContentType
3
+ run lambda { |env|
4
+ if env['rack.multithread'] == false &&
5
+ env['rainbows.model'] == :CoolioFiberSpawn
6
+ [ 200, {}, [ Thread.current.inspect << "\n" ] ]
7
+ else
8
+ raise env.inspect
9
+ end
10
+ }
@@ -0,0 +1,9 @@
1
+ use Rack::ContentLength
2
+ use Rack::ContentType
3
+ run lambda { |env|
4
+ if env['rack.multithread'] && env['rainbows.model'] == :CoolioThreadPool
5
+ [ 200, {}, [ env.inspect << "\n" ] ]
6
+ else
7
+ raise "rack.multithread is false"
8
+ end
9
+ }
@@ -0,0 +1,9 @@
1
+ use Rack::ContentLength
2
+ use Rack::ContentType
3
+ run lambda { |env|
4
+ if env['rack.multithread'] && env['rainbows.model'] == :CoolioThreadSpawn
5
+ [ 200, {}, [ env.inspect << "\n" ] ]
6
+ else
7
+ raise "rack.multithread is false"
8
+ end
9
+ }
@@ -5,8 +5,8 @@ t_plan 12 "heartbeat/timeout test for $model"
5
5
 
6
6
  t_begin "setup and startup" && {
7
7
  rainbows_setup $model
8
- echo timeout 3 >> $unicorn_config
9
- echo preload_app true >> $unicorn_config
8
+ echo timeout 3 >> $unicorn_config
9
+ echo preload_app true >> $unicorn_config
10
10
  rainbows -D heartbeat-timeout.ru -c $unicorn_config
11
11
  rainbows_wait_start
12
12
  }
@@ -5,7 +5,7 @@ t_plan 7 "ensure worker follows master to death"
5
5
  t_begin "setup" && {
6
6
  rtmpfiles curl_err curl_out
7
7
  rainbows_setup
8
- echo timeout 3 >> $unicorn_config
8
+ echo timeout 3 >> $unicorn_config
9
9
  rainbows -D -c $unicorn_config worker-follows-master-to-death.ru
10
10
  rainbows_wait_start
11
11
  }
@@ -6,7 +6,7 @@ then
6
6
  fi
7
7
  . ./test-lib.sh
8
8
 
9
- t_plan 5 "config.ru inside alt working_directory"
9
+ t_plan 6 "config.ru inside alt working_directory"
10
10
 
11
11
  t_begin "setup and start" && {
12
12
  rainbows_setup
@@ -41,6 +41,12 @@ EOF
41
41
  rainbows_wait_start
42
42
  }
43
43
 
44
+ t_begin "reload to avoid race condition" && {
45
+ curl -sSf http://$listen/ >/dev/null
46
+ kill -HUP $rainbows_pid
47
+ test xSTART = x"$(cat $fifo)"
48
+ }
49
+
44
50
  t_begin "hit with curl" && {
45
51
  body=$(curl -sSf http://$listen/)
46
52
  }
@@ -4,7 +4,7 @@ t_plan 6 "keepalive_timeout 0 tests for $model"
4
4
 
5
5
  t_begin "setup and start" && {
6
6
  rainbows_setup $model 2 0
7
- grep 'keepalive_timeout 0' $unicorn_config
7
+ grep 'keepalive_timeout 0' $unicorn_config
8
8
  rainbows -D env.ru -c $unicorn_config
9
9
  rainbows_wait_start
10
10
  }
@@ -0,0 +1,62 @@
1
+ #!/bin/sh
2
+ if test -z "$V" || test 0 -eq "$V"
3
+ then
4
+ exit 0
5
+ fi
6
+ . ./test-lib.sh
7
+ skip_models WriterThreadSpawn WriterThreadPool Base
8
+ t_plan 6 "keepalive_timeout CPU usage tests for $model"
9
+
10
+ t_begin "setup and start" && {
11
+ rainbows_setup $model 50 666
12
+ grep 'worker_connections 50' $unicorn_config
13
+ grep 'keepalive_timeout 666' $unicorn_config
14
+ rainbows -E deployment -D times.ru -c $unicorn_config
15
+ rainbows_wait_start
16
+ }
17
+
18
+ t_begin 'read current times' && {
19
+ eval "$(curl -sSf http://$listen/)"
20
+ before_utime=$utime
21
+ before_stime=$stime
22
+ echo "utime=$utime stime=$stime"
23
+ }
24
+
25
+ t_begin 'keepalive connections' && {
26
+ listen=$listen $RUBY -rsocket -e '
27
+ host, port = ENV["listen"].split(/:/)
28
+ port = port.to_i
29
+ socks = (1..49).map do |i|
30
+ s = TCPSocket.new(host, port)
31
+ # need to write something to get around deferred accepts
32
+ s.write "GET /#{i} HTTP/1.1\r\nHost: example.com\r\n\r\n"
33
+ s.readpartial 16384
34
+ s
35
+ end
36
+ sleep
37
+ ' &
38
+ ruby_pid=$!
39
+ for i in $(awk 'BEGIN { for(i=0;i<60;++i) print i }' </dev/null)
40
+ do
41
+ sleep 1
42
+ eval "$(curl -sSf http://$listen/)"
43
+ echo "utime[$i] $before_utime => $utime" \
44
+ "stime[$i] $before_stime => $stime"
45
+ done
46
+ kill $ruby_pid
47
+ }
48
+
49
+ t_begin "times not unreasonable" && {
50
+ echo "utime: $before_utime => $utime" \
51
+ "stime: $before_stime => $stime"
52
+ }
53
+
54
+ t_begin "killing succeeds" && {
55
+ kill $rainbows_pid
56
+ }
57
+
58
+ t_begin "check stderr" && {
59
+ check_stderr
60
+ }
61
+
62
+ t_done
@@ -0,0 +1,51 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 6 "keepalive_requests limit tests for $model"
4
+
5
+ t_begin "setup and start" && {
6
+ rainbows_setup $model 50 666
7
+ rtmpfiles curl_out curl_err
8
+ grep 'keepalive_timeout 666' $unicorn_config
9
+ ed -s $unicorn_config <<EOF
10
+ ,s/listen.*/&, :tcp_nodelay => true/
11
+ w
12
+ EOF
13
+ grep nodelay $unicorn_config
14
+ rainbows -E none -D env.ru -c $unicorn_config
15
+ rainbows_wait_start
16
+ }
17
+
18
+ t_begin "curl requests hit default keepalive_requests limit" && {
19
+ curl -sSfv http://$listen/[0-101] > $curl_out 2> $curl_err
20
+ test 1 -eq $(grep 'Connection: close' $curl_err |wc -l)
21
+ test 101 -eq $(grep 'Connection: keep-alive' $curl_err |wc -l)
22
+ }
23
+
24
+ t_begin "reload with smaller keepalive_requests limit" && {
25
+ ed -s $unicorn_config <<EOF
26
+ ,g/Rainbows!/
27
+ a
28
+ keepalive_requests 5
29
+ .
30
+ w
31
+ EOF
32
+ kill -HUP $rainbows_pid
33
+ test x"$(cat $fifo)" = xSTART
34
+ }
35
+
36
+ t_begin "curl requests hit smaller keepalive_requests limit" && {
37
+ rm -f $curl_out $curl_err
38
+ curl -sSfv http://$listen/[1-13] > $curl_out 2> $curl_err
39
+ test 2 -eq $(grep 'Connection: close' $curl_err |wc -l)
40
+ test 11 -eq $(grep 'Connection: keep-alive' $curl_err |wc -l)
41
+ }
42
+
43
+ t_begin "killing succeeds" && {
44
+ kill $rainbows_pid
45
+ }
46
+
47
+ t_begin "check stderr" && {
48
+ check_stderr
49
+ }
50
+
51
+ t_done
@@ -0,0 +1,109 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+
4
+ t_plan 29 "keepalive does not clear Rack env prematurely for $model"
5
+
6
+ t_begin "setup and start" && {
7
+ rainbows_setup
8
+ rtmpfiles curl_out curl_err
9
+ echo "preload_app true" >> $unicorn_config
10
+ rainbows -D close-has-env.ru -c $unicorn_config
11
+ rainbows_wait_start
12
+ }
13
+
14
+ req_pipelined () {
15
+ pfx=$1
16
+ t_begin "make pipelined requests to trigger $pfx response body" && {
17
+ > $r_out
18
+ (
19
+ cat $fifo > $tmp &
20
+ printf 'GET /%s/1 HTTP/1.1\r\n' $pfx
21
+ printf 'Host: example.com\r\n\r\n'
22
+ printf 'GET /%s/2 HTTP/1.1\r\n' $pfx
23
+ printf 'Host: example.com\r\n\r\n'
24
+ printf 'GET /%s/3 HTTP/1.1\r\n' $pfx
25
+ printf 'Host: example.com\r\n'
26
+ printf 'Connection: close\r\n\r\n'
27
+ wait
28
+ echo ok > $ok
29
+ ) | socat - TCP4:$listen > $fifo
30
+ test xok = x$(cat $ok)
31
+ }
32
+ }
33
+
34
+ reload () {
35
+ t_begin 'reloading Rainbows! to ensure writeout' && {
36
+ # reload to ensure everything is flushed
37
+ kill -HUP $rainbows_pid
38
+ test xSTART = x"$(cat $fifo)"
39
+ }
40
+ }
41
+
42
+ check_log () {
43
+ pfx="$1"
44
+ t_begin "check body close messages" && {
45
+ < $r_out awk '
46
+ /^path_info=\/'$pfx'\/[1-3]$/ { next }
47
+ { exit(2) }
48
+ END { exit(NR == 3 ? 0 : 1) }
49
+ '
50
+ }
51
+ }
52
+
53
+ req_keepalive () {
54
+ pfx="$1"
55
+ t_begin "make keepalive requests to trigger $pfx response body" && {
56
+ > $r_out
57
+ rm -f $curl_err $curl_out
58
+ curl -vsSf http://$listen/$pfx/[1-3] 2> $curl_err > $curl_out
59
+ }
60
+ }
61
+
62
+ req_keepalive file
63
+ reload
64
+ check_log file
65
+
66
+ req_pipelined file
67
+ reload
68
+ check_log file
69
+
70
+ req_keepalive blob
71
+ reload
72
+ check_log blob
73
+
74
+ req_pipelined blob
75
+ reload
76
+ check_log blob
77
+
78
+ req_keepalive pipe
79
+ reload
80
+ check_log pipe
81
+
82
+ req_pipelined pipe
83
+ reload
84
+ check_log pipe
85
+
86
+ t_begin "enable sendfile gem" && {
87
+ echo "require 'sendfile'" >> $unicorn_config
88
+ curl http://$listen/ >/dev/null # ensure worker is loaded before HUP
89
+ }
90
+
91
+ reload
92
+
93
+ req_keepalive file
94
+ reload
95
+ check_log file
96
+
97
+ req_pipelined file
98
+ reload
99
+ check_log file
100
+
101
+ t_begin "killing succeeds" && {
102
+ kill $rainbows_pid
103
+ }
104
+
105
+ t_begin "check stderr" && {
106
+ check_stderr
107
+ }
108
+
109
+ t_done
@@ -8,21 +8,21 @@ t_begin "setup and startup" && {
8
8
  rtmpfiles curl_out curl_err
9
9
  rainbows_setup $model
10
10
  rainbows -D sha1-random-size.ru -c $unicorn_config
11
- blob_sha1=$(rsha1 < random_blob)
12
- t_info "blob_sha1=$blob_sha1"
11
+ blob_sha1=$(rsha1 < random_blob)
12
+ t_info "blob_sha1=$blob_sha1"
13
13
  rainbows_wait_start
14
14
  }
15
15
 
16
16
  t_begin "regular request" && {
17
17
  curl -sSf -T random_blob http://$listen/ > $curl_out 2> $curl_err
18
- test x$blob_sha1 = x$(cat $curl_out)
19
- test ! -s $curl_err
18
+ test x$blob_sha1 = x$(cat $curl_out)
19
+ test ! -s $curl_err
20
20
  }
21
21
 
22
22
  t_begin "chunked request" && {
23
23
  curl -sSf -T- < random_blob http://$listen/ > $curl_out 2> $curl_err
24
- test x$blob_sha1 = x$(cat $curl_out)
25
- test ! -s $curl_err
24
+ test x$blob_sha1 = x$(cat $curl_out)
25
+ test ! -s $curl_err
26
26
  }
27
27
 
28
28
  t_begin "shutdown" && {
@@ -1,17 +1,63 @@
1
1
  #!/bin/sh
2
2
  . ./test-lib.sh
3
- t_plan 7 "rack.input pipelining test"
3
+ t_plan 11 "rack.input pipelining test"
4
4
 
5
5
  t_begin "setup and startup" && {
6
6
  rainbows_setup $model
7
- rtmpfiles req
7
+ rtmpfiles req
8
8
  rainbows -D sha1.ru -c $unicorn_config
9
9
  body=hello
10
10
  body_size=$(printf $body | wc -c)
11
11
  body_sha1=$(printf $body | rsha1)
12
+ random_blob_size=$(wc -c < random_blob)
13
+ random_blob_sha1=$(rsha1 < random_blob)
12
14
  rainbows_wait_start
13
15
  }
14
16
 
17
+ t_begin "send big pipelined chunked requests" && {
18
+ (
19
+ cat $fifo > $tmp &
20
+ content-md5-put < random_blob
21
+ content-md5-put < random_blob
22
+ content-md5-put < random_blob
23
+ printf 'PUT / HTTP/1.0\r\n'
24
+ printf 'Content-Length: %d\r\n\r\n' $random_blob_size
25
+ cat random_blob
26
+ wait
27
+ echo ok > $ok
28
+ ) | socat - TCP4:$listen > $fifo
29
+ test x"$(cat $ok)" = xok
30
+ }
31
+
32
+ t_begin "check responses" && {
33
+ dbgcat tmp
34
+ test 4 -eq $(grep $random_blob_sha1 $tmp | wc -l)
35
+ }
36
+
37
+ t_begin "send big pipelined identity requests" && {
38
+ (
39
+ cat $fifo > $tmp &
40
+ printf 'PUT / HTTP/1.0\r\n'
41
+ printf 'Connection: keep-alive\r\n'
42
+ printf 'Content-Length: %d\r\n\r\n' $random_blob_size
43
+ cat random_blob
44
+ printf 'PUT / HTTP/1.1\r\n'
45
+ printf 'Content-Length: %d\r\n\r\n' $random_blob_size
46
+ cat random_blob
47
+ printf 'PUT / HTTP/1.0\r\n'
48
+ printf 'Content-Length: %d\r\n\r\n' $random_blob_size
49
+ cat random_blob
50
+ wait
51
+ echo ok > $ok
52
+ ) | socat - TCP4:$listen > $fifo
53
+ test x"$(cat $ok)" = xok
54
+ }
55
+
56
+ t_begin "check responses" && {
57
+ dbgcat tmp
58
+ test 3 -eq $(grep $random_blob_sha1 $tmp | wc -l)
59
+ }
60
+
15
61
  t_begin "send pipelined identity requests" && {
16
62
 
17
63
  {
@@ -0,0 +1,28 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ skip_models EventMachine NeverBlock
4
+ skip_models Rev RevThreadSpawn RevThreadPool
5
+ skip_models Coolio CoolioThreadSpawn CoolioThreadPool
6
+
7
+ t_plan 4 "rewindable_input toggled to false"
8
+
9
+ t_begin "setup and start" && {
10
+ rainbows_setup
11
+ echo rewindable_input false >> $unicorn_config
12
+ rainbows -D -c $unicorn_config t0113.ru
13
+ rainbows_wait_start
14
+ }
15
+
16
+ t_begin "ensure worker is started" && {
17
+ test xOK = x$(curl -T t0113.ru -H Expect: -vsSf http://$listen/)
18
+ }
19
+
20
+ t_begin "killing succeeds" && {
21
+ kill $rainbows_pid
22
+ }
23
+
24
+ t_begin "check stderr" && {
25
+ check_stderr
26
+ }
27
+
28
+ t_done
data/t/t0113.ru ADDED
@@ -0,0 +1,12 @@
1
+ #\ -E none
2
+ use Rack::ContentLength
3
+ use Rack::ContentType, 'text/plain'
4
+ app = lambda do |env|
5
+ case env['rack.input']
6
+ when Unicorn::StreamInput
7
+ [ 200, {}, %w(OK) ]
8
+ else
9
+ [ 500, {}, %w(NO) ]
10
+ end
11
+ end
12
+ run app
@@ -0,0 +1,28 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ skip_models EventMachine NeverBlock
4
+ skip_models Rev RevThreadSpawn RevThreadPool
5
+ skip_models Coolio CoolioThreadSpawn CoolioThreadPool
6
+
7
+ t_plan 4 "rewindable_input toggled to true"
8
+
9
+ t_begin "setup and start" && {
10
+ rainbows_setup
11
+ echo rewindable_input true >> $unicorn_config
12
+ rainbows -D -c $unicorn_config t0114.ru
13
+ rainbows_wait_start
14
+ }
15
+
16
+ t_begin "ensure worker is started" && {
17
+ test xOK = x$(curl -T t0114.ru -sSf http://$listen/)
18
+ }
19
+
20
+ t_begin "killing succeeds" && {
21
+ kill $rainbows_pid
22
+ }
23
+
24
+ t_begin "check stderr" && {
25
+ check_stderr
26
+ }
27
+
28
+ t_done
data/t/t0114.ru ADDED
@@ -0,0 +1,12 @@
1
+ #\ -E none
2
+ use Rack::ContentLength
3
+ use Rack::ContentType, 'text/plain'
4
+ app = lambda do |env|
5
+ case env['rack.input']
6
+ when Unicorn::TeeInput
7
+ [ 200, {}, %w(OK) ]
8
+ else
9
+ [ 500, {}, %w(NO) ]
10
+ end
11
+ end
12
+ run app
@@ -1,11 +1,13 @@
1
1
  #!/bin/sh
2
2
  . ./test-lib.sh
3
3
  case $model in
4
- ThreadSpawn|ThreadPool|RevThreadSpawn|RevThreadPool) ;;
4
+ ThreadSpawn|ThreadPool) ;;
5
+ RevThreadSpawn|RevThreadPool) ;;
6
+ CoolioThreadSpawn|CoolioThreadPool) ;;
5
7
  *) t_info "$0 is only compatible with Thread*"; exit 0 ;;
6
8
  esac
7
9
 
8
- t_plan 5 "ThreadTimeout Rack middleware test for $model"
10
+ t_plan 6 "ThreadTimeout Rack middleware test for $model"
9
11
 
10
12
  t_begin "configure and start" && {
11
13
  rtmpfiles curl_err
@@ -25,6 +27,26 @@ t_begin "sleepy request times out with 408" && {
25
27
  grep 408 $curl_err
26
28
  }
27
29
 
30
+ t_begin "short requests do not timeout while making a long one" && {
31
+ rm -f $ok $curl_err
32
+ > $ok
33
+ curl -sSf http://$listen/2 2>$curl_err >/dev/null &
34
+ (
35
+ for i in $(awk </dev/null 'BEGIN{for(i=20;--i>=0;)print i}')
36
+ do
37
+ curl -sSf http://$listen/0.1 >> $ok 2>&1 &
38
+ test x"HI" = x"$(curl -sSf http://$listen/0.05)"
39
+ done
40
+ wait
41
+ )
42
+ test x"HI" = x"$(curl -sSf http://$listen/)"
43
+ wait
44
+ test -f $ok
45
+ test 20 -eq $(grep '^HI$' $ok | wc -l)
46
+ test x = x"$(grep -v '^HI$' $ok)"
47
+ grep 408 $curl_err
48
+ }
49
+
28
50
  t_begin "kill server" && {
29
51
  kill $rainbows_pid
30
52
  }
@@ -1,7 +1,9 @@
1
1
  #!/bin/sh
2
2
  . ./test-lib.sh
3
3
  case $model in
4
- ThreadSpawn|ThreadPool|RevThreadSpawn|RevThreadPool) ;;
4
+ ThreadSpawn|ThreadPool) ;;
5
+ RevThreadSpawn|RevThreadPool) ;;
6
+ CoolioThreadSpawn|CoolioThreadPool) ;;
5
7
  *) t_info "$0 is only compatible with Thread*"; exit 0 ;;
6
8
  esac
7
9
 
@@ -30,25 +32,16 @@ t_begin "8 sleepy requests do not time out" && {
30
32
  test xHI = x"$(sort < $curl_out | uniq)"
31
33
  }
32
34
 
33
- t_begin "9 sleepy requests do time out" && {
35
+ t_begin "9 sleepy requests, some time out" && {
34
36
  > $curl_err
35
37
  > $curl_out
36
38
  for i in 1 2 3 4 5 6 7 8 9
37
39
  do
38
- rtmpfiles curl_err_$i
39
40
  curl -sSf --no-buffer \
40
- http://$listen/3 2>> ${curl_err}_${i} >> $curl_out &
41
+ http://$listen/3 2>> $curl_err >> $curl_out &
41
42
  done
42
43
  wait
43
- if test -s $curl_out
44
- then
45
- dbgcat curl_out
46
- die "$curl_out should be empty"
47
- fi
48
- for i in 1 2 3 4 5 6 7 8 9
49
- do
50
- grep 408 ${curl_err}_${i}
51
- done
44
+ grep 408 $curl_err
52
45
  }
53
46
 
54
47
  t_begin "kill server" && {
data/t/test-lib.sh CHANGED
@@ -126,7 +126,7 @@ EOF
126
126
  if test $# -ge 1
127
127
  then
128
128
  echo " use :$1"
129
- test $# -eq 2 && echo " worker_connections $2"
129
+ test $# -ge 2 && echo " worker_connections $2"
130
130
  if test $# -eq 3
131
131
  then
132
132
  echo " keepalive_timeout $3"
@@ -200,6 +200,7 @@ req_curl_chunked_upload_err_check () {
200
200
 
201
201
  case $model in
202
202
  Rev) require_check rev Rev::VERSION ;;
203
+ Coolio) require_check coolio Coolio::VERSION ;;
203
204
  Revactor) require_check revactor Revactor::VERSION ;;
204
205
  EventMachine) require_check eventmachine EventMachine::VERSION ;;
205
206
  esac