fake_ftp 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
-