rainbows 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +12 -6
- data/README +3 -2
- data/Rakefile +3 -3
- data/TODO +2 -9
- data/lib/rainbows.rb +1 -0
- data/lib/rainbows/app_pool.rb +10 -6
- data/lib/rainbows/base.rb +1 -1
- data/lib/rainbows/const.rb +1 -1
- data/lib/rainbows/ev_core.rb +88 -0
- data/lib/rainbows/event_machine.rb +218 -0
- data/lib/rainbows/http_server.rb +4 -1
- data/lib/rainbows/rev.rb +21 -89
- data/lib/rainbows/revactor.rb +4 -10
- data/local.mk.sample +13 -7
- data/rainbows.gemspec +17 -2
- data/t/.gitignore +1 -0
- data/t/GNUmakefile +63 -40
- data/t/README +6 -2
- data/t/async_sinatra.ru +13 -0
- data/t/bin/unused_listen +1 -1
- data/t/large-file-response.ru +1 -0
- data/t/my-tap-lib.sh +200 -0
- data/t/simple-http_Base.ru +3 -0
- data/t/simple-http_EventMachine.ru +9 -0
- data/t/simple-http_Rev.ru +9 -0
- data/t/simple-http_Revactor.ru +10 -0
- data/t/simple-http_ThreadPool.ru +10 -0
- data/t/simple-http_ThreadSpawn.ru +10 -0
- data/t/t0000-simple-http.sh +142 -0
- data/t/t0001-unix-http.sh +103 -0
- data/t/t0002-graceful.sh +32 -0
- data/t/t0002-parser-error.sh +31 -0
- data/t/t0003-reopen-logs.sh +97 -0
- data/t/t0005-large-file-response.sh +83 -0
- data/t/t0100-rack-input-hammer.sh +45 -0
- data/t/t0101-rack-input-trailer.sh +68 -0
- data/t/t0200-async-response.sh +66 -0
- data/t/t0201-async-response-no-autochunk.sh +3 -0
- data/t/t0300-async_sinatra.sh +65 -0
- data/t/t9000-rack-app-pool.sh +45 -33
- data/t/test-lib.sh +67 -56
- metadata +26 -56
- data/t/lib-async-response-no-autochunk.sh +0 -6
- data/t/lib-async-response.sh +0 -45
- data/t/lib-graceful.sh +0 -40
- data/t/lib-input-trailer.sh +0 -63
- data/t/lib-large-file-response.sh +0 -45
- data/t/lib-parser-error.sh +0 -29
- data/t/lib-rack-input-hammer.sh +0 -38
- data/t/lib-reopen-logs.sh +0 -60
- data/t/lib-simple-http.sh +0 -92
- data/t/t0000-basic.sh +0 -2
- data/t/t1000-thread-pool-basic.sh +0 -2
- data/t/t1002-thread-pool-graceful.sh +0 -2
- data/t/t1003-thread-pool-reopen-logs.sh +0 -2
- data/t/t1004-thread-pool-async-response.sh +0 -45
- data/t/t1005-thread-pool-large-file-response.sh +0 -45
- data/t/t1006-thread-pool-async-response-no-autochunk.sh +0 -6
- data/t/t1100-thread-pool-rack-input.sh +0 -2
- data/t/t1101-thread-pool-input-trailer.sh +0 -2
- data/t/t2000-thread-spawn-basic.sh +0 -2
- data/t/t2002-thread-spawn-graceful.sh +0 -2
- data/t/t2003-thread-spawn-reopen-logs.sh +0 -2
- data/t/t2004-thread-spawn-async-response.sh +0 -45
- data/t/t2005-thread-spawn-large-file-response.sh +0 -45
- data/t/t2006-thread-spawn-async-response-no-autochunk.sh +0 -6
- data/t/t2100-thread-spawn-rack-input.sh +0 -2
- data/t/t2101-thread-spawn-input-trailer.sh +0 -2
- data/t/t3000-revactor-basic.sh +0 -2
- data/t/t3002-revactor-graceful.sh +0 -2
- data/t/t3003-revactor-reopen-logs.sh +0 -2
- data/t/t3004-revactor-async-response.sh +0 -45
- data/t/t3005-revactor-large-file-response.sh +0 -2
- data/t/t3006-revactor-async-response-no-autochunk.sh +0 -6
- data/t/t3100-revactor-rack-input.sh +0 -2
- data/t/t3101-revactor-rack-input-trailer.sh +0 -2
- data/t/t4000-rev-basic.sh +0 -2
- data/t/t4002-rev-graceful.sh +0 -2
- data/t/t4003-rev-parser-error.sh +0 -2
- data/t/t4003-rev-reopen-logs.sh +0 -2
- data/t/t4004-rev-async-response.sh +0 -45
- data/t/t4005-rev-large-file-response.sh +0 -2
- data/t/t4006-rev-async-response-no-autochunk.sh +0 -6
- data/t/t4100-rev-rack-input.sh +0 -2
- data/t/t4101-rev-rack-input-trailer.sh +0 -2
data/lib/rainbows/http_server.rb
CHANGED
@@ -33,7 +33,10 @@ module Rainbows
|
|
33
33
|
extend(mod)
|
34
34
|
Const::RACK_DEFAULTS['rainbows.model'] = @use = model
|
35
35
|
Const::RACK_DEFAULTS['rack.multithread'] = !!(/Thread/ =~ model.to_s)
|
36
|
-
|
36
|
+
case model
|
37
|
+
when :Rev, :EventMachine
|
38
|
+
Const::RACK_DEFAULTS['rainbows.autochunk'] = true
|
39
|
+
end
|
37
40
|
end
|
38
41
|
|
39
42
|
def worker_connections(*args)
|
data/lib/rainbows/rev.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
require 'rev'
|
3
|
-
|
4
|
-
|
5
|
-
# ref: http://rubyforge.org/pipermail/revactor-talk/2009-October/000034.html
|
6
|
-
defined?(Rev::Buffer) or Rev::Buffer = IO::Buffer
|
3
|
+
Rev::VERSION >= '0.3.0' or abort 'rev >= 0.3.0 is required'
|
4
|
+
require 'rainbows/ev_core'
|
7
5
|
|
8
6
|
module Rainbows
|
9
7
|
|
@@ -30,46 +28,22 @@ module Rainbows
|
|
30
28
|
include Base
|
31
29
|
|
32
30
|
class Client < ::Rev::IO
|
33
|
-
include
|
34
|
-
include Rainbows::Const
|
31
|
+
include Rainbows::EvCore
|
35
32
|
G = Rainbows::G
|
36
33
|
|
37
|
-
# queued, optional response bodies, it should only be unpollable "fast"
|
38
|
-
# devices where read(2) is uninterruptable. Unfortunately, NFS and ilk
|
39
|
-
# are also part of this. We'll also stick DeferredResponse bodies in
|
40
|
-
# here to prevent connections from being closed on us.
|
41
|
-
attr_reader :deferred_bodies
|
42
|
-
|
43
34
|
def initialize(io)
|
44
35
|
G.cur += 1
|
45
36
|
super(io)
|
46
|
-
|
47
|
-
@env = {}
|
48
|
-
@hp = HttpParser.new
|
49
|
-
@state = :headers # [ :body [ :trailers ] ] :app_call :close
|
50
|
-
@buf = ""
|
51
|
-
@deferred_bodies = [] # for (fast) regular files only
|
52
|
-
end
|
53
|
-
|
54
|
-
# graceful exit, like SIGQUIT
|
55
|
-
def quit
|
56
|
-
@deferred_bodies.clear
|
57
|
-
@state = :close
|
37
|
+
post_init
|
58
38
|
end
|
59
39
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
else
|
68
|
-
G.logger.error "Read error: #{e.inspect}"
|
69
|
-
G.logger.error e.backtrace.join("\n")
|
70
|
-
ERROR_500_RESPONSE
|
71
|
-
end
|
72
|
-
write(msg)
|
40
|
+
# queued, optional response bodies, it should only be unpollable "fast"
|
41
|
+
# devices where read(2) is uninterruptable. Unfortunately, NFS and ilk
|
42
|
+
# are also part of this. We'll also stick DeferredResponse bodies in
|
43
|
+
# here to prevent connections from being closed on us.
|
44
|
+
def defer_body(io)
|
45
|
+
@deferred_bodies << io
|
46
|
+
on_write_complete unless @hp.headers? # triggers a write
|
73
47
|
end
|
74
48
|
|
75
49
|
def app_call
|
@@ -89,7 +63,7 @@ module Rainbows
|
|
89
63
|
# keepalive requests are always body-less, so @input is unchanged
|
90
64
|
@hp.headers(@env, @buf) and next
|
91
65
|
else
|
92
|
-
|
66
|
+
quit
|
93
67
|
end
|
94
68
|
return
|
95
69
|
end while true
|
@@ -104,6 +78,7 @@ module Rainbows
|
|
104
78
|
rescue EOFError # expected at file EOF
|
105
79
|
@deferred_bodies.shift
|
106
80
|
body.close
|
81
|
+
close if :close == @state && @deferred_bodies.empty?
|
107
82
|
end
|
108
83
|
rescue Object => e
|
109
84
|
handle_error(e)
|
@@ -116,53 +91,6 @@ module Rainbows
|
|
116
91
|
def on_close
|
117
92
|
G.cur -= 1
|
118
93
|
end
|
119
|
-
|
120
|
-
def tmpio
|
121
|
-
io = Util.tmpio
|
122
|
-
def io.size
|
123
|
-
# already sync=true at creation, so no need to flush before stat
|
124
|
-
stat.size
|
125
|
-
end
|
126
|
-
io
|
127
|
-
end
|
128
|
-
|
129
|
-
# TeeInput doesn't map too well to this right now...
|
130
|
-
def on_read(data)
|
131
|
-
case @state
|
132
|
-
when :headers
|
133
|
-
@hp.headers(@env, @buf << data) or return
|
134
|
-
@state = :body
|
135
|
-
len = @hp.content_length
|
136
|
-
if len == 0
|
137
|
-
@input = HttpRequest::NULL_IO
|
138
|
-
app_call # common case
|
139
|
-
else # nil or len > 0
|
140
|
-
# since we don't do streaming input, we have no choice but
|
141
|
-
# to take over 100-continue handling from the Rack application
|
142
|
-
if @env[HTTP_EXPECT] =~ /\A100-continue\z/i
|
143
|
-
write(EXPECT_100_RESPONSE)
|
144
|
-
@env.delete(HTTP_EXPECT)
|
145
|
-
end
|
146
|
-
@input = len && len <= MAX_BODY ? StringIO.new("") : tmpio
|
147
|
-
@hp.filter_body(@buf2 = @buf.dup, @buf)
|
148
|
-
@input << @buf2
|
149
|
-
on_read("")
|
150
|
-
end
|
151
|
-
when :body
|
152
|
-
if @hp.body_eof?
|
153
|
-
@state = :trailers
|
154
|
-
on_read(data)
|
155
|
-
elsif data.size > 0
|
156
|
-
@hp.filter_body(@buf2, @buf << data)
|
157
|
-
@input << @buf2
|
158
|
-
on_read("")
|
159
|
-
end
|
160
|
-
when :trailers
|
161
|
-
@hp.trailers(@env, @buf << data) and app_call
|
162
|
-
end
|
163
|
-
rescue Object => e
|
164
|
-
handle_error(e)
|
165
|
-
end
|
166
94
|
end
|
167
95
|
|
168
96
|
class Server < ::Rev::IO
|
@@ -172,7 +100,7 @@ module Rainbows
|
|
172
100
|
return if G.cur >= G.max
|
173
101
|
begin
|
174
102
|
Client.new(@_io.accept_nonblock).attach(::Rev::Loop.default)
|
175
|
-
rescue Errno::EAGAIN, Errno::
|
103
|
+
rescue Errno::EAGAIN, Errno::ECONNABORTED
|
176
104
|
end
|
177
105
|
end
|
178
106
|
|
@@ -191,7 +119,7 @@ module Rainbows
|
|
191
119
|
# here since we can't get here without checking to_path first
|
192
120
|
io = body.to_io if body.respond_to?(:to_io)
|
193
121
|
io ||= ::IO.new($1.to_i) if body.to_path =~ %r{\A/dev/fd/(\d+)\z}
|
194
|
-
io ||= File.open(
|
122
|
+
io ||= File.open(body.to_path, 'rb')
|
195
123
|
st = io.stat
|
196
124
|
|
197
125
|
if st.socket? || st.pipe?
|
@@ -199,7 +127,11 @@ module Rainbows
|
|
199
127
|
do_chunk = false if headers.delete('X-Rainbows-Autochunk') == 'no'
|
200
128
|
# too tricky to support keepalive/pipelining when a response can
|
201
129
|
# take an indeterminate amount of time here.
|
202
|
-
out
|
130
|
+
if out.nil?
|
131
|
+
do_chunk = false
|
132
|
+
else
|
133
|
+
out[0] = CONN_CLOSE
|
134
|
+
end
|
203
135
|
|
204
136
|
io = new(io, client, do_chunk, body).attach(::Rev::Loop.default)
|
205
137
|
elsif st.file?
|
@@ -208,7 +140,7 @@ module Rainbows
|
|
208
140
|
else # char/block device, directory, whatever... nobody cares
|
209
141
|
return response
|
210
142
|
end
|
211
|
-
client.
|
143
|
+
client.defer_body(io)
|
212
144
|
[ response.first, headers.to_hash, [] ]
|
213
145
|
end
|
214
146
|
|
data/lib/rainbows/revactor.rb
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
require 'revactor'
|
3
|
-
|
4
|
-
# workaround revactor 0.1.4 still using the old Rev::Buffer
|
5
|
-
# ref: http://rubyforge.org/pipermail/revactor-talk/2009-October/000034.html
|
6
|
-
defined?(Rev::Buffer) or Rev::Buffer = IO::Buffer
|
3
|
+
Revactor::VERSION >= '0.1.5' or abort 'revactor 0.1.5 is required'
|
7
4
|
|
8
5
|
module Rainbows
|
9
6
|
|
@@ -137,16 +134,13 @@ module Rainbows
|
|
137
134
|
|
138
135
|
def revactorize_listeners!
|
139
136
|
LISTENERS.map! do |s|
|
140
|
-
|
137
|
+
case s
|
138
|
+
when TCPServer
|
141
139
|
::Revactor::TCP.listen(s, nil)
|
142
|
-
|
140
|
+
when UNIXServer
|
143
141
|
::Revactor::UNIX.listen(s)
|
144
|
-
else
|
145
|
-
logger.error "your version of Revactor can't handle #{s.inspect}"
|
146
|
-
nil
|
147
142
|
end
|
148
143
|
end
|
149
|
-
LISTENERS.compact!
|
150
144
|
end
|
151
145
|
|
152
146
|
end
|
data/local.mk.sample
CHANGED
@@ -5,18 +5,24 @@
|
|
5
5
|
# This is depends on a bunch of GNU-isms from bash, sed, touch.
|
6
6
|
|
7
7
|
DLEXT := so
|
8
|
-
gems :=
|
8
|
+
gems := rack-1.0.1
|
9
|
+
# gems += unicorn-0.93.3 # installed via setup.rb
|
10
|
+
gems += rev-0.3.1 iobuffer-0.1.1
|
11
|
+
gems += eventmachine-0.12.10
|
12
|
+
gems += async_sinatra-0.1.5 sinatra-0.9.4
|
9
13
|
|
10
14
|
# Avoid loading rubygems to speed up tests because gmake is
|
11
15
|
# fork+exec heavy with Ruby.
|
16
|
+
prefix = $(HOME)
|
12
17
|
ifeq ($(r19),)
|
13
|
-
|
14
|
-
gem_paths := $(addprefix $(
|
18
|
+
RUBY := $(prefix)/bin/ruby
|
19
|
+
gem_paths := $(addprefix $(prefix)/lib/ruby/gems/1.8/gems/,$(gems))
|
15
20
|
else
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
prefix := $(prefix)/ruby-1.9
|
22
|
+
export PATH := $(prefix)/bin:$(PATH)
|
23
|
+
RUBY := $(prefix)/bin/ruby --disable-gems
|
24
|
+
gems += case-0.5 revactor-0.1.5
|
25
|
+
gem_paths := $(addprefix $(prefix)/lib/ruby/gems/1.9.1/gems/,$(gems))
|
20
26
|
endif
|
21
27
|
|
22
28
|
ifdef gem_paths
|
data/rainbows.gemspec
CHANGED
@@ -40,8 +40,23 @@ Gem::Specification.new do |s|
|
|
40
40
|
|
41
41
|
s.test_files = test_files
|
42
42
|
|
43
|
-
|
44
|
-
s.add_dependency(%q<unicorn>, ["~> 0.93.
|
43
|
+
# we need Unicorn for the HTTP parser and process management
|
44
|
+
s.add_dependency(%q<unicorn>, ["~> 0.93.4"])
|
45
|
+
|
46
|
+
# Unicorn already depends on Rack
|
47
|
+
# s.add_dependency(%q<rack>)
|
48
|
+
|
49
|
+
# optional runtime dependencies depending on configuration
|
50
|
+
# see local.mk.sample for the exact versions we've tested with
|
51
|
+
#
|
52
|
+
# Revactor >= 0.1.5 includes UNIX domain socket support
|
53
|
+
# s.add_dependency(%q<revactor>, [">= 0.1.5"])
|
54
|
+
#
|
55
|
+
# Revactor depends on Rev, too, 0.3.0 got the ability to attach IOs
|
56
|
+
# s.add_dependency(%q<rev>, [">= 0.3.0"])
|
57
|
+
#
|
58
|
+
# We use the new EM::attach/watch API in 0.12.10
|
59
|
+
# s.add_dependency(%q<eventmachine>, ["~> 0.12.10"])
|
45
60
|
|
46
61
|
# s.licenses = %w(GPLv2 Ruby) # accessor not compatible with older Rubygems
|
47
62
|
end
|
data/t/.gitignore
CHANGED
data/t/GNUmakefile
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
all::
|
4
4
|
|
5
|
-
|
5
|
+
pid := $(shell echo $$PPID)
|
6
|
+
|
7
|
+
RUBY = $(ruby)
|
6
8
|
rainbows_lib := $(shell cd ../lib && pwd)
|
7
9
|
-include ../local.mk
|
8
10
|
ifeq ($(RUBY_VERSION),)
|
9
|
-
RUBY_VERSION := $(shell $(
|
11
|
+
RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
10
12
|
endif
|
11
13
|
|
12
14
|
ifeq ($(RUBYLIB),)
|
@@ -16,60 +18,81 @@ else
|
|
16
18
|
endif
|
17
19
|
export RUBYLIB RUBY_VERSION
|
18
20
|
|
21
|
+
models := ThreadPool ThreadSpawn Rev EventMachine
|
22
|
+
ifeq ($(RUBY_VERSION),1.9.1) # 1.9.2-preview1 was broken
|
23
|
+
models += Revactor
|
24
|
+
endif
|
25
|
+
all_models := $(models) Base
|
26
|
+
|
19
27
|
T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
|
20
28
|
|
29
|
+
MODEL_T := $(foreach m,$(all_models),$(addprefix $(m).,$(T)))
|
30
|
+
$(T): MODELS = $(models)
|
31
|
+
|
32
|
+
# some tests can be run with all models
|
33
|
+
t0000-simple-http.sh: MODELS = $(all_models)
|
34
|
+
t0001-unix-http.sh: MODELS = $(all_models)
|
35
|
+
t0002-graceful.sh: MODELS = $(all_models)
|
36
|
+
t0002-parser-error.sh: MODELS = $(all_models)
|
37
|
+
t0003-reopen-logs.sh: MODELS = $(all_models)
|
38
|
+
|
39
|
+
# this test is not compatible with non-Thread models yet
|
40
|
+
t9000-rack-app-pool.sh: MODELS = ThreadPool ThreadSpawn
|
41
|
+
|
42
|
+
# recursively run per-model tests
|
43
|
+
# haven't figured out a good way to make make non-recursive here, yet...
|
44
|
+
$(T):
|
45
|
+
$(MAKE) $(foreach m,$(MODELS),$(addprefix $(m).,$@))
|
46
|
+
|
47
|
+
$(all_models):
|
48
|
+
$(MAKE) $(filter $@.%,$(MODEL_T))
|
49
|
+
|
21
50
|
all:: $(T)
|
22
51
|
|
23
52
|
# can't rely on "set -o pipefail" since we don't require bash or ksh93 :<
|
24
53
|
t_pfx = trash/$@-$(RUBY_VERSION)
|
25
|
-
|
26
|
-
t_log = $(t_pfx).log
|
54
|
+
TEST_OPTS =
|
27
55
|
# TRACER = strace -f -o $(t_pfx).strace -s 100000
|
28
56
|
# TRACER = /usr/bin/time -o $(t_pfx).time
|
29
|
-
|
30
|
-
|
31
|
-
# prefix stdout messages with ':', and stderr messages with '!'
|
32
|
-
t_wrap = ( ( ( echo 42 > $(t_code); \
|
33
|
-
$(t_run); \
|
34
|
-
echo $$? > $(t_code) ) \
|
35
|
-
| sed 's/^/$(pfx):/' 1>&3 ) 2>&1 \
|
36
|
-
| sed 's/^/$(pfx)!/' 1>&2 ) 3>&1
|
37
|
-
|
38
|
-
ifndef V
|
39
|
-
quiet_pre = @echo '* $@';
|
40
|
-
quiet_post = > $(t_log) 2>&1; exit $$(cat $(t_code))
|
41
|
-
pfx =
|
42
|
-
else
|
57
|
+
|
58
|
+
ifdef V
|
43
59
|
ifeq ($(V),2)
|
44
|
-
|
60
|
+
TEST_OPTS += --trace
|
61
|
+
else
|
62
|
+
TEST_OPTS += --verbose
|
45
63
|
endif
|
46
|
-
quiet_pre = @echo '* $@';
|
47
|
-
quiet_post = 2>&1 | ./bin/utee $(t_log); exit $$(cat $(t_code))
|
48
|
-
pfx = $@
|
49
64
|
endif
|
50
65
|
|
51
|
-
|
52
|
-
|
53
|
-
test-bin-$(RUBY_VERSION)/rainbows: ruby_bin = $(shell which $(ruby))
|
66
|
+
test-bin-$(RUBY_VERSION)/rainbows: ruby_bin = $(shell which $(RUBY))
|
54
67
|
test-bin-$(RUBY_VERSION)/rainbows: ../bin/rainbows
|
55
68
|
mkdir -p $(@D)
|
56
|
-
install -m 755 $^
|
57
|
-
$(
|
58
|
-
|
59
|
-
$(RM) $@+
|
69
|
+
install -m 755 $^ $@.$(pid)
|
70
|
+
$(RUBY) -i -p -e '$$_.gsub!(%r{^#!.*$$},"#!$(ruby_bin)")' $@.$(pid)
|
71
|
+
mv $@.$(pid) $@
|
60
72
|
|
61
|
-
req_random_blob := $(wildcard t?1??-*.sh)
|
62
73
|
random_blob:
|
63
|
-
dd if=/dev/urandom bs=1M count=
|
64
|
-
mv
|
65
|
-
|
66
|
-
$(
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
$(
|
71
|
-
$(
|
72
|
-
$(
|
74
|
+
dd if=/dev/urandom bs=1M count=30 of=$@.$(pid)
|
75
|
+
mv $@.$(pid) $@
|
76
|
+
|
77
|
+
$(T): random_blob
|
78
|
+
|
79
|
+
dependencies := socat curl
|
80
|
+
deps := $(addprefix .dep+,$(dependencies))
|
81
|
+
$(deps): dep_bin = $(lastword $(subst +, ,$@))
|
82
|
+
$(deps):
|
83
|
+
@which $(dep_bin) > $@.$(pid) 2>/dev/null || :
|
84
|
+
@test -s $@.$(pid) || \
|
85
|
+
{ echo >&2 "E `$(dep_bin)' not found in PATH=$(PATH)"; exit 1; }
|
86
|
+
@mv $@.$(pid) $@
|
87
|
+
dep: $(deps)
|
88
|
+
|
89
|
+
$(MODEL_T): export model = $(firstword $(subst ., ,$@))
|
90
|
+
$(MODEL_T): script = $(subst $(model).,,$@)
|
91
|
+
$(MODEL_T): trash/.gitignore
|
92
|
+
$(MODEL_T): export RUBY := $(RUBY)
|
93
|
+
$(MODEL_T): export PATH := $(CURDIR)/test-bin-$(RUBY_VERSION):$(PATH)
|
94
|
+
$(MODEL_T): test-bin-$(RUBY_VERSION)/rainbows dep
|
95
|
+
$(TRACER) $(SHELL) $(SH_TEST_OPTS) $(script) $(TEST_OPTS)
|
73
96
|
|
74
97
|
trash/.gitignore:
|
75
98
|
mkdir -p $(@D)
|
data/t/README
CHANGED
@@ -28,9 +28,13 @@ To run the entire test suite with 8 tests running at once:
|
|
28
28
|
|
29
29
|
make -j8
|
30
30
|
|
31
|
-
To run one individual test:
|
31
|
+
To run one individual test for all concurrency models:
|
32
32
|
|
33
|
-
make t0000-
|
33
|
+
make t0000-simple-http.sh
|
34
|
+
|
35
|
+
To run one individual test for one concurrency model:
|
36
|
+
|
37
|
+
make Revactor.t0000-simple-http.sh
|
34
38
|
|
35
39
|
You may also increase verbosity by setting the "V" variable for
|
36
40
|
GNU make. To disable trapping of stdout/stderr:
|
data/t/async_sinatra.ru
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# See http://github.com/raggi/async_sinatra
|
2
|
+
# gem install async_sinatra -v0.1.5
|
3
|
+
require 'sinatra/async'
|
4
|
+
|
5
|
+
class AsyncTest < Sinatra::Base
|
6
|
+
register Sinatra::Async
|
7
|
+
|
8
|
+
aget '/:n' do |n|
|
9
|
+
EM.add_timer(n.to_i) { body { "delayed for #{n} seconds\n" } }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
run AsyncTest.new
|