stomper 2.0.1 → 2.0.2

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