rainbows 0.93.0 → 0.94.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 CHANGED
@@ -11,3 +11,4 @@ TODO
11
11
  TUNING
12
12
  vs_Unicorn
13
13
  Summary
14
+ Test_Suite
data/.gitignore CHANGED
@@ -16,4 +16,3 @@ pkg/
16
16
  /.manifest
17
17
  /GIT-VERSION-FILE
18
18
  /man
19
- /tmp
data/GIT-VERSION-GEN CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
 
3
3
  GVF=GIT-VERSION-FILE
4
- DEF_VER=v0.93.0.GIT
4
+ DEF_VER=v0.94.0.GIT
5
5
 
6
6
  LF='
7
7
  '
data/GNUmakefile CHANGED
@@ -2,8 +2,8 @@
2
2
  all::
3
3
  RUBY = ruby
4
4
  RAKE = rake
5
+ RSYNC = rsync
5
6
  GIT_URL = git://git.bogomips.org/rainbows.git
6
- ISOLATE_CONFIG = config/isolate.rb
7
7
 
8
8
  GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
9
9
  @./GIT-VERSION-GEN
@@ -16,12 +16,6 @@ ifeq ($(RUBY_VERSION),)
16
16
  RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
17
17
  endif
18
18
 
19
- # rake takes forever to start
20
- isolate: tmp/isolate/ruby-$(RUBY_VERSION)/.isolate
21
- tmp/isolate/ruby-$(RUBY_VERSION)/.isolate: $(ISOLATE_CONFIG)
22
- ISOLATE_CONFIG=$(ISOLATE_CONFIG) $(RAKE) isolate
23
- > $@
24
-
25
19
  base_bins := rainbows
26
20
  bins := $(addprefix bin/, $(base_bins))
27
21
  man1_rdoc := $(addsuffix _1, $(base_bins))
@@ -112,6 +106,19 @@ doc: .document NEWS ChangeLog
112
106
  cat Documentation/comparison.css >> doc/rdoc.css
113
107
  $(RM) $(man1_rdoc)
114
108
 
109
+ # publishes docs to http://rainbows.rubyforge.org
110
+ publish_doc: NEWS
111
+ -git set-file-times
112
+ $(RM) -r doc ChangeLog NEWS
113
+ $(MAKE) doc LOG_VERSION=$(shell git tag -l | tail -1)
114
+ awk 'BEGIN{RS="=== ";ORS=""}NR==2{sub(/\n$$/,"");print RS""$$0 }' \
115
+ < NEWS > doc/LATEST
116
+ -find doc/images doc/js -type f | \
117
+ TZ=UTC xargs touch -d '1970-01-01 00:00:01' doc/rdoc.css
118
+ chmod 644 $$(find doc -type f)
119
+ $(RSYNC) -av doc/ rubyforge.org:/var/www/gforge-projects/rainbows/
120
+ git ls-files | xargs touch
121
+
115
122
  ifneq ($(VERSION),)
116
123
  rfproject := rainbows
117
124
  rfpackage := rainbows
@@ -172,6 +179,8 @@ release: verify package $(release_notes) $(release_changes)
172
179
  # in case of gem downloads from RubyForge releases page
173
180
  -rubyforge add_file \
174
181
  $(rfproject) $(rfpackage) $(VERSION) $(pkggem)
182
+ $(RAKE) raa_update VERSION=$(VERSION)
183
+ $(RAKE) fm_update VERSION=$(VERSION)
175
184
  else
176
185
  gem install-gem: GIT-VERSION-FILE
177
186
  $(MAKE) $@ VERSION=$(GIT_VERSION)
data/Rakefile CHANGED
@@ -183,24 +183,3 @@ task :fm_update do
183
183
  p http.post(uri.path, req, {'Content-Type'=>'application/json'})
184
184
  end
185
185
  end
186
-
187
- desc 'isolate gems for development'
188
- task :isolate do
189
- require 'isolate'
190
- require 'rbconfig'
191
-
192
- Isolate.now! :file => ENV['ISOLATE_CONFIG'], :system => false
193
-
194
- # for Ruby 1.8 isolate uses "1.8" instead of "1.8.7" for paths,
195
- # but we'll still try to support 1.8.6 for now even though isolate
196
- # does not.
197
- if Gem.ruby_engine == "ruby" &&
198
- RbConfig::CONFIG["ruby_version"] != RUBY_VERSION
199
- require 'fileutils'
200
- Dir.chdir('tmp/isolate') do
201
- FileUtils.rm_rf("ruby-#{RUBY_VERSION}")
202
- File.symlink "ruby-#{RbConfig::CONFIG["ruby_version"]}",
203
- "ruby-#{RUBY_VERSION}"
204
- end
205
- end
206
- end
data/Test_Suite ADDED
@@ -0,0 +1,63 @@
1
+ = \Rainbows! test suite - YES OUR TEST SUITE IS CONCURRENT!
2
+
3
+ These are all integration tests that start the server on random, unused
4
+ TCP ports or Unix domain sockets. They're all designed to run
5
+ concurrently with other tests to minimize test time, but tests may be
6
+ run independently as well.
7
+
8
+ We write our tests primarily in Bourne shell because that's what we're
9
+ comfortable writing integration tests with. This test suite is also
10
+ easily portable to non-Ruby web servers.
11
+
12
+ == Requirements
13
+
14
+ * {Ruby 1.8 or 1.9}[http://www.ruby-lang.org/] (duh!)
15
+ * {isolate ~> 2.0.2}[http://github.com/jbarnette/isolate] - for dependencies
16
+ * {GNU make}[http://www.gnu.org/software/make/]
17
+ * {socat}[http://www.dest-unreach.org/socat/]
18
+ * {curl >= 7.18.0}[http://curl.haxx.se/]
19
+ * standard UNIX shell utilities (Bourne sh, awk, sed, grep, ...)
20
+
21
+ We do not use bashisms or any non-portable, non-POSIX constructs
22
+ in our shell code. We use the "pipefail" option if available and
23
+ mainly test with {ksh}[http://kornshell.com/], but occasionally
24
+ with {dash}[http://gondor.apana.org.au/~herbert/dash/] and
25
+ {bash}[http://www.gnu.org/software/bash/], too.
26
+
27
+ == Running Tests
28
+
29
+ *BSD users: use "gmake" instead of "make"
30
+
31
+ To run the entire test suite with 8 tests running at once:
32
+
33
+ make -j8
34
+
35
+ To run one individual test for all concurrency models:
36
+
37
+ make t0000-simple-http.sh
38
+
39
+ To run one individual test for one concurrency model:
40
+
41
+ make Revactor.t0000-simple-http.sh
42
+
43
+ To run all tests for one concurrency model:
44
+
45
+ make EventMachine
46
+
47
+ You may also increase verbosity by setting the "V" variable for
48
+ GNU make. To disable trapping of stdout/stderr:
49
+
50
+ make V=1
51
+
52
+ To enable the "set -x" option in shell scripts to trace execution
53
+
54
+ make V=2
55
+
56
+ == Performance
57
+
58
+ Some of the tests are rather I/O intensive due to the rewindability
59
+ requirement of "rack.input" in the Rack specification and the somewhat
60
+ complicated (but awesome!) nature of the TeeInput class leading us to
61
+ test it very heavily. If you have lots of RAM and a large tmpfs
62
+ partition, it is advisable to set your TMPDIR and also make the t/trash/
63
+ directory a symlink to a directory inside in your TMPDIR.
data/lib/rainbows.rb CHANGED
@@ -32,6 +32,7 @@ module Rainbows
32
32
  require 'rainbows/http_response'
33
33
  require 'rainbows/base'
34
34
  require 'rainbows/tee_input'
35
+ autoload :Sendfile, 'rainbows/sendfile'
35
36
  autoload :AppPool, 'rainbows/app_pool'
36
37
  autoload :DevFdResponse, 'rainbows/dev_fd_response'
37
38
  autoload :MaxBody, 'rainbows/max_body'
@@ -3,7 +3,7 @@
3
3
  module Rainbows
4
4
 
5
5
  module Const
6
- RAINBOWS_VERSION = '0.93.0'
6
+ RAINBOWS_VERSION = '0.94.0'
7
7
 
8
8
  include Unicorn::Const
9
9
 
@@ -0,0 +1,100 @@
1
+ # -*- encoding: binary -*-
2
+ module Rainbows
3
+
4
+ # This middleware handles X-\Sendfile headers generated by applications
5
+ # or middlewares down the stack. It should be placed at the top
6
+ # (outermost layer) of the middleware stack to avoid having its
7
+ # +to_path+ method clobbered by another middleware.
8
+ #
9
+ # This converts X-\Sendfile responses to bodies which respond to the
10
+ # +to_path+ method which allows certain concurrency models to serve
11
+ # efficiently using sendfile() or similar. With multithreaded models
12
+ # under Ruby 1.9, IO.copy_stream will be used.
13
+ #
14
+ # This middleware is the opposite of Rack::Contrib::Sendfile as it
15
+ # reverses the effect of Rack::Contrib::Sendfile. Unlike many Ruby
16
+ # web servers, some configurations of \Rainbows! are capable of
17
+ # serving static files efficiently.
18
+ #
19
+ # === Compatibility (via IO.copy_stream in Ruby 1.9):
20
+ # * ThreadSpawn
21
+ # * ThreadPool
22
+ # * WriterThreadPool
23
+ # * WriterThreadSpawn
24
+ #
25
+ # === Compatibility (Ruby 1.8 and 1.9)
26
+ # * EventMachine
27
+ # * NeverBlock (using EventMachine)
28
+ #
29
+ # DO NOT use this middleware if you're proxying to \Rainbows! with a
30
+ # server that understands X-\Sendfile (e.g. Apache, Lighttpd) natively.
31
+ #
32
+ # This does NOT understand X-Accel-Redirect headers intended for nginx.
33
+ # X-Accel-Redirect requires the application to be highly coupled with
34
+ # the corresponding nginx configuration, and is thus too complicated to
35
+ # be worth supporting.
36
+ #
37
+ # Example config.ru:
38
+ #
39
+ # use Rainbows::Sendfile
40
+ # run lambda { |env|
41
+ # path = "#{Dir.pwd}/random_blob"
42
+ # [ 200,
43
+ # {
44
+ # 'X-Sendfile' => path,
45
+ # 'Content-Type' => 'application/octet-stream'
46
+ # },
47
+ # []
48
+ # ]
49
+ # }
50
+
51
+ class Sendfile < Struct.new(:app)
52
+
53
+ # :stopdoc:
54
+ HH = Rack::Utils::HeaderHash
55
+ # :startdoc:
56
+
57
+ # Body wrapper, this allows us to fall back gracefully to
58
+ # +each+ in case a given concurrency model does not optimize
59
+ # +to_path+ calls.
60
+ class Body < Struct.new(:to_io)
61
+
62
+ def initialize(path, headers)
63
+ # Rainbows! will try #to_io if #to_path exists to avoid unnecessary
64
+ # open() calls.
65
+ self.to_io = File.open(path, 'rb')
66
+
67
+ unless headers['Content-Length']
68
+ stat = to_io.stat
69
+ headers['Content-Length'] = stat.size.to_s if stat.file?
70
+ end
71
+ end
72
+
73
+ def to_path
74
+ to_io.path
75
+ end
76
+
77
+ # fallback in case our +to_path+ doesn't get handled for whatever reason
78
+ def each(&block)
79
+ buf = ''
80
+ while to_io.read(0x4000, buf)
81
+ yield buf
82
+ end
83
+ end
84
+
85
+ def close
86
+ to_io.close
87
+ end
88
+ end
89
+
90
+ def call(env)
91
+ status, headers, body = app.call(env)
92
+ headers = HH.new(headers)
93
+ if path = headers.delete('X-Sendfile')
94
+ body = Body.new(path, headers) unless body.respond_to?(:to_path)
95
+ end
96
+ [ status, headers, body ]
97
+ end
98
+ end
99
+
100
+ end
@@ -46,13 +46,8 @@ module Rainbows
46
46
  end
47
47
  end
48
48
 
49
- alias base_write_body write_body
50
- if IO.respond_to?(:copy_stream)
51
- undef_method :write_body
52
-
53
- def write_body(qclient, body)
54
- qclient.q << [ qclient.to_io, :body, body ]
55
- end
49
+ def write_body(qclient, body)
50
+ qclient.q << [ qclient.to_io, :body, body ]
56
51
  end
57
52
 
58
53
  @@nr = 0
@@ -71,7 +66,7 @@ module Rainbows
71
66
  begin
72
67
  io, arg1, arg2 = response
73
68
  case arg1
74
- when :body then base_write_body(io, arg2)
69
+ when :body then Base.write_body(io, arg2)
75
70
  when :close then io.close unless io.closed?
76
71
  else
77
72
  io.write(arg1)
@@ -88,12 +88,8 @@ module Rainbows
88
88
  end
89
89
  end
90
90
 
91
- if IO.respond_to?(:copy_stream)
92
- undef_method :write_body
93
-
94
- def write_body(my_sock, body)
95
- my_sock.write_body(body)
96
- end
91
+ def write_body(my_sock, body)
92
+ my_sock.write_body(body)
97
93
  end
98
94
 
99
95
  def process_client(client)
data/local.mk.sample CHANGED
@@ -4,37 +4,32 @@
4
4
  #
5
5
  # This is depends on a bunch of GNU-isms from bash, sed, touch.
6
6
 
7
- RSYNC = rsync
8
7
  DLEXT := so
9
8
 
9
+ # if you have a decent amount of RAM, setting TMPDIR to be on tmpfs
10
+ # can significantly improve performance because uploads take a lot
11
+ # of disk I/O due to the rewindability requirement in Rack.
12
+ # TMPDIR := /dev/shm
13
+ # export TMPDIR
14
+
10
15
  # Avoid loading rubygems to speed up tests because gmake is
11
16
  # fork+exec heavy with Ruby.
12
17
  prefix = $(HOME)
13
18
 
14
- ifeq ($(r19),)
15
- RUBY := $(prefix)/bin/ruby
19
+ ifeq ($(r192),)
20
+ ifeq ($(r19),)
21
+ RUBY := $(prefix)/bin/ruby
22
+ else
23
+ prefix := $(prefix)/ruby-1.9
24
+ export PATH := $(prefix)/bin:$(PATH)
25
+ RUBY := $(prefix)/bin/ruby --disable-gems
26
+ endif
16
27
  else
17
- prefix := $(prefix)/ruby-1.9
28
+ prefix := $(prefix)/ruby-1.9.2
18
29
  export PATH := $(prefix)/bin:$(PATH)
19
30
  RUBY := $(prefix)/bin/ruby --disable-gems
20
31
  endif
21
32
 
22
- ifndef NO_ISOLATE
23
- x := $(shell test -d t/ && \
24
- PATH=$(PATH) NO_ISOLATE=T $(MAKE) -s isolate RUBY:="$(RUBY)")
25
- endif
26
-
27
- RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
28
-
29
- updir := $(shell git rev-parse --show-cdup)
30
- gem_paths := $(wildcard $(updir)tmp/isolate/ruby-$(RUBY_VERSION)/gems/*-*)
31
-
32
- ifdef gem_paths
33
- sp :=
34
- sp +=
35
- export RUBYLIB := $(subst $(sp),:,$(addsuffix /lib,$(gem_paths)))
36
- endif
37
-
38
33
  # pipefail is THE reason to use bash (v3+) or never revisions of ksh93
39
34
  # SHELL := /bin/bash -e -o pipefail
40
35
  SHELL := /bin/ksh93 -e -o pipefail
@@ -43,37 +38,10 @@ SHELL := /bin/ksh93 -e -o pipefail
43
38
  # TRACER = strace -f -o $(t_pfx).strace -s 100000
44
39
  TRACER = /usr/bin/time -v -o $(t_pfx).time
45
40
 
46
- full-test: test-18 test-19
41
+ full-test: test-18 test-191 test-192
47
42
  test-18:
48
43
  $(MAKE) test 2>&1 | sed -e 's!^!1.8 !'
49
- test-19:
50
- $(MAKE) test r19=T 2>&1 | sed -e 's!^!1.9 !'
51
-
52
- latest: NEWS
53
- @awk 'BEGIN{RS="=== ";ORS=""}NR==2{sub(/\n$$/,"");print RS""$$0 }' < $<
54
-
55
- # publishes docs to http://rainbows.rubyforge.org
56
- publish_doc:
57
- -git set-file-times
58
- $(RM) -r doc ChangeLog NEWS
59
- $(MAKE) doc LOG_VERSION=$(shell git tag -l | tail -1)
60
- $(MAKE) -s latest > doc/LATEST
61
- find doc/images doc/js -type f | \
62
- TZ=UTC xargs touch -d '1970-01-01 00:00:00' doc/rdoc.css
63
- $(MAKE) doc_gz
64
- chmod 644 $$(find doc -type f)
65
- $(RSYNC) -av doc/ rubyforge.org:/var/www/gforge-projects/rainbows/
66
- $(RSYNC) -av doc/ dcvr:/srv/rainbows/
67
- git ls-files | xargs touch
68
-
69
- # Create gzip variants of the same timestamp as the original so nginx
70
- # "gzip_static on" can serve the gzipped versions directly.
71
- doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
72
- doc_gz:
73
- touch doc/NEWS.atom.xml -d "$$(awk 'NR==1{print $$4,$$5,$$6}' NEWS)"
74
- for i in $(docs); do \
75
- gzip --rsyncable -9 < $$i > $$i.gz; touch -r $$i $$i.gz; done
76
-
77
- # launches any of the following shells with RUBYLIB set
78
- irb sh bash ksh:
79
- $@
44
+ test-191:
45
+ $(MAKE) test r19=T 2>&1 | sed -e 's!^!1.9.1 !'
46
+ test-192:
47
+ $(MAKE) test r192=T 2>&1 | sed -e 's!^!1.9.2 !'
data/rainbows.gemspec CHANGED
@@ -44,6 +44,7 @@ Gem::Specification.new do |s|
44
44
  # The HTTP parser in Unicorn <= 0.97.0 was vulnerable to a remote DoS
45
45
  # when exposed directly to untrusted clients.
46
46
  s.add_dependency(%q<unicorn>, [">= 0.97.1", "< 2.0.0"])
47
+ s.add_development_dependency(%q<isolate>, "~> 2.0.2")
47
48
 
48
49
  # Unicorn already depends on Rack
49
50
  # s.add_dependency(%q<rack>)
data/t/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  /random_blob
4
4
  /.dep+*
5
5
  /trash
6
+ /tmp
data/t/GNUmakefile CHANGED
@@ -15,12 +15,7 @@ ifeq ($(RUBY_VERSION),)
15
15
  $(error unable to detect RUBY_VERSION)
16
16
  endif
17
17
 
18
- ifeq ($(RUBYLIB),)
19
- RUBYLIB := $(rainbows_lib)
20
- else
21
- RUBYLIB := $(rainbows_lib):$(RUBYLIB)
22
- endif
23
- export RUBYLIB RUBY_VERSION
18
+ export RUBY_VERSION
24
19
 
25
20
  models += WriterThreadPool
26
21
  models += WriterThreadSpawn
@@ -99,15 +94,22 @@ $(deps):
99
94
  @test -s $@.$(pid) || \
100
95
  { echo >&2 "E '$(dep_bin)' not found in PATH=$(PATH)"; exit 1; }
101
96
  @mv $@.$(pid) $@
102
- dep: $(deps)
97
+
98
+ libs := tmp/isolate/ruby-$(RUBY_VERSION)/.libs
99
+ $(libs): test_isolate.rb
100
+ mkdir -p $(@D)
101
+ $(RUBY) $< > $@+
102
+ mv $@+ $@
103
+ t_deps := $(libs) $(deps) test-bin-$(RUBY_VERSION)/rainbows trash/.gitignore
104
+ $(T): $(t_deps)
103
105
 
104
106
  $(MODEL_T): export model = $(firstword $(subst ., ,$@))
105
107
  $(MODEL_T): script = $(subst $(model).,,$@)
106
- $(MODEL_T): trash/.gitignore
107
108
  $(MODEL_T): export RUBY := $(RUBY)
108
109
  $(MODEL_T): export PATH := $(CURDIR)/test-bin-$(RUBY_VERSION):$(PATH)
109
- $(MODEL_T): test-bin-$(RUBY_VERSION)/rainbows dep
110
- $(TRACER) $(SHELL) $(SH_TEST_OPTS) $(script) $(TEST_OPTS)
110
+ $(MODEL_T): $(t_deps)
111
+ RUBYLIB=$(rainbows_lib):$$(cat $(libs)) \
112
+ $(TRACER) $(SHELL) $(SH_TEST_OPTS) $(script) $(TEST_OPTS)
111
113
 
112
114
  trash/.gitignore:
113
115
  mkdir -p $(@D)
data/t/README CHANGED
@@ -1,19 +1,21 @@
1
- = Rainbows! test suite
1
+ = \Rainbows! test suite - YES OUR TEST SUITE IS CONCURRENT!
2
2
 
3
3
  These are all integration tests that start the server on random, unused
4
4
  TCP ports or Unix domain sockets. They're all designed to run
5
5
  concurrently with other tests to minimize test time, but tests may be
6
6
  run independently as well.
7
7
 
8
- We write our tests in Bourne shell because that's what we're
9
- comfortable writing integration tests with.
8
+ We write our tests primarily in Bourne shell because that's what we're
9
+ comfortable writing integration tests with. This test suite is also
10
+ easily portable to non-Ruby web servers.
10
11
 
11
12
  == Requirements
12
13
 
13
14
  * {Ruby 1.8 or 1.9}[http://www.ruby-lang.org/] (duh!)
15
+ * {isolate ~> 2.0.2}[http://github.com/jbarnette/isolate] - for dependencies
14
16
  * {GNU make}[http://www.gnu.org/software/make/]
15
17
  * {socat}[http://www.dest-unreach.org/socat/]
16
- * {curl}[http://curl.haxx.se/]
18
+ * {curl >= 7.18.0}[http://curl.haxx.se/]
17
19
  * standard UNIX shell utilities (Bourne sh, awk, sed, grep, ...)
18
20
 
19
21
  We do not use bashisms or any non-portable, non-POSIX constructs
@@ -24,6 +26,8 @@ with {dash}[http://gondor.apana.org.au/~herbert/dash/] and
24
26
 
25
27
  == Running Tests
26
28
 
29
+ *BSD users: use "gmake" instead of "make"
30
+
27
31
  To run the entire test suite with 8 tests running at once:
28
32
 
29
33
  make -j8
@@ -36,6 +40,10 @@ To run one individual test for one concurrency model:
36
40
 
37
41
  make Revactor.t0000-simple-http.sh
38
42
 
43
+ To run all tests for one concurrency model:
44
+
45
+ make EventMachine
46
+
39
47
  You may also increase verbosity by setting the "V" variable for
40
48
  GNU make. To disable trapping of stdout/stderr:
41
49
 
@@ -44,3 +52,12 @@ GNU make. To disable trapping of stdout/stderr:
44
52
  To enable the "set -x" option in shell scripts to trace execution
45
53
 
46
54
  make V=2
55
+
56
+ == Performance
57
+
58
+ Some of the tests are rather I/O intensive due to the rewindability
59
+ requirement of "rack.input" in the Rack specification and the somewhat
60
+ complicated (but awesome!) nature of the TeeInput class leading us to
61
+ test it very heavily. If you have lots of RAM and a large tmpfs
62
+ partition, it is advisable to set your TMPDIR and also make the t/trash/
63
+ directory a symlink to a directory inside in your TMPDIR.
@@ -18,7 +18,8 @@ t_begin "setup and startup" && {
18
18
  rainbows_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,18 +33,18 @@ 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
- size=$( (curl -sSfv http://$listen/random_blob &&
36
- echo ok >$ok) |wc -c)
37
- test $size -eq $random_blob_size
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
- size=$( (curl -0 -sSfv http://$listen/random_blob &&
45
- echo ok >$ok) |wc -c)
46
- test $size -eq $random_blob_size
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
 
@@ -54,7 +55,7 @@ t_begin "HTTP/0.9 test" && {
54
55
  wait
55
56
  echo ok > $ok
56
57
  ) | socat - TCP:$listen > $fifo
57
- test $(cat $tmp) = $(rsha1 < random_blob)
58
+ test $(cat $tmp) = $random_blob_sha1
58
59
  test xok = x$(cat $ok)
59
60
  }
60
61
 
@@ -1,5 +1,11 @@
1
1
  #!/bin/sh
2
2
  . ./test-lib.sh
3
+ case $RUBY_VERSION in
4
+ 1.9.2)
5
+ t_info "RUBY_VERSION=$RUBY_VERSION not supported with async_sinatra"
6
+ exit 0
7
+ ;;
8
+ esac
3
9
 
4
10
  # n - number of seconds to sleep
5
11
  n=10
@@ -0,0 +1,45 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+
4
+ t_plan 7 "Sendfile middleware test for $model"
5
+
6
+ t_begin "configure and start" && {
7
+ rtmpfiles curl_out curl_err
8
+ rainbows_setup
9
+
10
+ # do not allow default middleware to be loaded since it may
11
+ # kill body#to_path
12
+ rainbows -E none -D t9001.ru -c $unicorn_config
13
+ rainbows_wait_start
14
+ }
15
+
16
+ t_begin "hit with curl" && {
17
+ curl -sSfv http://$listen/ > $curl_out 2> $curl_err
18
+ }
19
+
20
+ t_begin "kill server" && {
21
+ kill $rainbows_pid
22
+ }
23
+
24
+ t_begin "file matches source" && {
25
+ cmp $curl_out random_blob
26
+ }
27
+
28
+ t_begin "no errors in Rainbows! stderr" && {
29
+ check_stderr
30
+ }
31
+
32
+ t_begin "X-Sendfile does not show up in headers" && {
33
+ dbgcat curl_err
34
+ if grep -i x-sendfile $curl_err
35
+ then
36
+ die "X-Sendfile did show up!"
37
+ fi
38
+ }
39
+
40
+ t_begin "Content-Length is set correctly in headers" && {
41
+ expect=$(wc -c < random_blob)
42
+ grep "^< Content-Length: $expect" $curl_err
43
+ }
44
+
45
+ t_done
data/t/t9001.ru ADDED
@@ -0,0 +1,11 @@
1
+ use Rainbows::Sendfile
2
+ run lambda { |env|
3
+ path = "#{Dir.pwd}/random_blob"
4
+ [ 200,
5
+ {
6
+ 'X-Sendfile' => path,
7
+ 'Content-Type' => 'application/octet-stream'
8
+ },
9
+ []
10
+ ]
11
+ }
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
@@ -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
data/t/test_isolate.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'rubygems'
2
+ require 'isolate'
3
+
4
+ path = "tmp/isolate/ruby-#{RUBY_VERSION}"
5
+ opts = {
6
+ :system => false,
7
+ # we want "ruby-1.8.7" and not "ruby-1.8", so disable multiruby
8
+ :multiruby => false,
9
+ :path => path,
10
+ }
11
+
12
+ old_out = $stdout.dup
13
+ $stdout.reopen($stderr)
14
+
15
+ Isolate.now!(opts) do
16
+ gem 'rack', '1.1.0'
17
+ gem 'unicorn', '0.99.0'
18
+
19
+ gem 'iobuffer', '0.1.3'
20
+ gem 'rev', '0.3.2'
21
+
22
+ gem 'eventmachine', '0.12.10'
23
+
24
+ gem 'sinatra', '0.9.4'
25
+ gem 'async_sinatra', '0.1.5'
26
+
27
+ gem 'neverblock', '0.1.6.2'
28
+
29
+ if defined?(::Fiber)
30
+ gem 'case', '0.5'
31
+ gem 'revactor', '0.1.5'
32
+ gem 'rack-fiber_pool', '0.9.0'
33
+ end
34
+
35
+ gem 'cramp', '0.11'
36
+ end
37
+
38
+ $stdout.reopen(old_out)
39
+ puts Dir["#{path}/gems/*-*/lib"].map { |x| File.expand_path(x) }.join(':')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rainbows
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.93.0
4
+ version: 0.94.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rainbows! hackers
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-05-29 00:00:00 +00:00
12
+ date: 2010-06-04 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -25,6 +25,16 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 2.0.0
27
27
  version:
28
+ - !ruby/object:Gem::Dependency
29
+ name: isolate
30
+ type: :development
31
+ version_requirement:
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ~>
35
+ - !ruby/object:Gem::Version
36
+ version: 2.0.2
37
+ version:
28
38
  description: |-
29
39
  \Rainbows! is an HTTP server for sleepy Rack applications. It is based on
30
40
  Unicorn, but designed to handle applications that expect long
@@ -73,6 +83,7 @@ extra_rdoc_files:
73
83
  - lib/rainbows/rev_thread_pool.rb
74
84
  - lib/rainbows/rev_thread_spawn.rb
75
85
  - lib/rainbows/revactor.rb
86
+ - lib/rainbows/sendfile.rb
76
87
  - lib/rainbows/tee_input.rb
77
88
  - lib/rainbows/thread_pool.rb
78
89
  - lib/rainbows/thread_spawn.rb
@@ -86,6 +97,7 @@ extra_rdoc_files:
86
97
  - TUNING
87
98
  - vs_Unicorn
88
99
  - Summary
100
+ - Test_Suite
89
101
  files:
90
102
  - .document
91
103
  - .gitignore
@@ -110,9 +122,8 @@ files:
110
122
  - Summary
111
123
  - TODO
112
124
  - TUNING
125
+ - Test_Suite
113
126
  - bin/rainbows
114
- - config/.gitignore
115
- - config/isolate.rb
116
127
  - lib/rainbows.rb
117
128
  - lib/rainbows/actor_spawn.rb
118
129
  - lib/rainbows/app_pool.rb
@@ -146,6 +157,7 @@ files:
146
157
  - lib/rainbows/rev_thread_pool.rb
147
158
  - lib/rainbows/rev_thread_spawn.rb
148
159
  - lib/rainbows/revactor.rb
160
+ - lib/rainbows/sendfile.rb
149
161
  - lib/rainbows/tee_input.rb
150
162
  - lib/rainbows/thread_pool.rb
151
163
  - lib/rainbows/thread_spawn.rb
@@ -231,7 +243,10 @@ files:
231
243
  - t/t0700-app-deferred.sh
232
244
  - t/t9000-rack-app-pool.sh
233
245
  - t/t9000.ru
246
+ - t/t9001-sendfile-to-path.sh
247
+ - t/t9001.ru
234
248
  - t/test-lib.sh
249
+ - t/test_isolate.rb
235
250
  - t/worker-follows-master-to-death.ru
236
251
  - vs_Unicorn
237
252
  has_rdoc: true
data/config/.gitignore DELETED
@@ -1 +0,0 @@
1
- /isolate_*.rb
data/config/isolate.rb DELETED
@@ -1,25 +0,0 @@
1
- # this the default config file used by John Barnette's isolate gem
2
- # you can create a config/isolate_local.rb file to override this
3
- # See the corresponding tasks in Rakefile and GNUmakefile
4
- # `rake isolate' or (faster in the unmodified case, `make isolate')
5
-
6
- gem 'rack', '1.1.0'
7
- gem 'unicorn', '0.99.0'
8
-
9
- gem 'iobuffer', '0.1.3'
10
- gem 'rev', '0.3.2'
11
-
12
- gem 'eventmachine', '0.12.10'
13
-
14
- gem 'sinatra', '0.9.4'
15
- gem 'async_sinatra', '0.1.5'
16
-
17
- gem 'neverblock', '0.1.6.2'
18
-
19
- if defined?(::Fiber)
20
- gem 'case', '0.5'
21
- gem 'revactor', '0.1.5'
22
- gem 'rack-fiber_pool', '0.9.0'
23
- end
24
-
25
- gem 'cramp', '0.11'