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