rainbows 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/GIT-VERSION-GEN +1 -1
  2. data/TODO +15 -0
  3. data/TUNING +14 -0
  4. data/lib/rainbows.rb +7 -0
  5. data/lib/rainbows/app_pool.rb +4 -3
  6. data/lib/rainbows/base.rb +17 -11
  7. data/lib/rainbows/const.rb +5 -1
  8. data/lib/rainbows/dev_fd_response.rb +69 -0
  9. data/lib/rainbows/http_response.rb +1 -0
  10. data/lib/rainbows/http_server.rb +2 -0
  11. data/lib/rainbows/rev.rb +136 -43
  12. data/lib/rainbows/revactor.rb +6 -14
  13. data/lib/rainbows/thread_pool.rb +11 -13
  14. data/lib/rainbows/thread_spawn.rb +4 -4
  15. data/local.mk.sample +9 -1
  16. data/t/GNUmakefile +4 -4
  17. data/t/README +1 -1
  18. data/t/async-response-no-autochunk.ru +24 -0
  19. data/t/async-response.ru +13 -0
  20. data/t/bin/content-md5-put +1 -1
  21. data/t/bin/utee +12 -0
  22. data/t/env.ru +3 -0
  23. data/t/large-file-response.ru +13 -0
  24. data/t/lib-async-response-no-autochunk.sh +6 -0
  25. data/t/lib-async-response.sh +45 -0
  26. data/t/lib-graceful.sh +40 -0
  27. data/t/lib-input-trailer.sh +63 -0
  28. data/t/lib-large-file-response.sh +45 -0
  29. data/t/lib-parser-error.sh +29 -0
  30. data/t/{t3100-revactor-tee-input.sh → lib-rack-input-hammer.sh} +3 -9
  31. data/t/lib-reopen-logs.sh +60 -0
  32. data/t/lib-simple-http.sh +92 -0
  33. data/t/sleep.ru +13 -6
  34. data/t/t0000-basic.sh +1 -36
  35. data/t/t1000-thread-pool-basic.sh +1 -41
  36. data/t/t1002-thread-pool-graceful.sh +1 -36
  37. data/t/t1003-thread-pool-reopen-logs.sh +2 -0
  38. data/t/t1004-thread-pool-async-response.sh +45 -0
  39. data/t/t1005-thread-pool-large-file-response.sh +45 -0
  40. data/t/t1006-thread-pool-async-response-no-autochunk.sh +6 -0
  41. data/t/t1100-thread-pool-rack-input.sh +2 -0
  42. data/t/t1101-thread-pool-input-trailer.sh +2 -0
  43. data/t/t2000-thread-spawn-basic.sh +1 -37
  44. data/t/t2002-thread-spawn-graceful.sh +1 -36
  45. data/t/t2003-thread-spawn-reopen-logs.sh +2 -0
  46. data/t/t2004-thread-spawn-async-response.sh +45 -0
  47. data/t/t2005-thread-spawn-large-file-response.sh +45 -0
  48. data/t/t2006-thread-spawn-async-response-no-autochunk.sh +6 -0
  49. data/t/t2100-thread-spawn-rack-input.sh +2 -0
  50. data/t/t2101-thread-spawn-input-trailer.sh +2 -0
  51. data/t/t3000-revactor-basic.sh +1 -39
  52. data/t/t3002-revactor-graceful.sh +1 -37
  53. data/t/t3003-revactor-reopen-logs.sh +1 -53
  54. data/t/t3004-revactor-async-response.sh +45 -0
  55. data/t/t3005-revactor-large-file-response.sh +2 -0
  56. data/t/t3006-revactor-async-response-no-autochunk.sh +6 -0
  57. data/t/t3100-revactor-rack-input.sh +2 -0
  58. data/t/t3101-revactor-rack-input-trailer.sh +2 -0
  59. data/t/t4000-rev-basic.sh +1 -50
  60. data/t/t4002-rev-graceful.sh +1 -51
  61. data/t/t4003-rev-parser-error.sh +1 -33
  62. data/t/t4003-rev-reopen-logs.sh +2 -0
  63. data/t/t4004-rev-async-response.sh +45 -0
  64. data/t/t4005-rev-large-file-response.sh +2 -0
  65. data/t/t4006-rev-async-response-no-autochunk.sh +6 -0
  66. data/t/t4100-rev-rack-input.sh +1 -43
  67. data/t/t4101-rev-rack-input-trailer.sh +1 -50
  68. data/t/t9000-rack-app-pool.sh +2 -3
  69. data/t/test-lib.sh +80 -18
  70. metadata +39 -4
  71. data/t/t3001-revactor-pipeline.sh +0 -46
@@ -0,0 +1,6 @@
1
+ #!/bin/sh
2
+ CONFIG_RU=async-response-no-autochunk.ru
3
+ . ./lib-async-response.sh
4
+ test x"$(cat $a)" = x0123456789
5
+ test x"$(cat $b)" = x0123456789
6
+ test x"$(cat $c)" = x0123456789
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ . ./lib-rack-input-hammer.sh
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ . ./lib-input-trailer.sh
data/t/t4000-rev-basic.sh CHANGED
@@ -1,51 +1,2 @@
1
1
  #!/bin/sh
2
- . ./test-lib.sh
3
- require_rev
4
-
5
- eval $(unused_listen)
6
- rtmpfiles unicorn_config pid r_err r_out tmp fifo ok
7
- rm -f $fifo
8
- mkfifo $fifo
9
-
10
- nr_client=30
11
-
12
- cat > $unicorn_config <<EOF
13
- listen "$listen"
14
- pid "$pid"
15
- stderr_path "$r_err"
16
- stdout_path "$r_out"
17
- Rainbows! do
18
- use :Rev
19
- worker_connections 50
20
- end
21
- EOF
22
-
23
- rainbows -D t4000.ru -c $unicorn_config
24
- wait_for_pid $pid
25
-
26
- echo "single request"
27
- curl -sSfv http://$listen/
28
-
29
- echo "two requests with keepalive"
30
- curl -sSfv http://$listen/a http://$listen/b > $tmp 2>&1
31
- grep 'Re-using existing connection' < $tmp
32
-
33
- echo "pipelining partial requests"
34
- req='GET / HTTP/1.1\r\nHost: example.com\r\n'
35
- (
36
- printf "$req"'\r\n'"$req"
37
- cat $fifo > $tmp &
38
- sleep 1
39
- printf 'Connection: close\r\n\r\n'
40
- wait
41
- echo ok > $ok
42
- ) | socat - TCP:$listen > $fifo
43
-
44
- kill $(cat $pid)
45
-
46
- test 2 -eq $(grep '^HTTP/1.1' $tmp | wc -l)
47
- test 2 -eq $(grep '^HTTP/1.1 200 OK' $tmp | wc -l)
48
- test 1 -eq $(grep '^Connection: keep-alive' $tmp | wc -l)
49
- test 1 -eq $(grep '^Connection: close' $tmp | wc -l)
50
- test x"$(cat $ok)" = xok
51
- ! grep Error $r_err
2
+ . ./lib-simple-http.sh
@@ -1,52 +1,2 @@
1
1
  #!/bin/sh
2
- . ./test-lib.sh
3
- require_rev
4
-
5
- eval $(unused_listen)
6
- rtmpfiles unicorn_config tmp pid r_err r_out out
7
- nr_client=10
8
- cat > $unicorn_config <<EOF
9
- listen "$listen"
10
- stderr_path "$r_err"
11
- stdout_path "$r_out"
12
- pid "$pid"
13
- Rainbows! do
14
- use :Rev
15
- end
16
- EOF
17
-
18
- rainbows -D sleep.ru -c $unicorn_config
19
- wait_for_pid $pid
20
-
21
- for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" </dev/null)
22
- do
23
- (
24
- rtmpfiles fifo tmp
25
- rm -f $fifo
26
- mkfifo $fifo
27
- (
28
- printf 'GET /0 HTTP/1.1\r\n'
29
- cat $fifo > $tmp &
30
- sleep 1
31
- printf 'Host: example.com\r\n'
32
- sleep 1
33
- printf 'Connection: close\r\n'
34
- sleep 1
35
- printf '\r\n'
36
- wait
37
- ) | socat - TCP:$listen > $fifo
38
- fgrep 'Hello' $tmp >> $out || :
39
- rm -f $fifo $tmp
40
- ) &
41
- done
42
-
43
- sleep 2 # potentially racy :<
44
- kill -QUIT $(cat $pid)
45
- wait
46
-
47
- test x"$(wc -l < $out)" = x$nr_client
48
- nr=$(sort < $out | uniq | wc -l)
49
- test "$nr" -eq 1
50
-
51
- test x$(sort < $out | uniq) = xHello
52
- ! grep Error $r_err
2
+ . ./lib-graceful.sh
@@ -1,34 +1,2 @@
1
1
  #!/bin/sh
2
- . ./test-lib.sh
3
- require_rev
4
-
5
- eval $(unused_listen)
6
- rtmpfiles unicorn_config pid r_err r_out tmp fifo ok
7
- rm -f $fifo
8
- mkfifo $fifo
9
-
10
- cat > $unicorn_config <<EOF
11
- listen "$listen"
12
- pid "$pid"
13
- stderr_path "$r_err"
14
- stdout_path "$r_out"
15
- Rainbows! do
16
- use :Rev
17
- end
18
- EOF
19
-
20
- rainbows -D t4000.ru -c $unicorn_config
21
- wait_for_pid $pid
22
-
23
- (
24
- printf 'GET / HTTP/1/1\r\nHost: example.com\r\n\r\n'
25
- cat $fifo > $tmp &
26
- wait
27
- echo ok > $ok
28
- ) | socat - TCP:$listen > $fifo
29
-
30
- kill $(cat $pid)
31
-
32
- dbgcat tmp
33
- grep -F 'HTTP/1.1 400 Bad Request' $tmp
34
- ! grep Error $r_err
2
+ . ./lib-parser-error.sh
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ . ./lib-reopen-logs.sh
@@ -0,0 +1,45 @@
1
+ CONFIG_RU=${CONFIG_RU-'async-response.ru'}
2
+ . ./test-lib.sh
3
+ echo "async response for model=$model"
4
+ eval $(unused_listen)
5
+ rtmpfiles unicorn_config a b c r_err r_out pid curl_err
6
+
7
+ cat > $unicorn_config <<EOF
8
+ listen "$listen"
9
+ stderr_path "$r_err"
10
+ stdout_path "$r_out"
11
+ pid "$pid"
12
+ Rainbows! { use :$model }
13
+ EOF
14
+
15
+ # can't load Rack::Lint here since it'll cause Rev to slurp
16
+ rainbows -E none -D $CONFIG_RU -c $unicorn_config
17
+ wait_for_pid $pid
18
+
19
+ t0=$(date +%s)
20
+ ( curl --no-buffer -sSf http://$listen/ 2>> $curl_err | utee $a) &
21
+ ( curl --no-buffer -sSf http://$listen/ 2>> $curl_err | utee $b) &
22
+ ( curl --no-buffer -sSf http://$listen/ 2>> $curl_err | utee $c) &
23
+ wait
24
+ t1=$(date +%s)
25
+
26
+ rainbows_pid=$(cat $pid)
27
+ kill -QUIT $rainbows_pid
28
+ elapsed=$(( $t1 - $t0 ))
29
+ echo "elapsed=$elapsed < 30"
30
+ test $elapsed -lt 30
31
+
32
+ dbgcat a
33
+ dbgcat b
34
+ dbgcat c
35
+ dbgcat r_err
36
+ dbgcat curl_err
37
+ test ! -s $curl_err
38
+ check_stderr
39
+
40
+ while kill -0 $rainbows_pid >/dev/null 2>&1
41
+ do
42
+ sleep 1
43
+ done
44
+
45
+ dbgcat r_err
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ . ./lib-large-file-response.sh
@@ -0,0 +1,6 @@
1
+ #!/bin/sh
2
+ CONFIG_RU=async-response-no-autochunk.ru
3
+ . ./lib-async-response.sh
4
+ test x"$(cat $a)" = x0123456789
5
+ test x"$(cat $b)" = x0123456789
6
+ test x"$(cat $c)" = x0123456789
@@ -1,44 +1,2 @@
1
1
  #!/bin/sh
2
- nr_client=${nr_client-25}
3
- nr=${nr-50}
4
-
5
- . ./test-lib.sh
6
- require_rev
7
- test -r random_blob || die "random_blob required, run with 'make $0'"
8
-
9
- eval $(unused_listen)
10
- rtmpfiles unicorn_config curl_out curl_err r_err r_out pid
11
-
12
- cat > $unicorn_config <<EOF
13
- listen "$listen"
14
- pid "$pid"
15
- stderr_path "$r_err"
16
- stdout_path "$r_out"
17
- Rainbows! do
18
- use :Rev
19
- worker_connections $nr
20
- end
21
- EOF
22
-
23
- echo pid=$pid
24
- rainbows -D sha1.ru -c $unicorn_config
25
- wait_for_pid $pid
26
-
27
- start=$(date +%s)
28
- for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" </dev/null)
29
- do
30
- (
31
- curl -sSf -T- http://$listen/$i \
32
- < random_blob >> $curl_out 2>> $curl_err
33
- ) &
34
- done
35
- wait
36
- echo elapsed=$(( $(date +%s) - $start ))
37
-
38
- kill $(cat $pid)
39
- test $nr_client -eq $(wc -l < $curl_out)
40
- test 1 -eq $(sort < $curl_out | uniq | wc -l)
41
- blob_sha1=$( expr "$(sha1sum < random_blob)" : '\([a-f0-9]\+\)')
42
- echo blob_sha1=$blob_sha1
43
- test x"$blob_sha1" = x"$(sort < $curl_out | uniq)"
44
- ! grep Error $r_err
2
+ . ./lib-rack-input-hammer.sh
@@ -1,51 +1,2 @@
1
1
  #!/bin/sh
2
- nr_client=${nr_client-25}
3
- nr=${nr-50}
4
-
5
- . ./test-lib.sh
6
- require_rev
7
- test -r random_blob || die "random_blob required, run with 'make $0'"
8
-
9
- eval $(unused_listen)
10
- rtmpfiles unicorn_config tmp r_err r_out pid fifo ok
11
- rm -f $fifo
12
- mkfifo $fifo
13
-
14
- cat > $unicorn_config <<EOF
15
- listen "$listen"
16
- pid "$pid"
17
- stderr_path "$r_err"
18
- stdout_path "$r_out"
19
- Rainbows! do
20
- use :Rev
21
- end
22
- EOF
23
-
24
- rainbows -D content-md5.ru -c $unicorn_config
25
- wait_for_pid $pid
26
-
27
- echo "small blob"
28
- (
29
- echo hello world | content-md5-put
30
- cat $fifo > $tmp &
31
- wait
32
- echo ok > $ok
33
- ) | socat - TCP:$listen | tee $fifo
34
-
35
- fgrep 'HTTP/1.1 200 OK' $tmp
36
- test xok = x"$(cat $ok)"
37
- ! grep Error $r_err
38
-
39
-
40
- echo "big blob"
41
- (
42
- content-md5-put < random_blob
43
- cat $fifo > $tmp &
44
- wait
45
- echo ok > $ok
46
- ) | socat - TCP:$listen | tee $fifo
47
-
48
- fgrep 'HTTP/1.1 200 OK' $tmp
49
- test xok = x"$(cat $ok)"
50
- ! grep Error $r_err
51
- kill $(cat $pid)
2
+ . ./lib-input-trailer.sh
@@ -31,7 +31,6 @@ echo elapsed=$(( $(date +%s) - $start ))
31
31
  kill $(cat $pid)
32
32
 
33
33
  test $APP_POOL_SIZE -eq $(sort < $curl_out | uniq | wc -l)
34
- ! test -s $curl_err
34
+ test ! -s $curl_err
35
35
 
36
- ! grep Error $r_err
37
- #
36
+ check_stderr
data/t/test-lib.sh CHANGED
@@ -1,11 +1,36 @@
1
1
  #!/bin/sh
2
2
  # Copyright (c) 2009 Rainbows! developers
3
3
 
4
- set -o pipefail >/dev/null 2>&1 || : # non-POSIX, but useful in ksh/bash
4
+ # pipefail is non-POSIX, but useful in ksh/bash
5
+ (
6
+ set +e
7
+ set -o pipefail 2>/dev/null
8
+ )
9
+ if test $? -eq 0
10
+ then
11
+ set -o pipefail
12
+ else
13
+ echo >&2 "WARNING: your shell does not understand pipefail"
14
+ fi
15
+
5
16
  set -e
6
- set -u
17
+
7
18
  T=$(basename $0)
8
- ruby="${ruby-ruby}"
19
+ if test -z "$model"
20
+ then
21
+ case $T in
22
+ t1???-thread-pool-*.sh) model=ThreadPool ;;
23
+ t2???-thread-spawn-*.sh) model=ThreadSpawn ;;
24
+ t3???-revactor-*.sh) model=Revactor ;;
25
+ t4???-rev-*.sh) model=Rev ;;
26
+ *) model=any ;;
27
+ esac
28
+ fi
29
+
30
+ ruby="${ruby-'ruby'}"
31
+ RUBY_VERSION=${RUBY_VERSION-$($ruby -e 'puts RUBY_VERSION')}
32
+ t_pfx=$PWD/trash/$T-$RUBY_VERSION
33
+ set -u
9
34
 
10
35
  # ensure a sane environment
11
36
  TZ=UTC LC_ALL=C LANG=C
@@ -17,8 +42,22 @@ die () {
17
42
  exit 1
18
43
  }
19
44
 
20
- _TEST_RM_LIST=""
21
- trap 'rm -f $_TEST_RM_LIST' 0
45
+ _test_on_exit () {
46
+ code=$?
47
+ case $code in
48
+ 0)
49
+ echo "ok $T"
50
+ rm -f $_TEST_OK_RM_LIST
51
+ ;;
52
+ *) echo "not ok $T" ;;
53
+ esac
54
+ rm -f $_TEST_RM_LIST
55
+ exit $code
56
+ }
57
+
58
+ _TEST_RM_LIST=
59
+ _TEST_OK_RM_LIST=
60
+ trap _test_on_exit EXIT
22
61
  PATH=$PWD/bin:$PATH
23
62
  export PATH
24
63
 
@@ -34,18 +73,12 @@ wait_for_pid () {
34
73
  done
35
74
  }
36
75
 
37
- require_revactor () {
38
- if ! $ruby -rrevactor -e "puts Revactor::VERSION" >/dev/null 2>&1
76
+ require_check () {
77
+ lib=$1
78
+ const=$2
79
+ if ! $ruby -r$lib -e "puts $const" >/dev/null 2>&1
39
80
  then
40
- echo >&2 "skipping $T since we don't have Revactor"
41
- exit 0
42
- fi
43
- }
44
-
45
- require_rev() {
46
- if ! $ruby -rrev -e "puts Rev::VERSION" >/dev/null 2>&1
47
- then
48
- echo >&2 "skipping $T since we don't have Rev"
81
+ echo >&2 "skipping $T since we don't have $lib"
49
82
  exit 0
50
83
  fi
51
84
  }
@@ -55,14 +88,43 @@ require_rev() {
55
88
  rtmpfiles () {
56
89
  for id in "$@"
57
90
  do
58
- _tmp=$(mktemp -t rainbows.$$.$id.XXXXXXXX)
91
+ name=$id
92
+ _tmp=$t_pfx.$id
93
+ > $_tmp
59
94
  eval "$id=$_tmp"
60
- _TEST_RM_LIST="$_TEST_RM_LIST $_tmp"
95
+ _TEST_OK_RM_LIST="$_TEST_OK_RM_LIST $_tmp"
96
+
97
+ case $name in
98
+ *fifo)
99
+ rm -f $_tmp
100
+ mkfifo $_tmp
101
+ _TEST_RM_LIST="$_TEST_RM_LIST $_tmp"
102
+ ;;
103
+ esac
61
104
  done
62
105
  }
63
106
 
64
107
  dbgcat () {
65
108
  id=$1
66
109
  eval '_file=$'$id
110
+ echo "==> $id <=="
67
111
  sed -e "s/^/$id:/" < $_file
68
112
  }
113
+
114
+ check_stderr () {
115
+ set +u
116
+ _r_err=${1-${r_err}}
117
+ set -u
118
+ if grep Error $_r_err
119
+ then
120
+ die "Errors found in $_r_err"
121
+ elif grep SIGKILL $_r_err
122
+ then
123
+ die "SIGKILL found in $_r_err"
124
+ fi
125
+ }
126
+
127
+ case $model in
128
+ Rev) require_check rev Rev::VERSION ;;
129
+ Revactor) require_check revactor Revactor::VERSION ;;
130
+ esac