hatetepe 0.5.2 → 0.6.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. data/.gitignore +7 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +4 -0
  4. data/.yardopts +1 -0
  5. data/Gemfile +9 -4
  6. data/Gemfile.devtools +55 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +39 -192
  9. data/Rakefile +3 -2
  10. data/bin/hatetepe +35 -2
  11. data/config/devtools.yml +2 -0
  12. data/config/flay.yml +3 -0
  13. data/config/flog.yml +2 -0
  14. data/config/mutant.yml +3 -0
  15. data/config/reek.yml +103 -0
  16. data/config/rubocop.yml +58 -0
  17. data/config/yardstick.yml +2 -0
  18. data/hatetepe.gemspec +23 -27
  19. data/lib/hatetepe/client/keep_alive.rb +59 -0
  20. data/lib/hatetepe/client/timeouts.rb +19 -0
  21. data/lib/hatetepe/client.rb +54 -302
  22. data/lib/hatetepe/connection/eventmachine.rb +61 -0
  23. data/lib/hatetepe/connection/status.rb +28 -0
  24. data/lib/hatetepe/errors.rb +7 -0
  25. data/lib/hatetepe/promise.rb +86 -0
  26. data/lib/hatetepe/request.rb +15 -39
  27. data/lib/hatetepe/response.rb +82 -22
  28. data/lib/hatetepe/serializer/encoding.rb +58 -0
  29. data/lib/hatetepe/serializer.rb +61 -0
  30. data/lib/hatetepe/server/keep_alive.rb +53 -13
  31. data/lib/hatetepe/server/timeouts.rb +17 -0
  32. data/lib/hatetepe/server.rb +37 -85
  33. data/lib/hatetepe/support/handlers.rb +19 -0
  34. data/lib/hatetepe/support/keep_alive.rb +14 -0
  35. data/lib/hatetepe/support/message.rb +40 -0
  36. data/lib/hatetepe/version.rb +3 -1
  37. data/lib/hatetepe.rb +29 -7
  38. data/spec/integration/error_handling_spec.rb +7 -0
  39. data/spec/integration/keep_alive_spec.rb +106 -0
  40. data/spec/integration/smoke_spec.rb +21 -0
  41. data/spec/integration/streaming_spec.rb +61 -0
  42. data/spec/integration/timeouts_spec.rb +82 -0
  43. data/spec/shared/integration/server_client_pair.rb +26 -0
  44. data/spec/spec_helper.rb +41 -10
  45. data/spec/support/handler.rb +55 -0
  46. data/spec/support/helper.rb +74 -0
  47. data/spec/unit/client_spec.rb +115 -156
  48. data/spec/unit/connection/eventmachine_spec.rb +146 -0
  49. data/spec/unit/request_spec.rb +35 -0
  50. data/spec/unit/response_spec.rb +42 -0
  51. data/spec/unit/server_spec.rb +65 -100
  52. data/spec/unit/support/keep_alive_spec.rb +52 -0
  53. data/spec/unit/support/message_spec.rb +41 -0
  54. metadata +68 -103
  55. data/Gemfile.lock +0 -46
  56. data/LICENSE +0 -19
  57. data/Procfile +0 -1
  58. data/config.ru +0 -7
  59. data/examples/parallel_requests.rb +0 -32
  60. data/lib/hatetepe/body.rb +0 -182
  61. data/lib/hatetepe/builder.rb +0 -171
  62. data/lib/hatetepe/cli.rb +0 -61
  63. data/lib/hatetepe/connection.rb +0 -73
  64. data/lib/hatetepe/events.rb +0 -35
  65. data/lib/hatetepe/message.rb +0 -13
  66. data/lib/hatetepe/parser.rb +0 -83
  67. data/lib/hatetepe/server/pipeline.rb +0 -20
  68. data/lib/hatetepe/server/rack_app.rb +0 -39
  69. data/lib/rack/handler/hatetepe.rb +0 -33
  70. data/spec/integration/cli/start_spec.rb +0 -113
  71. data/spec/integration/client/keep_alive_spec.rb +0 -23
  72. data/spec/integration/client/timeout_spec.rb +0 -97
  73. data/spec/integration/server/keep_alive_spec.rb +0 -27
  74. data/spec/integration/server/timeout_spec.rb +0 -51
  75. data/spec/unit/body_spec.rb +0 -205
  76. data/spec/unit/builder_spec.rb +0 -372
  77. data/spec/unit/connection_spec.rb +0 -62
  78. data/spec/unit/events_spec.rb +0 -96
  79. data/spec/unit/parser_spec.rb +0 -209
  80. data/spec/unit/rack_handler_spec.rb +0 -60
@@ -1,113 +0,0 @@
1
- require "spec_helper"
2
- require "hatetepe/cli"
3
- require "hatetepe/server"
4
- require "hatetepe/version"
5
- require "rack/builder"
6
-
7
- describe Hatetepe::CLI do
8
- let :rackup do
9
- [ proc {|*| }, {} ]
10
- end
11
-
12
- before do
13
- file = File.expand_path("config.ru")
14
- Rack::Builder.stub(:parse_file).with(file) { rackup }
15
-
16
- $stdout, $stderr = StringIO.new, StringIO.new
17
- @old_env = ENV.delete("RACK_ENV")
18
- end
19
-
20
- after do
21
- $stdout, $stderr = STDOUT, STDERR
22
- ENV["RACK_ENV"] = @old_env
23
- end
24
-
25
- describe "#version" do
26
- it "prints Hatetepe's version" do
27
- Hatetepe::CLI.start([ "version" ])
28
- $stdout.rewind
29
- $stdout.read.should include(Hatetepe::VERSION)
30
- end
31
- end
32
-
33
- describe "#start" do
34
- it "starts a server running the default configuration" do
35
- Hatetepe::Server.should_receive(:start) do |config|
36
- config[:host].should == "127.0.0.1"
37
- config[:port].should equal(3000)
38
- config[:timeout].should be_nil
39
-
40
- config[:app].should equal(rackup[0])
41
- ENV["RACK_ENV"].should == "development"
42
- end
43
- Hatetepe::CLI.start([])
44
- end
45
-
46
- it "writes stuff to stderr" do
47
- Hatetepe::CLI.start([])
48
- $stderr.rewind
49
- $stderr.read.should include("config.ru", "127.0.0.1:3000", "development")
50
- end
51
-
52
- it "starts an EventMachine reactor" do
53
- EM.should_receive(:synchrony)
54
- Hatetepe::CLI.start([])
55
- end
56
-
57
- it "enables epoll" do
58
- EM.should_receive(:epoll)
59
- Hatetepe::CLI.start([])
60
- end
61
-
62
- it "doesn't overwrite RACK_ENV" do
63
- ENV["RACK_ENV"] = "foobar"
64
- Hatetepe::CLI.start([])
65
- ENV["RACK_ENV"].should == "foobar"
66
- end
67
-
68
- describe "with --bind option" do
69
- it "passes the :host option to Server.start" do
70
- Hatetepe::Server.should_receive(:start) do |config|
71
- config[:host].should == "127.0.5.1"
72
- end
73
- Hatetepe::CLI.start([ "--bind", "127.0.5.1" ])
74
- end
75
- end
76
-
77
- describe "with --port option" do
78
- it "passes the :port option to Server.start" do
79
- Hatetepe::Server.should_receive(:start) do |config|
80
- config[:port].should == 5234
81
- end
82
- Hatetepe::CLI.start([ "--port", "5234" ])
83
- end
84
- end
85
-
86
- describe "with --timeout option" do
87
- it "passes the :timeout option to Server.start" do
88
- Hatetepe::Server.should_receive(:start) do |config|
89
- config[:timeout].should == 123.4
90
- end
91
- Hatetepe::CLI.start([ "--timeout", "123.4" ])
92
- end
93
- end
94
-
95
- describe "with --rackup option" do
96
- it "boots from the specified RackUp file" do
97
- file = File.expand_path("./other_config.ru")
98
- Rack::Builder.should_receive(:parse_file).with(file) { rackup }
99
- Hatetepe::Server.should_receive(:start) do |config|
100
- config[:app].should equal(rackup[0])
101
- end
102
- Hatetepe::CLI.start([ "--rackup", "other_config.ru" ])
103
- end
104
- end
105
-
106
- describe "with --env option" do
107
- it "sets RACK_ENV to the specified value" do
108
- Hatetepe::CLI.start([ "--env", "production" ])
109
- ENV["RACK_ENV"].should == "production"
110
- end
111
- end
112
- end
113
- end
@@ -1,23 +0,0 @@
1
- require "hatetepe/cli"
2
- require "hatetepe/client"
3
- require "spec_helper"
4
- require "stringio"
5
- require "yaml"
6
-
7
- describe Hatetepe::Client, "with Keep-Alive" do
8
- let :client do
9
- Hatetepe::Client.start :host => "127.0.0.1", :port => 30001
10
- end
11
-
12
- it "keeps the connection open"
13
-
14
- it "sends Connection: keep-alive"
15
-
16
- describe "and an obviously single request" do
17
- it "sends Connection: close"
18
-
19
- it "closes the connection immediately after the response"
20
- end
21
-
22
- it "closes the connection if the server tells it to"
23
- end
@@ -1,97 +0,0 @@
1
- require "spec_helper"
2
- require "hatetepe/client"
3
- require "hatetepe/server"
4
-
5
- describe Hatetepe::Client do
6
- let :options do
7
- { host: "127.0.0.1", port: 3123 }
8
- end
9
-
10
- let :options2 do
11
- { host: "1.2.3.4", port: 3123}
12
- end
13
-
14
- let :client do
15
- Hatetepe::Client.start(options)
16
- end
17
-
18
- before do
19
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
20
- pending "EventMachine timeouts are not available on JRuby"
21
- end
22
-
23
- Hatetepe::Server.start(options.merge(timeout: 0))
24
- end
25
-
26
- it "times out after 5 seconds of connection inactivity" do
27
- # only verify that 5 seconds is the default, but actually
28
- # use a smaller timeout to keep specs fast
29
- Hatetepe::Client::CONFIG_DEFAULTS[:timeout].should == 5
30
- end
31
-
32
- it "times out after 5 seconds trying to establish a connection" do
33
- # only verify that 5 seconds is the default, but actually
34
- # use a smaller timeout to keep specs fast
35
- Hatetepe::Client::CONFIG_DEFAULTS[:connect_timeout].should == 5
36
- end
37
-
38
- describe "with :timeout option" do
39
- let :client do
40
- Hatetepe::Client.start(options.merge(timeout: 0.5))
41
- end
42
-
43
- it "times out after n seconds of connection inactivity" do
44
- client.should_not be_closed
45
- EM::Synchrony.sleep(0.45)
46
- client.should_not be_closed
47
-
48
- EM::Synchrony.sleep(0.1)
49
- client.should be_closed
50
- client.should be_closed_by_timeout
51
- client.should_not be_closed_by_connect_timeout
52
- end
53
- end
54
-
55
- describe "with :timeout set to 0" do
56
- let :client do
57
- Hatetepe::Client.start(options.merge(timeout: 0))
58
- end
59
-
60
- it "never times out" do
61
- client.should_not be_closed
62
- EM::Synchrony.sleep(0.55)
63
- client.should_not be_closed
64
- end
65
- end
66
-
67
- describe "with :connect_timeout option" do
68
- let :client do
69
- Hatetepe::Client.start(options2.merge(connect_timeout: 0.5))
70
- end
71
-
72
- # this example fails if there's no network connection
73
- it "times out after n seconds trying to establish a connection" do
74
- client.should_not be_closed
75
- EM::Synchrony.sleep(0.45)
76
- client.should_not be_closed
77
-
78
- EM::Synchrony.sleep(0.1)
79
- client.should be_closed
80
- client.should be_closed_by_connect_timeout
81
- client.should_not be_closed_by_timeout
82
- end
83
- end
84
-
85
- describe "with :connect_timeout set to 0" do
86
- let :client do
87
- Hatetepe::Client.start(options2.merge(connect_timeout: 0))
88
- end
89
-
90
- # this example fails if there's no network connection
91
- it "never times out trying to establish a connection" do
92
- client.should_not be_closed
93
- EM::Synchrony.sleep(0.55)
94
- client.should_not be_closed
95
- end
96
- end
97
- end
@@ -1,27 +0,0 @@
1
- require "spec_helper"
2
- require "hatetepe/client"
3
- require "hatetepe/server"
4
-
5
- describe Hatetepe::Server, "with Keep-Alive" do
6
- describe "and :timeout option" do
7
- it "times out the connection after the specified amount of time"
8
- end
9
-
10
- describe "and :timeout option set to 0" do
11
- it "keeps the connection open until the client closes it"
12
- end
13
-
14
- it "closes the connection if the client sends Connection: close"
15
-
16
- it "responds with Connection: keep-alive if the client also sent it"
17
-
18
- ["1.0", "0.9"].each do |version|
19
- describe "and an HTTP #{version} client" do
20
- it "closes the connection after one request" do
21
- pending "http_parser.rb doesn't parse HTTP/0.9" if version == "0.9"
22
- end
23
-
24
- it "doesn't close the connection if the client sent Connection: Keep-Alive"
25
- end
26
- end
27
- end
@@ -1,51 +0,0 @@
1
- require "spec_helper"
2
- require "hatetepe/client"
3
- require "hatetepe/server"
4
-
5
- describe Hatetepe::Server do
6
- before do
7
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
8
- pending "EventMachine timeouts are not available on JRuby"
9
- end
10
- end
11
-
12
- let :options do
13
- { host: "127.0.0.1", port: 3123 }
14
- end
15
-
16
- let :client do
17
- Hatetepe::Client.start(options.merge(timeout: 0))
18
- end
19
-
20
- it "times out after 5 seconds of connection inactivity" do
21
- # only verify that 5 seconds is the default
22
- Hatetepe::Server::CONFIG_DEFAULTS[:timeout].should == 5
23
- end
24
-
25
- describe "with :timeout option" do
26
- before do
27
- Hatetepe::Server.start(options.merge(timeout: 0.5))
28
- end
29
-
30
- it "times out after the specified amount of seconds" do
31
- client.should_not be_closed
32
- EM::Synchrony.sleep(0.45)
33
- client.should_not be_closed
34
-
35
- EM::Synchrony.sleep(0.1)
36
- client.should be_closed_by_remote
37
- end
38
- end
39
-
40
- describe "with :timeout set to 0" do
41
- before do
42
- Hatetepe::Server.start(options.merge(timeout: 0))
43
- end
44
-
45
- it "never times out" do
46
- client.should_not be_closed
47
- EM::Synchrony.sleep(0.55)
48
- client.should_not be_closed
49
- end
50
- end
51
- end
@@ -1,205 +0,0 @@
1
- require "spec_helper"
2
- require "hatetepe/body"
3
-
4
- describe Hatetepe::Body do
5
- let(:body) { Hatetepe::Body.new }
6
-
7
- it "is deferrable" do
8
- body.should respond_to(:callback)
9
- end
10
-
11
- context "#initialize" do
12
- it "leaves the IO stream empty" do
13
- body.io.length.should be_zero
14
- end
15
- end
16
-
17
- context "#initialize(string)" do
18
- let(:body) { Hatetepe::Body.new "herp derp" }
19
-
20
- before { body.close_write }
21
-
22
- it "writes the passed string" do
23
- body.length.should equal(9)
24
- body.io.read.should == "herp derp"
25
- end
26
- end
27
-
28
- context "#sync" do
29
- let(:conn) { double "conn", :paused? => true }
30
-
31
- it "resumes the source connection if any" do
32
- body.source = conn
33
-
34
- conn.should_receive :resume
35
- Fiber.new { body.succeed }.resume
36
- body.sync
37
- end
38
-
39
- it "forwards to EM::Synchrony.sync(body)" do
40
- EM::Synchrony.should_receive(:sync).with(body)
41
- body.sync
42
- end
43
- end
44
-
45
- context "#length" do
46
- let(:length) { double "length" }
47
-
48
- it "forwards to io#length" do
49
- body.stub :sync
50
- body.io.stub :length => length
51
-
52
- body.length.should equal(length)
53
- end
54
-
55
- it "waits for the body to succeed" do
56
- succeeded = false
57
- Fiber.new {
58
- body.length
59
- succeeded = true
60
- }.resume
61
-
62
- succeeded.should be_false
63
-
64
- body.close_write
65
- succeeded.should be_true
66
- end
67
- end
68
-
69
- context "#empty?" do
70
- it "returns true if length is zero" do
71
- body.stub :length => 0
72
- body.empty?.should be_true
73
- end
74
-
75
- it "returns false if length is non-zero" do
76
- body.stub :length => 42
77
- body.empty?.should be_false
78
- end
79
- end
80
-
81
- context "#pos" do
82
- let(:pos) { double "pos" }
83
-
84
- it "forwards to io#pos" do
85
- body.io.stub :pos => pos
86
- body.pos.should equal(pos)
87
- end
88
- end
89
-
90
- context "#rewind" do
91
- it "blocks and forwards to io#rewind" do
92
- body.should_receive(:sync).ordered
93
- body.io.should_receive(:rewind).ordered
94
- body.rewind
95
- end
96
- end
97
-
98
- context "#close_write" do
99
- it "forwards to io#close_write" do
100
- body.io.should_receive :close_write
101
- body.close_write
102
- end
103
-
104
- it "succeeds the body" do
105
- body.should_receive :succeed
106
- body.close_write
107
- end
108
- end
109
-
110
- context "#closed_write?" do
111
- it "forwards to io#closed_write?" do
112
- ret = double("return")
113
- body.io.should_receive(:closed_write?) { ret }
114
-
115
- body.closed_write?.should equal(ret)
116
- end
117
- end
118
-
119
- context "#each {|chunk| ... }" do
120
- it "yields each written chunk until the body succeeds" do
121
- chunks = ["111", "222"]
122
- received, succeeded = [], false
123
-
124
- body.write chunks[0]
125
- Fiber.new {
126
- body.each {|chunk| received << chunk }
127
- succeeded = true
128
- }.resume
129
- received.should == chunks.values_at(0)
130
- succeeded.should be_false
131
-
132
- body.write chunks[1]
133
- received.should == chunks
134
- succeeded.should be_false
135
-
136
- body.succeed
137
- succeeded.should be_true
138
- end
139
-
140
- it "returns self" do
141
- Fiber.new { body.each {}.should == body }.resume
142
- body.succeed
143
- end
144
-
145
- describe "without a block" do
146
- let(:enumerator) { double }
147
-
148
- before { body.stub(:to_enum).with(:each) { enumerator } }
149
-
150
- it "immediately returns an Enumerator" do
151
- Fiber.new { body.each.should == enumerator }.resume
152
- body.succeed
153
- end
154
- end
155
- end
156
-
157
- context "#read(length, buffer)" do
158
- it "waits for the body to succeed" do
159
- ret, read = nil, false
160
-
161
- Fiber.new { body.read; read = true }.resume
162
- read.should be_false
163
-
164
- body.succeed
165
- read.should be_true
166
- end
167
-
168
- it "forwards to io#read" do
169
- body.succeed
170
- args, ret = [double("arg#1"), double("arg#2")], double("ret")
171
-
172
- body.io.should_receive(:read).with(*args) { ret }
173
- body.read(*args).should equal(ret)
174
- end
175
- end
176
-
177
- context "#gets" do
178
- it "waits for the body to succeed" do
179
- ret, read = nil, false
180
-
181
- Fiber.new { body.gets; read = true }.resume
182
- read.should be_false
183
-
184
- body.succeed
185
- read.should be_true
186
- end
187
-
188
- it "forwards to io#gets" do
189
- body.succeed
190
- ret = double("ret")
191
-
192
- body.io.should_receive(:gets) { ret }
193
- body.gets.should equal(ret)
194
- end
195
- end
196
-
197
- context "#write(chunk)" do
198
- it "forwards to io#write" do
199
- arg, ret = double("arg"), double("ret")
200
- body.io.should_receive(:write).with(arg) { ret }
201
-
202
- body.write(arg).should equal(ret)
203
- end
204
- end
205
- end