stomper 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,318 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- require 'spec_helper'
3
-
4
- module Stomper
5
- if RUBY_VERSION < '1.9'
6
- describe FrameSerializer do
7
- before(:each) do
8
- @messages = {
9
- :content_type_and_charset => "MESSAGE\ncontent-type:text/plain; charset=ISO-8859-1\ncontent-length:6\na-header: padded \n\nh\xEBllo!\000",
10
- :escaped_headers => "MESSAGE\ncontent-type:text/plain;charset=UTF-8\ncontent-length:7\na\\nspecial\\chead\\\\cer: padded\\c and using\\nspecial\\\\\\\\\\\\ncharacters \n\nh\xC3\xABllo!\000",
11
- :no_content_length => "MESSAGE\ncontent-type:text/plain\n\nh\xC3\xABllo!\000",
12
- :repeated_headers => "MESSAGE\ncontent-type:text/plain\nrepeated header:a value\nrepeated header:alternate value\n\nh\xC3\xABllo!\000",
13
- :non_text_content_type => "MESSAGE\ncontent-type:not-text/other\n\nh\xC3\xABllo!\000",
14
- :no_content_type => "MESSAGE\n\nh\xC3\xABllo!\000",
15
- :invalid_content_length => "MESSAGE\ncontent-length:4\n\n12345\000",
16
- :invalid_header_character => "MESSAGE\ngrandpa:he was:anti\n\n12345\000",
17
- :invalid_header_sequence => "MESSAGE\ngrandpa:he was\\ranti\n\n12345\000",
18
- :malformed_header => "MESSAGE\nearth_below_us\nfloating:weightless\n\n12345\000",
19
- :dangling_header_sequence => "MESSAGE\ngrandpa:he was anti\\\n\n12345\000",
20
- }
21
-
22
- @frames = {
23
- :common => ::Stomper::Frame.new('FRAME', {}, 'body of message'),
24
- :no_headers => ::Stomper::Frame.new('FRAME', {}, 'body of message'),
25
- :no_body => ::Stomper::Frame.new('FRAME'),
26
- :no_command => ::Stomper::Frame.new,
27
- :header_name_with_linefeed => ::Stomper::Frame.new('FRAME', { "a\ntest\nheader" => "va\\lue : is\n\nme"}),
28
- :header_name_with_colon => ::Stomper::Frame.new('FRAME', { "a:test:header" => "va\\lue : is\n\nme"}),
29
- :header_name_with_backslash => ::Stomper::Frame.new('FRAME', { "a\\test\\header" => "va\\lue : is\n\nme"}),
30
- :binary_body_no_content_type => ::Stomper::Frame.new('FRAME', {}, 'body of message'),
31
- :charset_header_text_body => ::Stomper::Frame.new('FRAME', {:'content-type' => 'text/plain; param="value";charset=ISO-8859-1'}, 'body of message'),
32
- :charset_header_binary_body => ::Stomper::Frame.new('FRAME', {:'content-type' => 'application/pdf; param="value";charset=ISO-8859-1'}, 'body of message')
33
- }
34
- #{ :header_1 => 'value 1', :header_2 => '3', :header_3 => '', :'content-type' => 'text/plain'}
35
- @frames[:common][:header_1] = 'value 1'
36
- @frames[:common][:header_2] = '3'
37
- @frames[:common][:header_3] = ''
38
- @frames[:common][:'content-type'] = 'text/plain'
39
- # :header_1 => 'val', :musical => '', :offering => '4'
40
- @frames[:no_body][:header_1] = 'val'
41
- @frames[:no_body][:musical] = ''
42
- @frames[:no_body][:offering] = '4'
43
- @frame_io = StringIO.new
44
- @frame_serializer = FrameSerializer.new(@frame_io)
45
- end
46
-
47
- describe "thread safety" do
48
- before(:each) do
49
- @frame_serializer = FrameSerializer.new(mock('frame io'))
50
- end
51
- it "should synchronize writing to the underlying IO" do
52
- first_called = false
53
- call_next = false
54
- ordered = []
55
- @frame_serializer.stub!(:__write_frame__).and_return do |f|
56
- first_called = true
57
- ordered << 1
58
- Thread.stop
59
- ordered << 2
60
- f
61
- end
62
-
63
- thread_1 = Thread.new do
64
- @frame_serializer.write_frame(mock('frame'))
65
- end
66
- thread_2 = Thread.new do
67
- Thread.pass until call_next
68
- Thread.pass
69
- thread_1.run
70
- end
71
- Thread.pass until first_called
72
- call_next = true
73
-
74
- @frame_serializer.stub!(:__write_frame__).and_return do |f|
75
- ordered << 3
76
- f
77
- end
78
- @frame_serializer.write_frame(mock('frame'))
79
- thread_1.join
80
- thread_2.join
81
- ordered.should == [1, 2, 3]
82
- end
83
-
84
- it "should synchronize reading from the underlying IO" do
85
- first_called = false
86
- call_next = false
87
- ordered = []
88
- @frame_serializer.stub!(:__read_frame__).and_return do
89
- first_called = true
90
- ordered << 1
91
- Thread.stop
92
- ordered << 2
93
- mock('frame 1')
94
- end
95
-
96
- thread_1 = Thread.new do
97
- @frame_serializer.read_frame
98
- end
99
- thread_2 = Thread.new do
100
- Thread.pass until call_next
101
- Thread.pass
102
- thread_1.run
103
- end
104
- Thread.pass until first_called
105
- call_next = true
106
-
107
- @frame_serializer.stub!(:__read_frame__).and_return do
108
- ordered << 3
109
- mock('frame 2')
110
- end
111
- @frame_serializer.read_frame
112
- thread_1.join
113
- thread_2.join
114
- ordered.should == [1, 2, 3]
115
- end
116
-
117
- it "should not make reading and writing mutually exclusive" do
118
- first_called = false
119
- call_next = false
120
- ordered = []
121
- @frame_serializer.stub!(:__write_frame__).and_return do |f|
122
- first_called = true
123
- ordered << 1
124
- Thread.stop
125
- ordered << 2
126
- f
127
- end
128
- @frame_serializer.stub!(:__read_frame__).and_return do
129
- ordered << 3
130
- mock('frame 2')
131
- end
132
-
133
- thread_1 = Thread.new do
134
- @frame_serializer.write_frame(mock('frame'))
135
- end
136
- thread_2 = Thread.new do
137
- Thread.pass until call_next
138
- Thread.pass
139
- thread_1.run
140
- end
141
- Thread.pass until first_called
142
- call_next = true
143
- @frame_serializer.read_frame
144
- thread_1.join
145
- thread_2.join
146
- ordered.should == [1, 3, 2]
147
- end
148
- end
149
-
150
- describe "Protocol 1.0" do
151
- it "should not have extended the V1_1 mixin" do
152
- ::Stomper::FrameSerializer::EXTEND_BY_VERSION['1.1'].each do |mod|
153
- @frame_serializer.should_not be_a_kind_of(mod)
154
- end
155
- end
156
-
157
- describe "writing frames" do
158
- it "should properly serialize a common frame" do
159
- @frame_serializer.write_frame(@frames[:common])
160
- @frame_io.string.should == "FRAME\nheader_1:value 1\nheader_2:3\nheader_3:\ncontent-type:text/plain;charset=UTF-8\ncontent-length:15\n\nbody of message\000"
161
- end
162
-
163
- it "should properly serialize a frame without headers - content type cannot be inferred in Ruby 1.8.7" do
164
- @frame_serializer.write_frame(@frames[:no_headers])
165
- @frame_io.string.should == "FRAME\ncontent-length:15\n\nbody of message\000"
166
- end
167
-
168
- it "should properly serialize a frame without a body" do
169
- @frame_serializer.write_frame(@frames[:no_body])
170
- @frame_io.string.should == "FRAME\nheader_1:val\nmusical:\noffering:4\n\n\000"
171
- end
172
-
173
- it "should properly serialize a frame without a command as a new line" do
174
- @frame_serializer.write_frame(@frames[:no_command])
175
- @frame_io.string.should == "\n"
176
- end
177
-
178
- it "should properly drop LF from header names and values" do
179
- @frame_serializer.write_frame(@frames[:header_name_with_linefeed])
180
- @frame_io.string.should == "FRAME\natestheader:va\\lue : isme\n\n\000"
181
- end
182
-
183
- it "should not escape backslash characters in header names or values" do
184
- @frame_serializer.write_frame(@frames[:header_name_with_backslash])
185
- @frame_io.string.should == "FRAME\na\\test\\header:va\\lue : isme\n\n\000"
186
- end
187
-
188
- it "should drop colons in header names, but leave them alone in values" do
189
- @frame_serializer.write_frame(@frames[:header_name_with_colon])
190
- @frame_io.string.should == "FRAME\natestheader:va\\lue : isme\n\n\000"
191
- end
192
-
193
- it "should not generate a content-type header if the encoding is binary" do
194
- @frame_serializer.write_frame(@frames[:binary_body_no_content_type])
195
- @frame_io.string.should == "FRAME\ncontent-length:15\n\nbody of message\000"
196
- end
197
-
198
- it "should preserve the charset parameter of text bodies, because we have nothing else to work with in Ruby 1.8.7" do
199
- @frame_serializer.write_frame(@frames[:charset_header_text_body])
200
- @frame_io.string.should == "FRAME\ncontent-type:text/plain; param=\"value\";charset=ISO-8859-1\ncontent-length:15\n\nbody of message\000"
201
- end
202
-
203
- it "should preserve the charset parameter of binary bodies, because we have nothing else to work with in Ruby 1.8.7" do
204
- @frame_serializer.write_frame(@frames[:charset_header_binary_body])
205
- @frame_io.string.should == "FRAME\ncontent-type:application/pdf; param=\"value\";charset=ISO-8859-1\ncontent-length:15\n\nbody of message\000"
206
- end
207
- end
208
- end
209
-
210
- describe "Protocol 1.1" do
211
- before(:each) do
212
- @frame_serializer.extend_for_protocol '1.1'
213
- end
214
-
215
- it "should have extended the V1_1 mixin" do
216
- ::Stomper::FrameSerializer::EXTEND_BY_VERSION['1.1'].each do |mod|
217
- @frame_serializer.should be_a_kind_of(mod)
218
- end
219
- end
220
-
221
- describe "writing frames" do
222
- it "should properly serialize a common frame" do
223
- @frame_serializer.write_frame(@frames[:common])
224
- @frame_io.string.should == "FRAME\nheader_1:value 1\nheader_2:3\nheader_3:\ncontent-type:text/plain;charset=UTF-8\ncontent-length:15\n\nbody of message\000"
225
- end
226
-
227
- it "should properly serialize a frame without headers - content type cannot be inferred in Ruby 1.8.7" do
228
- @frame_serializer.write_frame(@frames[:no_headers])
229
- @frame_io.string.should == "FRAME\ncontent-length:15\n\nbody of message\000"
230
- end
231
-
232
- it "should properly serialize a frame without a body" do
233
- @frame_serializer.write_frame(@frames[:no_body])
234
- @frame_io.string.should == "FRAME\nheader_1:val\nmusical:\noffering:4\n\n\000"
235
- end
236
-
237
- it "should properly serialize a frame without a command as a new line" do
238
- @frame_serializer.write_frame(@frames[:no_command])
239
- @frame_io.string.should == "\n"
240
- end
241
-
242
- it "should escape LF in header names and values" do
243
- @frame_serializer.write_frame(@frames[:header_name_with_linefeed])
244
- @frame_io.string.should == "FRAME\na\\ntest\\nheader:va\\\\lue \\c is\\n\\nme\n\n\000"
245
- end
246
-
247
- it "should escape backslashes in header names and values" do
248
- @frame_serializer.write_frame(@frames[:header_name_with_backslash])
249
- @frame_io.string.should == "FRAME\na\\\\test\\\\header:va\\\\lue \\c is\\n\\nme\n\n\000"
250
- end
251
-
252
- it "should escape colons in header names and values" do
253
- @frame_serializer.write_frame(@frames[:header_name_with_colon])
254
- @frame_io.string.should == "FRAME\na\\ctest\\cheader:va\\\\lue \\c is\\n\\nme\n\n\000"
255
- end
256
- end
257
-
258
- describe "reading frames" do
259
- it "should properly de-serialize a simple frame" do
260
- @frame_io.string = @messages[:content_type_and_charset]
261
- frame = @frame_serializer.read_frame
262
- frame.command.should == "MESSAGE"
263
- frame.headers.sort { |a, b| a.first <=> b.first }.should == [
264
- ['a-header', ' padded '], ['content-length', '6'],
265
- ['content-type', 'text/plain; charset=ISO-8859-1']
266
- ]
267
- frame.body.should == "h\xEBllo!"
268
- end
269
- it "should properly read a frame with special characters in its header" do
270
- @frame_io.string = @messages[:escaped_headers]
271
- frame = @frame_serializer.read_frame
272
- frame["a\nspecial:head\\cer"].should == " padded: and using\nspecial\\\\\\ncharacters "
273
- end
274
- it "should properly read a frame with a body and no content-length" do
275
- @frame_io.string = @messages[:no_content_length]
276
- frame = @frame_serializer.read_frame
277
- frame.body.should == "hëllo!"
278
- end
279
- it "should assume a binary charset if none is set and the content-type does not match text/*" do
280
- @frame_io.string = @messages[:non_text_content_type]
281
- frame = @frame_serializer.read_frame
282
- end
283
- it "should assume a binary charset if the content-type header is not specified" do
284
- @frame_io.string = @messages[:no_content_type]
285
- frame = @frame_serializer.read_frame
286
- end
287
- it "should set the value of a header to the first occurrence" do
288
- @frame_io.string = @messages[:repeated_headers]
289
- frame = @frame_serializer.read_frame
290
- end
291
- it "should raise a malformed frame error if the frame is not properly terminated" do
292
- @frame_io.string = @messages[:invalid_content_length]
293
- lambda { @frame_serializer.read_frame }.should raise_error(::Stomper::Errors::MalformedFrameError)
294
- end
295
- # While the spec suggests that all ":" chars be replaced with "\c", ActiveMQ 5.3.2 sends
296
- # a "session" header with a value that contains ":" chars. So, we are NOT going to
297
- # freak out if we receive more than one ":" on a header line.
298
- it "should not raise an error if the frame contains a header value with a raw ':'" do
299
- @frame_io.string = @messages[:invalid_header_character]
300
- lambda { @frame_serializer.read_frame }.should_not raise_error
301
- end
302
- it "should raise an invalid header esacape sequence error if the frame contains a header with an invalid escape sequence" do
303
- @frame_io.string = @messages[:invalid_header_sequence]
304
- lambda { @frame_serializer.read_frame }.should raise_error(::Stomper::Errors::InvalidHeaderEscapeSequenceError)
305
- end
306
- it "should raise an malfored header error if the frame contains an incomplete header" do
307
- @frame_io.string = @messages[:malformed_header]
308
- lambda { @frame_serializer.read_frame }.should raise_error(::Stomper::Errors::MalformedHeaderError)
309
- end
310
- it "should raise an invalid header esacape sequence error if the frame contains a header with a dangling escape sequence" do
311
- @frame_io.string = @messages[:dangling_header_sequence]
312
- lambda { @frame_serializer.read_frame }.should raise_error(::Stomper::Errors::InvalidHeaderEscapeSequenceError)
313
- end
314
- end
315
- end
316
- end
317
- end
318
- end