rainbows 0.3.0 → 0.4.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 (86) hide show
  1. data/GIT-VERSION-GEN +1 -1
  2. data/GNUmakefile +12 -6
  3. data/README +3 -2
  4. data/Rakefile +3 -3
  5. data/TODO +2 -9
  6. data/lib/rainbows.rb +1 -0
  7. data/lib/rainbows/app_pool.rb +10 -6
  8. data/lib/rainbows/base.rb +1 -1
  9. data/lib/rainbows/const.rb +1 -1
  10. data/lib/rainbows/ev_core.rb +88 -0
  11. data/lib/rainbows/event_machine.rb +218 -0
  12. data/lib/rainbows/http_server.rb +4 -1
  13. data/lib/rainbows/rev.rb +21 -89
  14. data/lib/rainbows/revactor.rb +4 -10
  15. data/local.mk.sample +13 -7
  16. data/rainbows.gemspec +17 -2
  17. data/t/.gitignore +1 -0
  18. data/t/GNUmakefile +63 -40
  19. data/t/README +6 -2
  20. data/t/async_sinatra.ru +13 -0
  21. data/t/bin/unused_listen +1 -1
  22. data/t/large-file-response.ru +1 -0
  23. data/t/my-tap-lib.sh +200 -0
  24. data/t/simple-http_Base.ru +3 -0
  25. data/t/simple-http_EventMachine.ru +9 -0
  26. data/t/simple-http_Rev.ru +9 -0
  27. data/t/simple-http_Revactor.ru +10 -0
  28. data/t/simple-http_ThreadPool.ru +10 -0
  29. data/t/simple-http_ThreadSpawn.ru +10 -0
  30. data/t/t0000-simple-http.sh +142 -0
  31. data/t/t0001-unix-http.sh +103 -0
  32. data/t/t0002-graceful.sh +32 -0
  33. data/t/t0002-parser-error.sh +31 -0
  34. data/t/t0003-reopen-logs.sh +97 -0
  35. data/t/t0005-large-file-response.sh +83 -0
  36. data/t/t0100-rack-input-hammer.sh +45 -0
  37. data/t/t0101-rack-input-trailer.sh +68 -0
  38. data/t/t0200-async-response.sh +66 -0
  39. data/t/t0201-async-response-no-autochunk.sh +3 -0
  40. data/t/t0300-async_sinatra.sh +65 -0
  41. data/t/t9000-rack-app-pool.sh +45 -33
  42. data/t/test-lib.sh +67 -56
  43. metadata +26 -56
  44. data/t/lib-async-response-no-autochunk.sh +0 -6
  45. data/t/lib-async-response.sh +0 -45
  46. data/t/lib-graceful.sh +0 -40
  47. data/t/lib-input-trailer.sh +0 -63
  48. data/t/lib-large-file-response.sh +0 -45
  49. data/t/lib-parser-error.sh +0 -29
  50. data/t/lib-rack-input-hammer.sh +0 -38
  51. data/t/lib-reopen-logs.sh +0 -60
  52. data/t/lib-simple-http.sh +0 -92
  53. data/t/t0000-basic.sh +0 -2
  54. data/t/t1000-thread-pool-basic.sh +0 -2
  55. data/t/t1002-thread-pool-graceful.sh +0 -2
  56. data/t/t1003-thread-pool-reopen-logs.sh +0 -2
  57. data/t/t1004-thread-pool-async-response.sh +0 -45
  58. data/t/t1005-thread-pool-large-file-response.sh +0 -45
  59. data/t/t1006-thread-pool-async-response-no-autochunk.sh +0 -6
  60. data/t/t1100-thread-pool-rack-input.sh +0 -2
  61. data/t/t1101-thread-pool-input-trailer.sh +0 -2
  62. data/t/t2000-thread-spawn-basic.sh +0 -2
  63. data/t/t2002-thread-spawn-graceful.sh +0 -2
  64. data/t/t2003-thread-spawn-reopen-logs.sh +0 -2
  65. data/t/t2004-thread-spawn-async-response.sh +0 -45
  66. data/t/t2005-thread-spawn-large-file-response.sh +0 -45
  67. data/t/t2006-thread-spawn-async-response-no-autochunk.sh +0 -6
  68. data/t/t2100-thread-spawn-rack-input.sh +0 -2
  69. data/t/t2101-thread-spawn-input-trailer.sh +0 -2
  70. data/t/t3000-revactor-basic.sh +0 -2
  71. data/t/t3002-revactor-graceful.sh +0 -2
  72. data/t/t3003-revactor-reopen-logs.sh +0 -2
  73. data/t/t3004-revactor-async-response.sh +0 -45
  74. data/t/t3005-revactor-large-file-response.sh +0 -2
  75. data/t/t3006-revactor-async-response-no-autochunk.sh +0 -6
  76. data/t/t3100-revactor-rack-input.sh +0 -2
  77. data/t/t3101-revactor-rack-input-trailer.sh +0 -2
  78. data/t/t4000-rev-basic.sh +0 -2
  79. data/t/t4002-rev-graceful.sh +0 -2
  80. data/t/t4003-rev-parser-error.sh +0 -2
  81. data/t/t4003-rev-reopen-logs.sh +0 -2
  82. data/t/t4004-rev-async-response.sh +0 -45
  83. data/t/t4005-rev-large-file-response.sh +0 -2
  84. data/t/t4006-rev-async-response-no-autochunk.sh +0 -6
  85. data/t/t4100-rev-rack-input.sh +0 -2
  86. data/t/t4101-rev-rack-input-trailer.sh +0 -2
@@ -0,0 +1,32 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+
4
+ t_plan 4 "graceful exit test for $model"
5
+
6
+ t_begin "setup and startup" && {
7
+ rtmpfiles curl_out
8
+ rainbows_setup $model
9
+ rainbows -D sleep.ru -c $unicorn_config
10
+ rainbows_wait_start
11
+ }
12
+
13
+ t_begin "send a request and SIGQUIT while request is processing" && {
14
+ curl -sSfv -T- </dev/null http://$listen/5 > $curl_out 2> $fifo &
15
+ awk -v rainbows_pid=$rainbows_pid '
16
+ { print $0 }
17
+ /100 Continue/ {
18
+ print "awk: sending SIGQUIT to", rainbows_pid
19
+ system("kill -QUIT "rainbows_pid)
20
+ }' $fifo
21
+ wait
22
+ }
23
+
24
+ dbgcat r_err
25
+
26
+ t_begin 'response returned "Hello"' && {
27
+ test x$(cat $curl_out) = xHello
28
+ }
29
+
30
+ t_begin 'stderr has no errors' && check_stderr
31
+
32
+ t_done
@@ -0,0 +1,31 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ t_plan 5 "parser error test for $model"
4
+
5
+ t_begin "setup and startup" && {
6
+ rainbows_setup $model
7
+ rainbows -D env.ru -c $unicorn_config
8
+ rainbows_wait_start
9
+ }
10
+
11
+ t_begin "send request" && {
12
+ (
13
+ printf 'GET / HTTP/1/1\r\nHost: example.com\r\n\r\n'
14
+ cat $fifo > $tmp &
15
+ wait
16
+ echo ok > $ok
17
+ ) | socat - TCP:$listen > $fifo
18
+ test xok = x$(cat $ok)
19
+ }
20
+
21
+ dbgcat tmp
22
+
23
+ t_begin "response should be a 400" && {
24
+ grep -F 'HTTP/1.1 400 Bad Request' $tmp
25
+ }
26
+
27
+ t_begin "server stderr should be clean" && check_stderr
28
+
29
+ t_begin "term signal sent" && kill $rainbows_pid
30
+
31
+ t_done
@@ -0,0 +1,97 @@
1
+ #!/bin/sh
2
+ # don't set nr_client for Rev, only _one_ app running at once :x
3
+ nr_client=${nr_client-2}
4
+ . ./test-lib.sh
5
+
6
+ t_plan 18 "reopen rotated logs"
7
+
8
+ t_begin "setup and startup" && {
9
+ rtmpfiles curl_out curl_err r_rot
10
+ rainbows_setup $model
11
+ rainbows -D sleep.ru -c $unicorn_config
12
+ rainbows_wait_start
13
+ }
14
+
15
+ t_begin "ensure server is responsive" && {
16
+ curl -sSf http://$listen/ >/dev/null
17
+ }
18
+
19
+ t_begin "start $nr_client concurrent requests" && {
20
+ start=$(date +%s)
21
+ for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" </dev/null)
22
+ do
23
+ ( curl -sSf http://$listen/2 >> $curl_out 2>> $curl_err ) &
24
+ done
25
+ }
26
+
27
+ t_begin "ensure stderr log is clean" && check_stderr
28
+
29
+ t_begin "external log rotation" && {
30
+ rm -f $r_rot
31
+ mv $r_err $r_rot
32
+ }
33
+
34
+ t_begin "send reopen log signal (USR1)" && {
35
+ kill -USR1 $rainbows_pid
36
+ }
37
+
38
+ t_begin "wait for rotated log to reappear" && {
39
+ nr=60
40
+ while ! test -f $r_err && test $nr -ge 0
41
+ do
42
+ sleep 1
43
+ nr=$(( $nr - 1 ))
44
+ done
45
+ }
46
+
47
+ dbgcat r_rot
48
+ dbgcat r_err
49
+
50
+ t_begin "wait curl requests to finish" && {
51
+ wait
52
+ t_info elapsed=$(( $(date +%s) - $start ))
53
+ }
54
+
55
+ t_begin "ensure no errors from curl" && {
56
+ test ! -s $curl_err
57
+ }
58
+
59
+ t_begin "curl got $nr_client responses" && {
60
+ test "$(wc -l < $curl_out)" -eq $nr_client
61
+ }
62
+
63
+ t_begin "all responses were identical" && {
64
+ nr=$(sort < $curl_out | uniq | wc -l)
65
+ test "$nr" -eq 1
66
+ }
67
+
68
+ t_begin 'response was "Hello"' && {
69
+ test x$(sort < $curl_out | uniq) = xHello
70
+ }
71
+
72
+ t_begin "current server stderr is clean" && check_stderr
73
+
74
+ t_begin "rotated stderr is clean" && {
75
+ check_stderr $r_rot
76
+ }
77
+
78
+ t_begin "server is now writing logs to new stderr" && {
79
+ before_rot=$(wc -c < $r_rot)
80
+ before_err=$(wc -c < $r_err)
81
+ curl -sSfv http://$listen/
82
+ after_rot=$(wc -c < $r_rot)
83
+ after_err=$(wc -c < $r_err)
84
+ test $after_rot -eq $before_rot
85
+ test $after_err -gt $before_err
86
+ }
87
+
88
+ t_begin "stop server" && {
89
+ kill $rainbows_pid
90
+ }
91
+
92
+ dbgcat r_err
93
+
94
+ t_begin "current server stderr is clean" && check_stderr
95
+ t_begin "rotated stderr is clean" && check_stderr $r_rot
96
+
97
+ t_done
@@ -0,0 +1,83 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ test -r random_blob || die "random_blob required, run with 'make $0'"
4
+
5
+ if ! grep -v ^VmRSS: /proc/self/status >/dev/null 2>&1
6
+ then
7
+ t_info "skipping, can't read RSS from /proc/self/status"
8
+ exit 0
9
+ fi
10
+
11
+ t_plan 10 "large file response slurp avoidance for $model"
12
+
13
+ t_begin "setup and startup" && {
14
+ rtmpfiles curl_out
15
+ rainbows_setup $model
16
+ # can't load Rack::Lint here since it'll cause Rev to slurp
17
+ rainbows -E none -D large-file-response.ru -c $unicorn_config
18
+ rainbows_wait_start
19
+ }
20
+
21
+ t_begin "read random blob size" && {
22
+ random_blob_size=$(wc -c < random_blob)
23
+ }
24
+
25
+ t_begin "read current RSS" && {
26
+ curl -v http://$listen/rss
27
+ dbgcat r_err
28
+ rss_before=$(curl -sSfv http://$listen/rss)
29
+ t_info "rss_before=$rss_before"
30
+ }
31
+
32
+ t_begin "send a series HTTP/1.1 requests sequentially" && {
33
+ for i in a b c
34
+ do
35
+ size=$( (curl -sSfv http://$listen/random_blob &&
36
+ echo ok >$ok) |wc -c)
37
+ test $size -eq $random_blob_size
38
+ test xok = x$(cat $ok)
39
+ done
40
+ }
41
+
42
+ # this was a problem during development
43
+ t_begin "HTTP/1.0 test" && {
44
+ size=$( (curl -0 -sSfv http://$listen/random_blob &&
45
+ echo ok >$ok) |wc -c)
46
+ test $size -eq $random_blob_size
47
+ test xok = x$(cat $ok)
48
+ }
49
+
50
+ t_begin "HTTP/0.9 test" && {
51
+ (
52
+ printf 'GET /random_blob\r\n'
53
+ cat $fifo > $tmp &
54
+ wait
55
+ echo ok > $ok
56
+ ) | socat - TCP:$listen > $fifo
57
+ cmp $tmp random_blob
58
+ test xok = x$(cat $ok)
59
+ }
60
+
61
+ dbgcat r_err
62
+
63
+ t_begin "read RSS again" && {
64
+ curl -v http://$listen/rss
65
+ rss_after=$(curl -sSfv http://$listen/rss)
66
+ t_info "rss_after=$rss_after"
67
+ }
68
+
69
+ t_begin "shutdown server" && {
70
+ kill -QUIT $rainbows_pid
71
+ }
72
+
73
+ t_begin "compare RSS before and after" && {
74
+ diff=$(( $rss_after - $rss_before ))
75
+ t_info "test diff=$diff < orig=$random_blob_size"
76
+ test $diff -le $random_blob_size
77
+ }
78
+
79
+ dbgcat r_err
80
+
81
+ t_begin "check stderr" && check_stderr
82
+
83
+ t_done
@@ -0,0 +1,45 @@
1
+ nr_client=${nr_client-4}
2
+ . ./test-lib.sh
3
+ test -r random_blob || die "random_blob required, run with 'make $0'"
4
+
5
+ t_plan 7 "concurrent rack.input hammer stress test"
6
+
7
+ t_begin "setup and startup" && {
8
+ rtmpfiles curl_out curl_err
9
+ rainbows_setup $model
10
+ rainbows -D sha1.ru -c $unicorn_config
11
+ rainbows_wait_start
12
+ }
13
+
14
+ t_begin "send $nr_client concurrent requests" && {
15
+ start=$(date +%s)
16
+ for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" </dev/null)
17
+ do
18
+ (
19
+ curl -sSf -T- http://$listen/$i \
20
+ < random_blob >> $curl_out 2>> $curl_err
21
+ ) &
22
+ done
23
+ wait
24
+ t_info elapsed=$(( $(date +%s) - $start ))
25
+ }
26
+
27
+ t_begin "kill server" && kill $rainbows_pid
28
+
29
+ t_begin "got $nr_client responses" && {
30
+ test $nr_client -eq $(wc -l < $curl_out)
31
+ }
32
+
33
+ t_begin "all responses identical" && {
34
+ test 1 -eq $(sort < $curl_out | uniq | wc -l)
35
+ }
36
+
37
+ t_begin "sha1 matches on-disk sha1" && {
38
+ blob_sha1=$( expr "$(sha1sum < random_blob)" : '\([a-f0-9]\+\)')
39
+ t_info blob_sha1=$blob_sha1
40
+ test x"$blob_sha1" = x"$(sort < $curl_out | uniq)"
41
+ }
42
+
43
+ t_begin "no errors in stderr log" && check_stderr
44
+
45
+ t_done
@@ -0,0 +1,68 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ test -r random_blob || die "random_blob required, run with 'make $0'"
4
+
5
+ t_plan 11 "input trailer test $model"
6
+
7
+ t_begin "setup and startup" && {
8
+ rtmpfiles curl_out
9
+ rainbows_setup $model
10
+ rainbows -D content-md5.ru -c $unicorn_config
11
+ rainbows_wait_start
12
+ }
13
+
14
+ t_begin "upload small blob" && {
15
+ (
16
+ cat $fifo > $tmp &
17
+ echo hello world | content-md5-put
18
+ wait
19
+ echo ok > $ok
20
+ ) | socat - TCP:$listen > $fifo
21
+ test xok = x"$(cat $ok)"
22
+ }
23
+
24
+ t_begin "HTTP response is OK" && fgrep 'HTTP/1.1 200 OK' $tmp
25
+ t_begin "no errors in stderr log" && check_stderr
26
+
27
+ t_begin "big blob request" && {
28
+ (
29
+ cat $fifo > $tmp &
30
+ content-md5-put < random_blob
31
+ wait
32
+ echo ok > $ok
33
+ ) | socat - TCP:$listen > $fifo
34
+ test xok = x"$(cat $ok)"
35
+ }
36
+
37
+ t_begin "HTTP response is OK" && fgrep 'HTTP/1.1 200 OK' $tmp
38
+ t_begin "no errors in stderr log" && check_stderr
39
+
40
+ t_begin "staggered blob upload" && {
41
+ (
42
+ cat $fifo > $tmp &
43
+ (
44
+ dd bs=164 count=1 < random_blob
45
+ sleep 2
46
+ dd bs=4545 count=1 < random_blob
47
+ sleep 2
48
+ dd bs=1234 count=1 < random_blob
49
+ echo subok > $ok
50
+ ) 2>/dev/null | content-md5-put
51
+ test xsubok = x"$(cat $ok)"
52
+ wait
53
+ echo ok > $ok
54
+ ) | socat - TCP:$listen > $fifo
55
+ test xok = x"$(cat $ok)"
56
+ }
57
+
58
+ t_begin "HTTP response is OK" && {
59
+ fgrep 'HTTP/1.1 200 OK' $tmp
60
+ }
61
+
62
+ t_begin "no errors in stderr log" && check_stderr
63
+
64
+ t_begin "kill server" && {
65
+ kill $rainbows_pid
66
+ }
67
+
68
+ t_done
@@ -0,0 +1,66 @@
1
+ #!/bin/sh
2
+ CONFIG_RU=${CONFIG_RU-'async-response.ru'}
3
+ . ./test-lib.sh
4
+
5
+ case $CONFIG_RU in
6
+ *no-autochunk.ru)
7
+ t_plan 7 "async response w/o autochunk for $model"
8
+ skip_autochunk=true
9
+ ;;
10
+ *)
11
+ t_plan 6 "async response for $model"
12
+ skip_autochunk=false
13
+ ;;
14
+ esac
15
+
16
+ t_begin "setup and start" && {
17
+ rainbows_setup
18
+ rtmpfiles a b c curl_err
19
+ # can't load Rack::Lint here since it'll cause Rev to slurp
20
+ rainbows -E none -D $CONFIG_RU -c $unicorn_config
21
+ rainbows_wait_start
22
+ }
23
+
24
+ t_begin "send async requests off in parallel" && {
25
+ t0=$(date +%s)
26
+ ( curl --no-buffer -sSf http://$listen/ 2>> $curl_err | utee $a) &
27
+ ( curl --no-buffer -sSf http://$listen/ 2>> $curl_err | utee $b) &
28
+ ( curl --no-buffer -sSf http://$listen/ 2>> $curl_err | utee $c) &
29
+ wait
30
+ t1=$(date +%s)
31
+ }
32
+
33
+ t_begin "ensure elapsed requests were processed in parallel" && {
34
+ elapsed=$(( $t1 - $t0 ))
35
+ echo "elapsed=$elapsed < 30"
36
+ test $elapsed -lt 30
37
+ }
38
+
39
+ t_begin "termination signal sent" && {
40
+ kill $rainbows_pid
41
+ }
42
+
43
+ dbgcat a
44
+ dbgcat b
45
+ dbgcat c
46
+ dbgcat r_err
47
+ dbgcat curl_err
48
+
49
+ t_begin "no errors from curl" && {
50
+ test ! -s $curl_err
51
+ }
52
+
53
+ t_begin "no errors in stderr" && check_stderr
54
+
55
+ dbgcat r_err
56
+
57
+ if $skip_autochunk
58
+ then
59
+ t_begin "no responses are chunked" && {
60
+ test x"$(cat $a)" = x0123456789
61
+ test x"$(cat $b)" = x0123456789
62
+ test x"$(cat $c)" = x0123456789
63
+ }
64
+ fi
65
+
66
+ t_done
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+ CONFIG_RU=async-response-no-autochunk.ru
3
+ . ./t0200-async-response.sh
@@ -0,0 +1,65 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+
4
+ # n - number of seconds to sleep
5
+ n=10
6
+ CONFIG_RU=async_sinatra.ru
7
+ case $model in
8
+ EventMachine) ;;
9
+ *)
10
+ t_info "skipping $T since it's not compatible with $model"
11
+ exit 0
12
+ ;;
13
+ esac
14
+
15
+ t_plan 7 "async_sinatra test for EM"
16
+
17
+ t_begin "setup and start" && {
18
+ rainbows_setup
19
+ rtmpfiles a b c curl_err
20
+
21
+ # Async Sinatra does not support Rack::Lint
22
+ rainbows -E none -D $CONFIG_RU -c $unicorn_config
23
+ rainbows_wait_start
24
+ }
25
+
26
+ t_begin "send async requests off in parallel" && {
27
+ t0=$(date +%s)
28
+ ( curl --no-buffer -sSf http://$listen/$n 2>> $curl_err | utee $a) &
29
+ ( curl --no-buffer -sSf http://$listen/$n 2>> $curl_err | utee $b) &
30
+ ( curl --no-buffer -sSf http://$listen/$n 2>> $curl_err | utee $c) &
31
+ }
32
+
33
+ t_begin "ensure elapsed requests were processed in parallel" && {
34
+ wait
35
+ t1=$(date +%s)
36
+ elapsed=$(( $t1 - $t0 ))
37
+ echo "elapsed=$elapsed < 30"
38
+ test $elapsed -lt 30
39
+ }
40
+
41
+ t_begin "termination signal sent" && {
42
+ kill $rainbows_pid
43
+ }
44
+
45
+ dbgcat a
46
+ dbgcat b
47
+ dbgcat c
48
+ dbgcat r_err
49
+ dbgcat curl_err
50
+
51
+ t_begin "no errors from curl" && {
52
+ test ! -s $curl_err
53
+ }
54
+
55
+ t_begin "no errors in stderr" && check_stderr
56
+
57
+ dbgcat r_err
58
+
59
+ t_begin "no responses are chunked" && {
60
+ test x"$(cat $a)" = x"delayed for $n seconds"
61
+ test x"$(cat $b)" = x"delayed for $n seconds"
62
+ test x"$(cat $c)" = x"delayed for $n seconds"
63
+ }
64
+
65
+ t_done