jubilee 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +5 -0
- data/CHANGELOG +5 -0
- data/Gemfile +4 -2
- data/Gemfile.lock +47 -8
- data/README.md +2 -0
- data/VERSION +1 -1
- data/java/src/jubilee/JubileeService.java +1 -2
- data/java/src/org/jruby/jubilee/Const.java +135 -131
- data/java/src/org/jruby/jubilee/RackApplication.java +12 -8
- data/java/src/org/jruby/jubilee/RackResponse.java +0 -2
- data/java/src/org/jruby/jubilee/Server.java +15 -7
- data/java/src/org/jruby/jubilee/impl/DefaultRackEnvironment.java +71 -71
- data/java/src/org/jruby/jubilee/impl/RubyIORackInput.java +171 -135
- data/jubilee.gemspec +100 -0
- data/lib/jubilee/configuration.rb +25 -14
- data/lib/jubilee/jubilee.jar +0 -0
- data/lib/jubilee/server.rb +1 -2
- data/test/jubilee/{test_persistent.rb → test_response.rb} +28 -2
- data/test/jubilee/test_server.rb +1 -1
- data/test/jubilee/test_upload.rb +298 -0
- data/test/test_helper.rb +32 -0
- metadata +12 -9
data/jubilee.gemspec
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "jubilee"
|
8
|
+
s.version = "0.4.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Isaiah Peng"]
|
12
|
+
s.date = "2013-09-16"
|
13
|
+
s.description = "Jubilee is a experimental webserver built for speed, it's based on Vertx."
|
14
|
+
s.email = "issaria@gmail.com"
|
15
|
+
s.executables = ["jubilee", "jubilee_d"]
|
16
|
+
s.extra_rdoc_files = [
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".ruby-version",
|
21
|
+
".travis.yml",
|
22
|
+
"CHANGELOG",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"Guardfile",
|
26
|
+
"README.md",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"bin/jubilee",
|
30
|
+
"bin/jubilee_d",
|
31
|
+
"examples/jubilee/keystore.jks",
|
32
|
+
"examples/jubilee/server-keystore.jks",
|
33
|
+
"examples/ssl/ServerTest.java",
|
34
|
+
"examples/ssl/webroot/index.html",
|
35
|
+
"jars/jackson-core-2.2.2.jar",
|
36
|
+
"jars/netty-all-4.0.4.Final.jar",
|
37
|
+
"jars/vertx-core-2.1.0-SNAPSHOT.jar",
|
38
|
+
"java/src/jubilee/JubileeService.java",
|
39
|
+
"java/src/org/jruby/jubilee/Const.java",
|
40
|
+
"java/src/org/jruby/jubilee/RackApplication.java",
|
41
|
+
"java/src/org/jruby/jubilee/RackEnvironment.java",
|
42
|
+
"java/src/org/jruby/jubilee/RackErrors.java",
|
43
|
+
"java/src/org/jruby/jubilee/RackInput.java",
|
44
|
+
"java/src/org/jruby/jubilee/RackResponse.java",
|
45
|
+
"java/src/org/jruby/jubilee/Server.java",
|
46
|
+
"java/src/org/jruby/jubilee/deploy/Starter.java",
|
47
|
+
"java/src/org/jruby/jubilee/impl/DefaultRackEnvironment.java",
|
48
|
+
"java/src/org/jruby/jubilee/impl/NullIO.java",
|
49
|
+
"java/src/org/jruby/jubilee/impl/RubyIORackErrors.java",
|
50
|
+
"java/src/org/jruby/jubilee/impl/RubyIORackInput.java",
|
51
|
+
"jubilee.gemspec",
|
52
|
+
"lib/jubilee.rb",
|
53
|
+
"lib/jubilee/application.rb",
|
54
|
+
"lib/jubilee/cli.rb",
|
55
|
+
"lib/jubilee/configuration.rb",
|
56
|
+
"lib/jubilee/const.rb",
|
57
|
+
"lib/jubilee/jubilee.jar",
|
58
|
+
"lib/jubilee/response.rb",
|
59
|
+
"lib/jubilee/server.rb",
|
60
|
+
"lib/jubilee/version.rb",
|
61
|
+
"lib/rack/handler/jubilee.rb",
|
62
|
+
"test/.ruby-version",
|
63
|
+
"test/config/app.rb",
|
64
|
+
"test/jubilee/test_cli.rb",
|
65
|
+
"test/jubilee/test_config.rb",
|
66
|
+
"test/jubilee/test_rack_server.rb",
|
67
|
+
"test/jubilee/test_response.rb",
|
68
|
+
"test/jubilee/test_server.rb",
|
69
|
+
"test/jubilee/test_upload.rb",
|
70
|
+
"test/sinatra_app/app.rb",
|
71
|
+
"test/sinatra_app/config.ru",
|
72
|
+
"test/sinatra_app/public/test.html",
|
73
|
+
"test/sinatra_app/unicorn.conf.rb",
|
74
|
+
"test/test_helper.rb"
|
75
|
+
]
|
76
|
+
s.homepage = "http://github.com/isaiah/jubilee"
|
77
|
+
s.licenses = ["MIT"]
|
78
|
+
s.require_paths = ["lib"]
|
79
|
+
s.rubygems_version = "1.8.24"
|
80
|
+
s.summary = "JRuby webserver based on Vertx"
|
81
|
+
|
82
|
+
if s.respond_to? :specification_version then
|
83
|
+
s.specification_version = 3
|
84
|
+
|
85
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
86
|
+
s.add_runtime_dependency(%q<rack>, [">= 1.4.1"])
|
87
|
+
s.add_runtime_dependency(%q<spoon>, ["~> 0.0.4"])
|
88
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
89
|
+
else
|
90
|
+
s.add_dependency(%q<rack>, [">= 1.4.1"])
|
91
|
+
s.add_dependency(%q<spoon>, ["~> 0.0.4"])
|
92
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
93
|
+
end
|
94
|
+
else
|
95
|
+
s.add_dependency(%q<rack>, [">= 1.4.1"])
|
96
|
+
s.add_dependency(%q<spoon>, ["~> 0.0.4"])
|
97
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Jubilee
|
2
2
|
class Configuration
|
3
|
+
attr_reader :app
|
4
|
+
|
3
5
|
def initialize(options, &block)
|
4
6
|
@options = options
|
5
7
|
@block = block
|
@@ -9,15 +11,6 @@ module Jubilee
|
|
9
11
|
@app = load_rack_adapter(@options, &@block)
|
10
12
|
end
|
11
13
|
|
12
|
-
def app
|
13
|
-
if !@options[:quiet] and @options[:environment] == "development"
|
14
|
-
logger = @options[:logger] || STDOUT
|
15
|
-
Rack::CommonLogger.new(@app, logger)
|
16
|
-
else
|
17
|
-
@app
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
14
|
def port
|
22
15
|
@options[:Port]
|
23
16
|
end
|
@@ -41,18 +34,36 @@ module Jubilee
|
|
41
34
|
private
|
42
35
|
def load_rack_adapter(options, &block)
|
43
36
|
if block
|
44
|
-
|
37
|
+
inner_app = Rack::Builder.new(&block).to_app
|
45
38
|
else
|
46
39
|
if options[:rackup]
|
47
40
|
Kernel.load(options[:rackup])
|
48
|
-
|
41
|
+
inner_app = Object.const_get(File.basename(options[:rackup], '.rb').capitalize.to_sym).new
|
49
42
|
else
|
50
43
|
Dir.chdir options[:chdir] if options[:chdir]
|
51
|
-
|
44
|
+
inner_app, opts = Rack::Builder.parse_file "config.ru"
|
52
45
|
end
|
53
46
|
end
|
54
|
-
|
47
|
+
case ENV["RACK_ENV"]
|
48
|
+
when "development"
|
49
|
+
Rack::Builder.new do
|
50
|
+
use Rack::ContentLength
|
51
|
+
use Rack::Chunked
|
52
|
+
use Rack::CommonLogger, $stderr
|
53
|
+
use Rack::ShowExceptions
|
54
|
+
use Rack::Lint
|
55
|
+
run inner_app
|
56
|
+
end.to_app
|
57
|
+
when "deployment"
|
58
|
+
Rack::Builder.new do
|
59
|
+
use Rack::ContentLength
|
60
|
+
use Rack::Chunked
|
61
|
+
use Rack::CommonLogger, $stderr
|
62
|
+
run inner_app
|
63
|
+
end.to_app
|
64
|
+
else
|
65
|
+
inner_app
|
66
|
+
end
|
55
67
|
end
|
56
|
-
|
57
68
|
end
|
58
69
|
end
|
data/lib/jubilee/jubilee.jar
CHANGED
Binary file
|
data/lib/jubilee/server.rb
CHANGED
@@ -2,8 +2,7 @@ require 'rack/methodoverride'
|
|
2
2
|
module Jubilee
|
3
3
|
class Server < VertxServer
|
4
4
|
def initialize(app, opts = {})
|
5
|
-
|
6
|
-
options = {Port: 3215, ssl: false}.merge(opts)
|
5
|
+
options = {Port: 3215, ssl: false, number_of_workers: 4}.merge(opts)
|
7
6
|
if (options[:ssl]) && options[:keystore_path].nil?
|
8
7
|
raise ArgumentError, "Please provide a keystore for ssl"
|
9
8
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require 'timeout'
|
3
3
|
require 'socket'
|
4
|
-
class
|
4
|
+
class TestResponse < MiniTest::Unit::TestCase
|
5
5
|
def setup
|
6
6
|
@valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
|
7
7
|
@close_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nConnection: Close\r\n\r\n"
|
@@ -26,7 +26,6 @@ class TestPersistent < MiniTest::Unit::TestCase
|
|
26
26
|
|
27
27
|
@server = Jubilee::Server.new @simple
|
28
28
|
@server.start
|
29
|
-
|
30
29
|
sleep 0.1
|
31
30
|
@client = TCPSocket.new @host, @port
|
32
31
|
end
|
@@ -243,5 +242,32 @@ class TestPersistent < MiniTest::Unit::TestCase
|
|
243
242
|
assert_equal "HTTP/1.1 200 OK\r\ncontent-length: #{sz}\r\nx-header: Works\r\n\r\n", lines(4, c2)
|
244
243
|
assert_equal "Hello", c2.read(5)
|
245
244
|
end
|
245
|
+
|
246
|
+
def test_client_shutdown_writes
|
247
|
+
bs = 15609315 * rand
|
248
|
+
sock = TCPSocket.new('127.0.0.1', @port)
|
249
|
+
sock.syswrite("PUT /hello HTTP/1.1\r\n")
|
250
|
+
sock.syswrite("Host: example.com\r\n")
|
251
|
+
sock.syswrite("Transfer-Encoding: chunked\r\n")
|
252
|
+
sock.syswrite("Trailer: X-Foo\r\n")
|
253
|
+
sock.syswrite("\r\n")
|
254
|
+
sock.syswrite("%x\r\n" % [ bs ])
|
255
|
+
sock.syswrite("F" * bs)
|
256
|
+
sock.syswrite("\r\n0\r\nX-")
|
257
|
+
"Foo: bar\r\n\r\n".each_byte do |x|
|
258
|
+
sock.syswrite x.chr
|
259
|
+
sleep 0.05
|
260
|
+
end
|
261
|
+
# we wrote the entire request before shutting down, server should
|
262
|
+
# continue to process our request and never hit EOFError on our sock
|
263
|
+
sock.shutdown(Socket::SHUT_WR)
|
264
|
+
buf = sock.read
|
265
|
+
assert_equal 'Hello', buf.split(/\r\n\r\n/).last
|
266
|
+
next_client = Net::HTTP.get(URI.parse("http://127.0.0.1:#@port/"))
|
267
|
+
assert_equal 'Hello', next_client
|
268
|
+
lines = File.readlines("test_stderr.#$$.log")
|
269
|
+
assert lines.grep(/^Unicorn::ClientShutdown: /).empty?
|
270
|
+
assert_nil sock.close
|
271
|
+
end
|
246
272
|
=end
|
247
273
|
end
|
data/test/jubilee/test_server.rb
CHANGED
@@ -42,7 +42,6 @@ class TestJubileeServer < MiniTest::Unit::TestCase
|
|
42
42
|
skip
|
43
43
|
end
|
44
44
|
|
45
|
-
|
46
45
|
def test_url_scheme_for_https
|
47
46
|
app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
|
48
47
|
server = Jubilee::Server.new(app, {port:@port, ssl:true,
|
@@ -65,4 +64,5 @@ class TestJubileeServer < MiniTest::Unit::TestCase
|
|
65
64
|
server.stop
|
66
65
|
assert_equal "https", body
|
67
66
|
end
|
67
|
+
|
68
68
|
end
|
@@ -0,0 +1,298 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'digest/md5'
|
5
|
+
|
6
|
+
class TestUpload < MiniTest::Unit::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@addr = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
|
10
|
+
@port = 3215
|
11
|
+
@hdr = {'Content-Type' => 'text/plain', 'Content-Length' => '0'}
|
12
|
+
@bs = 4096
|
13
|
+
@count = 256
|
14
|
+
@server = nil
|
15
|
+
@sha1 = Digest::SHA1.new
|
16
|
+
|
17
|
+
# we want random binary data to test 1.9 encoding-aware IO craziness
|
18
|
+
@random = File.open('/dev/urandom','rb')
|
19
|
+
@sha1_app = lambda do |env|
|
20
|
+
sha1 = Digest::SHA1.new
|
21
|
+
input = env['rack.input']
|
22
|
+
resp = {}
|
23
|
+
|
24
|
+
i = 0
|
25
|
+
while buf = input.read(@bs)
|
26
|
+
sha1.update(buf)
|
27
|
+
i += 1
|
28
|
+
end
|
29
|
+
resp[:sha1] = sha1.hexdigest
|
30
|
+
|
31
|
+
# rewind and read again
|
32
|
+
input.rewind
|
33
|
+
sha1.reset
|
34
|
+
|
35
|
+
while buf = input.read(@bs)
|
36
|
+
sha1.update(buf)
|
37
|
+
end
|
38
|
+
|
39
|
+
if resp[:sha1] == sha1.hexdigest
|
40
|
+
resp[:sysread_read_byte_match] = true
|
41
|
+
end
|
42
|
+
resp[:content_md5] = env['HTTP_CONTENT_MD5']
|
43
|
+
|
44
|
+
[ 200, @hdr.merge({'X-Resp' => resp.inspect}), [] ]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def teardown
|
49
|
+
@server.stop
|
50
|
+
@random.close
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_put
|
54
|
+
start_server(@sha1_app)
|
55
|
+
sock = TCPSocket.new(@addr, @port)
|
56
|
+
sock.syswrite("PUT / HTTP/1.0\r\nContent-Length: #{length}\r\n\r\n")
|
57
|
+
@count.times do |i|
|
58
|
+
buf = @random.sysread(@bs)
|
59
|
+
@sha1.update(buf)
|
60
|
+
sock.syswrite(buf)
|
61
|
+
end
|
62
|
+
read = sock.read.split(/\r\n/)
|
63
|
+
assert_equal "HTTP/1.0 200 OK", read[0]
|
64
|
+
resp = eval(read.grep(/^X-Resp: /).first.sub!(/X-Resp: /, ''))
|
65
|
+
assert_equal @sha1.hexdigest, resp[:sha1]
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_put_content_md5
|
69
|
+
start_server(@sha1_app)
|
70
|
+
md5 = Digest::MD5.new
|
71
|
+
sock = TCPSocket.new(@addr, @port)
|
72
|
+
sock.syswrite("PUT / HTTP/1.0\r\nTransfer-Encoding: chunked\r\n" \
|
73
|
+
"Trailer: Content-MD5\r\n\r\n")
|
74
|
+
@count.times do |i|
|
75
|
+
buf = @random.sysread(@bs)
|
76
|
+
@sha1.update(buf)
|
77
|
+
md5.update(buf)
|
78
|
+
sock.syswrite("#{'%x' % buf.size}\r\n")
|
79
|
+
sock.syswrite(buf << "\r\n")
|
80
|
+
end
|
81
|
+
sock.syswrite("0\r\n")
|
82
|
+
|
83
|
+
content_md5 = [ md5.digest! ].pack('m').strip.freeze
|
84
|
+
sock.syswrite("Content-MD5: #{content_md5}\r\n\r\n")
|
85
|
+
read = sock.read.split(/\r\n/)
|
86
|
+
assert_equal "HTTP/1.0 200 OK", read[0]
|
87
|
+
resp = eval(read.grep(/^X-Resp: /).first.sub!(/X-Resp: /, ''))
|
88
|
+
assert_equal @sha1.hexdigest, resp[:sha1]
|
89
|
+
#assert_equal content_md5, resp[:content_md5]
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_put_trickle_small
|
93
|
+
start_server(@sha1_app)
|
94
|
+
@count, @bs = 2, 128
|
95
|
+
assert_equal 256, length
|
96
|
+
sock = TCPSocket.new(@addr, @port)
|
97
|
+
hdr = "PUT / HTTP/1.0\r\nContent-Length: #{length}\r\n\r\n"
|
98
|
+
@count.times do
|
99
|
+
buf = @random.sysread(@bs)
|
100
|
+
@sha1.update(buf)
|
101
|
+
hdr << buf
|
102
|
+
sock.syswrite(hdr)
|
103
|
+
hdr = ''
|
104
|
+
sleep 0.6
|
105
|
+
end
|
106
|
+
read = sock.read.split(/\r\n/)
|
107
|
+
assert_equal "HTTP/1.0 200 OK", read[0]
|
108
|
+
resp = eval(read.grep(/^X-Resp: /).first.sub!(/X-Resp: /, ''))
|
109
|
+
assert_equal @sha1.hexdigest, resp[:sha1]
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_put_keepalive_truncates_small_overwrite
|
113
|
+
start_server(@sha1_app)
|
114
|
+
sock = TCPSocket.new(@addr, @port)
|
115
|
+
to_upload = length + 1
|
116
|
+
sock.syswrite("PUT / HTTP/1.0\r\nContent-Length: #{to_upload}\r\n\r\n")
|
117
|
+
@count.times do
|
118
|
+
buf = @random.sysread(@bs)
|
119
|
+
@sha1.update(buf)
|
120
|
+
sock.syswrite(buf)
|
121
|
+
end
|
122
|
+
sock.syswrite('12345') # write 4 bytes more than we expected
|
123
|
+
@sha1.update('1')
|
124
|
+
|
125
|
+
buf = sock.readpartial(4096)
|
126
|
+
while buf !~ /\r\n\r\n/
|
127
|
+
buf << sock.readpartial(4096)
|
128
|
+
end
|
129
|
+
read = buf.split(/\r\n/)
|
130
|
+
assert_equal "HTTP/1.0 200 OK", read[0]
|
131
|
+
resp = eval(read.grep(/^X-Resp: /).first.sub!(/X-Resp: /, ''))
|
132
|
+
#assert_equal to_upload, resp[:size]
|
133
|
+
assert_equal @sha1.hexdigest, resp[:sha1]
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_put_excessive_overwrite_closed
|
137
|
+
tmp = Tempfile.new('overwrite_check')
|
138
|
+
tmp.sync = true
|
139
|
+
start_server(lambda { |env|
|
140
|
+
nr = 0
|
141
|
+
while buf = env['rack.input'].read(65536)
|
142
|
+
nr += buf.size
|
143
|
+
end
|
144
|
+
tmp.write(nr.to_s)
|
145
|
+
[ 200, @hdr, [] ]
|
146
|
+
})
|
147
|
+
sock = TCPSocket.new(@addr, @port)
|
148
|
+
buf = ' ' * @bs
|
149
|
+
sock.syswrite("PUT / HTTP/1.0\r\nContent-Length: #{length}\r\n\r\n")
|
150
|
+
|
151
|
+
@count.times { sock.syswrite(buf) }
|
152
|
+
assert_raises(Errno::ECONNRESET, Errno::EPIPE) do
|
153
|
+
16384.times { sock.syswrite(buf) }
|
154
|
+
end
|
155
|
+
sock.gets
|
156
|
+
tmp.rewind
|
157
|
+
assert_equal length, tmp.read.to_i
|
158
|
+
end
|
159
|
+
|
160
|
+
# Despite reading numerous articles and inspecting the 1.9.1-p0 C
|
161
|
+
# source, Eric Wong will never trust that we're always handling
|
162
|
+
# encoding-aware IO objects correctly. Thus this test uses shell
|
163
|
+
# utilities that should always operate on files/sockets on a
|
164
|
+
# byte-level.
|
165
|
+
def test_uncomfortable_with_onenine_encodings
|
166
|
+
# POSIX doesn't require all of these to be present on a system
|
167
|
+
which('curl') or return
|
168
|
+
which('sha1sum') or return
|
169
|
+
which('dd') or return
|
170
|
+
|
171
|
+
start_server(@sha1_app)
|
172
|
+
|
173
|
+
tmp = Tempfile.new('dd_dest')
|
174
|
+
assert(system("dd", "if=#{@random.path}", "of=#{tmp.path}",
|
175
|
+
"bs=#{@bs}", "count=#{@count}"),
|
176
|
+
"dd #@random to #{tmp}")
|
177
|
+
sha1_re = %r!\b([a-f0-9]{40})\b!
|
178
|
+
sha1_out = `sha1sum #{tmp.path}`
|
179
|
+
|
180
|
+
assert $?.success?, 'sha1sum ran OK'
|
181
|
+
|
182
|
+
assert_match(sha1_re, sha1_out)
|
183
|
+
sha1 = sha1_re.match(sha1_out)[1]
|
184
|
+
resp = `curl -isSfN -T#{tmp.path} http://#@addr:#@port/`
|
185
|
+
|
186
|
+
assert $?.success?, 'curl ran OK'
|
187
|
+
assert_match(%r!\b#{sha1}\b!, resp)
|
188
|
+
assert_match(/sysread_read_byte_match/, resp)
|
189
|
+
|
190
|
+
# small StringIO path
|
191
|
+
assert(system("dd", "if=#{@random.path}", "of=#{tmp.path}",
|
192
|
+
"bs=1024", "count=1"),
|
193
|
+
"dd #@random to #{tmp}")
|
194
|
+
sha1_re = %r!\b([a-f0-9]{40})\b!
|
195
|
+
sha1_out = `sha1sum #{tmp.path}`
|
196
|
+
assert $?.success?, 'sha1sum ran OK'
|
197
|
+
|
198
|
+
assert_match(sha1_re, sha1_out)
|
199
|
+
sha1 = sha1_re.match(sha1_out)[1]
|
200
|
+
resp = `curl -isSfN -T#{tmp.path} http://#@addr:#@port/`
|
201
|
+
assert $?.success?, 'curl ran OK'
|
202
|
+
assert_match(%r!\b#{sha1}\b!, resp)
|
203
|
+
assert_match(/sysread_read_byte_match/, resp)
|
204
|
+
end
|
205
|
+
|
206
|
+
=begin
|
207
|
+
def test_chunked_upload_via_curl
|
208
|
+
# POSIX doesn't require all of these to be present on a system
|
209
|
+
which('curl') or return
|
210
|
+
which('sha1sum') or return
|
211
|
+
which('dd') or return
|
212
|
+
|
213
|
+
start_server(@sha1_app)
|
214
|
+
|
215
|
+
tmp = Tempfile.new('dd_dest')
|
216
|
+
assert(system("dd", "if=#{@random.path}", "of=#{tmp.path}",
|
217
|
+
"bs=#{@bs}", "count=#{@count}"),
|
218
|
+
"dd #@random to #{tmp}")
|
219
|
+
sha1_re = %r!\b([a-f0-9]{40})\b!
|
220
|
+
sha1_out = `sha1sum #{tmp.path}`
|
221
|
+
assert $?.success?, 'sha1sum ran OK'
|
222
|
+
|
223
|
+
assert_match(sha1_re, sha1_out)
|
224
|
+
sha1 = sha1_re.match(sha1_out)[1]
|
225
|
+
cmd = "curl -H 'X-Expect-Size: #{tmp.size}' --tcp-nodelay \
|
226
|
+
-isSf --no-buffer -T- " \
|
227
|
+
"http://#@addr:#@port/"
|
228
|
+
resp = Tempfile.new('resp')
|
229
|
+
resp.sync = true
|
230
|
+
|
231
|
+
rd, wr = IO.pipe
|
232
|
+
wr.sync = rd.sync = true
|
233
|
+
pid = fork {
|
234
|
+
STDIN.reopen(rd)
|
235
|
+
rd.close
|
236
|
+
wr.close
|
237
|
+
STDOUT.reopen(resp)
|
238
|
+
exec cmd
|
239
|
+
}
|
240
|
+
rd.close
|
241
|
+
|
242
|
+
tmp.rewind
|
243
|
+
@count.times { |i|
|
244
|
+
wr.write(tmp.read(@bs))
|
245
|
+
sleep(rand / 10) if 0 == i % 8
|
246
|
+
}
|
247
|
+
wr.close
|
248
|
+
pid, status = Process.waitpid2(pid)
|
249
|
+
|
250
|
+
resp.rewind
|
251
|
+
resp = resp.read
|
252
|
+
assert status.success?, 'curl ran OK'
|
253
|
+
assert_match(%r!\b#{sha1}\b!, resp)
|
254
|
+
assert_match(/sysread_read_byte_match/, resp)
|
255
|
+
assert_match(/expect_size_match/, resp)
|
256
|
+
end
|
257
|
+
=end
|
258
|
+
|
259
|
+
def test_curl_chunked_small
|
260
|
+
# POSIX doesn't require all of these to be present on a system
|
261
|
+
which('curl') or return
|
262
|
+
which('sha1sum') or return
|
263
|
+
which('dd') or return
|
264
|
+
|
265
|
+
start_server(@sha1_app)
|
266
|
+
|
267
|
+
tmp = Tempfile.new('dd_dest')
|
268
|
+
# small StringIO path
|
269
|
+
assert(system("dd", "if=#{@random.path}", "of=#{tmp.path}",
|
270
|
+
"bs=1024", "count=1"),
|
271
|
+
"dd #@random to #{tmp}")
|
272
|
+
sha1_re = %r!\b([a-f0-9]{40})\b!
|
273
|
+
sha1_out = `sha1sum #{tmp.path}`
|
274
|
+
assert $?.success?, 'sha1sum ran OK'
|
275
|
+
|
276
|
+
assert_match(sha1_re, sha1_out)
|
277
|
+
sha1 = sha1_re.match(sha1_out)[1]
|
278
|
+
resp = `curl -H 'X-Expect-Size: #{tmp.size}' --tcp-nodelay \
|
279
|
+
-isSf --no-buffer -T- http://#@addr:#@port/ < #{tmp.path}`
|
280
|
+
assert $?.success?, 'curl ran OK'
|
281
|
+
assert_match(%r!\b#{sha1}\b!, resp)
|
282
|
+
assert_match(/sysread_read_byte_match/, resp)
|
283
|
+
#assert_match(/expect_size_match/, resp)
|
284
|
+
end
|
285
|
+
|
286
|
+
private
|
287
|
+
|
288
|
+
def length
|
289
|
+
@bs * @count
|
290
|
+
end
|
291
|
+
|
292
|
+
def start_server(app)
|
293
|
+
@server = Jubilee::Server.new app
|
294
|
+
@server.start
|
295
|
+
sleep 0.1
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|