rainbows 0.94.0 → 0.95.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/.document +1 -0
- data/.manifest +18 -0
- data/ChangeLog +394 -226
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +6 -4
- data/NEWS +18 -0
- data/README +13 -5
- data/Static_Files +71 -0
- data/TODO +12 -0
- data/Test_Suite +1 -1
- data/bin/rainbows +1 -4
- data/lib/rainbows/actor_spawn.rb +1 -1
- data/lib/rainbows/app_pool.rb +1 -1
- data/lib/rainbows/base.rb +79 -89
- data/lib/rainbows/byte_slice.rb +17 -0
- data/lib/rainbows/configurator.rb +46 -0
- data/lib/rainbows/const.rb +2 -2
- data/lib/rainbows/dev_fd_response.rb +52 -44
- data/lib/rainbows/error.rb +1 -0
- data/lib/rainbows/ev_core.rb +3 -2
- data/lib/rainbows/event_machine.rb +26 -24
- data/lib/rainbows/fiber/base.rb +30 -40
- data/lib/rainbows/fiber/body.rb +34 -0
- data/lib/rainbows/fiber/io.rb +28 -8
- data/lib/rainbows/fiber/queue.rb +1 -0
- data/lib/rainbows/fiber/rev.rb +4 -2
- data/lib/rainbows/fiber.rb +1 -0
- data/lib/rainbows/fiber_pool.rb +2 -2
- data/lib/rainbows/fiber_spawn.rb +2 -2
- data/lib/rainbows/http_response.rb +20 -31
- data/lib/rainbows/http_server.rb +3 -4
- data/lib/rainbows/max_body.rb +1 -0
- data/lib/rainbows/never_block/event_machine.rb +2 -0
- data/lib/rainbows/never_block.rb +5 -4
- data/lib/rainbows/queue_pool.rb +1 -0
- data/lib/rainbows/response/body.rb +119 -0
- data/lib/rainbows/response.rb +43 -0
- data/lib/rainbows/rev/client.rb +79 -9
- data/lib/rainbows/rev/core.rb +4 -0
- data/lib/rainbows/rev/deferred_response.rb +1 -44
- data/lib/rainbows/rev/heartbeat.rb +1 -0
- data/lib/rainbows/rev/master.rb +1 -0
- data/lib/rainbows/rev/sendfile.rb +26 -0
- data/lib/rainbows/rev/thread.rb +2 -1
- data/lib/rainbows/rev.rb +2 -0
- data/lib/rainbows/rev_fiber_spawn.rb +3 -1
- data/lib/rainbows/rev_thread_pool.rb +7 -5
- data/lib/rainbows/rev_thread_spawn.rb +2 -2
- data/lib/rainbows/revactor.rb +146 -146
- data/lib/rainbows/sendfile.rb +10 -21
- data/lib/rainbows/server_token.rb +39 -0
- data/lib/rainbows/stream_file.rb +14 -0
- data/lib/rainbows/tee_input.rb +1 -0
- data/lib/rainbows/thread_pool.rb +12 -7
- data/lib/rainbows/thread_spawn.rb +2 -3
- data/lib/rainbows/writer_thread_pool.rb +13 -7
- data/lib/rainbows/writer_thread_spawn.rb +12 -9
- data/lib/rainbows.rb +16 -45
- data/rainbows.gemspec +8 -8
- data/t/.gitignore +1 -1
- data/t/GNUmakefile +26 -16
- data/t/README +1 -1
- data/t/async-response-no-autochunk.ru +0 -1
- data/t/async-response.ru +0 -1
- data/t/cramp/rainsocket.ru +26 -0
- data/t/fork-sleep.ru +0 -1
- data/t/my-tap-lib.sh +3 -2
- data/t/simple-http_ActorSpawn.ru +9 -0
- data/t/t0009-broken-app.sh +1 -1
- data/t/t0009.ru +0 -1
- data/t/t0011-close-on-exec-set.sh +1 -1
- data/t/t0015-working_directory.sh +56 -0
- data/t/t0016-onenine-encoding-is-tricky.sh +28 -0
- data/t/t0016.rb +15 -0
- data/t/t0020-large-sendfile-response.sh +141 -0
- data/t/t0300-async_sinatra.sh +0 -6
- data/t/t0501-cramp-rainsocket.sh +38 -0
- data/t/t9001-sendfile-to-path.sh +5 -4
- data/t/t9002-server-token.sh +37 -0
- data/t/t9002.ru +4 -0
- data/t/test-lib.sh +1 -1
- data/t/test_isolate.rb +14 -11
- metadata +87 -18
data/lib/rainbows.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
require 'unicorn'
|
3
|
+
# the value passed to TCP_DEFER_ACCEPT actually matters in Linux 2.6.32+
|
4
|
+
Unicorn::SocketHelper::DEFAULTS[:tcp_defer_accept] = 60
|
5
|
+
|
3
6
|
require 'rainbows/error'
|
7
|
+
require 'rainbows/configurator'
|
4
8
|
require 'fcntl'
|
5
9
|
|
6
10
|
module Rainbows
|
@@ -8,6 +12,7 @@ module Rainbows
|
|
8
12
|
# global vars because class/instance variables are confusing me :<
|
9
13
|
# this struct is only accessed inside workers and thus private to each
|
10
14
|
# G.cur may not be used in the network concurrency model
|
15
|
+
# :stopdoc:
|
11
16
|
class State < Struct.new(:alive,:m,:cur,:kato,:server,:tmp,:expire)
|
12
17
|
def tick
|
13
18
|
tmp.chmod(self.m = m == 0 ? 1 : 0)
|
@@ -22,14 +27,13 @@ module Rainbows
|
|
22
27
|
false
|
23
28
|
end
|
24
29
|
end
|
25
|
-
# :stopdoc:
|
26
30
|
G = State.new(true, 0, 0, 5)
|
27
31
|
O = {}
|
28
32
|
# :startdoc:
|
29
33
|
|
30
34
|
require 'rainbows/const'
|
31
35
|
require 'rainbows/http_server'
|
32
|
-
require 'rainbows/
|
36
|
+
require 'rainbows/response'
|
33
37
|
require 'rainbows/base'
|
34
38
|
require 'rainbows/tee_input'
|
35
39
|
autoload :Sendfile, 'rainbows/sendfile'
|
@@ -60,12 +64,12 @@ module Rainbows
|
|
60
64
|
|
61
65
|
# runs the Rainbows! HttpServer with +app+ and +options+ and does
|
62
66
|
# not return until the server has exited.
|
63
|
-
def run(app, options = {})
|
67
|
+
def run(app, options = {}) # :nodoc:
|
64
68
|
HttpServer.new(app, options).start.join
|
65
69
|
end
|
66
70
|
|
67
71
|
# returns nil if accept fails
|
68
|
-
def sync_accept(sock)
|
72
|
+
def sync_accept(sock) # :nodoc:
|
69
73
|
rv = sock.accept
|
70
74
|
rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
71
75
|
rv
|
@@ -73,7 +77,7 @@ module Rainbows
|
|
73
77
|
end
|
74
78
|
|
75
79
|
# returns nil if accept fails
|
76
|
-
def accept(sock)
|
80
|
+
def accept(sock) # :nodoc:
|
77
81
|
rv = sock.accept_nonblock
|
78
82
|
rv.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
79
83
|
rv
|
@@ -83,50 +87,18 @@ module Rainbows
|
|
83
87
|
# returns a string representing the address of the given client +io+
|
84
88
|
# For local UNIX domain sockets, this will return a string referred
|
85
89
|
# to by the (non-frozen) Unicorn::HttpRequest::LOCALHOST constant.
|
86
|
-
def addr(io)
|
90
|
+
def addr(io) # :nodoc:
|
87
91
|
io.respond_to?(:peeraddr) ?
|
88
|
-
io.peeraddr
|
92
|
+
io.peeraddr[-1] : Unicorn::HttpRequest::LOCALHOST
|
89
93
|
end
|
90
94
|
|
95
|
+
# :stopdoc:
|
91
96
|
# the default max body size is 1 megabyte (1024 * 1024 bytes)
|
92
97
|
@@max_bytes = 1024 * 1024
|
93
98
|
|
94
99
|
def max_bytes; @@max_bytes; end
|
95
100
|
def max_bytes=(nr); @@max_bytes = nr; end
|
96
|
-
|
97
|
-
|
98
|
-
# configures \Rainbows! with a given concurrency model to +use+ and
|
99
|
-
# a +worker_connections+ upper-bound. This method may be called
|
100
|
-
# inside a Unicorn/Rainbows configuration file:
|
101
|
-
#
|
102
|
-
# Rainbows! do
|
103
|
-
# use :Revactor # this may also be :ThreadSpawn or :ThreadPool
|
104
|
-
# worker_connections 400
|
105
|
-
# keepalive_timeout 0 # zero disables keepalives entirely
|
106
|
-
# client_max_body_size 5*1024*1024 # 5 megabytes
|
107
|
-
# end
|
108
|
-
#
|
109
|
-
# # the rest of the Unicorn configuration
|
110
|
-
# worker_processes 8
|
111
|
-
#
|
112
|
-
# See the documentation for the respective Revactor, ThreadSpawn,
|
113
|
-
# and ThreadPool classes for descriptions and recommendations for
|
114
|
-
# each of them. The total number of clients we're able to serve is
|
115
|
-
# +worker_processes+ * +worker_connections+, so in the above example
|
116
|
-
# we can serve 8 * 400 = 3200 clients concurrently.
|
117
|
-
#
|
118
|
-
# The default is +keepalive_timeout+ is 5 seconds, which should be
|
119
|
-
# enough under most conditions for browsers to render the page and
|
120
|
-
# start retrieving extra elements for. Increasing this beyond 5
|
121
|
-
# seconds is not recommended. Zero disables keepalive entirely
|
122
|
-
# (but pipelining fully-formed requests is still works).
|
123
|
-
#
|
124
|
-
# The default +client_max_body_size+ is 1 megabyte (1024 * 1024 bytes),
|
125
|
-
# setting this to +nil+ will disable body size checks and allow any
|
126
|
-
# size to be specified.
|
127
|
-
def Rainbows!(&block)
|
128
|
-
block_given? or raise ArgumentError, "Rainbows! requires a block"
|
129
|
-
HttpServer.setup(block)
|
101
|
+
# :startdoc:
|
130
102
|
end
|
131
103
|
|
132
104
|
# :stopdoc:
|
@@ -155,8 +127,7 @@ module Rainbows
|
|
155
127
|
end
|
156
128
|
# :startdoc:
|
157
129
|
autoload :Fiber, 'rainbows/fiber' # core class
|
158
|
-
|
130
|
+
autoload :ByteSlice, 'rainbows/byte_slice'
|
131
|
+
autoload :StreamFile, 'rainbows/stream_file'
|
132
|
+
autoload :HttpResponse, 'rainbows/http_response' # deprecated
|
159
133
|
end
|
160
|
-
|
161
|
-
# inject the Rainbows! method into Unicorn::Configurator
|
162
|
-
Unicorn::Configurator.class_eval { include Rainbows }
|
data/rainbows.gemspec
CHANGED
@@ -40,17 +40,17 @@ Gem::Specification.new do |s|
|
|
40
40
|
|
41
41
|
s.test_files = test_files
|
42
42
|
|
43
|
-
# we
|
44
|
-
|
45
|
-
# when exposed directly to untrusted clients.
|
46
|
-
s.add_dependency(%q<unicorn>, [">= 0.97.1", "< 2.0.0"])
|
47
|
-
s.add_development_dependency(%q<isolate>, "~> 2.0.2")
|
43
|
+
# we want a newer Rack for a valid HeaderHash#each
|
44
|
+
s.add_dependency(%q<rack>, ['~> 1.1'])
|
48
45
|
|
49
|
-
# Unicorn
|
50
|
-
#
|
46
|
+
# we need Unicorn for the HTTP parser and process management
|
47
|
+
# Unicorn 0.991.0 handles config.ru when started outside of
|
48
|
+
# the prespecified working_directory
|
49
|
+
s.add_dependency(%q<unicorn>, [">= 1.1.0", "< 2.0.0"])
|
50
|
+
s.add_development_dependency(%q<isolate>, "~> 2.1.0")
|
51
51
|
|
52
52
|
# optional runtime dependencies depending on configuration
|
53
|
-
# see
|
53
|
+
# see t/test_isolate.rb for the exact versions we've tested with
|
54
54
|
#
|
55
55
|
# Revactor >= 0.1.5 includes UNIX domain socket support
|
56
56
|
# s.add_dependency(%q<revactor>, [">= 0.1.5"])
|
data/t/.gitignore
CHANGED
data/t/GNUmakefile
CHANGED
@@ -4,6 +4,7 @@ all::
|
|
4
4
|
|
5
5
|
pid := $(shell echo $$PPID)
|
6
6
|
|
7
|
+
MRI = ruby
|
7
8
|
RUBY = ruby
|
8
9
|
rainbows_lib := $(shell cd ../lib && pwd)
|
9
10
|
-include ../local.mk
|
@@ -15,7 +16,8 @@ ifeq ($(RUBY_VERSION),)
|
|
15
16
|
$(error unable to detect RUBY_VERSION)
|
16
17
|
endif
|
17
18
|
|
18
|
-
|
19
|
+
RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
|
20
|
+
export RUBY_VERSION RUBY_ENGINE
|
19
21
|
|
20
22
|
models += WriterThreadPool
|
21
23
|
models += WriterThreadSpawn
|
@@ -27,13 +29,19 @@ models += NeverBlock
|
|
27
29
|
models += RevThreadSpawn
|
28
30
|
models += RevThreadPool
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
32
|
+
ifeq ($(RUBY_ENGINE),ruby)
|
33
|
+
rp := )
|
34
|
+
ONENINE := $(shell case $(RUBY_VERSION) in 1.9.*$(rp) echo true;;esac)
|
35
|
+
ifeq ($(ONENINE),true)
|
36
|
+
models += Revactor
|
37
|
+
models += FiberSpawn
|
38
|
+
models += RevFiberSpawn
|
39
|
+
models += FiberPool
|
40
|
+
endif
|
41
|
+
endif
|
42
|
+
|
43
|
+
ifeq ($(RUBY_ENGINE),rbx)
|
44
|
+
models += ActorSpawn
|
37
45
|
endif
|
38
46
|
all_models := $(models) Base
|
39
47
|
|
@@ -60,7 +68,7 @@ $(all_models):
|
|
60
68
|
all:: $(T)
|
61
69
|
|
62
70
|
# can't rely on "set -o pipefail" since we don't require bash or ksh93 :<
|
63
|
-
t_pfx = trash/$@-$(RUBY_VERSION)
|
71
|
+
t_pfx = trash/$@-$(RUBY_ENGINE)-$(RUBY_VERSION)
|
64
72
|
TEST_OPTS =
|
65
73
|
# TRACER = strace -f -o $(t_pfx).strace -s 100000
|
66
74
|
# TRACER = /usr/bin/time -o $(t_pfx).time
|
@@ -73,11 +81,13 @@ ifdef V
|
|
73
81
|
endif
|
74
82
|
endif
|
75
83
|
|
76
|
-
|
77
|
-
|
84
|
+
bindir := $(CURDIR)/bin-$(RUBY_ENGINE)-$(RUBY_VERSION)
|
85
|
+
bin_rainbows := $(bindir)/rainbows
|
86
|
+
$(bin_rainbows): ruby_bin = $(shell which $(RUBY))
|
87
|
+
$(bin_rainbows): ../bin/rainbows
|
78
88
|
mkdir -p $(@D)
|
79
89
|
install -m 755 $^ $@.$(pid)
|
80
|
-
$(
|
90
|
+
$(MRI) -i -p -e '$$_.gsub!(%r{^#!.*$$},"#!$(ruby_bin)")' $@.$(pid)
|
81
91
|
mv $@.$(pid) $@
|
82
92
|
|
83
93
|
random_blob:
|
@@ -95,18 +105,18 @@ $(deps):
|
|
95
105
|
{ echo >&2 "E '$(dep_bin)' not found in PATH=$(PATH)"; exit 1; }
|
96
106
|
@mv $@.$(pid) $@
|
97
107
|
|
98
|
-
libs := tmp/isolate
|
108
|
+
libs := tmp/isolate/$(RUBY_ENGINE)-$(RUBY_VERSION)/.libs
|
99
109
|
$(libs): test_isolate.rb
|
100
110
|
mkdir -p $(@D)
|
101
111
|
$(RUBY) $< > $@+
|
102
112
|
mv $@+ $@
|
103
|
-
t_deps := $(libs) $(deps)
|
113
|
+
t_deps := $(libs) $(deps) $(bin_rainbows) trash/.gitignore
|
104
114
|
$(T): $(t_deps)
|
105
115
|
|
106
116
|
$(MODEL_T): export model = $(firstword $(subst ., ,$@))
|
107
117
|
$(MODEL_T): script = $(subst $(model).,,$@)
|
108
118
|
$(MODEL_T): export RUBY := $(RUBY)
|
109
|
-
$(MODEL_T): export PATH := $(
|
119
|
+
$(MODEL_T): export PATH := $(bindir):$(PATH)
|
110
120
|
$(MODEL_T): $(t_deps)
|
111
121
|
RUBYLIB=$(rainbows_lib):$$(cat $(libs)) \
|
112
122
|
$(TRACER) $(SHELL) $(SH_TEST_OPTS) $(script) $(TEST_OPTS)
|
@@ -116,6 +126,6 @@ trash/.gitignore:
|
|
116
126
|
echo '*' > $@
|
117
127
|
|
118
128
|
clean:
|
119
|
-
$(RM) -r trash/*.log trash/*.code
|
129
|
+
$(RM) -r trash/*.log trash/*.code $(bindir)
|
120
130
|
|
121
131
|
.PHONY: $(T) clean
|
data/t/README
CHANGED
@@ -12,7 +12,7 @@ easily portable to non-Ruby web servers.
|
|
12
12
|
== Requirements
|
13
13
|
|
14
14
|
* {Ruby 1.8 or 1.9}[http://www.ruby-lang.org/] (duh!)
|
15
|
-
* {isolate ~> 2.0
|
15
|
+
* {isolate ~> 2.1.0}[http://github.com/jbarnette/isolate] - for dependencies
|
16
16
|
* {GNU make}[http://www.gnu.org/software/make/]
|
17
17
|
* {socat}[http://www.dest-unreach.org/socat/]
|
18
18
|
* {curl >= 7.18.0}[http://curl.haxx.se/]
|
data/t/async-response.ru
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
# based on examples/rainsocket.ru git://github.com/lifo/cramp
|
2
|
+
# Rack::Lint does not like async + EM stuff, so disable it:
|
3
|
+
#\ -E deployment
|
4
|
+
require 'cramp/controller'
|
5
|
+
|
6
|
+
Cramp::Controller::Websocket.backend = :rainbows
|
7
|
+
|
8
|
+
class WelcomeController < Cramp::Controller::Websocket
|
9
|
+
periodic_timer :send_hello_world, :every => 2
|
10
|
+
on_data :received_data
|
11
|
+
|
12
|
+
def received_data(data)
|
13
|
+
if data =~ /fuck/
|
14
|
+
render "You cant say fuck in here"
|
15
|
+
finish
|
16
|
+
else
|
17
|
+
render "Got your #{data}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_hello_world
|
22
|
+
render "Hello from the Server!\n"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
run WelcomeController
|
data/t/fork-sleep.ru
CHANGED
data/t/my-tap-lib.sh
CHANGED
@@ -188,9 +188,10 @@ then
|
|
188
188
|
|
189
189
|
(
|
190
190
|
# use a subshell so seds are not waitable
|
191
|
-
$SED -e 's/^/#: /' $t_stdout &
|
192
|
-
$SED -e 's/^/#! /' $t_stderr &
|
191
|
+
$SED -e 's/^/#: /' < $t_stdout &
|
192
|
+
$SED -e 's/^/#! /' < $t_stderr &
|
193
193
|
) &
|
194
|
+
wait
|
194
195
|
exec > $t_stdout 2> $t_stderr
|
195
196
|
else
|
196
197
|
exec > /dev/null 2> /dev/null
|
data/t/t0009-broken-app.sh
CHANGED
data/t/t0009.ru
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
if test -n "$RBX_SKIP"
|
3
|
+
then
|
4
|
+
echo "$0 is broken under Rubinius for now"
|
5
|
+
exit 0
|
6
|
+
fi
|
7
|
+
. ./test-lib.sh
|
8
|
+
|
9
|
+
t_plan 4 "config.ru inside alt working_directory"
|
10
|
+
|
11
|
+
t_begin "setup and start" && {
|
12
|
+
rainbows_setup
|
13
|
+
rtmpfiles unicorn_config_tmp
|
14
|
+
rm -rf $t_pfx.app
|
15
|
+
mkdir $t_pfx.app
|
16
|
+
|
17
|
+
cat > $t_pfx.app/config.ru <<EOF
|
18
|
+
#\--daemonize --listen $listen
|
19
|
+
use Rack::ContentLength
|
20
|
+
use Rack::ContentType, "text/plain"
|
21
|
+
run lambda { |env| [ 200, {}, [ "#{\$master_ppid}\\n" ] ] }
|
22
|
+
EOF
|
23
|
+
# we have --host/--port in config.ru instead
|
24
|
+
grep -v ^listen $unicorn_config > $unicorn_config_tmp
|
25
|
+
|
26
|
+
# the whole point of this exercise
|
27
|
+
echo "working_directory '$t_pfx.app'" >> $unicorn_config_tmp
|
28
|
+
|
29
|
+
# allows ppid to be 1 in before_fork
|
30
|
+
echo "preload_app true" >> $unicorn_config_tmp
|
31
|
+
cat >> $unicorn_config_tmp <<\EOF
|
32
|
+
before_fork do |server,worker|
|
33
|
+
$master_ppid = Process.ppid # should be zero to detect daemonization
|
34
|
+
end
|
35
|
+
EOF
|
36
|
+
|
37
|
+
mv $unicorn_config_tmp $unicorn_config
|
38
|
+
|
39
|
+
# rely on --daemonize switch, no & or -D
|
40
|
+
rainbows -c $unicorn_config
|
41
|
+
rainbows_wait_start
|
42
|
+
}
|
43
|
+
|
44
|
+
t_begin "hit with curl" && {
|
45
|
+
body=$(curl -sSf http://$listen/)
|
46
|
+
}
|
47
|
+
|
48
|
+
t_begin "killing succeeds" && {
|
49
|
+
kill $rainbows_pid
|
50
|
+
}
|
51
|
+
|
52
|
+
t_begin "response body ppid == 1 (daemonized)" && {
|
53
|
+
test "$body" -eq 1
|
54
|
+
}
|
55
|
+
|
56
|
+
t_done
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
t_plan 4 "proper handling of onenine encoding for $model"
|
4
|
+
|
5
|
+
t_begin "setup and startup" && {
|
6
|
+
rainbows_setup $model
|
7
|
+
rainbows -D ./t0016.rb -c $unicorn_config
|
8
|
+
rainbows_wait_start
|
9
|
+
expect_sha1=8ff79d8115f9fe38d18be858c66aa08a1cc27a66
|
10
|
+
}
|
11
|
+
|
12
|
+
t_begin "response matches expected" && {
|
13
|
+
rm -f $ok
|
14
|
+
(
|
15
|
+
curl -sSf http://$listen/ && echo ok > $ok
|
16
|
+
) | rsha1 > $tmp
|
17
|
+
test x$expect_sha1 = x"$(cat $tmp)"
|
18
|
+
}
|
19
|
+
|
20
|
+
t_begin "shutdown server" && {
|
21
|
+
kill -QUIT $rainbows_pid
|
22
|
+
}
|
23
|
+
|
24
|
+
dbgcat r_err
|
25
|
+
|
26
|
+
t_begin "check stderr" && check_stderr
|
27
|
+
|
28
|
+
t_done
|
data/t/t0016.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module T0016
|
3
|
+
CHUNK = '©' * 1024 * 1024
|
4
|
+
BODY = (1..50).map { CHUNK }
|
5
|
+
HEADER = {
|
6
|
+
# BODY.inject(0) { |m,c| m += c.bytesize }.to_s,
|
7
|
+
'Content-Length' => '104857600',
|
8
|
+
'Content-Type' => 'text/plain',
|
9
|
+
}
|
10
|
+
|
11
|
+
def self.call(env)
|
12
|
+
[ 200, HEADER, BODY ]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
$0 == __FILE__ and T0016::BODY.each { |x| $stdout.syswrite(x) }
|
@@ -0,0 +1,141 @@
|
|
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 12 "large sendfile response for $model"
|
13
|
+
|
14
|
+
t_begin "setup and startup" && {
|
15
|
+
rtmpfiles curl_out a b c slow_a slow_b
|
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
|
+
rainbows -E none -D large-file-response.ru -c $unicorn_config
|
22
|
+
rainbows_wait_start
|
23
|
+
}
|
24
|
+
|
25
|
+
t_begin "read random blob sha1" && {
|
26
|
+
random_blob_sha1=$(rsha1 < random_blob)
|
27
|
+
three_sha1=$(cat random_blob random_blob random_blob | rsha1)
|
28
|
+
}
|
29
|
+
|
30
|
+
t_begin "send keepalive HTTP/1.1 requests in parallel" && {
|
31
|
+
for i in $a $b $c $slow_a $slow_b
|
32
|
+
do
|
33
|
+
curl -sSf http://$listen/random_blob \
|
34
|
+
http://$listen/random_blob \
|
35
|
+
http://$listen/random_blob | rsha1 > $i &
|
36
|
+
done
|
37
|
+
wait
|
38
|
+
for i in $a $b $c $slow_a $slow_b
|
39
|
+
do
|
40
|
+
test x$(cat $i) = x$three_sha1
|
41
|
+
done
|
42
|
+
}
|
43
|
+
|
44
|
+
t_begin "send a batch of abortive HTTP/1.1 requests in parallel" && {
|
45
|
+
for i in $a $b $c $slow_a $slow_b
|
46
|
+
do
|
47
|
+
rm -f $i
|
48
|
+
(
|
49
|
+
curl -sSf --max-time 5 --limit-rate 1K \
|
50
|
+
http://$listen/random_blob >/dev/null || echo ok > $i
|
51
|
+
) &
|
52
|
+
done
|
53
|
+
wait
|
54
|
+
}
|
55
|
+
|
56
|
+
t_begin "all requests timed out" && {
|
57
|
+
for i in $a $b $c $slow_a $slow_b
|
58
|
+
do
|
59
|
+
test x$(cat $i) = xok
|
60
|
+
done
|
61
|
+
}
|
62
|
+
|
63
|
+
s='$NF ~ /worker_connections=[0-9]+/{gsub(/[^0-9]/,"",$3); print $3; exit}'
|
64
|
+
t_begin "check proc to ensure file is closed properly (Linux only)" && {
|
65
|
+
worker_pid=$(awk "$s" < $r_err)
|
66
|
+
test -n "$worker_pid"
|
67
|
+
if test -d /proc/$worker_pid/fd
|
68
|
+
then
|
69
|
+
if ls -l /proc/$worker_pid/fd | grep random_blob
|
70
|
+
then
|
71
|
+
t_info "random_blob file is open ($model)"
|
72
|
+
fi
|
73
|
+
else
|
74
|
+
t_info "/proc/$worker_pid/fd not found"
|
75
|
+
fi
|
76
|
+
}
|
77
|
+
|
78
|
+
t_begin "send a bunch of HTTP/1.1 requests in parallel" && {
|
79
|
+
(
|
80
|
+
curl -sSf --limit-rate 1M http://$listen/random_blob | \
|
81
|
+
rsha1 > $slow_a
|
82
|
+
) &
|
83
|
+
(
|
84
|
+
curl -sSf --limit-rate 750K http://$listen/random_blob | \
|
85
|
+
rsha1 > $slow_b
|
86
|
+
) &
|
87
|
+
for i in $a $b $c
|
88
|
+
do
|
89
|
+
(
|
90
|
+
curl -sSf http://$listen/random_blob | rsha1 > $i
|
91
|
+
) &
|
92
|
+
done
|
93
|
+
wait
|
94
|
+
for i in $a $b $c $slow_a $slow_b
|
95
|
+
do
|
96
|
+
test x$(cat $i) = x$random_blob_sha1
|
97
|
+
done
|
98
|
+
}
|
99
|
+
|
100
|
+
# this was a problem during development
|
101
|
+
t_begin "HTTP/1.0 test" && {
|
102
|
+
sha1=$( (curl -0 -sSf http://$listen/random_blob &&
|
103
|
+
echo ok >$ok) | rsha1)
|
104
|
+
test $sha1 = $random_blob_sha1
|
105
|
+
test xok = x$(cat $ok)
|
106
|
+
}
|
107
|
+
|
108
|
+
t_begin "HTTP/0.9 test" && {
|
109
|
+
(
|
110
|
+
printf 'GET /random_blob\r\n'
|
111
|
+
rsha1 < $fifo > $tmp &
|
112
|
+
wait
|
113
|
+
echo ok > $ok
|
114
|
+
) | socat - TCP:$listen > $fifo
|
115
|
+
test $(cat $tmp) = $random_blob_sha1
|
116
|
+
test xok = x$(cat $ok)
|
117
|
+
}
|
118
|
+
|
119
|
+
t_begin "check proc to ensure file is closed properly (Linux only)" && {
|
120
|
+
worker_pid=$(awk "$s" < $r_err)
|
121
|
+
test -n "$worker_pid"
|
122
|
+
if test -d /proc/$worker_pid/fd
|
123
|
+
then
|
124
|
+
if ls -l /proc/$worker_pid/fd | grep random_blob
|
125
|
+
then
|
126
|
+
t_info "random_blob file is open ($model)"
|
127
|
+
fi
|
128
|
+
else
|
129
|
+
t_info "/proc/$worker_pid/fd not found"
|
130
|
+
fi
|
131
|
+
}
|
132
|
+
|
133
|
+
t_begin "shutdown server" && {
|
134
|
+
kill -QUIT $rainbows_pid
|
135
|
+
}
|
136
|
+
|
137
|
+
dbgcat r_err
|
138
|
+
|
139
|
+
t_begin "check stderr" && check_stderr
|
140
|
+
|
141
|
+
t_done
|
data/t/t0300-async_sinatra.sh
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
case $model in
|
4
|
+
EventMachine) ;;
|
5
|
+
*)
|
6
|
+
t_info "skipping $T since it's not compatible with $model"
|
7
|
+
exit 0
|
8
|
+
;;
|
9
|
+
esac
|
10
|
+
require_check cramp Cramp::VERSION
|
11
|
+
|
12
|
+
t_plan 4 "WebSocket monkey patch validity test for Cramp"
|
13
|
+
|
14
|
+
CONFIG_RU=cramp/rainsocket.ru
|
15
|
+
|
16
|
+
t_begin "setup and start" && {
|
17
|
+
rainbows_setup
|
18
|
+
rtmpfiles curl_err
|
19
|
+
|
20
|
+
# Like the rest of the EM/async stuff, it's not Rack::Lint compatible
|
21
|
+
rainbows -E deployment -D $CONFIG_RU -c $unicorn_config
|
22
|
+
rainbows_wait_start
|
23
|
+
}
|
24
|
+
|
25
|
+
t_begin "wait for server to say hello to us" && {
|
26
|
+
ok=$((curl --no-buffer -sS http://$listen/ || :) | \
|
27
|
+
awk '/Hello from the Server/ { print "ok"; exit 0 }')
|
28
|
+
|
29
|
+
test x"$ok" = xok
|
30
|
+
}
|
31
|
+
|
32
|
+
t_begin "termination signal sent" && {
|
33
|
+
kill $rainbows_pid
|
34
|
+
}
|
35
|
+
|
36
|
+
t_begin "no errors in stderr" && check_stderr
|
37
|
+
|
38
|
+
t_done
|