ruby-net-nntp 0.2.2 → 1.0.0

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.
@@ -0,0 +1,634 @@
1
+ require File.join(File.dirname(__FILE__), %w[.. spec_helper])
2
+
3
+ describe Net::NNTP do
4
+ before(:each) do
5
+ @nntp = Net::NNTP.new
6
+ end
7
+
8
+ it 'should have server and port defaulting to localhost' do
9
+ @nntp.host.should == 'localhost'
10
+ @nntp.port.should == 119
11
+ end
12
+
13
+ it 'should be able to process an option hash as argument' do
14
+ nntp = Net::NNTP.new :host => '0.0.0.0', :port => 11911
15
+ nntp.host.should == '0.0.0.0'
16
+ nntp.port.should == 11911
17
+ end
18
+
19
+ it 'should be able to connect' do
20
+ socket = flexmock('socket')
21
+ socket.should_receive(:readline).and_return('200 Mock Server ready')
22
+ socket.should_receive(:closed?).once.and_return(false)
23
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
24
+ tcpsocket.should_receive(:new).once.and_return(socket)
25
+ response = @nntp.connect
26
+ response.should be_kind_of(Net::NNTP::PostingAllowed)
27
+ response.code.should == '200'
28
+ response.message.should == 'Mock Server ready'
29
+ @nntp.should be_connected
30
+ end
31
+
32
+ it 'should be able to close the connection' do
33
+ socket = flexmock('socket')
34
+ socket.should_receive(:readline).once.and_return('200 Mock Server ready').ordered
35
+ socket.should_receive(:closed?).twice.and_return(false).ordered
36
+ socket.should_receive(:close).once.and_return(nil).ordered
37
+ socket.should_receive(:closed?).once.and_return(true).ordered
38
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
39
+ tcpsocket.should_receive(:new).once.and_return(socket)
40
+ response = @nntp.connect
41
+ response.should be_kind_of(Net::NNTP::PostingAllowed)
42
+ response.code.should == '200'
43
+ response.message.should == 'Mock Server ready'
44
+ @nntp.should be_connected
45
+ @nntp.close
46
+ @nntp.should_not be_connected
47
+ end
48
+
49
+ it 'should be able to authenticate automagically' do
50
+ socket = flexmock('socket')
51
+ socket.should_receive(:closed?).and_return(false)
52
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
53
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
54
+ tcpsocket.should_receive(:new).once.and_return(socket)
55
+ response = @nntp.connect
56
+ response.should be_kind_of(Net::NNTP::PostingAllowed)
57
+ socket.should_receive(:write).once.with("GROUP alt.test\r\n").ordered
58
+ socket.should_receive(:readline).once.and_return("480 Authentication required\r\n").ordered
59
+ request = Net::NNTP::Group.new('alt.test')
60
+ response = @nntp.process(request)
61
+ response.should be_kind_of(Net::NNTP::AuthenticationRequired)
62
+ socket.should_receive(:write).once.with("AUTHINFO USER user\r\n").ordered
63
+ socket.should_receive(:readline).once.and_return("381 Password next\r\n").ordered
64
+ socket.should_receive(:write).once.with("AUTHINFO PASS example\r\n").ordered
65
+ socket.should_receive(:readline).once.and_return("281 Welcome\r\n").ordered
66
+ request = Net::NNTP::Authinfo.new('user', 'user')
67
+ response = @nntp.process(request)
68
+ response.should be_kind_of(Net::NNTP::PasswordRequired)
69
+ request = Net::NNTP::Authinfo.new('pass', 'example')
70
+ response = @nntp.process(request)
71
+ response.should be_kind_of(Net::NNTP::AuthenticationAccepted)
72
+ end
73
+
74
+ it 'should be able to process a request and chain the request to the response' do
75
+ socket = flexmock('socket')
76
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
77
+ tcpsocket.should_receive(:new).once.and_return(socket)
78
+ socket.should_expect { |s|
79
+ s.should_be_strict
80
+ s.readline { "200 Mock server ready\r\n" }.once
81
+ s.closed? { false }
82
+ s.write("GROUP alt.test\r\n")
83
+ s.readline {"211 1234 3000234 3002322 misc.test\r\n"}
84
+ }
85
+ response = @nntp.connect
86
+ request = Net::NNTP::Group.new('alt.test')
87
+ @response = @nntp.process(request)
88
+ @response.should == @nntp.last_response
89
+ @response.request.should == request
90
+ end
91
+
92
+ it 'should be able to initialize with a block and close the socket on exiting' do
93
+ socket = flexmock('socket')
94
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
95
+ tcpsocket.should_receive(:new).once.and_return(socket)
96
+ socket.should_expect {|s|
97
+ s.should_be_strict
98
+ s.readline { "200 Mock server ready" }
99
+ s.closed? {false}
100
+ s.write("GROUP misc.test\r\n")
101
+ s.readline {"211 1234 3000234 3002322 misc.test\r\n"}
102
+ s.closed? { false }
103
+ s.close
104
+ s.closed? { true }
105
+ }
106
+ nntp = Net::NNTP.new {|n|
107
+ n.connect
108
+ @response = n.group 'misc.test'
109
+ }
110
+ nntp.should_not be_connected
111
+ end
112
+
113
+ it 'should be able to initialize with a block and close the socket on exception in block' do
114
+ socket = flexmock('socket')
115
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
116
+ tcpsocket.should_receive(:new).once.and_return(socket)
117
+ socket.should_expect {|s|
118
+ s.should_be_strict
119
+ s.readline { "200 Mock server ready" }
120
+ s.closed? { false }
121
+ s.close
122
+ }
123
+ proc do
124
+ Net::NNTP.new {|n|
125
+ n.connect
126
+ raise "some error"
127
+ }
128
+ end.should raise_error(RuntimeError)
129
+ end
130
+
131
+ it 'should record the current group response' do
132
+ socket = flexmock('socket')
133
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
134
+ tcpsocket.should_receive(:new).once.and_return(socket)
135
+ socket.should_receive(:closed?).and_return(false)
136
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
137
+ socket.should_receive(:write).once.with("GROUP alt.test\r\n").ordered
138
+ socket.should_receive(:readline).once.and_return("211 1234 3000234 3002322 misc.test\r\n").ordered
139
+ response = @nntp.connect
140
+ request = Net::NNTP::Group.new('alt.test')
141
+ @response = @nntp.process(request)
142
+ @response.should == @nntp.last_response
143
+ @nntp.current_group.should == @response
144
+ end
145
+
146
+ it 'should record the current selected article' do
147
+ socket = flexmock('socket')
148
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
149
+ tcpsocket.should_receive(:new).once.and_return(socket)
150
+ socket.should_expect { |s|
151
+ s.should_be_strict
152
+ s.readline { "200 Mock Server ready\r\n" }.once
153
+ s.closed? { false }
154
+ s.write("GROUP alt.test\r\n")
155
+ s.readline {"211 1234 3000234 3002322 misc.test\r\n"}.once
156
+ s.closed? { false }
157
+ s.write("NEXT\r\n")
158
+ s.readline {"223 3000237 <668929@example.org> retrieved\r\n"}.once
159
+ }
160
+ #socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
161
+ #socket.should_receive(:closed?).once.and_return(false).ordered
162
+ #socket.should_receive(:write).once.with("GROUP alt.test\r\n").ordered
163
+ #socket.should_receive(:readline).once.and_return("211 1234 3000234 3002322 misc.test\r\n")
164
+ #socket.should_receive(:closed?).once.and_return(false).ordered
165
+ #socket.should_receive(:write).once.with("NEXT\r\n").ordered
166
+ #socket.should_receive(:readline).once.and_return("223 3000237 <668929@example.org> retrieved\r\n").ordered
167
+ response = @nntp.connect
168
+ request = Net::NNTP::Group.new('alt.test')
169
+ @response = @nntp.process(request)
170
+ request = Net::NNTP::Next.new
171
+ @response = @nntp.process(request)
172
+ @nntp.current_article.should == @response
173
+ @nntp.current_article.number.should == 3000237
174
+ end
175
+
176
+ it 'should be able to proxy the authentication cycle' do
177
+ socket = flexmock('socket')
178
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
179
+ tcpsocket.should_receive(:new).once.and_return(socket)
180
+ socket.should_receive(:closed?).and_return(false)
181
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
182
+ socket.should_receive(:write).once.with("GROUP alt.test\r\n").ordered
183
+ socket.should_receive(:readline).once.and_return("480 Authentication required\r\n").ordered
184
+ socket.should_receive(:write).once.with("AUTHINFO USER user\r\n").ordered
185
+ socket.should_receive(:readline).once.and_return("381 Password next\r\n").ordered
186
+ socket.should_receive(:write).once.with("AUTHINFO PASS example\r\n").ordered
187
+ socket.should_receive(:readline).once.and_return("281 Welcome\r\n").ordered
188
+ response = @nntp.connect
189
+ request = Net::NNTP::Group.new('alt.test')
190
+ response = @nntp.process(request)
191
+ @nntp.authenticate('user', 'example').should be_true
192
+ end
193
+
194
+ it 'should be able to reconnect and reauthenticate and replay group and article selection' do
195
+ socket = flexmock('socket')
196
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
197
+ tcpsocket.should_receive(:new).twice.and_return(socket)
198
+ socket.should_expect { |s|
199
+ s.should_be_strict
200
+ s.readline {"200 Mock Server ready\r\n"}
201
+ s.closed? { false }
202
+ s.write("GROUP alt.test\r\n")
203
+ s.readline {"480 Authentication required\r\n"}
204
+ s.closed? { false }
205
+ s.write("AUTHINFO USER user\r\n")
206
+ s.readline {"381 Password next\r\n"}
207
+ s.closed? { false }
208
+ s.write("AUTHINFO PASS example\r\n")
209
+ s.readline {"281 Welcome\r\n"}
210
+ s.closed? { false }
211
+ s.write("GROUP alt.test\r\n")
212
+ s.readline {"211 1234 3000234 3002322 misc.test\r\n"}
213
+ s.closed? { false }
214
+ s.write("STAT\r\n")
215
+ s.readline {"223 3000234 <434234@example.com>\r\n"}
216
+ s.closed? { false }
217
+ s.closed? { false }
218
+ s.close { false }
219
+ s.readline {"200 Mock Server ready\r\n"}
220
+ s.closed? { false }
221
+ s.write("AUTHINFO USER user\r\n")
222
+ s.readline {"381 Password next\r\n"}
223
+ s.closed? { false }
224
+ s.write("AUTHINFO PASS example\r\n")
225
+ s.readline {"281 Welcome\r\n"}
226
+ s.closed? { false }
227
+ s.write("GROUP alt.test\r\n")
228
+ s.readline {"211 1234 3000234 3002322 misc.test\r\n"}
229
+ s.closed? { false }
230
+ s.write("STAT\r\n").once.ordered
231
+ s.readline {"223 3000234 <434234@example.com>\r\n"}
232
+ }
233
+ response = @nntp.connect
234
+ request = Net::NNTP::Group.new('alt.test')
235
+ response = @nntp.process(request)
236
+ @nntp.authenticate('user', 'example').should be_true
237
+ @nntp.group 'alt.test'
238
+ @nntp.stat
239
+ @nntp.reconnect
240
+ end
241
+
242
+ it 'should be able to proxy an ARTICLE command' do
243
+ socket = flexmock('socket')
244
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
245
+ tcpsocket.should_receive(:new).once.and_return(socket)
246
+ socket.should_receive(:closed?).and_return(false)
247
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
248
+ @nntp.connect
249
+ socket.should_receive(:write).once.with("ARTICLE <this.message.id@is.not.invalid.in.my.net>\r\n").ordered
250
+ lines = "220 3000234 <45223423@example.com>\r\nPath: pathost!demo!whitehouse!not-for-mail\r\nFrom: \Demo User\ <nobody@example.net>\r\nNewsgroups: misc.test\r\nSubject: I am just a test article\r\nDate: 6 Oct 1998 04:38:40 -0500\r\nOrganization: An Example Net, Uncertain, Texas\r\nMessage-ID: <45223423@example.com>\r\n\r\nThis is just a test article.\r\n.\r\n"
251
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
252
+ @response = @nntp.article('<this.message.id@is.not.invalid.in.my.net>')
253
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
254
+ @response.article.subject.should == 'I am just a test article'
255
+ end
256
+
257
+ it 'should be able to proxy a BODY command' do
258
+ socket = flexmock('socket')
259
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
260
+ tcpsocket.should_receive(:new).once.and_return(socket)
261
+ socket.should_receive(:closed?).and_return(false)
262
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
263
+ @nntp.connect
264
+ socket.should_receive(:write).once.with("BODY <45223423@example.com>\r\n").ordered
265
+ lines = "222 3000234 <45223423@example.com>\r\nThis is just a test article.\r\n.\r\n"
266
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
267
+ @response = @nntp.body('<45223423@example.com>')
268
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
269
+ end
270
+
271
+ it 'should be able to proxy a HEAD command' do
272
+ socket = flexmock('socket')
273
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
274
+ tcpsocket.should_receive(:new).once.and_return(socket)
275
+ socket.should_receive(:closed?).and_return(false)
276
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
277
+ @nntp.connect
278
+ socket.should_receive(:write).once.with("HEAD <this.message.id@is.not.invalid.in.my.net>\r\n").ordered
279
+ lines ="221 3000234 <45223423@example.com>\r\nPath: pathost!demo!whitehouse!not-for-mail\r\nFrom: \"Demo User\" <nobody@example.net>\r\nNewsgroups: misc.test\r\nSubject: I am just a test article\r\nDate: 6 Oct 1998 04:38:40 -0500\r\nOrganization: An Example Net, Uncertain, Texas\r\nMessage-ID: <45223423@example.com>\r\n.\r\n"
280
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
281
+ @response = @nntp.head('<this.message.id@is.not.invalid.in.my.net>')
282
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
283
+ @response.header['subject'].to_s.should == 'I am just a test article'
284
+ @response['subject'].should == 'I am just a test article'
285
+ end
286
+
287
+ it 'should be able to proxy a HELP command' do
288
+ socket = flexmock('socket')
289
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
290
+ tcpsocket.should_receive(:new).once.and_return(socket)
291
+ socket.should_receive(:closed?).and_return(false)
292
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
293
+ @nntp.connect
294
+ socket.should_receive(:write).once.with("HELP\r\n").ordered
295
+ lines = "100 Help text follows\r\nThis is some help text. There is no specific\r\nformatting requirement for this test, though\r\nit is customary for it to list the valid commands\r\nand give a brief definition of what they do.\r\n.\r\n"
296
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
297
+ @response = @nntp.help
298
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
299
+ end
300
+
301
+ it 'should be able to proxy a GROUP command' do
302
+ socket = flexmock('socket')
303
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
304
+ tcpsocket.should_receive(:new).once.and_return(socket)
305
+ socket.should_receive(:closed?).and_return(false)
306
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
307
+ @nntp.connect
308
+ socket.should_receive(:write).once.with("GROUP misc.test\r\n").ordered
309
+ socket.should_receive(:readline).once.and_return("211 1234 3000234 3002322 misc.test\r\n").ordered
310
+ @response = @nntp.group('misc.test')
311
+ @response.should == Net::NNTP::GroupSelected.new(@response.request, '211', '1234 3000234 3002322 misc.test')
312
+ end
313
+
314
+ it 'should be able to proxy a NEXT command' do
315
+ socket = flexmock('socket')
316
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
317
+ tcpsocket.should_receive(:new).once.and_return(socket)
318
+ socket.should_receive(:closed?).and_return(false)
319
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
320
+ @nntp.connect
321
+ socket.should_receive(:write).once.with("NEXT\r\n").ordered
322
+ socket.should_receive(:readline).once.and_return("412 No group selected\r\n").ordered
323
+ @response = @nntp.next
324
+ @response.should be_a_kind_of(Net::NNTP::NoGroupSelected)
325
+ socket.should_receive(:write).once.with("GROUP misc.test\r\n").ordered
326
+ socket.should_receive(:readline).once.and_return("211 1234 3000234 3002322 misc.test\r\n").ordered
327
+ @response = @nntp.group('misc.test')
328
+ socket.should_receive(:write).once.with("NEXT\r\n").ordered
329
+ socket.should_receive(:readline).once.and_return("223 3000237 <668929@example.org> retrieved\r\n").ordered
330
+ @response = @nntp.next
331
+ @response.should == Net::NNTP::ArticleSelected.new(@response.request, '223', '3000237 <668929@example.org> retrieved')
332
+ end
333
+
334
+ it 'should be able to proxy a LAST command' do
335
+ socket = flexmock('socket')
336
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
337
+ tcpsocket.should_receive(:new).once.and_return(socket)
338
+ socket.should_receive(:closed?).and_return(false)
339
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
340
+ @nntp.connect
341
+ socket.should_receive(:write).once.with("LAST\r\n").ordered
342
+ socket.should_receive(:readline).once.and_return("412 No group selected\r\n").ordered
343
+ @response = @nntp.last
344
+ @response.should be_a_kind_of(Net::NNTP::NoGroupSelected)
345
+ socket.should_receive(:write).once.with("GROUP misc.test\r\n").ordered
346
+ socket.should_receive(:readline).once.and_return("211 1234 3000234 3002322 misc.test\r\n").ordered
347
+ @response = @nntp.group('misc.test')
348
+ socket.should_receive(:write).once.with("LAST\r\n").ordered
349
+ socket.should_receive(:readline).once.and_return("422 No previous article\r\n").ordered
350
+ @response = @nntp.last
351
+ @response.should be_a_kind_of(Net::NNTP::NoPreviousArticle)
352
+ socket.should_receive(:write).once.with("NEXT\r\n").ordered
353
+ socket.should_receive(:readline).once.and_return("223 3000237 <668929@example.org> retrieved\r\n")
354
+ @response = @nntp.next
355
+ @response.should == Net::NNTP::ArticleSelected.new(@response.request, '223', '3000237 <668929@example.org> retrieved')
356
+ socket.should_receive(:write).once.with("LAST\r\n").ordered
357
+ socket.should_receive(:readline).once.and_return("223 3000234 <45223423@example.com> retrieved\r\n")
358
+ @response = @nntp.last
359
+ @response.should == Net::NNTP::ArticleSelected.new(@response.request, '223', '3000234 <45223423@example.com> retrieved')
360
+ end
361
+
362
+ it 'should be able to proxy a LIST (ACTIVE) command' do
363
+ socket = flexmock('socket')
364
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
365
+ tcpsocket.should_receive(:new).once.and_return(socket)
366
+ socket.should_receive(:closed?).and_return(false)
367
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
368
+ @nntp.connect
369
+ socket.should_receive(:write).once.with("LIST\r\n").ordered
370
+ lines ="215 List information follows\r\nat.test 3 5 y\r\nalt.test 8 30 y\r\n.\r\n"
371
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
372
+ @response = @nntp.list
373
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
374
+ @response.list[0].name.should == 'at.test'
375
+ @response.list[0].high.should == 5
376
+ @response.list[0].low.should == 3
377
+ @response.list[0].status.should == 'y'
378
+ end
379
+
380
+ it 'should be able to proxy a LISTGROUP command' do
381
+ socket = flexmock('socket')
382
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
383
+ tcpsocket.should_receive(:new).once.and_return(socket)
384
+ socket.should_receive(:closed?).and_return(false)
385
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
386
+ @nntp.connect
387
+ socket.should_receive(:write).once.with("LISTGROUP\r\n").ordered
388
+ lines = "211 2000 3000234 3002322 misc.test list follows\r\n3000234\r\n3000237\r\n3000238\r\n3000239\r\n3002322\r\n.\r\n"
389
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
390
+ @response = @nntp.listgroup
391
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
392
+ @response.list.should == %w(3000234 3000237 3000238 3000239 3002322)
393
+ end
394
+
395
+ it 'should be able to proxy a QUIT command' do
396
+ socket = flexmock('socket')
397
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
398
+ tcpsocket.should_receive(:new).once.and_return(socket)
399
+ socket.should_receive(:closed?).and_return(false)
400
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
401
+ @nntp.connect
402
+ socket.should_receive(:write).once.with("QUIT\r\n").ordered
403
+ socket.should_receive(:readline).and_return("501 good bye\r\n")
404
+ @response = @nntp.quit
405
+ @response.message.should == 'good bye'
406
+ end
407
+
408
+ it 'should be able to proxy a STAT command' do
409
+ socket = flexmock('socket')
410
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
411
+ tcpsocket.should_receive(:new).once.and_return(socket)
412
+ socket.should_receive(:closed?).and_return(false)
413
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
414
+ @nntp.connect
415
+ socket.should_receive(:write).once.with("STAT <45223423@example.com>\r\n").ordered
416
+ socket.should_receive(:readline).and_return("223 0 <45223423@example.com>\r\n")
417
+ @response = @nntp.stat('<45223423@example.com>')
418
+ @response.code.should == '223'
419
+ @response.number.should == 0
420
+ @response.message_id.should == '<45223423@example.com>'
421
+ end
422
+
423
+ it 'should be able to proxy a HDR command' do
424
+ socket = flexmock('socket')
425
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
426
+ tcpsocket.should_receive(:new).once.and_return(socket)
427
+ socket.should_receive(:closed?).and_return(false)
428
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
429
+ @nntp.connect
430
+ socket.should_receive(:write).once.with("HDR Subject 3000234-3000238\r\n").ordered
431
+ lines = "225 Headers follow\r\n3000234 I am just a test article\r\n3000235\r\n3000237 Re: I am just a test article\r\n3000238 Ditto\r\n.\r\n"
432
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
433
+ @response = @nntp.hdr('Subject', :start => 3000234, :end => 3000238)
434
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
435
+ end
436
+
437
+ it 'should be able to proxy a XHDR command' do
438
+ socket = flexmock('socket')
439
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
440
+ tcpsocket.should_receive(:new).once.and_return(socket)
441
+ socket.should_receive(:closed?).and_return(false)
442
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
443
+ @nntp.connect
444
+ socket.should_receive(:write).once.with("XHDR Subject 3000234-3000238\r\n").ordered
445
+ lines = "221 Headers follow\r\n3000234 I am just a test article\r\n3000235\r\n3000237 Re: I am just a test article\r\n3000238 Ditto\r\n.\r\n"
446
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
447
+ @response = @nntp.xhdr('Subject', :start => 3000234, :end => 3000238)
448
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
449
+ end
450
+
451
+ it 'should be able to proxy an OVER command' do
452
+ socket = flexmock('socket')
453
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
454
+ tcpsocket.should_receive(:new).once.and_return(socket)
455
+ socket.should_receive(:closed?).and_return(false)
456
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
457
+ @nntp.connect
458
+ socket.should_receive(:write).once.with("OVER\r\n").ordered
459
+ lines = "224 Overview Information follows\r\n3000234 I am just a test article \"Demo User\" <nobody@example.com> 6 Oct 1998 04:38:40 -0500 <45223423@example.com> <45454@example.net> 1234 17 Xref: news.example.com misc.test:3000363\r\n.\r\n"
460
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
461
+ @response = @nntp.over
462
+ @response.optional_headers['xref'].should == 'news.example.com misc.test:3000363'
463
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
464
+ end
465
+
466
+ it 'should be able to proxy an XOVER command' do
467
+ socket = flexmock('socket')
468
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
469
+ tcpsocket.should_receive(:new).once.and_return(socket)
470
+ socket.should_receive(:closed?).and_return(false)
471
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
472
+ @nntp.connect
473
+ socket.should_receive(:write).once.with("XOVER\r\n").ordered
474
+ lines = "224 Overview Information follows\r\n3000234 I am just a test article \"Demo User\" <nobody@example.com> 6 Oct 1998 04:38:40 -0500 <45223423@example.com> <45454@example.net> 1234 17 Xref: news.example.com misc.test:3000363\r\n.\r\n"
475
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
476
+ @response = @nntp.xover
477
+ @response.optional_headers['xref'].should == 'news.example.com misc.test:3000363'
478
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
479
+ end
480
+
481
+ it 'should be able to process a posting request' do
482
+ body = "From: \"Demo User\" <nobody@example.net>\r\nNewsgroups: misc.test\r\nSubject: I am just a test article\r\nOrganization: An Example Net\r\n\r\nThis is just a test article.\r\n.but with a trick.\r\n..\r\n.\r\n"
483
+ stuffed = body.gsub(/^\./m, "..")
484
+ article = TMail::Mail.parse(body)
485
+ article_stuffed = TMail::Mail.parse(stuffed)
486
+ socket = flexmock('socket')
487
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
488
+ tcpsocket.should_receive(:new).once.and_return(socket)
489
+ socket.should_receive(:closed?).and_return(false)
490
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
491
+ @nntp.connect
492
+ socket.should_receive(:write).once.with("POST\r\n").ordered
493
+ socket.should_receive(:readline).once.and_return("340 Gimmeh!\r\n").ordered
494
+ article_stuffed.to_s.split(/\r?\n/).each do |line|
495
+ line += "\r\n"
496
+ socket.should_receive(:write).once.with(line).ordered
497
+ end
498
+ socket.should_receive(:write).once.with(".\r\n").ordered
499
+ socket.should_receive(:readline).once.and_return("240 done!\r\n").ordered
500
+ request = Net::NNTP::Post.new
501
+ request.body = body
502
+ response = @nntp.process request
503
+ response.should be_kind_of(Net::NNTP::ArticleReceived)
504
+ end
505
+
506
+ it 'should handle a posting rejection gracefully' do
507
+ body ="From: \"Demo User\" <nobody@example.net>\r\nNewsgroups: misc.test\r\nSubject: I am just a test article\r\nOrganization: An Example Net\r\n\r\nThis is just a test article.\r\n.but with a trick.\r\n..\r\n.\r\n"
508
+ stuffed = body.gsub(/^\./m, "..")
509
+ article = TMail::Mail.parse(body)
510
+ article_stuffed = TMail::Mail.parse(stuffed)
511
+ socket = flexmock('socket')
512
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
513
+ tcpsocket.should_receive(:new).once.and_return(socket)
514
+ socket.should_receive(:closed?).and_return(false)
515
+ socket.should_receive(:readline).once.and_return("201 Mock Server ready - no posting\r\n").ordered
516
+ @nntp.connect
517
+ socket.should_receive(:write).once.with("POST\r\n").ordered
518
+ socket.should_receive(:readline).once.and_return("440 Naaah!\r\n").ordered
519
+ request = Net::NNTP::Post.new
520
+ request.body = body
521
+ response = @nntp.process request
522
+ response.should be_kind_of(Net::NNTP::PostingNotPermitted)
523
+ end
524
+
525
+ it 'should be able to process an ihave request' do
526
+ body = "From: \"Demo User\" <nobody@example.net>\r\nNewsgroups: misc.test\r\nSubject: I am just a test article\r\nOrganization: An Example Net\r\nMessage-ID: <45223423@example.com>\r\n\r\nThis is just a test article.\r\n.but with a trick.\r\n..\r\n.\r\n"
527
+ stuffed = body.gsub(/^\./m, "..")
528
+ article = TMail::Mail.parse(body)
529
+ article_stuffed = TMail::Mail.parse(stuffed).to_s
530
+ socket = flexmock('socket')
531
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
532
+ tcpsocket.should_receive(:new).once.and_return(socket)
533
+ socket.should_receive(:closed?).and_return(false)
534
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
535
+ @nntp.connect
536
+ socket.should_receive(:write).once.with("IHAVE <45223423@example.com>\r\n").ordered
537
+ socket.should_receive(:readline).once.and_return("335 Hand over already!\r\n").ordered
538
+ article_stuffed.split(/\r?\n/).each do |line|
539
+ line += "\r\n"
540
+ socket.should_receive(:write).once.with(line).ordered
541
+ end
542
+ socket.should_receive(:write).once.with(".\r\n").ordered
543
+ socket.should_receive(:readline).once.and_return("235 done!\r\n").ordered
544
+ request = Net::NNTP::Ihave.new('<45223423@example.com>')
545
+ request.body = body
546
+ response = @nntp.process request
547
+ response.should be_kind_of(Net::NNTP::TransferOK)
548
+ end
549
+
550
+ it 'should handle an ihave rejection gracefully' do
551
+ body ="Path: pathost!demo!whitehouse!not-for-mail\r\nFrom: \"Demo User\" <nobody@example.net>\r\nNewsgroups: misc.test\r\nSubject: I am just a test article\r\nDate: 6 Oct 1998 04:38:40 -0500\r\nOrganization: An Example Net, Uncertain, Texas\r\nMessage-ID: <45223423@example.com>\r\n\r\nThis is just a test article.\r\n.with special properties\r\n...\r\n..\r\n.\r\n"
552
+ stuffed = body.gsub(/^\./m, "..")
553
+ article = TMail::Mail.parse(body)
554
+ article_stuffed = TMail::Mail.parse(stuffed).to_s
555
+ socket = flexmock('socket')
556
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
557
+ tcpsocket.should_receive(:new).once.and_return(socket)
558
+ socket.should_receive(:closed?).and_return(false)
559
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
560
+ @nntp.connect
561
+ socket.should_receive(:write).once.with("IHAVE <45223423@example.com>\r\n").ordered
562
+ socket.should_receive(:readline).once.and_return("437 not for yoo!\r\n").ordered
563
+ request = Net::NNTP::Ihave.new('<45223423@example.com>')
564
+ request.body = body
565
+ response = @nntp.process request
566
+ response.should be_kind_of(Net::NNTP::TransferRejected)
567
+ end
568
+
569
+ it 'should be able to process a dotstuffed article response' do
570
+ socket = flexmock('socket')
571
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
572
+ tcpsocket.should_receive(:new).once.and_return(socket)
573
+ socket.should_receive(:closed?).and_return(false)
574
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
575
+ @nntp.connect
576
+ socket.should_receive(:write).once.with("ARTICLE <this.message.id@is.not.invalid.in.my.net>\r\n").ordered
577
+ lines ="220 3000234 <45223423@example.com>\r\nPath: pathost!demo!whitehouse!not-for-mail\r\nFrom: \"Demo User\" <nobody@example.net>\r\nNewsgroups: misc.test\r\nSubject: I am just a test article\r\nDate: 6 Oct 1998 04:38:40 -0500\r\nOrganization: An Example Net, Uncertain, Texas\r\nMessage-ID: <45223423@example.com>\r\n\r\nThis is just a test article.\r\n.with special properties\r\n...\r\n..\r\n.\r\n"
578
+ preamble ="This is just a test article.\r\nwith special properties\r\n..\r\n.\r\n\r\n"
579
+ socket.should_receive(:readline).and_return(*lines.scan(/.*\r\n/))
580
+ @response = @nntp.article('<this.message.id@is.not.invalid.in.my.net>')
581
+ @response.raw.should == lines.scan(/.*\r\n/)[1..-1].join
582
+ @response.article.subject.should == 'I am just a test article'
583
+ @response.article.preamble.should == preamble
584
+ end
585
+
586
+ it 'should be able to proxy a POST request' do
587
+ body ="From: \"Demo User\" <nobody@example.net>\r\nNewsgroups: misc.test\r\nSubject: I am just a test article\r\nOrganization: An Example Net\r\n\r\nThis is just a test article.\r\n.but with a trick.\r\n..\r\n.\r\n"
588
+ stuffed = body.gsub(/^\./m, "..")
589
+ article = TMail::Mail.parse(body)
590
+ article_stuffed = TMail::Mail.parse(stuffed)
591
+ socket = flexmock('socket')
592
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
593
+ tcpsocket.should_receive(:new).once.and_return(socket)
594
+ socket.should_receive(:closed?).and_return(false)
595
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
596
+ @nntp.connect
597
+ socket.should_receive(:write).once.with("POST\r\n").ordered
598
+ socket.should_receive(:readline).once.and_return("340 Gimmeh!\r\n").ordered
599
+ article_stuffed.to_s.split(/\r?\n/).each do |line|
600
+ line += "\r\n"
601
+ socket.should_receive(:write).once.with(line).ordered
602
+ end
603
+ socket.should_receive(:write).once.with(".\r\n").ordered
604
+ socket.should_receive(:readline).once.and_return("240 done!\r\n").ordered
605
+ response = @nntp.post(body)
606
+ response.should be_kind_of(Net::NNTP::ArticleReceived)
607
+ end
608
+
609
+ it 'should be able to proxy an IHAVE command' do
610
+ body = "From: \"Demo User\" <nobody@example.net>\r\nNewsgroups: misc.test\r\nSubject: I am just a test article\r\nOrganization: An Example Net\r\nMessage-ID: <45223423@example.com>\r\n\r\nThis is just a test article.\r\n.but with a trick.\r\n..\r\n.\r\n"
611
+ stuffed = body.gsub(/^\./m, "..")
612
+ article = TMail::Mail.parse(body)
613
+ article_stuffed = TMail::Mail.parse(stuffed).to_s
614
+ socket = flexmock('socket')
615
+ tcpsocket = flexmock(TCPSocket, 'tcpsocket')
616
+ tcpsocket.should_receive(:new).once.and_return(socket)
617
+ socket.should_receive(:closed?).and_return(false)
618
+ socket.should_receive(:readline).once.and_return("200 Mock Server ready\r\n").ordered
619
+ @nntp.connect
620
+ socket.should_receive(:write).once.with("IHAVE <45223423@example.com>\r\n").ordered
621
+ socket.should_receive(:readline).once.and_return("335 Hand over already!\r\n").ordered
622
+ article_stuffed.to_s.split(/\r?\n/).each do |line|
623
+ line += "\r\n"
624
+ socket.should_receive(:write).once.with(line).ordered
625
+ end
626
+ socket.should_receive(:write).once.with(".\r\n").ordered
627
+ socket.should_receive(:readline).once.and_return("235 done!\r\n").ordered
628
+ response = @nntp.ihave('<45223423@example.com>', body)
629
+ response.should be_kind_of(Net::NNTP::TransferOK)
630
+ end
631
+
632
+
633
+ end
634
+ # EOF