rainbows 0.95.1 → 0.96.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.
- data/Documentation/comparison.haml +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +2 -1
- data/Rakefile +16 -3
- data/Static_Files +11 -11
- data/TODO +1 -6
- data/lib/rainbows.rb +3 -2
- data/lib/rainbows/base.rb +12 -9
- data/lib/rainbows/const.rb +2 -4
- data/lib/rainbows/dev_fd_response.rb +16 -13
- data/lib/rainbows/error.rb +2 -0
- data/lib/rainbows/ev_core.rb +13 -0
- data/lib/rainbows/event_machine.rb +85 -128
- data/lib/rainbows/event_machine/response_chunk_pipe.rb +25 -0
- data/lib/rainbows/event_machine/response_pipe.rb +30 -0
- data/lib/rainbows/event_machine/try_defer.rb +27 -0
- data/lib/rainbows/fiber/body.rb +6 -4
- data/lib/rainbows/fiber/io.rb +4 -4
- data/lib/rainbows/fiber/rev.rb +16 -8
- data/lib/rainbows/http_response.rb +5 -6
- data/lib/rainbows/response.rb +37 -22
- data/lib/rainbows/response/body.rb +19 -16
- data/lib/rainbows/response/range.rb +34 -0
- data/lib/rainbows/rev.rb +2 -1
- data/lib/rainbows/rev/client.rb +105 -77
- data/lib/rainbows/rev/deferred_chunk_response.rb +16 -0
- data/lib/rainbows/rev/deferred_response.rb +16 -24
- data/lib/rainbows/rev/sendfile.rb +4 -13
- data/lib/rainbows/rev/thread.rb +3 -12
- data/lib/rainbows/rev_thread_pool.rb +2 -2
- data/lib/rainbows/revactor.rb +16 -9
- data/lib/rainbows/revactor/body.rb +42 -0
- data/lib/rainbows/revactor/proxy.rb +55 -0
- data/lib/rainbows/sendfile.rb +12 -14
- data/lib/rainbows/stream_file.rb +3 -3
- data/lib/rainbows/writer_thread_pool.rb +12 -12
- data/lib/rainbows/writer_thread_spawn.rb +6 -7
- data/t/GNUmakefile +2 -2
- data/t/close-pipe-response.ru +25 -0
- data/t/cramp/rainsocket.ru +1 -1
- data/t/fast-pipe-response.ru +10 -0
- data/t/file-wrap-to_path.ru +24 -0
- data/t/t0015-working_directory.sh +5 -1
- data/t/t0020-large-sendfile-response.sh +3 -3
- data/t/t0021-sendfile-wrap-to_path.sh +108 -0
- data/t/t0022-copy_stream-byte-range.sh +139 -0
- data/t/t0023-sendfile-byte-range.sh +63 -0
- data/t/t0024-pipelined-sendfile-response.sh +89 -0
- data/t/t0030-fast-pipe-response.sh +63 -0
- data/t/t0031-close-pipe-response.sh +96 -0
- data/t/t0034-pipelined-pipe-response.sh +87 -0
- data/t/t0105-rack-input-limit-bigger.sh +5 -2
- data/t/t0500-cramp-streaming.sh +0 -1
- data/t/t0501-cramp-rainsocket.sh +1 -0
- data/t/t9000-rack-app-pool.sh +1 -1
- data/t/test_isolate.rb +1 -0
- metadata +29 -5
data/t/GNUmakefile
CHANGED
@@ -27,7 +27,6 @@ models += Rev
|
|
27
27
|
models += EventMachine
|
28
28
|
models += NeverBlock
|
29
29
|
models += RevThreadSpawn
|
30
|
-
models += RevThreadPool
|
31
30
|
|
32
31
|
ifeq ($(RUBY_ENGINE),ruby)
|
33
32
|
rp := )
|
@@ -37,6 +36,7 @@ ifeq ($(RUBY_ENGINE),ruby)
|
|
37
36
|
models += FiberSpawn
|
38
37
|
models += RevFiberSpawn
|
39
38
|
models += FiberPool
|
39
|
+
models += RevThreadPool
|
40
40
|
endif
|
41
41
|
endif
|
42
42
|
|
@@ -118,7 +118,7 @@ $(MODEL_T): script = $(subst $(model).,,$@)
|
|
118
118
|
$(MODEL_T): export RUBY := $(RUBY)
|
119
119
|
$(MODEL_T): export PATH := $(bindir):$(PATH)
|
120
120
|
$(MODEL_T): $(t_deps)
|
121
|
-
RUBYLIB=$(rainbows_lib):$$(cat $(libs)) \
|
121
|
+
RUBYLIB=$(rainbows_lib):$$(cat $(libs)):$(RUBYLIB) \
|
122
122
|
$(TRACER) $(SHELL) $(SH_TEST_OPTS) $(script) $(TEST_OPTS)
|
123
123
|
|
124
124
|
trash/.gitignore:
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# must be run without Rack::Lint since that clobbers to_path
|
2
|
+
class CloseWrapper < Struct.new(:to_io)
|
3
|
+
def each(&block)
|
4
|
+
to_io.each(&block)
|
5
|
+
end
|
6
|
+
|
7
|
+
def close
|
8
|
+
::File.open(ENV['fifo'], 'wb') do |fp|
|
9
|
+
fp.syswrite("CLOSING #{to_io}\n")
|
10
|
+
if to_io.respond_to?(:close) && ! to_io.closed?
|
11
|
+
to_io.close
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
use Rainbows::DevFdResponse
|
17
|
+
run(lambda { |env|
|
18
|
+
io = IO.popen('cat random_blob', 'rb')
|
19
|
+
[ 200,
|
20
|
+
{
|
21
|
+
'Content-Length' => ::File.stat('random_blob').size.to_s,
|
22
|
+
'Content-Type' => 'application/octet-stream',
|
23
|
+
},
|
24
|
+
CloseWrapper[io] ]
|
25
|
+
})
|
data/t/cramp/rainsocket.ru
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
# must be run without Rack::Lint since that clobbers to_path
|
2
|
+
use Rainbows::DevFdResponse
|
3
|
+
run(lambda { |env|
|
4
|
+
[ 200,
|
5
|
+
{
|
6
|
+
'Content-Length' => ::File.stat('random_blob').size.to_s,
|
7
|
+
'Content-Type' => 'application/octet-stream',
|
8
|
+
},
|
9
|
+
IO.popen('cat random_blob', 'rb') ]
|
10
|
+
})
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# must be run without Rack::Lint since that clobbers to_path
|
2
|
+
class Wrapper < Struct.new(:app)
|
3
|
+
def call(env)
|
4
|
+
status, headers, body = app.call(env)
|
5
|
+
body = Body.new(body) if body.respond_to?(:to_path)
|
6
|
+
[ status, headers, body ]
|
7
|
+
end
|
8
|
+
|
9
|
+
class Body < Struct.new(:body)
|
10
|
+
def to_path
|
11
|
+
body.to_path
|
12
|
+
end
|
13
|
+
|
14
|
+
def each(&block)
|
15
|
+
body.each(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def close
|
19
|
+
::File.open(ENV['fifo'], 'wb') { |fp| fp.puts "CLOSING" }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
use Wrapper
|
24
|
+
run Rack::File.new(Dir.pwd)
|
@@ -6,7 +6,7 @@ then
|
|
6
6
|
fi
|
7
7
|
. ./test-lib.sh
|
8
8
|
|
9
|
-
t_plan
|
9
|
+
t_plan 5 "config.ru inside alt working_directory"
|
10
10
|
|
11
11
|
t_begin "setup and start" && {
|
12
12
|
rainbows_setup
|
@@ -53,4 +53,8 @@ t_begin "response body ppid == 1 (daemonized)" && {
|
|
53
53
|
test "$body" -eq 1
|
54
54
|
}
|
55
55
|
|
56
|
+
t_begin "cleanup working directory" && {
|
57
|
+
rm -r $t_pfx.app
|
58
|
+
}
|
59
|
+
|
56
60
|
t_done
|
@@ -46,7 +46,7 @@ t_begin "send a batch of abortive HTTP/1.1 requests in parallel" && {
|
|
46
46
|
do
|
47
47
|
rm -f $i
|
48
48
|
(
|
49
|
-
curl -sSf --max-time
|
49
|
+
curl -sSf --max-time 2 --limit-rate 1K \
|
50
50
|
http://$listen/random_blob >/dev/null || echo ok > $i
|
51
51
|
) &
|
52
52
|
done
|
@@ -77,11 +77,11 @@ t_begin "check proc to ensure file is closed properly (Linux only)" && {
|
|
77
77
|
|
78
78
|
t_begin "send a bunch of HTTP/1.1 requests in parallel" && {
|
79
79
|
(
|
80
|
-
curl -sSf --limit-rate
|
80
|
+
curl -sSf --limit-rate 5M http://$listen/random_blob | \
|
81
81
|
rsha1 > $slow_a
|
82
82
|
) &
|
83
83
|
(
|
84
|
-
curl -sSf --limit-rate
|
84
|
+
curl -sSf --limit-rate 6M http://$listen/random_blob | \
|
85
85
|
rsha1 > $slow_b
|
86
86
|
) &
|
87
87
|
for i in $a $b $c
|
@@ -0,0 +1,108 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
test -r random_blob || die "random_blob required, run with 'make $0'"
|
4
|
+
case $RUBY_ENGINE in
|
5
|
+
ruby) ;;
|
6
|
+
*)
|
7
|
+
t_info "skipping $T since it can't load the sendfile gem, yet"
|
8
|
+
exit 0
|
9
|
+
;;
|
10
|
+
esac
|
11
|
+
|
12
|
+
t_plan 16 "sendfile wrap body response for $model"
|
13
|
+
|
14
|
+
t_begin "setup and startup" && {
|
15
|
+
rtmpfiles out err http_fifo sub_ok
|
16
|
+
rainbows_setup $model
|
17
|
+
echo 'require "sendfile"' >> $unicorn_config
|
18
|
+
echo 'def (::IO).copy_stream(*x); abort "NO"; end' >> $unicorn_config
|
19
|
+
|
20
|
+
# can't load Rack::Lint here since it clobbers body#to_path
|
21
|
+
export fifo
|
22
|
+
rainbows -E none -D file-wrap-to_path.ru -c $unicorn_config
|
23
|
+
rainbows_wait_start
|
24
|
+
}
|
25
|
+
|
26
|
+
t_begin "read random blob sha1" && {
|
27
|
+
random_blob_sha1=$(rsha1 < random_blob)
|
28
|
+
}
|
29
|
+
|
30
|
+
t_begin "start FIFO reader" && {
|
31
|
+
cat $fifo > $out &
|
32
|
+
}
|
33
|
+
|
34
|
+
t_begin "single request matches" && {
|
35
|
+
sha1=$(curl -sSfv 2> $err http://$listen/random_blob | rsha1)
|
36
|
+
test -n "$sha1"
|
37
|
+
test x"$sha1" = x"$random_blob_sha1"
|
38
|
+
}
|
39
|
+
|
40
|
+
t_begin "body.close called" && {
|
41
|
+
wait # for cat $fifo
|
42
|
+
grep CLOSING $out || die "body.close not logged"
|
43
|
+
}
|
44
|
+
|
45
|
+
t_begin "start FIFO reader for abortive HTTP/1.1 request" && {
|
46
|
+
cat $fifo > $out &
|
47
|
+
}
|
48
|
+
|
49
|
+
t_begin "send abortive HTTP/1.1 request" && {
|
50
|
+
rm -f $ok
|
51
|
+
(
|
52
|
+
printf 'GET /random_blob HTTP/1.1\r\nHost: example.com\r\n\r\n'
|
53
|
+
dd bs=4096 count=1 < $http_fifo >/dev/null
|
54
|
+
echo ok > $ok
|
55
|
+
) | socat - TCP:$listen > $http_fifo || :
|
56
|
+
test xok = x$(cat $ok)
|
57
|
+
}
|
58
|
+
|
59
|
+
t_begin "body.close called for aborted HTTP/1.1 request" && {
|
60
|
+
wait # for cat $fifo
|
61
|
+
grep CLOSING $out || die "body.close not logged"
|
62
|
+
}
|
63
|
+
|
64
|
+
t_begin "start FIFO reader for abortive HTTP/1.0 request" && {
|
65
|
+
cat $fifo > $out &
|
66
|
+
}
|
67
|
+
|
68
|
+
t_begin "send abortive HTTP/1.0 request" && {
|
69
|
+
rm -f $ok
|
70
|
+
(
|
71
|
+
printf 'GET /random_blob HTTP/1.0\r\n\r\n'
|
72
|
+
dd bs=4096 count=1 < $http_fifo >/dev/null
|
73
|
+
echo ok > $ok
|
74
|
+
) | socat - TCP:$listen > $http_fifo || :
|
75
|
+
test xok = x$(cat $ok)
|
76
|
+
}
|
77
|
+
|
78
|
+
t_begin "body.close called for aborted HTTP/1.0 request" && {
|
79
|
+
wait # for cat $fifo
|
80
|
+
grep CLOSING $out || die "body.close not logged"
|
81
|
+
}
|
82
|
+
|
83
|
+
t_begin "start FIFO reader for abortive HTTP/0.9 request" && {
|
84
|
+
cat $fifo > $out &
|
85
|
+
}
|
86
|
+
|
87
|
+
t_begin "send abortive HTTP/0.9 request" && {
|
88
|
+
rm -f $ok
|
89
|
+
(
|
90
|
+
printf 'GET /random_blob\r\n'
|
91
|
+
dd bs=4096 count=1 < $http_fifo >/dev/null
|
92
|
+
echo ok > $ok
|
93
|
+
) | socat - TCP:$listen > $http_fifo || :
|
94
|
+
test xok = x$(cat $ok)
|
95
|
+
}
|
96
|
+
|
97
|
+
t_begin "body.close called for aborted HTTP/0.9 request" && {
|
98
|
+
wait # for cat $fifo
|
99
|
+
grep CLOSING $out || die "body.close not logged"
|
100
|
+
}
|
101
|
+
|
102
|
+
t_begin "shutdown server" && {
|
103
|
+
kill -QUIT $rainbows_pid
|
104
|
+
}
|
105
|
+
|
106
|
+
t_begin "check stderr" && check_stderr
|
107
|
+
|
108
|
+
t_done
|
@@ -0,0 +1,139 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
test -r random_blob || die "random_blob required, run with 'make $0'"
|
4
|
+
case $RUBY_VERSION in
|
5
|
+
1.9.*) ;;
|
6
|
+
*)
|
7
|
+
t_info "skipping $T since it can't IO.copy_stream"
|
8
|
+
exit 0
|
9
|
+
;;
|
10
|
+
esac
|
11
|
+
|
12
|
+
case $model in
|
13
|
+
ThreadSpawn|WriterThreadSpawn|ThreadPool|WriterThreadPool|Base) ;;
|
14
|
+
*)
|
15
|
+
t_info "skipping $T since it doesn't use IO.copy_stream"
|
16
|
+
exit 0
|
17
|
+
;;
|
18
|
+
esac
|
19
|
+
|
20
|
+
t_plan 11 "IO.copy_stream byte range response for $model"
|
21
|
+
|
22
|
+
t_begin "setup and startup" && {
|
23
|
+
rtmpfiles out err
|
24
|
+
rainbows_setup $model
|
25
|
+
# can't load Rack::Lint here since it clobbers body#to_path
|
26
|
+
rainbows -E none -D large-file-response.ru -c $unicorn_config
|
27
|
+
rainbows_wait_start
|
28
|
+
random_blob_size=$(wc -c < random_blob)
|
29
|
+
rb_1=$(( $random_blob_size - 1 ))
|
30
|
+
range_head=-r-365
|
31
|
+
range_tail=-r155-
|
32
|
+
range_mid=-r200-300
|
33
|
+
range_n1=-r0-$rb_1
|
34
|
+
range_n2=-r0-$(($rb_1 - 1))
|
35
|
+
range_1b_head=-r0-0
|
36
|
+
range_1b_tail=-r$rb_1-$rb_1
|
37
|
+
range_1b_mid=-r200-200
|
38
|
+
range_all=-r0-$random_blob_size
|
39
|
+
url=http://$listen/random_blob
|
40
|
+
}
|
41
|
+
|
42
|
+
check_content_range () {
|
43
|
+
# Content-Range: bytes #{offset}-#{offset+count-1}/#{clen}
|
44
|
+
awk -F/ -v E=0 -v size=$random_blob_size '
|
45
|
+
$2 == size && /^< Content-Range: bytes [0-9]+-[0-9]+\// {
|
46
|
+
split($1, a, /-/);
|
47
|
+
if (a[1] < size) {
|
48
|
+
E = 0;
|
49
|
+
exit(0);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
END { exit(E) }
|
53
|
+
' < $err
|
54
|
+
}
|
55
|
+
|
56
|
+
t_begin "read random blob sha1s" && {
|
57
|
+
sha1_head=$(curl -sSff $range_head file://random_blob | rsha1)
|
58
|
+
sha1_tail=$(curl -sSff $range_tail file://random_blob | rsha1)
|
59
|
+
sha1_mid=$(curl -sSff $range_mid file://random_blob | rsha1)
|
60
|
+
sha1_n1=$(curl -sSff $range_n1 file://random_blob | rsha1)
|
61
|
+
sha1_n2=$(curl -sSff $range_n2 file://random_blob | rsha1)
|
62
|
+
sha1_1b_head=$(curl -sSff $range_1b_head file://random_blob | rsha1)
|
63
|
+
sha1_1b_tail=$(curl -sSff $range_1b_tail file://random_blob | rsha1)
|
64
|
+
sha1_1b_mid=$(curl -sSff $range_1b_mid file://random_blob | rsha1)
|
65
|
+
sha1_all=$(rsha1 < random_blob)
|
66
|
+
echo "$sha1_all=$sha1_n1"
|
67
|
+
}
|
68
|
+
|
69
|
+
t_begin "normal full request matches" && {
|
70
|
+
sha1="$(curl -v 2>$err -sSf $url | rsha1)"
|
71
|
+
test x"$sha1_all" = x"$sha1"
|
72
|
+
grep 'Content-Range:' $err && die "Content-Range unexpected"
|
73
|
+
grep 'HTTP/1.1 200 OK' $err || die "200 response expected"
|
74
|
+
}
|
75
|
+
|
76
|
+
t_begin "crazy offset goes over" && {
|
77
|
+
range_insane=-r$(($random_blob_size * 2))-$(($random_blob_size * 4))
|
78
|
+
curl -vsS 2>$err $range_insane $url
|
79
|
+
grep 'HTTP/1\.[01] 416 ' $err || die "expected 416 error"
|
80
|
+
}
|
81
|
+
|
82
|
+
t_begin "full request matches with explicit ranges" && {
|
83
|
+
sha1="$(curl -v 2>$err $range_all -sSf $url | rsha1)"
|
84
|
+
check_content_range
|
85
|
+
test x"$sha1_all" = x"$sha1"
|
86
|
+
|
87
|
+
sha1="$(curl -v 2>$err $range_n1 -sSf $url | rsha1)"
|
88
|
+
check_content_range
|
89
|
+
test x"$sha1_all" = x"$sha1"
|
90
|
+
|
91
|
+
range_over=-r0-$(($random_blob_size * 2))
|
92
|
+
sha1="$(curl -v 2>$err $range_over -sSf $url | rsha1)"
|
93
|
+
check_content_range
|
94
|
+
test x"$sha1_all" = x"$sha1"
|
95
|
+
}
|
96
|
+
|
97
|
+
t_begin "no fence post errors" && {
|
98
|
+
sha1="$(curl -v 2>$err $range_n2 -sSf $url | rsha1)"
|
99
|
+
check_content_range
|
100
|
+
test x"$sha1_n2" = x"$sha1"
|
101
|
+
|
102
|
+
sha1="$(curl -v 2>$err $range_1b_head -sSf $url | rsha1)"
|
103
|
+
check_content_range
|
104
|
+
test x"$sha1_1b_head" = x"$sha1"
|
105
|
+
|
106
|
+
sha1="$(curl -v 2>$err $range_1b_tail -sSf $url | rsha1)"
|
107
|
+
check_content_range
|
108
|
+
test x"$sha1_1b_tail" = x"$sha1"
|
109
|
+
|
110
|
+
sha1="$(curl -v 2>$err $range_1b_mid -sSf $url | rsha1)"
|
111
|
+
check_content_range
|
112
|
+
test x"$sha1_1b_mid" = x"$sha1"
|
113
|
+
}
|
114
|
+
|
115
|
+
t_begin "head range matches" && {
|
116
|
+
sha1="$(curl -sSfv $range_head $url | rsha1)"
|
117
|
+
check_content_range
|
118
|
+
test x"$sha1_head" = x"$sha1"
|
119
|
+
}
|
120
|
+
|
121
|
+
t_begin "tail range matches" && {
|
122
|
+
sha1="$(curl -sSf $range_tail $url | rsha1)"
|
123
|
+
check_content_range
|
124
|
+
test x"$sha1_tail" = x"$sha1"
|
125
|
+
}
|
126
|
+
|
127
|
+
t_begin "mid range matches" && {
|
128
|
+
sha1="$(curl -sSf $range_mid $url | rsha1)"
|
129
|
+
check_content_range
|
130
|
+
test x"$sha1_mid" = x"$sha1"
|
131
|
+
}
|
132
|
+
|
133
|
+
t_begin "shutdown server" && {
|
134
|
+
kill -QUIT $rainbows_pid
|
135
|
+
}
|
136
|
+
|
137
|
+
t_begin "check stderr" && check_stderr
|
138
|
+
|
139
|
+
t_done
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
test -r random_blob || die "random_blob required, run with 'make $0'"
|
4
|
+
case $RUBY_ENGINE in
|
5
|
+
ruby) ;;
|
6
|
+
*)
|
7
|
+
t_info "skipping $T since it can't load the sendfile gem, yet"
|
8
|
+
exit 0
|
9
|
+
;;
|
10
|
+
esac
|
11
|
+
|
12
|
+
case $model in
|
13
|
+
EventMachine|NeverBlock)
|
14
|
+
t_info "skipping $T since it's not compatible with $model"
|
15
|
+
exit 0
|
16
|
+
;;
|
17
|
+
*) ;;
|
18
|
+
esac
|
19
|
+
|
20
|
+
t_plan 7 "sendfile byte range response for $model"
|
21
|
+
|
22
|
+
t_begin "setup and startup" && {
|
23
|
+
rtmpfiles out err
|
24
|
+
rainbows_setup $model
|
25
|
+
echo 'require "sendfile"' >> $unicorn_config
|
26
|
+
echo 'def (::IO).copy_stream(*x); abort "NO"; end' >> $unicorn_config
|
27
|
+
|
28
|
+
# can't load Rack::Lint here since it clobbers body#to_path
|
29
|
+
rainbows -E none -D large-file-response.ru -c $unicorn_config
|
30
|
+
rainbows_wait_start
|
31
|
+
range_head=-r-365
|
32
|
+
range_tail=-r155-
|
33
|
+
range_mid=-r200-300
|
34
|
+
}
|
35
|
+
|
36
|
+
t_begin "read random blob sha1s" && {
|
37
|
+
sha1_head=$(curl -sSf $range_head file://random_blob | rsha1)
|
38
|
+
sha1_tail=$(curl -sSf $range_tail file://random_blob | rsha1)
|
39
|
+
sha1_mid=$(curl -sSf $range_mid file://random_blob | rsha1)
|
40
|
+
}
|
41
|
+
|
42
|
+
t_begin "head range matches" && {
|
43
|
+
sha1="$(curl -sSv $range_head http://$listen/random_blob | rsha1)"
|
44
|
+
test x"$sha1_head" = x"$sha1"
|
45
|
+
}
|
46
|
+
|
47
|
+
t_begin "tail range matches" && {
|
48
|
+
sha1="$(curl -sS $range_tail http://$listen/random_blob | rsha1)"
|
49
|
+
test x"$sha1_tail" = x"$sha1"
|
50
|
+
}
|
51
|
+
|
52
|
+
t_begin "mid range matches" && {
|
53
|
+
sha1="$(curl -sS $range_mid http://$listen/random_blob | rsha1)"
|
54
|
+
test x"$sha1_mid" = x"$sha1"
|
55
|
+
}
|
56
|
+
|
57
|
+
t_begin "shutdown server" && {
|
58
|
+
kill -QUIT $rainbows_pid
|
59
|
+
}
|
60
|
+
|
61
|
+
t_begin "check stderr" && check_stderr
|
62
|
+
|
63
|
+
t_done
|