fake_ftp 0.0.8 → 0.0.9
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/lib/fake_ftp/server.rb +3 -3
- data/lib/fake_ftp/version.rb +1 -1
- data/spec/models/fake_ftp/server_spec.rb +391 -407
- metadata +7 -7
data/lib/fake_ftp/server.rb
CHANGED
@@ -44,7 +44,7 @@ module FakeFtp
|
|
44
44
|
@thread = Thread.new do
|
45
45
|
while @started
|
46
46
|
@client = @server.accept
|
47
|
-
respond_with('
|
47
|
+
respond_with('220 Can has FTP?')
|
48
48
|
@connection = Thread.new(@client) do |socket|
|
49
49
|
while @started && !socket.nil? && !socket.closed?
|
50
50
|
respond_with parse(socket.gets)
|
@@ -225,9 +225,9 @@ module FakeFtp
|
|
225
225
|
def active?
|
226
226
|
@mode == :active
|
227
227
|
end
|
228
|
-
|
228
|
+
|
229
229
|
private
|
230
|
-
|
230
|
+
|
231
231
|
def port_is_open?(port)
|
232
232
|
begin
|
233
233
|
Timeout::timeout(1) do
|
data/lib/fake_ftp/version.rb
CHANGED
@@ -1,506 +1,490 @@
|
|
1
1
|
require "spec_helper.rb"
|
2
2
|
require 'net/ftp'
|
3
3
|
|
4
|
-
describe FakeFtp::Server do
|
4
|
+
describe FakeFtp::Server, 'setup' do
|
5
|
+
it "starts a server on port n" do
|
6
|
+
server = FakeFtp::Server.new(21212)
|
7
|
+
server.port.should == 21212
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should defaults to port 21" do
|
11
|
+
server = FakeFtp::Server.new
|
12
|
+
server.port.should == 21
|
13
|
+
end
|
14
|
+
|
15
|
+
it "starts a passive server on port p" do
|
16
|
+
server = FakeFtp::Server.new(21212, 21213)
|
17
|
+
server.passive_port.should == 21213
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should start and stop" do
|
21
|
+
server = FakeFtp::Server.new(21212)
|
22
|
+
server.is_running?.should be_false
|
23
|
+
server.start
|
24
|
+
server.is_running?.should be_true
|
25
|
+
server.stop
|
26
|
+
server.is_running?.should be_false
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should default :mode to :active" do
|
30
|
+
server = FakeFtp::Server.new(21212, 21213)
|
31
|
+
server.mode.should == :active
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should start and stop passive port" do
|
35
|
+
server = FakeFtp::Server.new(21212, 21213)
|
36
|
+
server.is_running?(21213).should be_false
|
37
|
+
server.start
|
38
|
+
server.is_running?(21213).should be_true
|
39
|
+
server.stop
|
40
|
+
server.is_running?(21213).should be_false
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should raise if attempting to use a bound port" do
|
44
|
+
server = FakeFtp::Server.new(21212)
|
45
|
+
server.start
|
46
|
+
proc { FakeFtp::Server.new(21212) }.should raise_error(Errno::EADDRINUSE, "Address already in use - 21212")
|
47
|
+
server.stop
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should raise if attempting to use a bound passive_port" do
|
51
|
+
server = FakeFtp::Server.new(21212, 21213)
|
52
|
+
server.start
|
53
|
+
proc { FakeFtp::Server.new(21214, 21213) }.should raise_error(Errno::EADDRINUSE, "Address already in use - 21213")
|
54
|
+
server.stop
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe FakeFtp::Server, 'files' do
|
59
|
+
let(:file) { FakeFtp::File.new('filename', 34) }
|
60
|
+
let(:server) { FakeFtp::Server.new(21212) }
|
61
|
+
|
62
|
+
before { server.instance_variable_set(:@files, [file]) }
|
5
63
|
|
6
|
-
|
7
|
-
|
8
|
-
@bin_filename = File.expand_path("../../fixtures/invisible_bike.jpg", File.dirname(__FILE__))
|
64
|
+
it "returns filenames from :files" do
|
65
|
+
server.files.should include('filename')
|
9
66
|
end
|
10
67
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
68
|
+
it "can be accessed with :file" do
|
69
|
+
server.file('filename').should == file
|
70
|
+
end
|
71
|
+
|
72
|
+
it "can reset files" do
|
73
|
+
server.reset
|
74
|
+
server.files.should == []
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe FakeFtp::Server, 'commands' do
|
79
|
+
let(:server) { FakeFtp::Server.new(21212, 21213) }
|
80
|
+
|
81
|
+
before { server.start }
|
82
|
+
after { server.stop }
|
83
|
+
|
84
|
+
context 'general' do
|
85
|
+
before :each do
|
86
|
+
@client = TCPSocket.open('127.0.0.1', 21212)
|
15
87
|
end
|
16
88
|
|
17
|
-
|
18
|
-
|
19
|
-
server.port.should == 21
|
89
|
+
after :each do
|
90
|
+
@client.close
|
20
91
|
end
|
21
92
|
|
22
|
-
it "
|
23
|
-
|
24
|
-
server.passive_port.should == 21213
|
93
|
+
it "should accept connections" do
|
94
|
+
@client.gets.should == "220 Can has FTP?\r\n"
|
25
95
|
end
|
26
96
|
|
27
|
-
it "should
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
server.is_running?.should be_true
|
32
|
-
server.stop
|
33
|
-
server.is_running?.should be_false
|
97
|
+
it "should get unknown command response when nothing is sent" do
|
98
|
+
@client.gets
|
99
|
+
@client.puts
|
100
|
+
@client.gets.should == "500 Unknown command\r\n"
|
34
101
|
end
|
35
102
|
|
36
|
-
it "
|
37
|
-
|
38
|
-
|
103
|
+
it "accepts QUIT" do
|
104
|
+
@client.gets
|
105
|
+
@client.puts "QUIT"
|
106
|
+
@client.gets.should == "221 OMG bye!\r\n"
|
39
107
|
end
|
40
108
|
|
41
|
-
it "should
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
109
|
+
it "should accept multiple commands in one session" do
|
110
|
+
@client.gets
|
111
|
+
@client.puts "USER thing"
|
112
|
+
@client.gets
|
113
|
+
@client.puts "PASS thing"
|
114
|
+
@client.gets
|
115
|
+
@client.puts "ACCT thing"
|
116
|
+
@client.gets
|
117
|
+
@client.puts "USER thing"
|
48
118
|
end
|
119
|
+
end
|
49
120
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
proc { FakeFtp::Server.new(21212) }.should raise_error(Errno::EADDRINUSE, "Address already in use - 21212")
|
54
|
-
server.stop
|
121
|
+
context 'passive' do
|
122
|
+
after :each do
|
123
|
+
@client.close
|
55
124
|
end
|
56
125
|
|
57
|
-
it "
|
58
|
-
server
|
126
|
+
it "accepts PASV" do
|
127
|
+
server.mode.should == :active
|
128
|
+
@client = TCPSocket.open('127.0.0.1', 21212)
|
129
|
+
@client.gets
|
130
|
+
@client.puts "PASV"
|
131
|
+
@client.gets.should == "227 Entering Passive Mode (127,0,0,1,82,221)\r\n"
|
132
|
+
server.mode.should == :passive
|
133
|
+
end
|
134
|
+
|
135
|
+
it "responds with correct PASV port" do
|
136
|
+
server.stop
|
137
|
+
server.passive_port = 21111
|
59
138
|
server.start
|
60
|
-
|
139
|
+
@client = TCPSocket.open('127.0.0.1', 21212)
|
140
|
+
@client.gets
|
141
|
+
@client.puts "PASV"
|
142
|
+
@client.gets.should == "227 Entering Passive Mode (127,0,0,1,82,119)\r\n"
|
143
|
+
end
|
144
|
+
|
145
|
+
it "does not accept PASV if no port set" do
|
61
146
|
server.stop
|
147
|
+
server.passive_port = nil
|
148
|
+
server.start
|
149
|
+
@client = TCPSocket.open('127.0.0.1', 21212)
|
150
|
+
@client.gets
|
151
|
+
@client.puts "PASV"
|
152
|
+
@client.gets.should == "502 Aww hell no, use Active\r\n"
|
62
153
|
end
|
63
154
|
end
|
64
155
|
|
65
|
-
context '
|
156
|
+
context 'active' do
|
66
157
|
before :each do
|
67
|
-
@
|
68
|
-
@
|
69
|
-
|
158
|
+
@client = TCPSocket.open('127.0.0.1', 21212)
|
159
|
+
@client.gets
|
160
|
+
|
161
|
+
@data_server = ::TCPServer.new('127.0.0.1', 21216)
|
162
|
+
@data_connection = Thread.new do
|
163
|
+
@server_client = @data_server.accept
|
164
|
+
@server_client.should_not be_nil
|
165
|
+
end
|
70
166
|
end
|
71
167
|
|
72
|
-
|
73
|
-
@
|
168
|
+
after :each do
|
169
|
+
@data_server.close
|
170
|
+
@data_server = nil
|
171
|
+
@data_connection = nil
|
172
|
+
@client.close
|
74
173
|
end
|
75
174
|
|
76
|
-
it "
|
77
|
-
@
|
175
|
+
it "accepts PORT and connects to port" do
|
176
|
+
@client.puts "PORT 127,0,0,1,82,224"
|
177
|
+
@client.gets.should == "200 Okay\r\n"
|
178
|
+
|
179
|
+
@data_connection.join
|
78
180
|
end
|
79
181
|
|
80
|
-
it "
|
81
|
-
|
82
|
-
@
|
182
|
+
it "should switch to :active on port command" do
|
183
|
+
server.mode.should == :active
|
184
|
+
@client.puts 'PASV'
|
185
|
+
@client.gets
|
186
|
+
server.mode.should == :passive
|
187
|
+
|
188
|
+
@client.puts "PORT 127,0,0,1,82,224"
|
189
|
+
@client.gets.should == "200 Okay\r\n"
|
190
|
+
|
191
|
+
@data_connection.join
|
192
|
+
|
193
|
+
server.mode.should == :active
|
83
194
|
end
|
84
195
|
end
|
85
196
|
|
86
|
-
context '
|
197
|
+
context 'authentication commands' do
|
87
198
|
before :each do
|
88
|
-
@
|
89
|
-
@
|
199
|
+
@client = TCPSocket.open('127.0.0.1', 21212)
|
200
|
+
@client.gets ## connection successful response
|
90
201
|
end
|
91
202
|
|
92
203
|
after :each do
|
93
|
-
@
|
94
|
-
@server = nil
|
204
|
+
@client.close
|
95
205
|
end
|
96
206
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
after :each do
|
104
|
-
@client.close
|
105
|
-
end
|
207
|
+
it "accepts USER" do
|
208
|
+
@client.puts "USER some_dude"
|
209
|
+
@client.gets.should == "331 send your password\r\n"
|
210
|
+
end
|
106
211
|
|
107
|
-
|
108
|
-
|
109
|
-
|
212
|
+
it "accepts anonymous USER" do
|
213
|
+
@client.puts "USER anonymous"
|
214
|
+
@client.gets.should == "230 logged in\r\n"
|
215
|
+
end
|
110
216
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end
|
217
|
+
it "accepts PASS" do
|
218
|
+
@client.puts "PASS password"
|
219
|
+
@client.gets.should == "230 logged in\r\n"
|
220
|
+
end
|
116
221
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
222
|
+
it "accepts ACCT" do
|
223
|
+
@client.puts "ACCT"
|
224
|
+
@client.gets.should == "230 WHATEVER!\r\n"
|
225
|
+
end
|
226
|
+
end
|
122
227
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
@client.gets
|
129
|
-
@client.puts "ACCT thing"
|
130
|
-
@client.gets
|
131
|
-
@client.puts "USER thing"
|
132
|
-
end
|
133
|
-
end
|
228
|
+
context 'directory commands' do
|
229
|
+
before :each do
|
230
|
+
@client = TCPSocket.open('127.0.0.1', 21212)
|
231
|
+
@client.gets ## connection successful response
|
232
|
+
end
|
134
233
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
end
|
234
|
+
after :each do
|
235
|
+
@client.close
|
236
|
+
end
|
139
237
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
@client.puts "PASV"
|
145
|
-
@client.gets.should == "227 Entering Passive Mode (127,0,0,1,82,221)\r\n"
|
146
|
-
@server.mode.should == :passive
|
147
|
-
end
|
238
|
+
it "returns directory on PWD" do
|
239
|
+
@client.puts "PWD"
|
240
|
+
@client.gets.should == "257 \"/pub\" is current directory\r\n"
|
241
|
+
end
|
148
242
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
@client.puts "PASV"
|
156
|
-
@client.gets.should == "227 Entering Passive Mode (127,0,0,1,82,119)\r\n"
|
157
|
-
end
|
243
|
+
it "says OK to any CWD, CDUP, without doing anything" do
|
244
|
+
@client.puts "CWD somewhere/else"
|
245
|
+
@client.gets.should == "250 OK!\r\n"
|
246
|
+
@client.puts "CDUP"
|
247
|
+
@client.gets.should == "250 OK!\r\n"
|
248
|
+
end
|
158
249
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
@client.gets
|
165
|
-
@client.puts "PASV"
|
166
|
-
@client.gets.should == "502 Aww hell no, use Active\r\n"
|
167
|
-
end
|
168
|
-
end
|
250
|
+
it "does not respond to MKD" do
|
251
|
+
@client.puts "MKD some_dir"
|
252
|
+
@client.gets.should == "500 Unknown command\r\n"
|
253
|
+
end
|
254
|
+
end
|
169
255
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
256
|
+
context 'file commands' do
|
257
|
+
before :each do
|
258
|
+
@client = TCPSocket.open('127.0.0.1', 21212)
|
259
|
+
@client.gets ## connection successful response
|
260
|
+
end
|
174
261
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
@server_client.should_not be_nil
|
179
|
-
end
|
180
|
-
end
|
262
|
+
after :each do
|
263
|
+
@client.close
|
264
|
+
end
|
181
265
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
@client.close
|
187
|
-
end
|
266
|
+
it "accepts TYPE ascii" do
|
267
|
+
@client.puts "TYPE A"
|
268
|
+
@client.gets.should == "200 Type set to A.\r\n"
|
269
|
+
end
|
188
270
|
|
189
|
-
|
190
|
-
|
191
|
-
|
271
|
+
it "accepts TYPE image" do
|
272
|
+
@client.puts "TYPE I"
|
273
|
+
@client.gets.should == "200 Type set to I.\r\n"
|
274
|
+
end
|
192
275
|
|
193
|
-
|
194
|
-
|
276
|
+
it "does not accept TYPEs other than ascii or image" do
|
277
|
+
@client.puts "TYPE E"
|
278
|
+
@client.gets.should == "504 We don't allow those\r\n"
|
279
|
+
@client.puts "TYPE N"
|
280
|
+
@client.gets.should == "504 We don't allow those\r\n"
|
281
|
+
@client.puts "TYPE T"
|
282
|
+
@client.gets.should == "504 We don't allow those\r\n"
|
283
|
+
@client.puts "TYPE C"
|
284
|
+
@client.gets.should == "504 We don't allow those\r\n"
|
285
|
+
@client.puts "TYPE L"
|
286
|
+
@client.gets.should == "504 We don't allow those\r\n"
|
287
|
+
end
|
195
288
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
289
|
+
context 'passive' do
|
290
|
+
before :each do
|
291
|
+
@client.puts 'PASV'
|
292
|
+
@client.gets.should == "227 Entering Passive Mode (127,0,0,1,82,221)\r\n"
|
293
|
+
end
|
201
294
|
|
202
|
-
|
203
|
-
|
295
|
+
it "accepts STOR with filename" do
|
296
|
+
@client.puts "STOR some_file"
|
297
|
+
@client.gets.should == "125 Do it!\r\n"
|
298
|
+
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
299
|
+
@data_client.puts "1234567890"
|
300
|
+
@data_client.close
|
301
|
+
@client.gets.should == "226 Did it!\r\n"
|
302
|
+
server.files.should include('some_file')
|
303
|
+
server.file('some_file').bytes.should == 10
|
304
|
+
end
|
204
305
|
|
205
|
-
|
306
|
+
it "does not accept RETR without a filename" do
|
307
|
+
@client.puts "RETR"
|
308
|
+
@client.gets.should == "501 No filename given\r\n"
|
309
|
+
end
|
206
310
|
|
207
|
-
|
208
|
-
|
311
|
+
it "does not serve files that do not exist" do
|
312
|
+
@client.puts "RETR some_file"
|
313
|
+
@client.gets.should == "550 File not found\r\n"
|
209
314
|
end
|
210
315
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
316
|
+
it "accepts RETR with a filename" do
|
317
|
+
server.add_file('some_file', '1234567890')
|
318
|
+
@client.puts "RETR some_file"
|
319
|
+
@client.gets.should == "150 File status ok, about to open data connection\r\n"
|
320
|
+
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
321
|
+
data = @data_client.read(1024)
|
322
|
+
@data_client.close
|
323
|
+
data.should == '1234567890'
|
324
|
+
@client.gets.should == "226 File transferred\r\n"
|
325
|
+
end
|
216
326
|
|
217
|
-
|
218
|
-
|
219
|
-
|
327
|
+
it "accepts a LIST command" do
|
328
|
+
server.add_file('some_file', '1234567890')
|
329
|
+
server.add_file('another_file', '1234567890')
|
330
|
+
@client.puts "LIST"
|
331
|
+
@client.gets.should == "150 Listing status ok, about to open data connection\r\n"
|
332
|
+
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
333
|
+
data = @data_client.read(2048)
|
334
|
+
@data_client.close
|
335
|
+
data.should == [
|
336
|
+
"-rw-r--r--\t1\towner\tgroup\t10\t#{server.file('some_file').created.strftime('%b %d %H:%M')}\tsome_file",
|
337
|
+
"-rw-r--r--\t1\towner\tgroup\t10\t#{server.file('another_file').created.strftime('%b %d %H:%M')}\tanother_file",
|
338
|
+
].join("\n")
|
339
|
+
@client.gets.should == "226 List information transferred\r\n"
|
340
|
+
end
|
220
341
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
342
|
+
it "accepts an NLST command" do
|
343
|
+
server.add_file('some_file', '1234567890')
|
344
|
+
server.add_file('another_file', '1234567890')
|
345
|
+
@client.puts "NLST"
|
346
|
+
@client.gets.should == "150 Listing status ok, about to open data connection\r\n"
|
347
|
+
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
348
|
+
data = @data_client.read(1024)
|
349
|
+
@data_client.close
|
350
|
+
data.should == "some_file\nanother_file"
|
351
|
+
@client.gets.should == "226 List information transferred\r\n"
|
352
|
+
end
|
225
353
|
|
226
|
-
|
227
|
-
@client.puts "USER anonymous"
|
228
|
-
@client.gets.should == "230 logged in\r\n"
|
229
|
-
end
|
354
|
+
end
|
230
355
|
|
231
|
-
|
232
|
-
|
233
|
-
|
356
|
+
context 'active' do
|
357
|
+
before :each do
|
358
|
+
@data_server = ::TCPServer.new('127.0.0.1', 21216)
|
359
|
+
@data_connection = Thread.new do
|
360
|
+
@server_client = @data_server.accept
|
234
361
|
end
|
362
|
+
end
|
235
363
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
364
|
+
after :each do
|
365
|
+
@data_server.close
|
366
|
+
@data_connection = nil
|
367
|
+
@data_server = nil
|
240
368
|
end
|
241
369
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
end
|
370
|
+
it "sends error message if no PORT received" do
|
371
|
+
@client.puts "STOR some_file"
|
372
|
+
@client.gets.should == "425 Ain't no data port!\r\n"
|
373
|
+
end
|
247
374
|
|
248
|
-
|
249
|
-
|
250
|
-
|
375
|
+
it "accepts STOR with filename" do
|
376
|
+
@client.puts "PORT 127,0,0,1,82,224"
|
377
|
+
@client.gets.should == "200 Okay\r\n"
|
251
378
|
|
252
|
-
|
253
|
-
|
254
|
-
@client.gets.should == "257 \"/pub\" is current directory\r\n"
|
255
|
-
end
|
379
|
+
@client.puts "STOR some_other_file"
|
380
|
+
@client.gets.should == "125 Do it!\r\n"
|
256
381
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
@client.puts "CDUP"
|
261
|
-
@client.gets.should == "250 OK!\r\n"
|
262
|
-
end
|
382
|
+
@data_connection.join
|
383
|
+
@server_client.print "12345"
|
384
|
+
@server_client.close
|
263
385
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
end
|
386
|
+
@client.gets.should == "226 Did it!\r\n"
|
387
|
+
server.files.should include('some_other_file')
|
388
|
+
server.file('some_other_file').bytes.should == 5
|
268
389
|
end
|
269
390
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
@client.gets ## connection successful response
|
274
|
-
end
|
391
|
+
it "accepts RETR with a filename" do
|
392
|
+
@client.puts "PORT 127,0,0,1,82,224"
|
393
|
+
@client.gets.should == "200 Okay\r\n"
|
275
394
|
|
276
|
-
|
277
|
-
|
278
|
-
|
395
|
+
server.add_file('some_file', '1234567890')
|
396
|
+
@client.puts "RETR some_file"
|
397
|
+
@client.gets.should == "150 File status ok, about to open data connection\r\n"
|
279
398
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
end
|
284
|
-
|
285
|
-
it "accepts TYPE image" do
|
286
|
-
@client.puts "TYPE I"
|
287
|
-
@client.gets.should == "200 Type set to I.\r\n"
|
288
|
-
end
|
399
|
+
@data_connection.join
|
400
|
+
data = @server_client.read(1024)
|
401
|
+
@server_client.close
|
289
402
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
@client.puts "TYPE N"
|
294
|
-
@client.gets.should == "504 We don't allow those\r\n"
|
295
|
-
@client.puts "TYPE T"
|
296
|
-
@client.gets.should == "504 We don't allow those\r\n"
|
297
|
-
@client.puts "TYPE C"
|
298
|
-
@client.gets.should == "504 We don't allow those\r\n"
|
299
|
-
@client.puts "TYPE L"
|
300
|
-
@client.gets.should == "504 We don't allow those\r\n"
|
301
|
-
end
|
403
|
+
data.should == '1234567890'
|
404
|
+
@client.gets.should == "226 File transferred\r\n"
|
405
|
+
end
|
302
406
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
@client.gets.should == "227 Entering Passive Mode (127,0,0,1,82,221)\r\n"
|
307
|
-
end
|
308
|
-
|
309
|
-
it "accepts STOR with filename" do
|
310
|
-
@client.puts "STOR some_file"
|
311
|
-
@client.gets.should == "125 Do it!\r\n"
|
312
|
-
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
313
|
-
@data_client.puts "1234567890"
|
314
|
-
@data_client.close
|
315
|
-
@client.gets.should == "226 Did it!\r\n"
|
316
|
-
@server.files.should include('some_file')
|
317
|
-
@server.file('some_file').bytes.should == 10
|
318
|
-
end
|
319
|
-
|
320
|
-
it "does not accept RETR without a filename" do
|
321
|
-
@client.puts "RETR"
|
322
|
-
@client.gets.should == "501 No filename given\r\n"
|
323
|
-
end
|
324
|
-
|
325
|
-
it "does not serve files that do not exist" do
|
326
|
-
@client.puts "RETR some_file"
|
327
|
-
@client.gets.should == "550 File not found\r\n"
|
328
|
-
end
|
329
|
-
|
330
|
-
it "accepts RETR with a filename" do
|
331
|
-
@server.add_file('some_file', '1234567890')
|
332
|
-
@client.puts "RETR some_file"
|
333
|
-
@client.gets.should == "150 File status ok, about to open data connection\r\n"
|
334
|
-
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
335
|
-
data = @data_client.read(1024)
|
336
|
-
@data_client.close
|
337
|
-
data.should == '1234567890'
|
338
|
-
@client.gets.should == "226 File transferred\r\n"
|
339
|
-
end
|
340
|
-
|
341
|
-
it "accepts a LIST command" do
|
342
|
-
@server.add_file('some_file', '1234567890')
|
343
|
-
@server.add_file('another_file', '1234567890')
|
344
|
-
@client.puts "LIST"
|
345
|
-
@client.gets.should == "150 Listing status ok, about to open data connection\r\n"
|
346
|
-
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
347
|
-
data = @data_client.read(2048)
|
348
|
-
@data_client.close
|
349
|
-
data.should == [
|
350
|
-
"-rw-r--r--\t1\towner\tgroup\t10\t#{@server.file('some_file').created.strftime('%b %d %H:%M')}\tsome_file",
|
351
|
-
"-rw-r--r--\t1\towner\tgroup\t10\t#{@server.file('another_file').created.strftime('%b %d %H:%M')}\tanother_file",
|
352
|
-
].join("\n")
|
353
|
-
@client.gets.should == "226 List information transferred\r\n"
|
354
|
-
end
|
355
|
-
|
356
|
-
it "accepts an NLST command" do
|
357
|
-
@server.add_file('some_file', '1234567890')
|
358
|
-
@server.add_file('another_file', '1234567890')
|
359
|
-
@client.puts "NLST"
|
360
|
-
@client.gets.should == "150 Listing status ok, about to open data connection\r\n"
|
361
|
-
@data_client = TCPSocket.open('127.0.0.1', 21213)
|
362
|
-
data = @data_client.read(1024)
|
363
|
-
@data_client.close
|
364
|
-
data.should == "some_file\nanother_file"
|
365
|
-
@client.gets.should == "226 List information transferred\r\n"
|
366
|
-
end
|
407
|
+
it "accepts an NLST command" do
|
408
|
+
@client.puts "PORT 127,0,0,1,82,224"
|
409
|
+
@client.gets.should == "200 Okay\r\n"
|
367
410
|
|
368
|
-
|
411
|
+
server.add_file('some_file', '1234567890')
|
412
|
+
server.add_file('another_file', '1234567890')
|
413
|
+
@client.puts "NLST"
|
414
|
+
@client.gets.should == "150 Listing status ok, about to open data connection\r\n"
|
369
415
|
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
@data_connection = Thread.new do
|
374
|
-
@server_client = @data_server.accept
|
375
|
-
end
|
376
|
-
end
|
377
|
-
|
378
|
-
after :each do
|
379
|
-
@data_server.close
|
380
|
-
@data_connection = nil
|
381
|
-
@data_server = nil
|
382
|
-
end
|
383
|
-
|
384
|
-
it "sends error message if no PORT received" do
|
385
|
-
@client.puts "STOR some_file"
|
386
|
-
@client.gets.should == "425 Ain't no data port!\r\n"
|
387
|
-
end
|
388
|
-
|
389
|
-
it "accepts STOR with filename" do
|
390
|
-
@client.puts "PORT 127,0,0,1,82,224"
|
391
|
-
@client.gets.should == "200 Okay\r\n"
|
392
|
-
|
393
|
-
@client.puts "STOR some_other_file"
|
394
|
-
@client.gets.should == "125 Do it!\r\n"
|
395
|
-
|
396
|
-
@data_connection.join
|
397
|
-
@server_client.print "12345"
|
398
|
-
@server_client.close
|
399
|
-
|
400
|
-
@client.gets.should == "226 Did it!\r\n"
|
401
|
-
@server.files.should include('some_other_file')
|
402
|
-
@server.file('some_other_file').bytes.should == 5
|
403
|
-
end
|
404
|
-
|
405
|
-
it "accepts RETR with a filename" do
|
406
|
-
@client.puts "PORT 127,0,0,1,82,224"
|
407
|
-
@client.gets.should == "200 Okay\r\n"
|
408
|
-
|
409
|
-
@server.add_file('some_file', '1234567890')
|
410
|
-
@client.puts "RETR some_file"
|
411
|
-
@client.gets.should == "150 File status ok, about to open data connection\r\n"
|
412
|
-
|
413
|
-
@data_connection.join
|
414
|
-
data = @server_client.read(1024)
|
415
|
-
@server_client.close
|
416
|
-
|
417
|
-
data.should == '1234567890'
|
418
|
-
@client.gets.should == "226 File transferred\r\n"
|
419
|
-
end
|
420
|
-
|
421
|
-
it "accepts an NLST command" do
|
422
|
-
@client.puts "PORT 127,0,0,1,82,224"
|
423
|
-
@client.gets.should == "200 Okay\r\n"
|
424
|
-
|
425
|
-
@server.add_file('some_file', '1234567890')
|
426
|
-
@server.add_file('another_file', '1234567890')
|
427
|
-
@client.puts "NLST"
|
428
|
-
@client.gets.should == "150 Listing status ok, about to open data connection\r\n"
|
429
|
-
|
430
|
-
@data_connection.join
|
431
|
-
data = @server_client.read(1024)
|
432
|
-
@server_client.close
|
433
|
-
|
434
|
-
data.should == "some_file\nanother_file"
|
435
|
-
@client.gets.should == "226 List information transferred\r\n"
|
436
|
-
end
|
416
|
+
@data_connection.join
|
417
|
+
data = @server_client.read(1024)
|
418
|
+
@server_client.close
|
437
419
|
|
438
|
-
|
420
|
+
data.should == "some_file\nanother_file"
|
421
|
+
@client.gets.should == "226 List information transferred\r\n"
|
439
422
|
end
|
440
423
|
end
|
424
|
+
end
|
425
|
+
end
|
441
426
|
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
427
|
+
describe FakeFtp::Server, 'with ftp client' do
|
428
|
+
let(:server) { FakeFtp::Server.new(21212, 21213) }
|
429
|
+
let(:client) { Net::FTP.new }
|
430
|
+
let(:text_filename) { File.expand_path("../../fixtures/text_file.txt", File.dirname(__FILE__)) }
|
446
431
|
|
447
|
-
|
448
|
-
@ftp.close
|
449
|
-
end
|
432
|
+
before { server.start }
|
450
433
|
|
451
|
-
|
452
|
-
|
453
|
-
|
434
|
+
after :each do
|
435
|
+
client.close
|
436
|
+
server.stop
|
437
|
+
end
|
454
438
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
end
|
439
|
+
it 'should accept connections' do
|
440
|
+
proc { client.connect('127.0.0.1', 21212) }.should_not raise_error
|
441
|
+
end
|
459
442
|
|
460
|
-
|
461
|
-
|
462
|
-
proc { @ftp.login('someone', 'password') }.should_not raise_error
|
463
|
-
end
|
443
|
+
context "" do
|
444
|
+
before { client.connect("127.0.0.1", 21212) }
|
464
445
|
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
proc { @ftp.quit }.should_not raise_error
|
469
|
-
end
|
446
|
+
it "should allow anonymous authentication" do
|
447
|
+
proc { client.login }.should_not raise_error
|
448
|
+
end
|
470
449
|
|
471
|
-
|
472
|
-
|
450
|
+
it "should allow named authentication" do
|
451
|
+
proc { client.login('someone', 'password') }.should_not raise_error
|
452
|
+
end
|
473
453
|
|
474
|
-
|
475
|
-
|
476
|
-
|
454
|
+
it "should allow client to quit" do
|
455
|
+
proc { client.login('someone', 'password') }.should_not raise_error
|
456
|
+
proc { client.quit }.should_not raise_error
|
457
|
+
end
|
477
458
|
|
478
|
-
|
479
|
-
|
480
|
-
@server.file('text_file.txt').should be_passive
|
481
|
-
@server.file('text_file.txt').should_not be_active
|
482
|
-
end
|
459
|
+
it "should put files using PASV" do
|
460
|
+
File.stat(text_filename).size.should == 20
|
483
461
|
|
484
|
-
|
485
|
-
|
462
|
+
client.passive = true
|
463
|
+
proc { client.put(text_filename) }.should_not raise_error
|
486
464
|
|
487
|
-
|
488
|
-
|
489
|
-
|
465
|
+
server.files.should include('text_file.txt')
|
466
|
+
server.file('text_file.txt').bytes.should == 20
|
467
|
+
server.file('text_file.txt').should be_passive
|
468
|
+
server.file('text_file.txt').should_not be_active
|
469
|
+
end
|
490
470
|
|
491
|
-
|
492
|
-
|
493
|
-
@server.file('text_file.txt').should_not be_passive
|
494
|
-
@server.file('text_file.txt').should be_active
|
495
|
-
end
|
471
|
+
it "should put files using active" do
|
472
|
+
File.stat(text_filename).size.should == 20
|
496
473
|
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
474
|
+
client.passive = false
|
475
|
+
proc { client.put(text_filename) }.should_not raise_error
|
476
|
+
|
477
|
+
server.files.should include('text_file.txt')
|
478
|
+
server.file('text_file.txt').bytes.should == 20
|
479
|
+
server.file('text_file.txt').should_not be_passive
|
480
|
+
server.file('text_file.txt').should be_active
|
481
|
+
end
|
482
|
+
|
483
|
+
xit "should disconnect clients on close" do
|
484
|
+
# TODO: when this succeeds, we can care less about manually closing clients
|
485
|
+
# otherwise we get a CLOSE_WAIT process hanging around that blocks our port
|
486
|
+
server.stop
|
487
|
+
client.closed?.should be_true
|
504
488
|
end
|
505
489
|
end
|
506
490
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fake_ftp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -14,7 +14,7 @@ date: 2011-11-21 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: bundler
|
17
|
-
requirement: &
|
17
|
+
requirement: &70105228104020 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 1.0.10
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70105228104020
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: rspec
|
28
|
-
requirement: &
|
28
|
+
requirement: &70105228103560 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>'
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '2'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70105228103560
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: rake
|
39
|
-
requirement: &
|
39
|
+
requirement: &70105228103100 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,7 +44,7 @@ dependencies:
|
|
44
44
|
version: 0.8.7
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *70105228103100
|
48
48
|
description: Testing FTP? Use this!
|
49
49
|
email:
|
50
50
|
- sax+github@livinginthepast.org
|