File: headers_frame.rb

package info (click to toggle)
ruby-protocol-http2 0.24.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 484 kB
  • sloc: ruby: 3,671; makefile: 4
file content (145 lines) | stat: -rw-r--r-- 3,431 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2019-2024, by Samuel Williams.

require "protocol/http2/headers_frame"

require "protocol/http2/connection_context"
require "protocol/http2/a_frame"

describe Protocol::HTTP2::HeadersFrame do
	let(:data) {"Hello World!"}
	let(:frame) {subject.new}
	
	it_behaves_like Protocol::HTTP2::AFrame do
		def before
			frame.set_flags(Protocol::HTTP2::END_HEADERS)
			frame.pack data
			
			super
		end
	end
	
	with "#pack" do
		it "adds appropriate padding" do
			frame.pack data
			
			expect(frame.length).to be == 12
			expect(frame).not.to be(:priority?)
		end
		
		it "ignores priority data" do
			frame.pack "xxxxx" + data
			frame.set_flags(Protocol::HTTP2::PRIORITY)
			
			expect(frame.length).to be == 17
			expect(frame).to be(:priority?)
			
			expect(frame.unpack).to be == data
		end
	end
	
	with "#unpack" do
		it "removes padding" do
			frame.pack data
			
			expect(frame.unpack).to be == data
		end
	end
	
	with "#continuation" do
		let(:stream) {StringIO.new}
		
		def before
			frame.pack "Hello World", maximum_size: 8
			
			super
		end
		
		it "generates chain of frames" do
			expect(frame).to be(:continued?)
			expect(frame.continuation).to be(:end_headers?)
			
			expect(frame.length).to be == 8
			expect(frame.continuation).not.to be_nil
			expect(frame.continuation.length).to be == 3
		end
		
		it "can read and write continuation frames" do
			frame.write(stream)
			stream.rewind
			
			frame2 = subject.new
			frame2.read(stream, 128)
			
			expect(frame).to be(:continued?)
			expect(frame.continuation).to be(:end_headers?)
			
			expect(frame.length).to be == 8
			expect(frame.continuation).not.to be_nil
			expect(frame.continuation.length).to be == 3
		end
		
		it "fails if the stream id of the continuation doesn't match" do
			frame.continuation.stream_id = frame.stream_id+1
			frame.write(stream)
			stream.rewind
			
			frame2 = subject.new
			expect do
				frame2.read(stream, 128)
			end.to raise_exception(Protocol::HTTP2::ProtocolError, message: be =~ /Invalid stream id/)
		end
		
		it "fails if the frame type of the continuation doesn't match" do
			frame.continuation.type = frame.type+1
			frame.write(stream)
			stream.rewind
			
			frame2 = subject.new
			expect do
				frame2.read(stream, 128)
			end.to raise_exception(Protocol::HTTP2::ProtocolError, message: be =~ /Invalid frame type/)
		end
	end
	
	with "client/server connection" do
		include_context Protocol::HTTP2::ConnectionContext
		
		def before
			client.open!
			server.open!
			
			# We force this to something low so we can exceed it without hitting the socket buffer:
			server.local_settings.current.instance_variable_set(:@maximum_frame_size, 128)
			
			super
		end
		
		let(:stream) {client.create_stream}
		
		it "rejects headers frame that exceeds maximum frame size" do
			frame.stream_id = stream.id
			frame.pack "\0" * (server.local_settings.maximum_frame_size + 1)
			
			client.write_frame(frame)
			
			expect do
				server.read_frame
			end.to raise_exception(Protocol::HTTP2::FrameSizeError)
			
			expect(client).to receive(:receive_goaway)
			
			expect do
				client.read_frame
			end.to raise_exception(Protocol::HTTP2::GoawayError)
		end
	end
	
	with "#inspect" do
		it "can generate a string representation" do
			expect(frame.inspect).to be =~ /Protocol::HTTP2::HeadersFrame stream_id=0 flags=0 0b/
		end
	end
end