fake_ftp 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/.travis.yml +2 -2
- data/CONTRIBUTORS.md +19 -0
- data/{README.markdown → README.md} +43 -11
- data/fake_ftp.gemspec +1 -0
- data/lib/fake_ftp/server.rb +6 -4
- data/lib/fake_ftp/version.rb +1 -1
- data/spec/functional/server_spec.rb +468 -0
- data/spec/integration/server_spec.rb +81 -0
- data/spec/models/fake_ftp/server_spec.rb +0 -547
- data/spec/spec_helper.rb +6 -1
- metadata +17 -11
- data/.rvmrc +0 -1
- data/Gemfile.travis +0 -5
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'net/ftp'
|
3
|
+
|
4
|
+
describe FakeFtp::Server, 'with ftp client' do
|
5
|
+
let(:server) { FakeFtp::Server.new(21212, 21213) }
|
6
|
+
let(:client) { Net::FTP.new }
|
7
|
+
let(:text_filename) { File.expand_path("../fixtures/text_file.txt", File.dirname(__FILE__)) }
|
8
|
+
|
9
|
+
before { server.start }
|
10
|
+
|
11
|
+
after :each do
|
12
|
+
client.close
|
13
|
+
server.stop
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should accept connections' do
|
17
|
+
expect { client.connect('127.0.0.1', 21212) }.to_not raise_error
|
18
|
+
end
|
19
|
+
|
20
|
+
context "with client" do
|
21
|
+
before { client.connect("127.0.0.1", 21212) }
|
22
|
+
|
23
|
+
it "should allow anonymous authentication" do
|
24
|
+
expect { client.login }.to_not raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should allow named authentication" do
|
28
|
+
expect { client.login('someone', 'password') }.to_not raise_error
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should allow client to quit" do
|
32
|
+
expect { client.login('someone', 'password') }.to_not raise_error
|
33
|
+
expect { client.quit }.to_not raise_error
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should allow mtime" do
|
37
|
+
filename = 'someone'
|
38
|
+
time = Time.now
|
39
|
+
server.add_file(filename, "some data", time)
|
40
|
+
|
41
|
+
client.passive = false
|
42
|
+
mtime = client.mtime(filename)
|
43
|
+
expect(mtime.to_s).to eql(time.to_s)
|
44
|
+
|
45
|
+
client.passive = true
|
46
|
+
mtime = client.mtime(filename)
|
47
|
+
expect(mtime.to_s).to eql(time.to_s)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should put files using PASV" do
|
51
|
+
expect(File.stat(text_filename).size).to eql(20)
|
52
|
+
|
53
|
+
client.passive = true
|
54
|
+
expect { client.put(text_filename) }.to_not raise_error
|
55
|
+
|
56
|
+
expect(server.files).to include('text_file.txt')
|
57
|
+
expect(server.file('text_file.txt').bytes).to eql(20)
|
58
|
+
expect(server.file('text_file.txt')).to be_passive
|
59
|
+
expect(server.file('text_file.txt')).to_not be_active
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should put files using active" do
|
63
|
+
expect(File.stat(text_filename).size).to eql(20)
|
64
|
+
|
65
|
+
client.passive = false
|
66
|
+
expect { client.put(text_filename) }.to_not raise_error
|
67
|
+
|
68
|
+
expect(server.files).to include('text_file.txt')
|
69
|
+
expect(server.file('text_file.txt').bytes).to eql(20)
|
70
|
+
expect(server.file('text_file.txt')).to_not be_passive
|
71
|
+
expect(server.file('text_file.txt')).to be_active
|
72
|
+
end
|
73
|
+
|
74
|
+
xit "should disconnect clients on close" do
|
75
|
+
# TODO: when this succeeds, we can care less about manually closing clients
|
76
|
+
# otherwise we get a CLOSE_WAIT process hanging around that blocks our port
|
77
|
+
server.stop
|
78
|
+
expect(client.closed?).to be_true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require "spec_helper.rb"
|
2
|
-
require 'net/ftp'
|
3
2
|
|
4
3
|
describe FakeFtp::Server, 'setup' do
|
5
4
|
it "starts a server on port n" do
|
@@ -75,549 +74,3 @@ describe FakeFtp::Server, 'files' do
|
|
75
74
|
end
|
76
75
|
end
|
77
76
|
|
78
|
-
describe FakeFtp::Server, 'commands' do
|
79
|
-
let(:server) { FakeFtp::Server.new(21212, 21213) }
|
80
|
-
let(:client) { TCPSocket.open('127.0.0.1', 21212) }
|
81
|
-
|
82
|
-
before { server.start }
|
83
|
-
after {
|
84
|
-
client.close
|
85
|
-
server.stop
|
86
|
-
}
|
87
|
-
|
88
|
-
context 'general' do
|
89
|
-
|
90
|
-
it "should accept connections" do
|
91
|
-
expect(client.gets).to eql("220 Can has FTP?\r\n")
|
92
|
-
end
|
93
|
-
|
94
|
-
it "should get unknown command response when nothing is sent" do
|
95
|
-
client.gets
|
96
|
-
client.puts
|
97
|
-
expect(client.gets).to eql("500 Unknown command\r\n")
|
98
|
-
end
|
99
|
-
|
100
|
-
it "accepts QUIT" do
|
101
|
-
client.gets
|
102
|
-
client.puts "QUIT"
|
103
|
-
expect(client.gets).to eql("221 OMG bye!\r\n")
|
104
|
-
end
|
105
|
-
|
106
|
-
it "should accept multiple commands in one session" do
|
107
|
-
client.gets
|
108
|
-
client.puts "USER thing"
|
109
|
-
client.gets
|
110
|
-
client.puts "PASS thing"
|
111
|
-
client.gets
|
112
|
-
client.puts "ACCT thing"
|
113
|
-
client.gets
|
114
|
-
client.puts "USER thing"
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
context 'passive' do
|
119
|
-
|
120
|
-
it "accepts PASV" do
|
121
|
-
expect(server.mode).to eql(:active)
|
122
|
-
client.gets
|
123
|
-
client.puts "PASV"
|
124
|
-
expect(client.gets).to eql("227 Entering Passive Mode (127,0,0,1,82,221)\r\n")
|
125
|
-
expect(server.mode).to eql(:passive)
|
126
|
-
end
|
127
|
-
|
128
|
-
it "responds with correct PASV port" do
|
129
|
-
server.stop
|
130
|
-
server.passive_port = 21111
|
131
|
-
server.start
|
132
|
-
client.gets
|
133
|
-
client.puts "PASV"
|
134
|
-
expect(client.gets).to eql("227 Entering Passive Mode (127,0,0,1,82,119)\r\n")
|
135
|
-
end
|
136
|
-
|
137
|
-
it "does not accept PASV if no port set" do
|
138
|
-
server.stop
|
139
|
-
server.passive_port = nil
|
140
|
-
server.start
|
141
|
-
client.gets
|
142
|
-
client.puts "PASV"
|
143
|
-
expect(client.gets).to eql("502 Aww hell no, use Active\r\n")
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
context 'active' do
|
148
|
-
before :each do
|
149
|
-
client.gets
|
150
|
-
|
151
|
-
@data_server = ::TCPServer.new('127.0.0.1', 21216)
|
152
|
-
@data_connection = Thread.new do
|
153
|
-
@server_client = @data_server.accept
|
154
|
-
expect(@server_client).to_not be_nil
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
after :each do
|
159
|
-
@data_server.close
|
160
|
-
@data_server = nil
|
161
|
-
@data_connection = nil
|
162
|
-
end
|
163
|
-
|
164
|
-
it "accepts PORT and connects to port" do
|
165
|
-
client.puts "PORT 127,0,0,1,82,224"
|
166
|
-
expect(client.gets).to eql("200 Okay\r\n")
|
167
|
-
|
168
|
-
@data_connection.join
|
169
|
-
end
|
170
|
-
|
171
|
-
it "should switch to :active on port command" do
|
172
|
-
expect(server.mode).to eql(:active)
|
173
|
-
client.puts 'PASV'
|
174
|
-
client.gets
|
175
|
-
expect(server.mode).to eql(:passive)
|
176
|
-
|
177
|
-
client.puts "PORT 127,0,0,1,82,224"
|
178
|
-
expect(client.gets).to eql("200 Okay\r\n")
|
179
|
-
|
180
|
-
@data_connection.join
|
181
|
-
|
182
|
-
expect(server.mode).to eql(:active)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
context 'authentication commands' do
|
187
|
-
before :each do
|
188
|
-
client.gets ## connection successful response
|
189
|
-
end
|
190
|
-
|
191
|
-
it "accepts USER" do
|
192
|
-
client.puts "USER some_dude"
|
193
|
-
expect(client.gets).to eql("331 send your password\r\n")
|
194
|
-
end
|
195
|
-
|
196
|
-
it "accepts anonymous USER" do
|
197
|
-
client.puts "USER anonymous"
|
198
|
-
expect(client.gets).to eql("230 logged in\r\n")
|
199
|
-
end
|
200
|
-
|
201
|
-
it "accepts PASS" do
|
202
|
-
client.puts "PASS password"
|
203
|
-
expect(client.gets).to eql("230 logged in\r\n")
|
204
|
-
end
|
205
|
-
|
206
|
-
it "accepts ACCT" do
|
207
|
-
client.puts "ACCT"
|
208
|
-
expect(client.gets).to eql("230 WHATEVER!\r\n")
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
context 'directory commands' do
|
213
|
-
before :each do
|
214
|
-
client.gets ## connection successful response
|
215
|
-
end
|
216
|
-
|
217
|
-
it "returns directory on PWD" do
|
218
|
-
client.puts "PWD"
|
219
|
-
expect(client.gets).to eql("257 \"/pub\" is current directory\r\n")
|
220
|
-
end
|
221
|
-
|
222
|
-
it "says OK to any CWD, CDUP, without doing anything" do
|
223
|
-
client.puts "CWD somewhere/else"
|
224
|
-
expect(client.gets).to eql("250 OK!\r\n")
|
225
|
-
client.puts "CDUP"
|
226
|
-
expect(client.gets).to eql("250 OK!\r\n")
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
context 'file commands' do
|
231
|
-
before :each do
|
232
|
-
client.gets ## connection successful response
|
233
|
-
end
|
234
|
-
|
235
|
-
it "accepts TYPE ascii" do
|
236
|
-
client.puts "TYPE A"
|
237
|
-
expect(client.gets).to eql("200 Type set to A.\r\n")
|
238
|
-
end
|
239
|
-
|
240
|
-
it "accepts TYPE image" do
|
241
|
-
client.puts "TYPE I"
|
242
|
-
expect(client.gets).to eql("200 Type set to I.\r\n")
|
243
|
-
end
|
244
|
-
|
245
|
-
it "does not accept TYPEs other than ascii or image" do
|
246
|
-
client.puts "TYPE E"
|
247
|
-
expect(client.gets).to eql("504 We don't allow those\r\n")
|
248
|
-
client.puts "TYPE N"
|
249
|
-
expect(client.gets).to eql("504 We don't allow those\r\n")
|
250
|
-
client.puts "TYPE T"
|
251
|
-
expect(client.gets).to eql("504 We don't allow those\r\n")
|
252
|
-
client.puts "TYPE C"
|
253
|
-
expect(client.gets).to eql("504 We don't allow those\r\n")
|
254
|
-
client.puts "TYPE L"
|
255
|
-
expect(client.gets).to eql("504 We don't allow those\r\n")
|
256
|
-
end
|
257
|
-
|
258
|
-
context 'passive' do
|
259
|
-
let(:data_client) { TCPSocket.open('127.0.0.1', 21213) }
|
260
|
-
|
261
|
-
before :each do
|
262
|
-
client.puts 'PASV'
|
263
|
-
expect(client.gets).to eql("227 Entering Passive Mode (127,0,0,1,82,221)\r\n")
|
264
|
-
end
|
265
|
-
|
266
|
-
it "accepts STOR with filename" do
|
267
|
-
client.puts "STOR some_file"
|
268
|
-
expect(client.gets).to eql("125 Do it!\r\n")
|
269
|
-
data_client.puts "1234567890"
|
270
|
-
data_client.close
|
271
|
-
expect(client.gets).to eql("226 Did it!\r\n")
|
272
|
-
expect(server.files).to include('some_file')
|
273
|
-
expect(server.file('some_file').bytes).to eql(10)
|
274
|
-
expect(server.file('some_file').data).to eql("1234567890")
|
275
|
-
end
|
276
|
-
|
277
|
-
it "accepts STOR with filename and trailing newline" do
|
278
|
-
client.puts "STOR some_file"
|
279
|
-
client.gets
|
280
|
-
# puts tries to be smart and only write a single \n
|
281
|
-
data_client.puts "1234567890\n\n"
|
282
|
-
data_client.close
|
283
|
-
expect(client.gets).to eql("226 Did it!\r\n")
|
284
|
-
expect(server.files).to include('some_file')
|
285
|
-
expect(server.file('some_file').bytes).to eql(11)
|
286
|
-
expect(server.file('some_file').data).to eql("1234567890\n")
|
287
|
-
end
|
288
|
-
|
289
|
-
it "accepts STOR with filename and long file" do
|
290
|
-
client.puts "STOR some_file"
|
291
|
-
expect(client.gets).to eql("125 Do it!\r\n")
|
292
|
-
data_client.puts("1234567890" * 10_000)
|
293
|
-
data_client.close
|
294
|
-
expect(client.gets).to eql("226 Did it!\r\n")
|
295
|
-
expect(server.files).to include('some_file')
|
296
|
-
end
|
297
|
-
|
298
|
-
it "accepts STOR with streams" do
|
299
|
-
client.puts "STOR some_file"
|
300
|
-
expect(client.gets).to eql("125 Do it!\r\n")
|
301
|
-
data_client.write "1234567890"
|
302
|
-
data_client.flush
|
303
|
-
data_client.write "1234567890"
|
304
|
-
data_client.flush
|
305
|
-
data_client.close
|
306
|
-
expect(client.gets).to eql("226 Did it!\r\n")
|
307
|
-
expect(server.file('some_file').data).to eql("12345678901234567890")
|
308
|
-
end
|
309
|
-
|
310
|
-
it "does not accept RETR without a filename" do
|
311
|
-
client.puts "RETR"
|
312
|
-
expect(client.gets).to eql("501 No filename given\r\n")
|
313
|
-
end
|
314
|
-
|
315
|
-
it "does not serve files that do not exist" do
|
316
|
-
client.puts "RETR some_file"
|
317
|
-
expect(client.gets).to eql("550 File not found\r\n")
|
318
|
-
end
|
319
|
-
|
320
|
-
it "accepts RETR with a filename" do
|
321
|
-
server.add_file('some_file', '1234567890')
|
322
|
-
client.puts "RETR some_file"
|
323
|
-
expect(client.gets).to eql("150 File status ok, about to open data connection\r\n")
|
324
|
-
data = data_client.read(1024)
|
325
|
-
data_client.close
|
326
|
-
expect(data).to eql('1234567890')
|
327
|
-
expect(client.gets).to eql("226 File transferred\r\n")
|
328
|
-
end
|
329
|
-
|
330
|
-
it "accepts DELE with a filename" do
|
331
|
-
server.add_file('some_file', '1234567890')
|
332
|
-
client.puts "DELE some_file"
|
333
|
-
expect(client.gets).to eql("250 Delete operation successful.\r\n")
|
334
|
-
expect(server.files).to_not include('some_file')
|
335
|
-
end
|
336
|
-
|
337
|
-
it "gives error message when trying to delete a file that does not exist" do
|
338
|
-
client.puts "DELE non_existing_file"
|
339
|
-
expect(client.gets).to eql("550 Delete operation failed.\r\n")
|
340
|
-
end
|
341
|
-
|
342
|
-
it "accepts a LIST command" do
|
343
|
-
server.add_file('some_file', '1234567890')
|
344
|
-
server.add_file('another_file', '1234567890')
|
345
|
-
client.puts "LIST"
|
346
|
-
expect(client.gets).to eql("150 Listing status ok, about to open data connection\r\n")
|
347
|
-
data = data_client.read(2048)
|
348
|
-
data_client.close
|
349
|
-
expect(data).to eql([
|
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
|
-
expect(client.gets).to eql("226 List information transferred\r\n")
|
354
|
-
end
|
355
|
-
|
356
|
-
it "accepts a LIST command with a wildcard argument" do
|
357
|
-
files = ['test.jpg', 'test-2.jpg', 'test.txt']
|
358
|
-
files.each do |file|
|
359
|
-
server.add_file(file, '1234567890')
|
360
|
-
end
|
361
|
-
|
362
|
-
client.puts "LIST *.jpg"
|
363
|
-
expect(client.gets).to eql("150 Listing status ok, about to open data connection\r\n")
|
364
|
-
|
365
|
-
data = data_client.read(2048)
|
366
|
-
data_client.close
|
367
|
-
expect(data).to eql(files[0,2].map do |file|
|
368
|
-
"-rw-r--r--\t1\towner\tgroup\t10\t#{server.file(file).created.strftime('%b %d %H:%M')}\t#{file}"
|
369
|
-
end.join("\n"))
|
370
|
-
expect(client.gets).to eql("226 List information transferred\r\n")
|
371
|
-
end
|
372
|
-
|
373
|
-
it "accepts a LIST command with multiple wildcard arguments" do
|
374
|
-
files = ['test.jpg', 'test.gif', 'test.txt']
|
375
|
-
files.each do |file|
|
376
|
-
server.add_file(file, '1234567890')
|
377
|
-
end
|
378
|
-
|
379
|
-
client.puts "LIST *.jpg *.gif"
|
380
|
-
expect(client.gets).to eql("150 Listing status ok, about to open data connection\r\n")
|
381
|
-
|
382
|
-
data = data_client.read(2048)
|
383
|
-
data_client.close
|
384
|
-
expect(data).to eql(files[0,2].map do |file|
|
385
|
-
"-rw-r--r--\t1\towner\tgroup\t10\t#{server.file(file).created.strftime('%b %d %H:%M')}\t#{file}"
|
386
|
-
end.join("\n"))
|
387
|
-
expect(client.gets).to eql("226 List information transferred\r\n")
|
388
|
-
end
|
389
|
-
|
390
|
-
it "accepts an NLST command" do
|
391
|
-
server.add_file('some_file', '1234567890')
|
392
|
-
server.add_file('another_file', '1234567890')
|
393
|
-
client.puts "NLST"
|
394
|
-
expect(client.gets).to eql("150 Listing status ok, about to open data connection\r\n")
|
395
|
-
data = data_client.read(1024)
|
396
|
-
data_client.close
|
397
|
-
expect(data).to eql("some_file\nanother_file")
|
398
|
-
expect(client.gets).to eql("226 List information transferred\r\n")
|
399
|
-
end
|
400
|
-
|
401
|
-
it "should allow mdtm" do
|
402
|
-
filename = "file.txt"
|
403
|
-
now = Time.now
|
404
|
-
server.add_file(filename, "some dummy content", now)
|
405
|
-
client.puts "MDTM #{filename}"
|
406
|
-
expect(client.gets).to eql("213 #{now.strftime("%Y%m%d%H%M%S")}\r\n")
|
407
|
-
end
|
408
|
-
end
|
409
|
-
|
410
|
-
context 'active' do
|
411
|
-
before :each do
|
412
|
-
@data_server = ::TCPServer.new('127.0.0.1', 21216)
|
413
|
-
@data_connection = Thread.new do
|
414
|
-
@server_client = @data_server.accept
|
415
|
-
end
|
416
|
-
end
|
417
|
-
|
418
|
-
after :each do
|
419
|
-
@data_server.close
|
420
|
-
@data_connection = nil
|
421
|
-
@data_server = nil
|
422
|
-
end
|
423
|
-
|
424
|
-
it 'creates a directory on MKD' do
|
425
|
-
client.puts "MKD some_dir"
|
426
|
-
expect(client.gets).to eql("257 OK!\r\n")
|
427
|
-
end
|
428
|
-
|
429
|
-
it 'should save the directory after you CWD' do
|
430
|
-
client.puts "CWD /somewhere/else"
|
431
|
-
expect(client.gets).to eql("250 OK!\r\n")
|
432
|
-
client.puts "PWD"
|
433
|
-
expect(client.gets).to eql("257 \"/somewhere/else\" is current directory\r\n")
|
434
|
-
end
|
435
|
-
|
436
|
-
it 'CWD should add a / to the beginning of the directory' do
|
437
|
-
client.puts "CWD somewhere/else"
|
438
|
-
expect(client.gets).to eql("250 OK!\r\n")
|
439
|
-
client.puts "PWD"
|
440
|
-
expect(client.gets).to eql("257 \"/somewhere/else\" is current directory\r\n")
|
441
|
-
end
|
442
|
-
|
443
|
-
it 'should not change the directory on CDUP' do
|
444
|
-
client.puts "CDUP"
|
445
|
-
expect(client.gets).to eql("250 OK!\r\n")
|
446
|
-
client.puts "PWD"
|
447
|
-
expect(client.gets).to eql("257 \"/pub\" is current directory\r\n")
|
448
|
-
end
|
449
|
-
|
450
|
-
it "sends error message if no PORT received" do
|
451
|
-
client.puts "STOR some_file"
|
452
|
-
expect(client.gets).to eql("425 Ain't no data port!\r\n")
|
453
|
-
end
|
454
|
-
|
455
|
-
it "accepts STOR with filename" do
|
456
|
-
client.puts "PORT 127,0,0,1,82,224"
|
457
|
-
expect(client.gets).to eql("200 Okay\r\n")
|
458
|
-
|
459
|
-
client.puts "STOR some_other_file"
|
460
|
-
expect(client.gets).to eql("125 Do it!\r\n")
|
461
|
-
|
462
|
-
@data_connection.join
|
463
|
-
@server_client.print "12345"
|
464
|
-
@server_client.close
|
465
|
-
|
466
|
-
expect(client.gets).to eql("226 Did it!\r\n")
|
467
|
-
expect(server.files).to include('some_other_file')
|
468
|
-
expect(server.file('some_other_file').bytes).to eql(5)
|
469
|
-
end
|
470
|
-
|
471
|
-
it "accepts RETR with a filename" do
|
472
|
-
client.puts "PORT 127,0,0,1,82,224"
|
473
|
-
expect(client.gets).to eql("200 Okay\r\n")
|
474
|
-
|
475
|
-
server.add_file('some_file', '1234567890')
|
476
|
-
client.puts "RETR some_file"
|
477
|
-
expect(client.gets).to eql("150 File status ok, about to open data connection\r\n")
|
478
|
-
|
479
|
-
@data_connection.join
|
480
|
-
data = @server_client.read(1024)
|
481
|
-
@server_client.close
|
482
|
-
|
483
|
-
expect(data).to eql('1234567890')
|
484
|
-
expect(client.gets).to eql("226 File transferred\r\n")
|
485
|
-
end
|
486
|
-
|
487
|
-
it "accepts RNFR without filename" do
|
488
|
-
client.puts "RNFR"
|
489
|
-
expect(client.gets).to eql("501 Send path name.\r\n")
|
490
|
-
end
|
491
|
-
|
492
|
-
it "accepts RNTO without RNFR" do
|
493
|
-
client.puts "RNTO some_other_file"
|
494
|
-
expect(client.gets).to eql("503 Send RNFR first.\r\n")
|
495
|
-
end
|
496
|
-
|
497
|
-
it "accepts RNTO and RNFR without filename" do
|
498
|
-
client.puts "RNFR from_file"
|
499
|
-
expect(client.gets).to eql("350 Send RNTO to complete rename.\r\n")
|
500
|
-
|
501
|
-
client.puts "RNTO"
|
502
|
-
expect(client.gets).to eql("501 Send path name.\r\n")
|
503
|
-
end
|
504
|
-
|
505
|
-
it "accepts RNTO and RNFR for not existing file" do
|
506
|
-
client.puts "RNFR from_file"
|
507
|
-
expect(client.gets).to eql("350 Send RNTO to complete rename.\r\n")
|
508
|
-
|
509
|
-
client.puts "RNTO to_file"
|
510
|
-
expect(client.gets).to eql("550 File not found.\r\n")
|
511
|
-
end
|
512
|
-
|
513
|
-
it "accepts RNTO and RNFR" do
|
514
|
-
server.add_file('from_file', '1234567890')
|
515
|
-
|
516
|
-
client.puts "RNFR from_file"
|
517
|
-
expect(client.gets).to eql("350 Send RNTO to complete rename.\r\n")
|
518
|
-
|
519
|
-
client.puts "RNTO to_file"
|
520
|
-
expect(client.gets).to eql("250 Path renamed.\r\n")
|
521
|
-
|
522
|
-
expect(server.files).to include('to_file')
|
523
|
-
expect(server.files).to_not include('from_file')
|
524
|
-
end
|
525
|
-
|
526
|
-
it "accepts an NLST command" do
|
527
|
-
client.puts "PORT 127,0,0,1,82,224"
|
528
|
-
expect(client.gets).to eql("200 Okay\r\n")
|
529
|
-
|
530
|
-
server.add_file('some_file', '1234567890')
|
531
|
-
server.add_file('another_file', '1234567890')
|
532
|
-
client.puts "NLST"
|
533
|
-
expect(client.gets).to eql("150 Listing status ok, about to open data connection\r\n")
|
534
|
-
|
535
|
-
@data_connection.join
|
536
|
-
data = @server_client.read(1024)
|
537
|
-
@server_client.close
|
538
|
-
|
539
|
-
expect(data).to eql("some_file\nanother_file")
|
540
|
-
expect(client.gets).to eql("226 List information transferred\r\n")
|
541
|
-
end
|
542
|
-
end
|
543
|
-
end
|
544
|
-
end
|
545
|
-
|
546
|
-
describe FakeFtp::Server, 'with ftp client' do
|
547
|
-
let(:server) { FakeFtp::Server.new(21212, 21213) }
|
548
|
-
let(:client) { Net::FTP.new }
|
549
|
-
let(:text_filename) { File.expand_path("../../fixtures/text_file.txt", File.dirname(__FILE__)) }
|
550
|
-
|
551
|
-
before { server.start }
|
552
|
-
|
553
|
-
after :each do
|
554
|
-
client.close
|
555
|
-
server.stop
|
556
|
-
end
|
557
|
-
|
558
|
-
it 'should accept connections' do
|
559
|
-
expect { client.connect('127.0.0.1', 21212) }.to_not raise_error
|
560
|
-
end
|
561
|
-
|
562
|
-
context "" do
|
563
|
-
before { client.connect("127.0.0.1", 21212) }
|
564
|
-
|
565
|
-
it "should allow anonymous authentication" do
|
566
|
-
expect { client.login }.to_not raise_error
|
567
|
-
end
|
568
|
-
|
569
|
-
it "should allow named authentication" do
|
570
|
-
expect { client.login('someone', 'password') }.to_not raise_error
|
571
|
-
end
|
572
|
-
|
573
|
-
it "should allow client to quit" do
|
574
|
-
expect { client.login('someone', 'password') }.to_not raise_error
|
575
|
-
expect { client.quit }.to_not raise_error
|
576
|
-
end
|
577
|
-
|
578
|
-
it "should allow mtime" do
|
579
|
-
filename = 'someone'
|
580
|
-
time = Time.now
|
581
|
-
server.add_file(filename, "some data", time)
|
582
|
-
|
583
|
-
client.passive = false
|
584
|
-
mtime = client.mtime(filename)
|
585
|
-
expect(mtime.to_s).to eql(time.to_s)
|
586
|
-
|
587
|
-
client.passive = true
|
588
|
-
mtime = client.mtime(filename)
|
589
|
-
expect(mtime.to_s).to eql(time.to_s)
|
590
|
-
end
|
591
|
-
|
592
|
-
it "should put files using PASV" do
|
593
|
-
expect(File.stat(text_filename).size).to eql(20)
|
594
|
-
|
595
|
-
client.passive = true
|
596
|
-
expect { client.put(text_filename) }.to_not raise_error
|
597
|
-
|
598
|
-
expect(server.files).to include('text_file.txt')
|
599
|
-
expect(server.file('text_file.txt').bytes).to eql(20)
|
600
|
-
expect(server.file('text_file.txt')).to be_passive
|
601
|
-
expect(server.file('text_file.txt')).to_not be_active
|
602
|
-
end
|
603
|
-
|
604
|
-
it "should put files using active" do
|
605
|
-
expect(File.stat(text_filename).size).to eql(20)
|
606
|
-
|
607
|
-
client.passive = false
|
608
|
-
expect { client.put(text_filename) }.to_not raise_error
|
609
|
-
|
610
|
-
expect(server.files).to include('text_file.txt')
|
611
|
-
expect(server.file('text_file.txt').bytes).to eql(20)
|
612
|
-
expect(server.file('text_file.txt')).to_not be_passive
|
613
|
-
expect(server.file('text_file.txt')).to be_active
|
614
|
-
end
|
615
|
-
|
616
|
-
xit "should disconnect clients on close" do
|
617
|
-
# TODO: when this succeeds, we can care less about manually closing clients
|
618
|
-
# otherwise we get a CLOSE_WAIT process hanging around that blocks our port
|
619
|
-
server.stop
|
620
|
-
expect(client.closed?).to be_true
|
621
|
-
end
|
622
|
-
end
|
623
|
-
end
|
data/spec/spec_helper.rb
CHANGED
@@ -10,4 +10,9 @@ require 'fake_ftp' # and any other gems you need
|
|
10
10
|
|
11
11
|
RSpec.configure do |config|
|
12
12
|
|
13
|
-
|
13
|
+
# Run specs in random order to surface order dependencies. If you find an
|
14
|
+
# order dependency and want to debug it, you can fix the order by providing
|
15
|
+
# the seed, which is printed after each run.
|
16
|
+
# --seed 1234
|
17
|
+
config.order = 'random'
|
18
|
+
end
|