unicorn 0.1.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.
@@ -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