zbatery 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.manifest +4 -0
- data/ChangeLog +32 -1
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +40 -8
- data/NEWS +5 -0
- data/Rakefile +30 -3
- data/lib/zbatery.rb +36 -32
- data/t/.gitignore +3 -1
- data/t/GNUmakefile +37 -23
- data/t/my-tap-lib.sh +3 -2
- data/t/sha1-random-size.ru +19 -0
- data/t/t0005-large-file-response.sh +16 -11
- data/t/t0020-large-sendfile-response.sh +141 -0
- data/t/t0103-rack-input-limit.sh +61 -0
- data/t/test-lib.sh +37 -12
- data/t/test_isolate.rb +43 -0
- data/zbatery.gemspec +4 -3
- metadata +53 -11
data/.manifest
CHANGED
@@ -27,8 +27,12 @@ t/bin/unused_listen
|
|
27
27
|
t/bin/utee
|
28
28
|
t/large-file-response.ru
|
29
29
|
t/my-tap-lib.sh
|
30
|
+
t/sha1-random-size.ru
|
30
31
|
t/sleep.ru
|
31
32
|
t/t0003-reopen-logs.sh
|
32
33
|
t/t0005-large-file-response.sh
|
34
|
+
t/t0020-large-sendfile-response.sh
|
35
|
+
t/t0103-rack-input-limit.sh
|
33
36
|
t/test-lib.sh
|
37
|
+
t/test_isolate.rb
|
34
38
|
zbatery.gemspec
|
data/ChangeLog
CHANGED
@@ -1,5 +1,36 @@
|
|
1
|
-
ChangeLog from git://git.bogomips.org/zbatery.git (v0.1.1..v0.
|
1
|
+
ChangeLog from git://git.bogomips.org/zbatery.git (v0.1.1..v0.3.0)
|
2
2
|
|
3
|
+
commit d4f095ed8ed0da4f190280eb957c14b3f5e9a2e9
|
4
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
5
|
+
Date: Sat Jul 10 09:56:27 2010 +0000
|
6
|
+
|
7
|
+
Zbatery v0.3.0 - for newer Rainbows!
|
8
|
+
|
9
|
+
Rainbows! v0.95.0 is more awesome than v0.94.0, so we've updated
|
10
|
+
ourselves to use it and be more awesome as well!
|
11
|
+
|
12
|
+
commit 00f570d6c3363794ee4489fae17b05555b78b2cf
|
13
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
14
|
+
Date: Sat Jul 10 09:55:20 2010 +0000
|
15
|
+
|
16
|
+
gemspec: small doc updates
|
17
|
+
|
18
|
+
commit 59d3b3f6318a85e4d68592e1f7b992dd54832aa0
|
19
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
20
|
+
Date: Sat Jul 10 09:53:52 2010 +0000
|
21
|
+
|
22
|
+
add additional tests for newish Rainbows! features
|
23
|
+
|
24
|
+
commit bd6b2263869c271113577b88d526c7c2a6f1455d
|
25
|
+
Author: Eric Wong <normalperson@yhbt.net>
|
26
|
+
Date: Sat Jul 10 02:41:46 2010 -0700
|
27
|
+
|
28
|
+
updates for Rainbows! 0.95.0
|
29
|
+
|
30
|
+
Rainbows! 0.95.0 made some incompatible changes, so update
|
31
|
+
everything. Unfortunately we have to avoid subclassing here.
|
32
|
+
Tests use isolate now.
|
33
|
+
|
3
34
|
commit 5764336aa3785af8a08be7ec7b40846ec139eb6c
|
4
35
|
Author: Eric Wong <normalperson@yhbt.net>
|
5
36
|
Date: Mon Apr 19 14:14:46 2010 -0700
|
data/GIT-VERSION-FILE
CHANGED
@@ -1 +1 @@
|
|
1
|
-
GIT_VERSION = 0.
|
1
|
+
GIT_VERSION = 0.3.0
|
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# use GNU Make to run tests in parallel, and without depending on RubyGems
|
2
2
|
all::
|
3
|
+
MRI = ruby
|
3
4
|
RUBY = ruby
|
4
5
|
RAKE = rake
|
6
|
+
RSYNC = rsync
|
5
7
|
GIT_URL = git://git.bogomips.org/zbatery.git
|
6
8
|
|
7
9
|
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
@@ -14,9 +16,11 @@ endif
|
|
14
16
|
ifeq ($(RUBY_VERSION),)
|
15
17
|
RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
16
18
|
endif
|
19
|
+
RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
|
17
20
|
|
18
21
|
base_bins := zbatery
|
19
22
|
bins := $(addprefix bin/, $(base_bins))
|
23
|
+
man1_rdoc := $(addsuffix _1, $(base_bins))
|
20
24
|
man1_bins := $(addsuffix .1, $(base_bins))
|
21
25
|
man1_paths := $(addprefix man/man1/, $(man1_bins))
|
22
26
|
|
@@ -76,26 +80,52 @@ cgit_atom := http://git.bogomips.org/cgit/zbatery.git/atom/?h=master
|
|
76
80
|
atom = <link rel="alternate" title="Atom feed" href="$(1)" \
|
77
81
|
type="application/atom+xml"/>
|
78
82
|
|
79
|
-
# using rdoc 2.
|
83
|
+
# using rdoc 2.5.x+
|
80
84
|
doc: .document NEWS ChangeLog
|
81
|
-
for i in $(
|
82
|
-
|
85
|
+
for i in $(man1_rdoc); do echo > $$i; done
|
86
|
+
find bin lib -type f -name '*.rbc' -exec rm -f '{}' ';'
|
87
|
+
rdoc -t "$(shell sed -ne '1s/^= //p' README)"
|
83
88
|
install -m644 COPYING doc/COPYING
|
84
89
|
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
85
90
|
$(MAKE) -C Documentation install-html install-man
|
86
91
|
install -m644 $(man1_paths) doc/
|
87
92
|
cd doc && for i in $(base_bins); do \
|
93
|
+
$(RM) 1.html $${i}.1.html; \
|
88
94
|
sed -e '/"documentation">/r man1/'$$i'.1.html' \
|
89
|
-
< $${i}_1.html > tmp && mv tmp $${i}_1.html;
|
90
|
-
|
95
|
+
< $${i}_1.html > tmp && mv tmp $${i}_1.html; \
|
96
|
+
ln $${i}_1.html $${i}.1.html; \
|
97
|
+
done
|
98
|
+
$(MRI) -i -p -e \
|
91
99
|
'$$_.gsub!("</title>",%q{\&$(call atom,$(cgit_atom))})' \
|
92
100
|
doc/ChangeLog.html
|
93
|
-
$(
|
101
|
+
$(MRI) -i -p -e \
|
94
102
|
'$$_.gsub!("</title>",%q{\&$(call atom,$(news_atom))})' \
|
95
103
|
doc/NEWS.html doc/README.html
|
96
104
|
$(RAKE) -s news_atom > doc/NEWS.atom.xml
|
97
105
|
cd doc && ln README.html tmp && mv tmp index.html
|
98
|
-
$(RM) $(
|
106
|
+
$(RM) $(man1_rdoc)
|
107
|
+
|
108
|
+
# publishes docs to http://zbatery.bogomip.org/
|
109
|
+
publish_doc:
|
110
|
+
-git set-file-times
|
111
|
+
$(RM) -r doc ChangeLog NEWS
|
112
|
+
$(MAKE) doc LOG_VERSION=$(shell git tag -l | tail -1)
|
113
|
+
awk 'BEGIN{RS="=== ";ORS=""}NR==2{sub(/\n$$/,"");print RS""$$0 }' \
|
114
|
+
< NEWS > doc/LATEST
|
115
|
+
find doc/images doc/js -type f | \
|
116
|
+
TZ=UTC xargs touch -d '1970-01-01 00:00:01' doc/rdoc.css
|
117
|
+
$(MAKE) doc_gz
|
118
|
+
chmod 644 $$(find doc -type f)
|
119
|
+
$(RSYNC) -av doc/ zbatery.bogomip.org:/srv/zbatery/
|
120
|
+
git ls-files | xargs touch
|
121
|
+
|
122
|
+
# Create gzip variants of the same timestamp as the original so nginx
|
123
|
+
# "gzip_static on" can serve the gzipped versions directly.
|
124
|
+
doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
|
125
|
+
doc_gz:
|
126
|
+
touch doc/NEWS.atom.xml -d "$$(awk 'NR==1{print $$4,$$5,$$6}' NEWS)"
|
127
|
+
for i in $(docs); do \
|
128
|
+
gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
|
99
129
|
|
100
130
|
ifneq ($(VERSION),)
|
101
131
|
rfproject := rainbows
|
@@ -152,11 +182,13 @@ release: verify package $(release_notes) $(release_changes)
|
|
152
182
|
# make tgz release on RubyForge
|
153
183
|
rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
|
154
184
|
$(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
|
155
|
-
# push gem to
|
185
|
+
# push gem to RubyGems.org
|
156
186
|
gem push $(pkggem)
|
157
187
|
# in case of gem downloads from RubyForge releases page
|
158
188
|
-rubyforge add_file \
|
159
189
|
$(rfproject) $(rfpackage) $(VERSION) $(pkggem)
|
190
|
+
$(RAKE) raa_update VERSION=$(VERSION)
|
191
|
+
$(RAKE) fm_update VERSION=$(VERSION)
|
160
192
|
else
|
161
193
|
gem install-gem: GIT-VERSION-FILE
|
162
194
|
$(MAKE) $@ VERSION=$(GIT_VERSION)
|
data/NEWS
CHANGED
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
+
autoload :Gem, 'rubygems'
|
2
3
|
|
3
4
|
# most tasks are in the GNUmakefile which offers better parallelism
|
4
5
|
|
@@ -89,8 +90,6 @@ end
|
|
89
90
|
|
90
91
|
desc "print release notes for Rubyforge"
|
91
92
|
task :release_notes do
|
92
|
-
require 'rubygems'
|
93
|
-
|
94
93
|
spec = Gem::Specification.load('zbatery.gemspec')
|
95
94
|
puts spec.description.strip
|
96
95
|
puts ""
|
@@ -121,7 +120,6 @@ end
|
|
121
120
|
|
122
121
|
desc "post to RAA"
|
123
122
|
task :raa_update do
|
124
|
-
require 'rubygems'
|
125
123
|
require 'net/http'
|
126
124
|
require 'net/netrc'
|
127
125
|
rc = Net::Netrc.locate('zbatery-raa') or abort "~/.netrc not found"
|
@@ -156,3 +154,32 @@ task :raa_update do
|
|
156
154
|
p res
|
157
155
|
puts res.body
|
158
156
|
end
|
157
|
+
|
158
|
+
desc "post to FM"
|
159
|
+
task :fm_update do
|
160
|
+
require 'tempfile'
|
161
|
+
require 'net/http'
|
162
|
+
require 'net/netrc'
|
163
|
+
require 'json'
|
164
|
+
version = ENV['VERSION'] or abort "VERSION= needed"
|
165
|
+
uri = URI.parse('http://freshmeat.net/projects/zbatery/releases.json')
|
166
|
+
rc = Net::Netrc.locate('zbatery-fm') or abort "~/.netrc not found"
|
167
|
+
api_token = rc.password
|
168
|
+
changelog = tags.find { |t| t[:tag] == "v#{version}" }[:body]
|
169
|
+
tmp = Tempfile.new('fm-changelog')
|
170
|
+
tmp.syswrite(changelog)
|
171
|
+
system(ENV["VISUAL"], tmp.path) or abort "#{ENV["VISUAL"]} failed: #$?"
|
172
|
+
changelog = File.read(tmp.path).strip
|
173
|
+
|
174
|
+
req = {
|
175
|
+
"auth_code" => api_token,
|
176
|
+
"release" => {
|
177
|
+
"tag_list" => "Stable",
|
178
|
+
"version" => version,
|
179
|
+
"changelog" => changelog,
|
180
|
+
},
|
181
|
+
}.to_json
|
182
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
183
|
+
p http.post(uri.path, req, {'Content-Type'=>'application/json'})
|
184
|
+
end
|
185
|
+
end
|
data/lib/zbatery.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
|
+
# :enddoc:
|
2
3
|
require 'rainbows'
|
3
4
|
|
4
5
|
module Zbatery
|
5
6
|
|
6
7
|
# current version of Zbatery
|
7
|
-
VERSION = "0.
|
8
|
+
VERSION = "0.3.0"
|
8
9
|
|
9
10
|
class << self
|
10
11
|
|
11
12
|
# runs the Zbatery HttpServer with +app+ and +options+ and does
|
12
13
|
# not return until the server has exited.
|
13
14
|
def run(app, options = {})
|
14
|
-
HttpServer.new(app, options).start.join
|
15
|
+
Rainbows::HttpServer.new(app, options).start.join
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
@@ -32,7 +33,37 @@ module Zbatery
|
|
32
33
|
# config files...
|
33
34
|
FORK_HOOK = lambda { |_,_| }
|
34
35
|
|
35
|
-
|
36
|
+
end
|
37
|
+
|
38
|
+
# :stopdoc:
|
39
|
+
# override stuff we don't need or can't use portably
|
40
|
+
module Rainbows
|
41
|
+
|
42
|
+
module Base
|
43
|
+
# master == worker in our case
|
44
|
+
def init_worker_process(worker)
|
45
|
+
after_fork.call(self, worker)
|
46
|
+
worker.user(*user) if user.kind_of?(Array) && ! worker.switched
|
47
|
+
build_app! unless preload_app
|
48
|
+
Rainbows::Response.setup(self.class)
|
49
|
+
Rainbows::MaxBody.setup
|
50
|
+
|
51
|
+
# avoid spurious wakeups and blocking-accept() with 1.8 green threads
|
52
|
+
if RUBY_VERSION.to_f < 1.9
|
53
|
+
require "io/nonblock"
|
54
|
+
HttpServer::LISTENERS.each { |l| l.nonblock = true }
|
55
|
+
end
|
56
|
+
|
57
|
+
logger.info "Zbatery #@use worker_connections=#@worker_connections"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# we can't/don't need to do the fchmod heartbeat Unicorn/Rainbows! does
|
62
|
+
def G.tick
|
63
|
+
alive
|
64
|
+
end
|
65
|
+
|
66
|
+
class HttpServer
|
36
67
|
|
37
68
|
# this class is only used to avoid breaking Unicorn user switching
|
38
69
|
class DeadIO
|
@@ -115,47 +146,20 @@ module Zbatery
|
|
115
146
|
|
116
147
|
def before_fork
|
117
148
|
hook = super
|
118
|
-
hook == FORK_HOOK or
|
149
|
+
hook == Zbatery::FORK_HOOK or
|
119
150
|
logger.warn "calling before_fork without forking"
|
120
151
|
hook
|
121
152
|
end
|
122
153
|
|
123
154
|
def after_fork
|
124
155
|
hook = super
|
125
|
-
hook == FORK_HOOK or
|
156
|
+
hook == Zbatery::FORK_HOOK or
|
126
157
|
logger.warn "calling after_fork without having forked"
|
127
158
|
hook
|
128
159
|
end
|
129
160
|
end
|
130
161
|
end
|
131
162
|
|
132
|
-
# :stopdoc:
|
133
|
-
# override stuff we don't need or can't use portably
|
134
|
-
module Rainbows
|
135
|
-
|
136
|
-
module Base
|
137
|
-
# master == worker in our case
|
138
|
-
def init_worker_process(worker)
|
139
|
-
after_fork.call(self, worker)
|
140
|
-
worker.user(*user) if user.kind_of?(Array) && ! worker.switched
|
141
|
-
build_app! unless preload_app
|
142
|
-
|
143
|
-
# avoid spurious wakeups and blocking-accept() with 1.8 green threads
|
144
|
-
if RUBY_VERSION.to_f < 1.9
|
145
|
-
require "io/nonblock"
|
146
|
-
HttpServer::LISTENERS.each { |l| l.nonblock = true }
|
147
|
-
end
|
148
|
-
|
149
|
-
logger.info "Zbatery #@use worker_connections=#@worker_connections"
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
# we can't/don't need to do the fchmod heartbeat Unicorn/Rainbows! does
|
154
|
-
def G.tick
|
155
|
-
alive
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
163
|
module Unicorn
|
160
164
|
|
161
165
|
class Configurator
|
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
|
zbatery_lib := $(shell cd ../lib && pwd)
|
9
10
|
-include ../local.mk
|
@@ -15,13 +16,11 @@ ifeq ($(RUBY_VERSION),)
|
|
15
16
|
$(error unable to detect RUBY_VERSION)
|
16
17
|
endif
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
else
|
21
|
-
RUBYLIB := $(zbatery_lib):$(RUBYLIB)
|
22
|
-
endif
|
23
|
-
export RUBYLIB RUBY_VERSION
|
19
|
+
RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
|
20
|
+
export RUBY_VERSION RUBY_ENGINE
|
24
21
|
|
22
|
+
models += WriterThreadPool
|
23
|
+
models += WriterThreadSpawn
|
25
24
|
models += ThreadPool
|
26
25
|
models += ThreadSpawn
|
27
26
|
models += Rev
|
@@ -30,13 +29,19 @@ models += NeverBlock
|
|
30
29
|
models += RevThreadSpawn
|
31
30
|
models += RevThreadPool
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
40
45
|
endif
|
41
46
|
all_models := $(models) Base
|
42
47
|
|
@@ -63,7 +68,7 @@ $(all_models):
|
|
63
68
|
all:: $(T)
|
64
69
|
|
65
70
|
# can't rely on "set -o pipefail" since we don't require bash or ksh93 :<
|
66
|
-
t_pfx = trash/$@-$(RUBY_VERSION)
|
71
|
+
t_pfx = trash/$@-$(RUBY_ENGINE)-$(RUBY_VERSION)
|
67
72
|
TEST_OPTS =
|
68
73
|
# TRACER = strace -f -o $(t_pfx).strace -s 100000
|
69
74
|
# TRACER = /usr/bin/time -o $(t_pfx).time
|
@@ -76,11 +81,13 @@ ifdef V
|
|
76
81
|
endif
|
77
82
|
endif
|
78
83
|
|
79
|
-
|
80
|
-
|
84
|
+
bindir := $(CURDIR)/bin-$(RUBY_ENGINE)-$(RUBY_VERSION)
|
85
|
+
bin_zbatery := $(bindir)/zbatery
|
86
|
+
$(bin_zbatery): ruby_bin = $(shell which $(RUBY))
|
87
|
+
$(bin_zbatery): ../bin/zbatery
|
81
88
|
mkdir -p $(@D)
|
82
89
|
install -m 755 $^ $@.$(pid)
|
83
|
-
$(
|
90
|
+
$(MRI) -i -p -e '$$_.gsub!(%r{^#!.*$$},"#!$(ruby_bin)")' $@.$(pid)
|
84
91
|
mv $@.$(pid) $@
|
85
92
|
|
86
93
|
random_blob:
|
@@ -97,21 +104,28 @@ $(deps):
|
|
97
104
|
@test -s $@.$(pid) || \
|
98
105
|
{ echo >&2 "E '$(dep_bin)' not found in PATH=$(PATH)"; exit 1; }
|
99
106
|
@mv $@.$(pid) $@
|
100
|
-
|
107
|
+
|
108
|
+
libs := tmp/isolate/$(RUBY_ENGINE)-$(RUBY_VERSION)/.libs
|
109
|
+
$(libs): test_isolate.rb
|
110
|
+
mkdir -p $(@D)
|
111
|
+
$(RUBY) $< > $@+
|
112
|
+
mv $@+ $@
|
113
|
+
t_deps := $(libs) $(deps) $(bin_zbatery) trash/.gitignore
|
114
|
+
$(T): $(t_deps)
|
101
115
|
|
102
116
|
$(MODEL_T): export model = $(firstword $(subst ., ,$@))
|
103
117
|
$(MODEL_T): script = $(subst $(model).,,$@)
|
104
|
-
$(MODEL_T): trash/.gitignore
|
105
118
|
$(MODEL_T): export RUBY := $(RUBY)
|
106
|
-
$(MODEL_T): export PATH := $(
|
107
|
-
$(MODEL_T):
|
108
|
-
|
119
|
+
$(MODEL_T): export PATH := $(bindir):$(PATH)
|
120
|
+
$(MODEL_T): $(t_deps)
|
121
|
+
RUBYLIB=$(zbatery_lib):$$(cat $(libs)) \
|
122
|
+
$(TRACER) $(SHELL) $(SH_TEST_OPTS) $(script) $(TEST_OPTS)
|
109
123
|
|
110
124
|
trash/.gitignore:
|
111
125
|
mkdir -p $(@D)
|
112
126
|
echo '*' > $@
|
113
127
|
|
114
128
|
clean:
|
115
|
-
$(RM) -r trash/*.log trash/*.code
|
129
|
+
$(RM) -r trash/*.log trash/*.code $(bindir)
|
116
130
|
|
117
131
|
.PHONY: $(T) clean
|
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
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# SHA1 checksum generator
|
2
|
+
require 'digest/sha1'
|
3
|
+
use Rack::ContentLength
|
4
|
+
cap = 16384
|
5
|
+
app = lambda do |env|
|
6
|
+
/\A100-continue\z/i =~ env['HTTP_EXPECT'] and
|
7
|
+
return [ 100, {}, [] ]
|
8
|
+
digest = Digest::SHA1.new
|
9
|
+
input = env['rack.input']
|
10
|
+
if buf = input.read(rand(cap))
|
11
|
+
begin
|
12
|
+
raise "#{buf.size} > #{cap}" if buf.size > cap
|
13
|
+
digest.update(buf)
|
14
|
+
end while input.read(rand(cap), buf)
|
15
|
+
end
|
16
|
+
|
17
|
+
[ 200, {'Content-Type' => 'text/plain'}, [ digest.hexdigest << "\n" ] ]
|
18
|
+
end
|
19
|
+
run app
|
@@ -12,13 +12,14 @@ t_plan 10 "large file response slurp avoidance for $model"
|
|
12
12
|
|
13
13
|
t_begin "setup and startup" && {
|
14
14
|
rtmpfiles curl_out
|
15
|
-
zbatery_setup $model
|
15
|
+
zbatery_setup $model 1
|
16
16
|
# can't load Rack::Lint here since it'll cause Rev to slurp
|
17
17
|
zbatery -E none -D large-file-response.ru -c $unicorn_config
|
18
18
|
zbatery_wait_start
|
19
19
|
}
|
20
20
|
|
21
|
-
t_begin "read random blob size" && {
|
21
|
+
t_begin "read random blob sha1 and size" && {
|
22
|
+
random_blob_sha1=$(rsha1 < random_blob)
|
22
23
|
random_blob_size=$(wc -c < random_blob)
|
23
24
|
}
|
24
25
|
|
@@ -32,29 +33,29 @@ t_begin "read current RSS" && {
|
|
32
33
|
t_begin "send a series HTTP/1.1 requests sequentially" && {
|
33
34
|
for i in a b c
|
34
35
|
do
|
35
|
-
|
36
|
-
echo ok >$ok) |
|
37
|
-
test $
|
36
|
+
sha1=$( (curl -sSfv http://$listen/random_blob &&
|
37
|
+
echo ok >$ok) | rsha1)
|
38
|
+
test $sha1 = $random_blob_sha1
|
38
39
|
test xok = x$(cat $ok)
|
39
40
|
done
|
40
41
|
}
|
41
42
|
|
42
43
|
# this was a problem during development
|
43
44
|
t_begin "HTTP/1.0 test" && {
|
44
|
-
|
45
|
-
echo ok >$ok) |
|
46
|
-
test $
|
45
|
+
sha1=$( (curl -0 -sSfv http://$listen/random_blob &&
|
46
|
+
echo ok >$ok) | rsha1)
|
47
|
+
test $sha1 = $random_blob_sha1
|
47
48
|
test xok = x$(cat $ok)
|
48
49
|
}
|
49
50
|
|
50
51
|
t_begin "HTTP/0.9 test" && {
|
51
52
|
(
|
52
53
|
printf 'GET /random_blob\r\n'
|
53
|
-
|
54
|
+
rsha1 < $fifo > $tmp &
|
54
55
|
wait
|
55
56
|
echo ok > $ok
|
56
57
|
) | socat - TCP:$listen > $fifo
|
57
|
-
|
58
|
+
test $(cat $tmp) = $random_blob_sha1
|
58
59
|
test xok = x$(cat $ok)
|
59
60
|
}
|
60
61
|
|
@@ -72,8 +73,12 @@ t_begin "shutdown server" && {
|
|
72
73
|
|
73
74
|
t_begin "compare RSS before and after" && {
|
74
75
|
diff=$(( $rss_after - $rss_before ))
|
76
|
+
|
77
|
+
# default GC malloc limit in MRI:
|
78
|
+
fudge=$(( 8 * 1024 * 1024 ))
|
79
|
+
|
75
80
|
t_info "test diff=$diff < orig=$random_blob_size"
|
76
|
-
test $diff -le $random_blob_size
|
81
|
+
test $diff -le $(( $random_blob_size + $fudge ))
|
77
82
|
}
|
78
83
|
|
79
84
|
dbgcat r_err
|
@@ -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
|
+
zbatery_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
|
+
zbatery -E none -D large-file-response.ru -c $unicorn_config
|
22
|
+
zbatery_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 $zbatery_pid
|
135
|
+
}
|
136
|
+
|
137
|
+
dbgcat r_err
|
138
|
+
|
139
|
+
t_begin "check stderr" && check_stderr
|
140
|
+
|
141
|
+
t_done
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
. ./test-lib.sh
|
3
|
+
test -r random_blob || die "random_blob required, run with 'make $0'"
|
4
|
+
req_curl_chunked_upload_err_check
|
5
|
+
|
6
|
+
t_plan 6 "rack.input client_max_body_size default"
|
7
|
+
|
8
|
+
t_begin "setup and startup" && {
|
9
|
+
rtmpfiles curl_out curl_err cmbs_config
|
10
|
+
zbatery_setup $model
|
11
|
+
grep -v client_max_body_size < $unicorn_config > $cmbs_config
|
12
|
+
zbatery -D sha1-random-size.ru -c $cmbs_config
|
13
|
+
zbatery_wait_start
|
14
|
+
}
|
15
|
+
|
16
|
+
t_begin "regular request" && {
|
17
|
+
rm -f $ok
|
18
|
+
curl -vsSf -T random_blob -H Expect: \
|
19
|
+
http://$listen/ > $curl_out 2> $curl_err || > $ok
|
20
|
+
dbgcat curl_err
|
21
|
+
dbgcat curl_out
|
22
|
+
test -e $ok
|
23
|
+
}
|
24
|
+
|
25
|
+
t_begin "chunked request" && {
|
26
|
+
rm -f $ok
|
27
|
+
curl -vsSf -T- < random_blob -H Expect: \
|
28
|
+
http://$listen/ > $curl_out 2> $curl_err || > $ok
|
29
|
+
dbgcat curl_err
|
30
|
+
dbgcat curl_out
|
31
|
+
test -e $ok
|
32
|
+
}
|
33
|
+
|
34
|
+
t_begin "default size sha1 chunked" && {
|
35
|
+
blob_sha1=3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
|
36
|
+
rm -f $ok
|
37
|
+
> $r_err
|
38
|
+
dd if=/dev/zero bs=1048576 count=1 | \
|
39
|
+
curl -vsSf -T- -H Expect: \
|
40
|
+
http://$listen/ > $curl_out 2> $curl_err
|
41
|
+
test "$(cat $curl_out)" = $blob_sha1
|
42
|
+
dbgcat curl_err
|
43
|
+
dbgcat curl_out
|
44
|
+
}
|
45
|
+
|
46
|
+
t_begin "default size sha1 content-length" && {
|
47
|
+
blob_sha1=3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3
|
48
|
+
rm -f $ok
|
49
|
+
dd if=/dev/zero bs=1048576 count=1 of=$tmp
|
50
|
+
curl -vsSf -T $tmp -H Expect: \
|
51
|
+
http://$listen/ > $curl_out 2> $curl_err
|
52
|
+
test "$(cat $curl_out)" = $blob_sha1
|
53
|
+
dbgcat curl_err
|
54
|
+
dbgcat curl_out
|
55
|
+
}
|
56
|
+
|
57
|
+
t_begin "shutdown" && {
|
58
|
+
kill $zbatery_pid
|
59
|
+
}
|
60
|
+
|
61
|
+
t_done
|
data/t/test-lib.sh
CHANGED
@@ -3,6 +3,12 @@
|
|
3
3
|
. ./my-tap-lib.sh
|
4
4
|
|
5
5
|
set +u
|
6
|
+
|
7
|
+
# sometimes we rely on http_proxy to avoid wasting bandwidth with Isolate
|
8
|
+
# and multiple Ruby versions
|
9
|
+
NO_PROXY=${UNICORN_TEST_ADDR-127.0.0.1}
|
10
|
+
export NO_PROXY
|
11
|
+
|
6
12
|
if test -z "$model"
|
7
13
|
then
|
8
14
|
# defaulting to Base would unfortunately fail some concurrency tests
|
@@ -13,7 +19,7 @@ fi
|
|
13
19
|
set -e
|
14
20
|
RUBY="${RUBY-ruby}"
|
15
21
|
RUBY_VERSION=${RUBY_VERSION-$($RUBY -e 'puts RUBY_VERSION')}
|
16
|
-
t_pfx=$PWD/trash/$model.$T-$RUBY_VERSION
|
22
|
+
t_pfx=$PWD/trash/$model.$T-$RUBY_ENGINE-$RUBY_VERSION
|
17
23
|
set -u
|
18
24
|
|
19
25
|
PATH=$PWD/bin:$PATH
|
@@ -21,16 +27,6 @@ export PATH
|
|
21
27
|
|
22
28
|
test -x $PWD/bin/unused_listen || die "must be run in 't' directory"
|
23
29
|
|
24
|
-
wait_for_pid () {
|
25
|
-
path="$1"
|
26
|
-
nr=30
|
27
|
-
while ! test -s "$path" && test $nr -gt 0
|
28
|
-
do
|
29
|
-
nr=$(($nr - 1))
|
30
|
-
sleep 1
|
31
|
-
done
|
32
|
-
}
|
33
|
-
|
34
30
|
# requires $1 and prints out the value of $2
|
35
31
|
require_check () {
|
36
32
|
lib=$1
|
@@ -42,6 +38,19 @@ require_check () {
|
|
42
38
|
fi
|
43
39
|
}
|
44
40
|
|
41
|
+
skip_models () {
|
42
|
+
for i in "$@"
|
43
|
+
do
|
44
|
+
if test x"$model" != x"$i"
|
45
|
+
then
|
46
|
+
continue
|
47
|
+
fi
|
48
|
+
t_info "skipping $T since it is not compatible with $model"
|
49
|
+
exit 0
|
50
|
+
done
|
51
|
+
}
|
52
|
+
|
53
|
+
|
45
54
|
# given a list of variable names, create temporary files and assign
|
46
55
|
# the pathnames to those variables
|
47
56
|
rtmpfiles () {
|
@@ -113,6 +122,7 @@ EOF
|
|
113
122
|
# boxes and sometimes sleep 1s in tests
|
114
123
|
kato=5
|
115
124
|
echo 'Rainbows! do'
|
125
|
+
echo " client_max_body_size nil"
|
116
126
|
if test $# -ge 1
|
117
127
|
then
|
118
128
|
echo " use :$1"
|
@@ -145,7 +155,22 @@ rsha1 () {
|
|
145
155
|
|
146
156
|
# last resort, see comments in sha1sum.rb for reasoning
|
147
157
|
test -n "$_cmd" || _cmd=sha1sum.rb
|
148
|
-
expr "$($_cmd
|
158
|
+
expr "$($_cmd)" : '\([a-f0-9]\{40\}\)'
|
159
|
+
}
|
160
|
+
|
161
|
+
req_curl_chunked_upload_err_check () {
|
162
|
+
set +e
|
163
|
+
curl --version 2>/dev/null | awk '$1 == "curl" {
|
164
|
+
split($2, v, /\./)
|
165
|
+
if ((v[1] < 7) || (v[1] == 7 && v[2] < 18))
|
166
|
+
code = 1
|
167
|
+
}
|
168
|
+
END { exit(code) }'
|
169
|
+
if test $? -ne 0
|
170
|
+
then
|
171
|
+
t_info "curl >= 7.18.0 required for $T"
|
172
|
+
exit 0
|
173
|
+
fi
|
149
174
|
}
|
150
175
|
|
151
176
|
case $model in
|
data/t/test_isolate.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'isolate'
|
3
|
+
engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
|
4
|
+
|
5
|
+
path = "tmp/isolate/#{engine}-#{RUBY_VERSION}"
|
6
|
+
opts = {
|
7
|
+
:system => false,
|
8
|
+
# we want "ruby-1.8.7" and not "ruby-1.8", so disable multiruby
|
9
|
+
:multiruby => false,
|
10
|
+
:path => path,
|
11
|
+
}
|
12
|
+
|
13
|
+
old_out = $stdout.dup
|
14
|
+
$stdout.reopen($stderr)
|
15
|
+
|
16
|
+
Isolate.now!(opts) do
|
17
|
+
gem 'rack', '1.1.0'
|
18
|
+
gem 'unicorn', '1.1.0'
|
19
|
+
gem 'rainbows', '0.95.0'
|
20
|
+
|
21
|
+
if engine == "ruby"
|
22
|
+
gem 'sendfile', '1.0.0' # next Rubinius should support this
|
23
|
+
|
24
|
+
gem 'iobuffer', '0.1.3'
|
25
|
+
gem 'rev', '0.3.2'
|
26
|
+
|
27
|
+
gem 'eventmachine', '0.12.10'
|
28
|
+
gem 'sinatra', '1.0.0'
|
29
|
+
gem 'async_sinatra', '0.2.1'
|
30
|
+
|
31
|
+
gem 'neverblock', '0.1.6.2'
|
32
|
+
gem 'cramp', '0.11'
|
33
|
+
end
|
34
|
+
|
35
|
+
if defined?(::Fiber) && engine == "ruby"
|
36
|
+
gem 'case', '0.5'
|
37
|
+
gem 'revactor', '0.1.5'
|
38
|
+
gem 'rack-fiber_pool', '0.9.0'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
$stdout.reopen(old_out)
|
43
|
+
puts Dir["#{path}/gems/*-*/lib"].map { |x| File.expand_path(x) }.join(':')
|
data/zbatery.gemspec
CHANGED
@@ -34,13 +34,13 @@ Gem::Specification.new do |s|
|
|
34
34
|
s.files = manifest
|
35
35
|
s.homepage = %q{http://zbatery.bogomip.org/}
|
36
36
|
s.summary = %q{Rack HTTP server without a fork stuck in it}
|
37
|
-
s.rdoc_options = [ "-
|
37
|
+
s.rdoc_options = [ "-t", "Zbatery - #{s.summary}" ]
|
38
38
|
s.require_paths = %w(lib)
|
39
39
|
s.rubyforge_project = %q{rainbows}
|
40
40
|
|
41
41
|
s.test_files = test_files
|
42
42
|
|
43
|
-
# rainbows has a boatload of dependencies
|
43
|
+
# rainbows has a boatload of optional dependencies
|
44
44
|
# required:
|
45
45
|
# unicorn + rack
|
46
46
|
# optional:
|
@@ -54,7 +54,8 @@ Gem::Specification.new do |s|
|
|
54
54
|
# Unicorn were vulnerable to a remote DoS when exposed directly to
|
55
55
|
# untrusted clients (a configuration only supported by Zbatery and Rainbows!,
|
56
56
|
# Unicorn has never and will never be supported without trusted LAN clients.
|
57
|
-
s.add_dependency(%q<rainbows>, [">= 0.
|
57
|
+
s.add_dependency(%q<rainbows>, [">= 0.95.0", "<= 1.0.0"])
|
58
|
+
s.add_development_dependency(%q<isolate>, "~> 2.1.0")
|
58
59
|
|
59
60
|
# s.licenses = %w(GPLv2 Ruby) # accessor not compatible with older RubyGems
|
60
61
|
end
|
metadata
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zbatery
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 19
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
5
11
|
platform: ruby
|
6
12
|
authors:
|
7
13
|
- Zbatery hackers
|
@@ -9,22 +15,49 @@ autorequire:
|
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
17
|
|
12
|
-
date: 2010-
|
18
|
+
date: 2010-07-10 00:00:00 +00:00
|
13
19
|
default_executable:
|
14
20
|
dependencies:
|
15
21
|
- !ruby/object:Gem::Dependency
|
16
22
|
name: rainbows
|
17
|
-
|
18
|
-
|
19
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
20
26
|
requirements:
|
21
27
|
- - ">="
|
22
28
|
- !ruby/object:Gem::Version
|
23
|
-
|
29
|
+
hash: 355
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 95
|
33
|
+
- 0
|
34
|
+
version: 0.95.0
|
24
35
|
- - <=
|
25
36
|
- !ruby/object:Gem::Version
|
37
|
+
hash: 23
|
38
|
+
segments:
|
39
|
+
- 1
|
40
|
+
- 0
|
41
|
+
- 0
|
26
42
|
version: 1.0.0
|
27
|
-
|
43
|
+
type: :runtime
|
44
|
+
version_requirements: *id001
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: isolate
|
47
|
+
prerelease: false
|
48
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
hash: 11
|
54
|
+
segments:
|
55
|
+
- 2
|
56
|
+
- 1
|
57
|
+
- 0
|
58
|
+
version: 2.1.0
|
59
|
+
type: :development
|
60
|
+
version_requirements: *id002
|
28
61
|
description: |-
|
29
62
|
Zbatery is an HTTP server for Rack applications on systems that either
|
30
63
|
do not support fork(), or have no memory (nor need) to run the
|
@@ -75,10 +108,14 @@ files:
|
|
75
108
|
- t/bin/utee
|
76
109
|
- t/large-file-response.ru
|
77
110
|
- t/my-tap-lib.sh
|
111
|
+
- t/sha1-random-size.ru
|
78
112
|
- t/sleep.ru
|
79
113
|
- t/t0003-reopen-logs.sh
|
80
114
|
- t/t0005-large-file-response.sh
|
115
|
+
- t/t0020-large-sendfile-response.sh
|
116
|
+
- t/t0103-rack-input-limit.sh
|
81
117
|
- t/test-lib.sh
|
118
|
+
- t/test_isolate.rb
|
82
119
|
- zbatery.gemspec
|
83
120
|
has_rdoc: true
|
84
121
|
homepage: http://zbatery.bogomip.org/
|
@@ -86,27 +123,32 @@ licenses: []
|
|
86
123
|
|
87
124
|
post_install_message:
|
88
125
|
rdoc_options:
|
89
|
-
- -Na
|
90
126
|
- -t
|
91
127
|
- Zbatery - Rack HTTP server without a fork stuck in it
|
92
128
|
require_paths:
|
93
129
|
- lib
|
94
130
|
required_ruby_version: !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
95
132
|
requirements:
|
96
133
|
- - ">="
|
97
134
|
- !ruby/object:Gem::Version
|
135
|
+
hash: 3
|
136
|
+
segments:
|
137
|
+
- 0
|
98
138
|
version: "0"
|
99
|
-
version:
|
100
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
|
+
none: false
|
101
141
|
requirements:
|
102
142
|
- - ">="
|
103
143
|
- !ruby/object:Gem::Version
|
144
|
+
hash: 3
|
145
|
+
segments:
|
146
|
+
- 0
|
104
147
|
version: "0"
|
105
|
-
version:
|
106
148
|
requirements: []
|
107
149
|
|
108
150
|
rubyforge_project: rainbows
|
109
|
-
rubygems_version: 1.3.
|
151
|
+
rubygems_version: 1.3.7
|
110
152
|
signing_key:
|
111
153
|
specification_version: 3
|
112
154
|
summary: Rack HTTP server without a fork stuck in it
|