unicorn 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,151 @@
1
+ # Copyright (c) 2009 Eric Wong
2
+ require 'test/test_helper'
3
+
4
+ include Unicorn
5
+
6
+ class UploadTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ @addr = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
10
+ @port = unused_port
11
+ @hdr = {'Content-Type' => 'text/plain', 'Content-Length' => '0'}
12
+ @bs = 4096
13
+ @count = 256
14
+ @server = nil
15
+
16
+ # we want random binary data to test 1.9 encoding-aware IO craziness
17
+ @random = File.open('/dev/urandom','rb')
18
+ @sha1 = Digest::SHA1.new
19
+ @sha1_app = lambda do |env|
20
+ input = env['rack.input']
21
+ resp = { :pos => input.pos, :size => input.stat.size }
22
+ begin
23
+ loop { @sha1.update(input.sysread(@bs)) }
24
+ rescue EOFError
25
+ end
26
+ resp[:sha1] = @sha1.hexdigest
27
+ [ 200, @hdr.merge({'X-Resp' => resp.inspect}), [] ]
28
+ end
29
+ end
30
+
31
+ def teardown
32
+ redirect_test_io { @server.stop(true) } if @server
33
+ @random.close
34
+ end
35
+
36
+ def test_put
37
+ start_server(@sha1_app)
38
+ sock = TCPSocket.new(@addr, @port)
39
+ sock.syswrite("PUT / HTTP/1.0\r\nContent-Length: #{length}\r\n\r\n")
40
+ @count.times do
41
+ buf = @random.sysread(@bs)
42
+ @sha1.update(buf)
43
+ sock.syswrite(buf)
44
+ end
45
+ read = sock.read.split(/\r\n/)
46
+ assert_equal "HTTP/1.1 200 OK", read[0]
47
+ resp = eval(read.grep(/^X-Resp: /).first.sub!(/X-Resp: /, ''))
48
+ assert_equal length, resp[:size]
49
+ assert_equal 0, resp[:pos]
50
+ assert_equal @sha1.hexdigest, resp[:sha1]
51
+ end
52
+
53
+
54
+ def test_put_keepalive_truncates_small_overwrite
55
+ start_server(@sha1_app)
56
+ sock = TCPSocket.new(@addr, @port)
57
+ to_upload = length + 1
58
+ sock.syswrite("PUT / HTTP/1.0\r\nContent-Length: #{to_upload}\r\n\r\n")
59
+ @count.times do
60
+ buf = @random.sysread(@bs)
61
+ @sha1.update(buf)
62
+ sock.syswrite(buf)
63
+ end
64
+ sock.syswrite('12345') # write 4 bytes more than we expected
65
+ @sha1.update('1')
66
+
67
+ read = sock.read.split(/\r\n/)
68
+ assert_equal "HTTP/1.1 200 OK", read[0]
69
+ resp = eval(read.grep(/^X-Resp: /).first.sub!(/X-Resp: /, ''))
70
+ assert_equal to_upload, resp[:size]
71
+ assert_equal 0, resp[:pos]
72
+ assert_equal @sha1.hexdigest, resp[:sha1]
73
+ end
74
+
75
+ def test_put_excessive_overwrite_closed
76
+ start_server(lambda { |env| [ 200, @hdr, [] ] })
77
+ sock = TCPSocket.new(@addr, @port)
78
+ buf = ' ' * @bs
79
+ sock.syswrite("PUT / HTTP/1.0\r\nContent-Length: #{length}\r\n\r\n")
80
+ @count.times { sock.syswrite(buf) }
81
+ assert_raise(Errno::ECONNRESET, Errno::EPIPE) do
82
+ ::Unicorn::Const::CHUNK_SIZE.times { sock.syswrite(buf) }
83
+ end
84
+ end
85
+
86
+ def test_put_handler_closed_file
87
+ nr = '0'
88
+ start_server(lambda { |env|
89
+ env['rack.input'].close
90
+ resp = { :nr => nr.succ! }
91
+ [ 200, @hdr.merge({ 'X-Resp' => resp.inspect}), [] ]
92
+ })
93
+ sock = TCPSocket.new(@addr, @port)
94
+ buf = ' ' * @bs
95
+ sock.syswrite("PUT / HTTP/1.0\r\nContent-Length: #{length}\r\n\r\n")
96
+ @count.times { sock.syswrite(buf) }
97
+ read = sock.read.split(/\r\n/)
98
+ assert_equal "HTTP/1.1 200 OK", read[0]
99
+ resp = eval(read.grep(/^X-Resp: /).first.sub!(/X-Resp: /, ''))
100
+ assert_equal '1', resp[:nr]
101
+
102
+ # server still alive?
103
+ sock = TCPSocket.new(@addr, @port)
104
+ sock.syswrite("GET / HTTP/1.0\r\n\r\n")
105
+ read = sock.read.split(/\r\n/)
106
+ assert_equal "HTTP/1.1 200 OK", read[0]
107
+ resp = eval(read.grep(/^X-Resp: /).first.sub!(/X-Resp: /, ''))
108
+ assert_equal '2', resp[:nr]
109
+ end
110
+
111
+ def test_renamed_file_not_closed
112
+ start_server(lambda { |env|
113
+ new_tmp = Tempfile.new('unicorn_test')
114
+ input = env['rack.input']
115
+ File.rename(input.path, new_tmp.path)
116
+ resp = {
117
+ :inode => input.stat.ino,
118
+ :size => input.stat.size,
119
+ :new_tmp => new_tmp.path,
120
+ :old_tmp => input.path,
121
+ }
122
+ [ 200, @hdr.merge({ 'X-Resp' => resp.inspect}), [] ]
123
+ })
124
+ sock = TCPSocket.new(@addr, @port)
125
+ buf = ' ' * @bs
126
+ sock.syswrite("PUT / HTTP/1.0\r\nContent-Length: #{length}\r\n\r\n")
127
+ @count.times { sock.syswrite(buf) }
128
+ read = sock.read.split(/\r\n/)
129
+ assert_equal "HTTP/1.1 200 OK", read[0]
130
+ resp = eval(read.grep(/^X-Resp: /).first.sub!(/X-Resp: /, ''))
131
+ new_tmp = File.open(resp[:new_tmp])
132
+ assert_equal resp[:inode], new_tmp.stat.ino
133
+ assert_equal length, resp[:size]
134
+ assert ! File.exist?(resp[:old_tmp])
135
+ assert_equal resp[:size], new_tmp.stat.size
136
+ end
137
+
138
+ private
139
+
140
+ def length
141
+ @bs * @count
142
+ end
143
+
144
+ def start_server(app)
145
+ redirect_test_io do
146
+ @server = HttpServer.new(app, :listeners => [ "#{@addr}:#{@port}" ] )
147
+ @server.start
148
+ end
149
+ end
150
+
151
+ end
data/unicorn.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{unicorn}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Eric Wong"]
9
+ s.date = %q{2009-03-10}
10
+ s.default_executable = %q{unicorn}
11
+ s.description = %q{A small fast HTTP library and server for Rack applications.}
12
+ s.email = %q{normalperson@yhbt.net}
13
+ s.executables = ["unicorn"]
14
+ s.extensions = ["ext/unicorn/http11/extconf.rb"]
15
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "TODO", "bin/unicorn", "ext/unicorn/http11/ext_help.h", "ext/unicorn/http11/extconf.rb", "ext/unicorn/http11/http11.c", "ext/unicorn/http11/http11_parser.c", "ext/unicorn/http11/http11_parser.h", "ext/unicorn/http11/http11_parser.rl", "ext/unicorn/http11/http11_parser_common.rl", "lib/unicorn.rb", "lib/unicorn/configurator.rb", "lib/unicorn/const.rb", "lib/unicorn/http_request.rb", "lib/unicorn/http_response.rb", "lib/unicorn/socket.rb", "lib/unicorn/util.rb"]
16
+ s.files = [".document", ".gitignore", "CHANGELOG", "CONTRIBUTORS", "DESIGN", "GNUmakefile", "LICENSE", "Manifest", "README", "Rakefile", "SIGNALS", "TODO", "bin/unicorn", "ext/unicorn/http11/ext_help.h", "ext/unicorn/http11/extconf.rb", "ext/unicorn/http11/http11.c", "ext/unicorn/http11/http11_parser.c", "ext/unicorn/http11/http11_parser.h", "ext/unicorn/http11/http11_parser.rl", "ext/unicorn/http11/http11_parser_common.rl", "lib/unicorn.rb", "lib/unicorn/configurator.rb", "lib/unicorn/const.rb", "lib/unicorn/http_request.rb", "lib/unicorn/http_response.rb", "lib/unicorn/socket.rb", "lib/unicorn/util.rb", "setup.rb", "test/aggregate.rb", "test/benchmark/previous.rb", "test/benchmark/simple.rb", "test/benchmark/utils.rb", "test/exec/README", "test/exec/test_exec.rb", "test/test_helper.rb", "test/tools/trickletest.rb", "test/unit/test_configurator.rb", "test/unit/test_http_parser.rb", "test/unit/test_response.rb", "test/unit/test_server.rb", "test/unit/test_upload.rb", "unicorn.gemspec"]
17
+ s.has_rdoc = true
18
+ s.homepage = %q{http://unicorn.bogomips.org}
19
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Unicorn", "--main", "README"]
20
+ s.require_paths = ["lib", "ext"]
21
+ s.rubyforge_project = %q{unicorn}
22
+ s.rubygems_version = %q{1.3.1}
23
+ s.summary = %q{A small fast HTTP library and server for Rack applications.}
24
+ s.test_files = ["test/unit/test_configurator.rb", "test/unit/test_response.rb", "test/unit/test_upload.rb", "test/unit/test_http_parser.rb", "test/unit/test_server.rb"]
25
+
26
+ if s.respond_to? :specification_version then
27
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
28
+ s.specification_version = 2
29
+
30
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
31
+ else
32
+ end
33
+ else
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unicorn
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Eric Wong
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-10 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A small fast HTTP library and server for Rack applications.
17
+ email: normalperson@yhbt.net
18
+ executables:
19
+ - unicorn
20
+ extensions:
21
+ - ext/unicorn/http11/extconf.rb
22
+ extra_rdoc_files:
23
+ - CHANGELOG
24
+ - LICENSE
25
+ - README
26
+ - TODO
27
+ - bin/unicorn
28
+ - ext/unicorn/http11/ext_help.h
29
+ - ext/unicorn/http11/extconf.rb
30
+ - ext/unicorn/http11/http11.c
31
+ - ext/unicorn/http11/http11_parser.c
32
+ - ext/unicorn/http11/http11_parser.h
33
+ - ext/unicorn/http11/http11_parser.rl
34
+ - ext/unicorn/http11/http11_parser_common.rl
35
+ - lib/unicorn.rb
36
+ - lib/unicorn/configurator.rb
37
+ - lib/unicorn/const.rb
38
+ - lib/unicorn/http_request.rb
39
+ - lib/unicorn/http_response.rb
40
+ - lib/unicorn/socket.rb
41
+ - lib/unicorn/util.rb
42
+ files:
43
+ - .document
44
+ - .gitignore
45
+ - CHANGELOG
46
+ - CONTRIBUTORS
47
+ - DESIGN
48
+ - GNUmakefile
49
+ - LICENSE
50
+ - Manifest
51
+ - README
52
+ - Rakefile
53
+ - SIGNALS
54
+ - TODO
55
+ - bin/unicorn
56
+ - ext/unicorn/http11/ext_help.h
57
+ - ext/unicorn/http11/extconf.rb
58
+ - ext/unicorn/http11/http11.c
59
+ - ext/unicorn/http11/http11_parser.c
60
+ - ext/unicorn/http11/http11_parser.h
61
+ - ext/unicorn/http11/http11_parser.rl
62
+ - ext/unicorn/http11/http11_parser_common.rl
63
+ - lib/unicorn.rb
64
+ - lib/unicorn/configurator.rb
65
+ - lib/unicorn/const.rb
66
+ - lib/unicorn/http_request.rb
67
+ - lib/unicorn/http_response.rb
68
+ - lib/unicorn/socket.rb
69
+ - lib/unicorn/util.rb
70
+ - setup.rb
71
+ - test/aggregate.rb
72
+ - test/benchmark/previous.rb
73
+ - test/benchmark/simple.rb
74
+ - test/benchmark/utils.rb
75
+ - test/exec/README
76
+ - test/exec/test_exec.rb
77
+ - test/test_helper.rb
78
+ - test/tools/trickletest.rb
79
+ - test/unit/test_configurator.rb
80
+ - test/unit/test_http_parser.rb
81
+ - test/unit/test_response.rb
82
+ - test/unit/test_server.rb
83
+ - test/unit/test_upload.rb
84
+ - unicorn.gemspec
85
+ has_rdoc: true
86
+ homepage: http://unicorn.bogomips.org
87
+ post_install_message:
88
+ rdoc_options:
89
+ - --line-numbers
90
+ - --inline-source
91
+ - --title
92
+ - Unicorn
93
+ - --main
94
+ - README
95
+ require_paths:
96
+ - lib
97
+ - ext
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: "0"
103
+ version:
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: "1.2"
109
+ version:
110
+ requirements: []
111
+
112
+ rubyforge_project: unicorn
113
+ rubygems_version: 1.3.1
114
+ signing_key:
115
+ specification_version: 2
116
+ summary: A small fast HTTP library and server for Rack applications.
117
+ test_files:
118
+ - test/unit/test_configurator.rb
119
+ - test/unit/test_response.rb
120
+ - test/unit/test_upload.rb
121
+ - test/unit/test_http_parser.rb
122
+ - test/unit/test_server.rb