jubilee 0.4.0 → 0.4.1
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/.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
|