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.
@@ -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
- end
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