rainbows 2.0.1 → 2.1.0

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 (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