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.
- 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
|