plum 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +84 -12
  3. data/circle.yml +27 -0
  4. data/examples/client/large.rb +20 -0
  5. data/examples/client/twitter.rb +51 -0
  6. data/examples/non_tls_server.rb +15 -9
  7. data/examples/static_server.rb +30 -23
  8. data/lib/plum.rb +9 -2
  9. data/lib/plum/client.rb +198 -0
  10. data/lib/plum/client/client_session.rb +91 -0
  11. data/lib/plum/client/connection.rb +19 -0
  12. data/lib/plum/client/legacy_client_session.rb +118 -0
  13. data/lib/plum/client/response.rb +100 -0
  14. data/lib/plum/client/upgrade_client_session.rb +46 -0
  15. data/lib/plum/connection.rb +58 -65
  16. data/lib/plum/connection_utils.rb +1 -1
  17. data/lib/plum/errors.rb +7 -3
  18. data/lib/plum/flow_control.rb +3 -3
  19. data/lib/plum/rack/listener.rb +3 -3
  20. data/lib/plum/rack/server.rb +1 -0
  21. data/lib/plum/rack/session.rb +5 -2
  22. data/lib/plum/server/connection.rb +42 -0
  23. data/lib/plum/{http_connection.rb → server/http_connection.rb} +7 -14
  24. data/lib/plum/{https_connection.rb → server/https_connection.rb} +2 -9
  25. data/lib/plum/stream.rb +54 -24
  26. data/lib/plum/stream_utils.rb +0 -12
  27. data/lib/plum/version.rb +1 -1
  28. data/plum.gemspec +2 -2
  29. data/test/plum/client/test_client.rb +152 -0
  30. data/test/plum/client/test_connection.rb +11 -0
  31. data/test/plum/client/test_legacy_client_session.rb +90 -0
  32. data/test/plum/client/test_response.rb +74 -0
  33. data/test/plum/client/test_upgrade_client_session.rb +45 -0
  34. data/test/plum/connection/test_handle_frame.rb +4 -1
  35. data/test/plum/{test_http_connection.rb → server/test_http_connection.rb} +4 -4
  36. data/test/plum/{test_https_connection.rb → server/test_https_connection.rb} +14 -8
  37. data/test/plum/test_connection.rb +9 -2
  38. data/test/plum/test_connection_utils.rb +9 -0
  39. data/test/plum/test_error.rb +1 -2
  40. data/test/plum/test_frame_factory.rb +37 -0
  41. data/test/plum/test_stream.rb +24 -4
  42. data/test/plum/test_stream_utils.rb +0 -1
  43. data/test/test_helper.rb +5 -2
  44. data/test/utils/assertions.rb +9 -9
  45. data/test/utils/client.rb +19 -0
  46. data/test/utils/server.rb +6 -6
  47. data/test/utils/string_socket.rb +15 -0
  48. metadata +36 -12
@@ -23,7 +23,6 @@ class ConnectionTest < Minitest::Test
23
23
  con << Frame.new(type: :settings, stream_id: 0, payload: _settings * (limit / 6 + 1)).assemble
24
24
  }
25
25
  }
26
-
27
26
  new_con.call {|con|
28
27
  assert_connection_error(:frame_size_error) {
29
28
  con << Frame.new(type: :headers, stream_id: 3, payload: "\x00" * (limit + 1)).assemble
@@ -89,8 +88,16 @@ class ConnectionTest < Minitest::Test
89
88
  }
90
89
  prepare.call {|con|
91
90
  assert_equal(:waiting_continuation, con.state)
92
- con << Frame.new(type: :continuation, flags: [:end_headers], stream_id: 3, payload: "hello").assemble
91
+ con << Frame.new(type: :continuation, flags: [:end_headers], stream_id: 3, payload: "").assemble
93
92
  assert_equal(:open, con.state)
94
93
  }
95
94
  end
95
+
96
+ def test_connection_local_error
97
+ open_server_connection { |con|
98
+ assert_raises(LocalConnectionError) {
99
+ con << Frame.goaway(0, :frame_size_error).assemble
100
+ }
101
+ }
102
+ end
96
103
  end
@@ -26,4 +26,13 @@ class ServerConnectionUtilsTest < Minitest::Test
26
26
  assert_equal(HTTPError::ERROR_CODES[:stream_closed], last.payload.uint32(4))
27
27
  }
28
28
  end
29
+
30
+ def test_push_enabled
31
+ open_server_connection {|con|
32
+ con << Frame.settings(enable_push: 0).assemble
33
+ assert_equal(false, con.push_enabled?)
34
+ con << Frame.settings(enable_push: 1).assemble
35
+ assert_equal(true, con.push_enabled?)
36
+ }
37
+ end
29
38
  end
@@ -7,7 +7,6 @@ class ErrorTest < Minitest::Test
7
7
  assert_equal(0x08, e.http2_error_code)
8
8
  }
9
9
 
10
- test.call ConnectionError
11
- test.call StreamError
10
+ test.call HTTPError
12
11
  end
13
12
  end
@@ -53,4 +53,41 @@ class FrameFactoryTest < Minitest::Test
53
53
  flags: [:ack],
54
54
  payload: "12345678")
55
55
  end
56
+
57
+ def test_continuation
58
+ frame = Frame.continuation(123, "abc", :end_headers)
59
+ assert_frame(frame,
60
+ type: :continuation,
61
+ stream_id: 123,
62
+ flags: [:end_headers],
63
+ payload: "abc")
64
+ end
65
+
66
+ def test_data
67
+ frame = Frame.data(123, "abc".force_encoding("UTF-8"))
68
+ assert_frame(frame,
69
+ type: :data,
70
+ stream_id: 123,
71
+ flags: [],
72
+ payload: "abc")
73
+ assert_equal(Encoding::BINARY, frame.payload.encoding)
74
+ end
75
+
76
+ def test_headers
77
+ frame = Frame.headers(123, "abc", :end_stream)
78
+ assert_frame(frame,
79
+ type: :headers,
80
+ stream_id: 123,
81
+ flags: [:end_stream],
82
+ payload: "abc")
83
+ end
84
+
85
+ def test_push_promise
86
+ frame = Frame.push_promise(345, 2, "abc", :end_headers)
87
+ assert_frame(frame,
88
+ type: :push_promise,
89
+ stream_id: 345,
90
+ flags: [:end_headers],
91
+ payload: "\x00\x00\x00\x02abc")
92
+ end
56
93
  end
@@ -19,14 +19,34 @@ class StreamTest < Minitest::Test
19
19
  }
20
20
  end
21
21
 
22
- def test_stream_close
23
- open_new_stream(state: :half_closed_local) {|stream|
24
- stream.close(:frame_size_error)
22
+ def test_stream_remote_error
23
+ open_server_connection { |con|
24
+ stream = nil
25
+ con.on(:headers) { |s|
26
+ stream = s
27
+ raise RemoteStreamError.new(:frame_size_error)
28
+ }
29
+
30
+ assert_stream_error(:frame_size_error) {
31
+ con << Frame.headers(1, "", :end_headers).assemble
32
+ }
25
33
 
26
34
  last = sent_frames.last
27
35
  assert_equal(:rst_stream, last.type)
28
- assert_equal(StreamError.new(:frame_size_error).http2_error_code, last.payload.uint32)
36
+ assert_equal(HTTPError::ERROR_CODES[:frame_size_error], last.payload.uint32)
29
37
  assert_equal(:closed, stream.state)
30
38
  }
31
39
  end
40
+
41
+ def test_stream_local_error
42
+ open_server_connection { |con|
43
+ stream = nil
44
+ con.on(:headers) { |s| stream = s }
45
+
46
+ con << Frame.headers(1, "", :end_headers).assemble
47
+ assert_raises(LocalStreamError) {
48
+ con << Frame.rst_stream(1, :frame_size_error).assemble
49
+ }
50
+ }
51
+ end
32
52
  end
@@ -1,7 +1,6 @@
1
1
  require "test_helper"
2
2
 
3
3
  using BinaryString
4
-
5
4
  class StreamUtilsTest < Minitest::Test
6
5
  def test_stream_promise
7
6
  open_new_stream {|stream|
@@ -1,5 +1,3 @@
1
- LISTEN_PORT = ENV["PLUM_LISTEN_PORT"] || 40444
2
-
3
1
  unless ENV["SKIP_COVERAGE"]
4
2
  begin
5
3
  require "simplecov"
@@ -26,3 +24,8 @@ include Plum
26
24
  Dir.glob(File.expand_path("../utils/*.rb", __FILE__)).each do |file|
27
25
  require file
28
26
  end
27
+
28
+ LISTEN_PORT = ENV["PLUM_LISTEN_PORT"] || 40444
29
+ TLS_CERT = OpenSSL::X509::Certificate.new File.read(File.expand_path("../server.crt", __FILE__))
30
+ TLS_KEY = OpenSSL::PKey::RSA.new File.read(File.expand_path("../server.key", __FILE__))
31
+ ExampleError = Class.new(RuntimeError)
@@ -1,21 +1,21 @@
1
1
  module CustomAssertions
2
2
  def assert_connection_error(type, &blk)
3
- assert_http_error(Plum::ConnectionError, type, &blk)
3
+ assert_http_error(Plum::RemoteConnectionError, type, &blk)
4
4
  end
5
5
 
6
6
  def assert_stream_error(type, &blk)
7
- assert_http_error(Plum::StreamError, type, &blk)
7
+ assert_http_error(Plum::RemoteStreamError, type, &blk)
8
8
  end
9
9
 
10
10
  def assert_no_error(stream: nil, connection: nil, &blk)
11
- Plum::ConnectionError.reset
12
- Plum::StreamError.reset
11
+ Plum::RemoteConnectionError.reset
12
+ Plum::RemoteStreamError.reset
13
13
  begin
14
14
  blk.call
15
- rescue Plum::HTTPError
15
+ rescue Plum::RemoteHTTPError
16
16
  end
17
- assert_nil(Plum::StreamError.last, "No stream error expected but raised: #{Plum::StreamError.last}")
18
- assert_nil(Plum::ConnectionError.last, "No connection error expected but raised: #{Plum::ConnectionError.last}")
17
+ assert_nil(Plum::RemoteStreamError.last, "No stream error expected but raised: #{Plum::RemoteStreamError.last}")
18
+ assert_nil(Plum::RemoteConnectionError.last, "No connection error expected but raised: #{Plum::RemoteConnectionError.last}")
19
19
  end
20
20
 
21
21
  def assert_frame(frame, **args)
@@ -56,5 +56,5 @@ module LastErrorExtension
56
56
  base.reset
57
57
  end
58
58
  end
59
- Plum::ConnectionError.__send__(:prepend, LastErrorExtension)
60
- Plum::StreamError.__send__(:prepend, LastErrorExtension)
59
+ Plum::RemoteConnectionError.__send__(:prepend, LastErrorExtension)
60
+ Plum::RemoteStreamError.__send__(:prepend, LastErrorExtension)
@@ -0,0 +1,19 @@
1
+ require "timeout"
2
+
3
+ module ServerUtils
4
+ def open_client_connection(scheme = :https)
5
+ io = StringIO.new
6
+ @_ccon = ClientConnection.new(io.method(:write))
7
+ @_ccon << Frame.new(type: :settings, stream_id: 0, flags: [:ack]).assemble
8
+ @_ccon << Frame.new(type: :settings, stream_id: 0).assemble
9
+ if block_given?
10
+ yield @_ccon
11
+ else
12
+ @_ccon
13
+ end
14
+ end
15
+ end
16
+
17
+ class Minitest::Test
18
+ include ServerUtils
19
+ end
@@ -3,7 +3,7 @@ require "timeout"
3
3
  module ServerUtils
4
4
  def open_server_connection(scheme = :https)
5
5
  io = StringIO.new
6
- @_con = (scheme == :https ? HTTPSConnection : HTTPConnection).new(io)
6
+ @_con = (scheme == :https ? HTTPSServerConnection : HTTPServerConnection).new(io)
7
7
  @_con << Connection::CLIENT_CONNECTION_PREFACE
8
8
  @_con << Frame.new(type: :settings, stream_id: 0).assemble
9
9
  if block_given?
@@ -13,16 +13,16 @@ module ServerUtils
13
13
  end
14
14
  end
15
15
 
16
- def open_new_stream(arg1 = nil, **kwargs)
17
- if arg1.is_a?(Connection)
16
+ def open_new_stream(arg1 = nil, state: :idle, **kwargs)
17
+ if arg1.is_a?(ServerConnection)
18
18
  con = arg1
19
19
  else
20
20
  con = open_server_connection
21
21
  end
22
22
 
23
- @_stream = con.instance_eval {
24
- new_stream((con.streams.keys.last||0/2)*2+1, **kwargs)
25
- }
23
+ @_stream = con.instance_eval { stream(((@max_stream_id+1)/2)*2+1) }
24
+ @_stream.set_state(state)
25
+ @_stream.update_dependency(**kwargs)
26
26
  if block_given?
27
27
  yield @_stream
28
28
  else
@@ -0,0 +1,15 @@
1
+ class StringSocket < IO
2
+ # remove all methods
3
+ (IO.instance_methods - Object.instance_methods).each { |symbol| undef_method symbol }
4
+
5
+ extend Forwardable
6
+ def_delegators :@rio, :readpartial
7
+ def_delegators :@wio, :<<, :write
8
+
9
+ attr_reader :rio, :wio
10
+
11
+ def initialize(str = nil)
12
+ @rio = StringIO.new(str.to_s)
13
+ @wio = StringIO.new
14
+ end
15
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - rhenium
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-01 00:00:00.000000000 Z
11
+ date: 2015-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 5.7.0
89
+ version: 5.8.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 5.7.0
96
+ version: 5.8.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -150,7 +150,7 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
- description: A minimal implementation of HTTP/2 server.
153
+ description: An HTTP/2 Library for Ruby
154
154
  email:
155
155
  - k@rhe.jp
156
156
  executables:
@@ -167,11 +167,20 @@ files:
167
167
  - Rakefile
168
168
  - bin/.gitkeep
169
169
  - bin/plum
170
+ - circle.yml
171
+ - examples/client/large.rb
172
+ - examples/client/twitter.rb
170
173
  - examples/non_tls_server.rb
171
174
  - examples/rack.ru
172
175
  - examples/static_server.rb
173
176
  - lib/plum.rb
174
177
  - lib/plum/binary_string.rb
178
+ - lib/plum/client.rb
179
+ - lib/plum/client/client_session.rb
180
+ - lib/plum/client/connection.rb
181
+ - lib/plum/client/legacy_client_session.rb
182
+ - lib/plum/client/response.rb
183
+ - lib/plum/client/upgrade_client_session.rb
175
184
  - lib/plum/connection.rb
176
185
  - lib/plum/connection_utils.rb
177
186
  - lib/plum/errors.rb
@@ -185,8 +194,6 @@ files:
185
194
  - lib/plum/hpack/decoder.rb
186
195
  - lib/plum/hpack/encoder.rb
187
196
  - lib/plum/hpack/huffman.rb
188
- - lib/plum/http_connection.rb
189
- - lib/plum/https_connection.rb
190
197
  - lib/plum/rack.rb
191
198
  - lib/plum/rack/cli.rb
192
199
  - lib/plum/rack/config.rb
@@ -194,16 +201,26 @@ files:
194
201
  - lib/plum/rack/listener.rb
195
202
  - lib/plum/rack/server.rb
196
203
  - lib/plum/rack/session.rb
204
+ - lib/plum/server/connection.rb
205
+ - lib/plum/server/http_connection.rb
206
+ - lib/plum/server/https_connection.rb
197
207
  - lib/plum/stream.rb
198
208
  - lib/plum/stream_utils.rb
199
209
  - lib/plum/version.rb
200
210
  - lib/rack/handler/plum.rb
201
211
  - plum.gemspec
212
+ - test/plum/client/test_client.rb
213
+ - test/plum/client/test_connection.rb
214
+ - test/plum/client/test_legacy_client_session.rb
215
+ - test/plum/client/test_response.rb
216
+ - test/plum/client/test_upgrade_client_session.rb
202
217
  - test/plum/connection/test_handle_frame.rb
203
218
  - test/plum/hpack/test_context.rb
204
219
  - test/plum/hpack/test_decoder.rb
205
220
  - test/plum/hpack/test_encoder.rb
206
221
  - test/plum/hpack/test_huffman.rb
222
+ - test/plum/server/test_http_connection.rb
223
+ - test/plum/server/test_https_connection.rb
207
224
  - test/plum/stream/test_handle_frame.rb
208
225
  - test/plum/test_binary_string.rb
209
226
  - test/plum/test_connection.rb
@@ -214,8 +231,6 @@ files:
214
231
  - test/plum/test_frame.rb
215
232
  - test/plum/test_frame_factory.rb
216
233
  - test/plum/test_frame_utils.rb
217
- - test/plum/test_http_connection.rb
218
- - test/plum/test_https_connection.rb
219
234
  - test/plum/test_stream.rb
220
235
  - test/plum/test_stream_utils.rb
221
236
  - test/server.crt
@@ -223,7 +238,9 @@ files:
223
238
  - test/server.key
224
239
  - test/test_helper.rb
225
240
  - test/utils/assertions.rb
241
+ - test/utils/client.rb
226
242
  - test/utils/server.rb
243
+ - test/utils/string_socket.rb
227
244
  homepage: https://github.com/rhenium/plum
228
245
  licenses:
229
246
  - MIT
@@ -247,13 +264,20 @@ rubyforge_project:
247
264
  rubygems_version: 2.4.5.1
248
265
  signing_key:
249
266
  specification_version: 4
250
- summary: A minimal implementation of HTTP/2 server.
267
+ summary: An HTTP/2 Library for Ruby
251
268
  test_files:
269
+ - test/plum/client/test_client.rb
270
+ - test/plum/client/test_connection.rb
271
+ - test/plum/client/test_legacy_client_session.rb
272
+ - test/plum/client/test_response.rb
273
+ - test/plum/client/test_upgrade_client_session.rb
252
274
  - test/plum/connection/test_handle_frame.rb
253
275
  - test/plum/hpack/test_context.rb
254
276
  - test/plum/hpack/test_decoder.rb
255
277
  - test/plum/hpack/test_encoder.rb
256
278
  - test/plum/hpack/test_huffman.rb
279
+ - test/plum/server/test_http_connection.rb
280
+ - test/plum/server/test_https_connection.rb
257
281
  - test/plum/stream/test_handle_frame.rb
258
282
  - test/plum/test_binary_string.rb
259
283
  - test/plum/test_connection.rb
@@ -264,8 +288,6 @@ test_files:
264
288
  - test/plum/test_frame.rb
265
289
  - test/plum/test_frame_factory.rb
266
290
  - test/plum/test_frame_utils.rb
267
- - test/plum/test_http_connection.rb
268
- - test/plum/test_https_connection.rb
269
291
  - test/plum/test_stream.rb
270
292
  - test/plum/test_stream_utils.rb
271
293
  - test/server.crt
@@ -273,5 +295,7 @@ test_files:
273
295
  - test/server.key
274
296
  - test/test_helper.rb
275
297
  - test/utils/assertions.rb
298
+ - test/utils/client.rb
276
299
  - test/utils/server.rb
300
+ - test/utils/string_socket.rb
277
301
  has_rdoc: