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.
- data/CHANGELOG +145 -128
- data/CHANGELOG.debian +5 -0
- data/Manifest.txt +37 -0
- data/README.txt +69 -0
- data/Rakefile +28 -0
- data/build-stamp +0 -0
- data/lib/net/nntp.rb +261 -327
- data/lib/net/nntp/request.rb +840 -0
- data/lib/net/nntp/response.rb +731 -0
- data/lib/net/nntp/version.rb +2 -1
- data/script/console +12 -0
- data/spec/net/nntp/request_spec.rb +771 -0
- data/spec/net/nntp/response_spec.rb +994 -0
- data/spec/net/nntp_spec.rb +634 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/stories/all.rb +2 -0
- data/spec/stories/helper.rb +17 -0
- data/spec/stories/net/nntp.rb +7 -0
- data/spec/stories/net/nntp.story +12 -0
- data/spec/stories/steps/nntp.rb +18 -0
- data/tasks/ann.rake +81 -0
- data/tasks/bones.rake +21 -0
- data/tasks/gem.rake +126 -0
- data/tasks/git.rake +41 -0
- data/tasks/manifest.rake +49 -0
- data/tasks/mercurial.rake +6 -0
- data/tasks/notes.rake +28 -0
- data/tasks/pallet.rake +17 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +57 -0
- data/tasks/setup.rb +268 -0
- data/tasks/spec.rake +55 -0
- data/tasks/svn.rake +48 -0
- data/tasks/test.rake +38 -0
- metadata +57 -33
- data/README +0 -46
- data/lib/net/nntp/article.rb +0 -188
- data/lib/net/nntp/group.rb +0 -83
- data/test/functional/test_nntp.rb +0 -288
- data/test/mock/mock_socket.rb +0 -359
- data/test/unit/test_nntp_article.rb +0 -98
- data/test/unit/test_nntp_group.rb +0 -60
@@ -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
|