ftpd 0.2.2 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -43,12 +43,17 @@ module Ftpd
43
43
  "Contents of #{path}"
44
44
  end
45
45
 
46
+ def add_symlink(target_path, symlink_path)
47
+ FileUtils.ln_s data_path(target_path), data_path(symlink_path)
48
+ end
49
+
46
50
  before(:each) do
47
51
  write_file 'file'
48
52
  make_directory 'dir'
49
53
  write_file 'dir/file_in_dir'
50
54
  make_directory 'unwritable_dir'
51
55
  write_file 'unwritable_dir/file'
56
+ add_symlink 'file', 'symlink'
52
57
  end
53
58
 
54
59
  describe '#accessible?' do
@@ -179,108 +184,102 @@ module Ftpd
179
184
 
180
185
  end
181
186
 
182
- describe '#name_list' do
187
+ describe '#rename' do
183
188
 
184
- subject do
185
- disk_file_system.name_list(path)
186
- end
189
+ let(:from_path) {'file'}
190
+ let(:to_path) {'renamed_file'}
187
191
 
188
- shared_examples 'returns short list of root' do
189
- it {should =~ /^dir$/}
190
- it {should =~ /^file$/}
191
- it {should =~ /^unwritable_dir$/}
192
- its('lines.to_a.size') {should == 3}
192
+ context '(success)' do
193
+ specify do
194
+ disk_file_system.rename(from_path, to_path)
195
+ exists?(from_path).should be_false
196
+ exists?(to_path).should be_true
197
+ end
193
198
  end
194
199
 
195
- context '(root)' do
196
- let(:path) {'/'}
197
- it_behaves_like 'returns short list of root'
200
+ context '(error)' do
201
+ specify do
202
+ expect {
203
+ disk_file_system.rename(missing_path, to_path)
204
+ }.to raise_error *missing_file_error
205
+ end
198
206
  end
199
207
 
200
- context '(empty path)' do
201
- let(:path) {''}
202
- it_behaves_like 'returns short list of root'
203
- end
208
+ end
204
209
 
205
- context '(specific file)' do
206
- let(:path) {'/file'}
207
- it {should == "file\n"}
210
+ describe '#file_info' do
211
+
212
+ let(:identifier) {"#{stat.dev}.#{stat.ino}"}
213
+ let(:owner) {Etc.getpwuid(stat.uid).name}
214
+ let(:group) {Etc.getgrgid(stat.gid).name}
215
+ let(:stat) {File.stat(data_path(path))}
216
+ subject {disk_file_system.file_info(path)}
217
+
218
+ shared_examples 'file info' do
219
+ its(:ftype) {should == stat.ftype}
220
+ its(:group) {should == group}
221
+ its(:mode) {should == stat.mode}
222
+ its(:mtime) {should == stat.mtime}
223
+ its(:nlink) {should == stat.nlink}
224
+ its(:owner) {should == owner}
225
+ its(:size) {should == stat.size}
226
+ its(:path) {should == path}
227
+ its(:identifier) {should == identifier}
208
228
  end
209
229
 
210
- context '(specific directory)' do
211
- let(:path) {'/dir'}
212
- it {should == "file_in_dir\n"}
230
+ context '(file)' do
231
+ let(:path) {'file'}
232
+ it_behaves_like 'file info'
213
233
  end
214
234
 
215
- context '(missing directory)' do
216
- let(:path) {'/missing/file'}
217
- it {should be_empty}
235
+ context '(symlink)' do
236
+ let(:path) {'symlink'}
237
+ it_behaves_like 'file info'
218
238
  end
219
239
 
220
240
  end
221
241
 
222
- describe '#list' do
242
+ describe '#dir' do
223
243
 
224
- subject do
225
- disk_file_system.list(path)
244
+ subject(:dir) do
245
+ disk_file_system.dir(path)
226
246
  end
227
247
 
228
- shared_examples 'returns long list of root' do
229
- it {should =~ /^d.*dir$/}
230
- it {should =~ /^-.*file$/}
231
- it {should =~ /^d.*unwritable_dir$/}
232
- its('lines.to_a.size') {should == 3}
248
+ context '(no such file)' do
249
+ let(:path) {'missing'}
250
+ it {should be_empty}
233
251
  end
234
252
 
235
- context '(root)' do
236
- let(:path) {'/'}
237
- it_behaves_like 'returns long list of root'
253
+ context '(file)' do
254
+ let(:path) {'file'}
255
+ it {should include '/file'}
238
256
  end
239
257
 
240
- context '(empty path)' do
241
- let(:path) {''}
242
- it_behaves_like 'returns long list of root'
258
+ context '(directory)' do
259
+ let(:path) {'dir'}
260
+ it {should include '/dir'}
261
+ it {should_not include '/dir/file_in_dir'}
243
262
  end
244
263
 
245
- context '(specific file)' do
246
- let(:path) {'/file'}
247
- it {should =~ /^-.*file$/}
264
+ context '(directory + wildcard)' do
265
+ let(:path) {'dir/*'}
266
+ it {should_not include '/dir'}
267
+ it {should include '/dir/file_in_dir'}
248
268
  end
249
269
 
250
- context '(specific directory)' do
251
- let(:path) {'/dir'}
252
- it {should =~ /^-.*file_in_dir\n/}
270
+ context '(wildcard)' do
271
+ let(:path) {'*'}
272
+ it {should include '/unwritable_dir'}
273
+ it {should include '/file'}
274
+ it {should include '/dir'}
253
275
  end
254
276
 
255
- context '(missing directory)' do
256
- let(:path) {'/missing/file'}
277
+ context '(no such directory)' do
278
+ let(:path) {'foo/*'}
257
279
  it {should be_empty}
258
280
  end
259
281
 
260
282
  end
261
283
 
262
- describe '#rename' do
263
-
264
- let(:from_path) {'file'}
265
- let(:to_path) {'renamed_file'}
266
-
267
- context '(success)' do
268
- specify do
269
- disk_file_system.rename(from_path, to_path)
270
- exists?(from_path).should be_false
271
- exists?(to_path).should be_true
272
- end
273
- end
274
-
275
- context '(error)' do
276
- specify do
277
- expect {
278
- disk_file_system.rename(missing_path, to_path)
279
- }.to raise_error *missing_file_error
280
- end
281
- end
282
-
283
- end
284
-
285
284
  end
286
285
  end
@@ -0,0 +1,59 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+
3
+ module Ftpd
4
+ describe FileInfo do
5
+
6
+ subject {FileInfo.new(opts)}
7
+
8
+ def self.it_has_attribute(attribute)
9
+ describe "##{attribute}" do
10
+ let(:value) {"#{attribute} value"}
11
+ let(:opts) {{attribute => value}}
12
+ its(attribute) {should == value}
13
+ end
14
+ end
15
+
16
+ it_has_attribute :ftype
17
+ it_has_attribute :group
18
+ it_has_attribute :identifier
19
+ it_has_attribute :mode
20
+ it_has_attribute :mtime
21
+ it_has_attribute :nlink
22
+ it_has_attribute :owner
23
+ it_has_attribute :path
24
+ it_has_attribute :size
25
+
26
+ describe '#file?' do
27
+
28
+ let(:opts) {{:ftype => ftype}}
29
+
30
+ context '(file)' do
31
+ let(:ftype) {'file'}
32
+ its(:file?) {should be_true}
33
+ end
34
+
35
+ context '(directory)' do
36
+ let(:ftype) {'directory'}
37
+ its(:file?) {should be_false}
38
+ end
39
+
40
+ end
41
+
42
+ describe '#directory?' do
43
+
44
+ let(:opts) {{:ftype => ftype}}
45
+
46
+ context '(file)' do
47
+ let(:ftype) {'file'}
48
+ its(:directory?) {should be_false}
49
+ end
50
+
51
+ context '(directory)' do
52
+ let(:ftype) {'directory'}
53
+ its(:directory?) {should be_true}
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,62 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+
3
+ module Ftpd
4
+ module ListFormat
5
+ describe Eplf do
6
+
7
+ context '(file)' do
8
+
9
+ let(:file_info) do
10
+ FileInfo.new(:ftype => 'file',
11
+ :mode => 0100644,
12
+ :mtime => Time.mktime(2013, 3, 3, 8, 38, 0),
13
+ :path => 'foo',
14
+ :size => 1234)
15
+ end
16
+ subject(:formatter) {Eplf.new(file_info)}
17
+
18
+ it 'should produce EPLF format' do
19
+ formatter.to_s.should == "+r,s1234,m1362325080\tfoo"
20
+ end
21
+
22
+ end
23
+
24
+ context '(directory)' do
25
+
26
+ let(:file_info) do
27
+ FileInfo.new(:ftype => 'directory',
28
+ :mode => 0100644,
29
+ :mtime => Time.mktime(2013, 3, 3, 8, 38, 0),
30
+ :path => 'foo',
31
+ :size => 1024)
32
+ end
33
+ subject(:formatter) {Eplf.new(file_info)}
34
+
35
+ it 'should produce EPLF format' do
36
+ formatter.to_s.should == "+/,m1362325080\tfoo"
37
+ end
38
+
39
+ end
40
+
41
+ context '(with identifier)' do
42
+
43
+ let(:file_info) do
44
+ FileInfo.new(:ftype => 'file',
45
+ :mode => 0100644,
46
+ :mtime => Time.mktime(2013, 3, 3, 8, 38, 0),
47
+ :path => 'foo',
48
+ :identifier => '1234.5678',
49
+ :size => 1234)
50
+ end
51
+ subject(:formatter) {Eplf.new(file_info)}
52
+
53
+ it 'should produce EPLF format' do
54
+ formatter.to_s.should ==
55
+ "+r,s1234,m1362325080,i1234.5678\tfoo"
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,270 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+
3
+ module Ftpd
4
+ module ListFormat
5
+
6
+ describe Ls do
7
+
8
+ let(:file_info) do
9
+ FileInfo.new(:ftype => 'file',
10
+ :group => 'group',
11
+ :mode => 0100644,
12
+ :mtime => Time.mktime(2013, 3, 3, 8, 38, 0),
13
+ :nlink => 1,
14
+ :owner => 'user',
15
+ :path => 'foo',
16
+ :size => 1234)
17
+ end
18
+ subject(:formatter) {Ls.new(file_info)}
19
+
20
+ it 'should approximate ls -l format' do
21
+ Timecop.freeze(2013, 3, 3, 8, 38, 0) do
22
+ formatter.to_s.should ==
23
+ '-rw-r--r-- 1 user group 1234 Mar 3 08:38 foo'
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ describe Ls::FileType do
30
+
31
+ [
32
+ ['file', '-'],
33
+ ['directory', 'd'],
34
+ ['characterSpecial', 'c'],
35
+ ['blockSpecial', 'b'],
36
+ ['fifo', 'p'],
37
+ ['link', 'l'],
38
+ ['socket', 's'],
39
+ ['unknown', '?'],
40
+ ].each do |ftype, letter|
41
+ context "(#{ftype})" do
42
+ specify do
43
+ Ls::FileType.letter(ftype).should == letter
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ describe Ls::FileMode do
51
+
52
+ let(:other_execute) {0}
53
+ let(:other_write) {0}
54
+ let(:other_read) {0}
55
+ let(:group_execute) {0}
56
+ let(:group_write) {0}
57
+ let(:group_read) {0}
58
+ let(:owner_execute) {0}
59
+ let(:owner_write) {0}
60
+ let(:owner_read) {0}
61
+ let(:sticky) {0}
62
+ let(:setgid) {0}
63
+ let(:setuid) {0}
64
+ let(:mode) do
65
+ other_execute << 0 |
66
+ other_write << 1 |
67
+ other_read << 2 |
68
+ group_execute << 3 |
69
+ group_write << 4 |
70
+ group_read << 5 |
71
+ owner_execute << 6 |
72
+ owner_write << 7 |
73
+ owner_read << 8 |
74
+ sticky << 9 |
75
+ setgid << 10 |
76
+ setuid << 11
77
+ end
78
+
79
+ let(:letters) {Ls::FileMode.new(mode).letters}
80
+
81
+ describe 'owner read' do
82
+ subject {letters[0..0]}
83
+ context '(0)' do
84
+ let(:owner_read) {0}
85
+ it {should == '-'}
86
+ end
87
+ context '(1)' do
88
+ let(:owner_read) {1}
89
+ it {should == 'r'}
90
+ end
91
+ end
92
+
93
+ describe 'owner write' do
94
+ subject {letters[1..1]}
95
+ context '(0)' do
96
+ let(:owner_write) {0}
97
+ it {should == '-'}
98
+ end
99
+ context '(1)' do
100
+ let(:owner_write) {1}
101
+ it {should == 'w'}
102
+ end
103
+ end
104
+
105
+ describe 'owner execute' do
106
+
107
+ subject {letters[2..2]}
108
+
109
+ context '(setuid 0)' do
110
+ let(:setuid) {0}
111
+ context '(execute 0)' do
112
+ let(:owner_execute) {0}
113
+ it {should == '-'}
114
+ end
115
+ context '(execute 1)' do
116
+ let(:owner_execute) {1}
117
+ it {should == 'x'}
118
+ end
119
+ end
120
+
121
+ context '(setuid 1)' do
122
+ let(:setuid) {1}
123
+ context '(execute 0)' do
124
+ let(:owner_execute) {0}
125
+ it {should == 'S'}
126
+ end
127
+ context '(execute 1)' do
128
+ let(:owner_execute) {1}
129
+ it {should == 's'}
130
+ end
131
+ end
132
+
133
+ end
134
+
135
+ describe 'group read' do
136
+ subject {letters[3..3]}
137
+ context '(0)' do
138
+ let(:group_read) {0}
139
+ it {should == '-'}
140
+ end
141
+ context '(1)' do
142
+ let(:group_read) {1}
143
+ it {should == 'r'}
144
+ end
145
+ end
146
+
147
+ describe 'group write' do
148
+ subject {letters[4..4]}
149
+ context '(0)' do
150
+ let(:group_write) {0}
151
+ it {should == '-'}
152
+ end
153
+ context '(1)' do
154
+ let(:group_write) {1}
155
+ it {should == 'w'}
156
+ end
157
+ end
158
+
159
+ describe 'group execute' do
160
+
161
+ subject {letters[5..5]}
162
+
163
+ context '(setgid 0)' do
164
+ let(:setgid) {0}
165
+ context '(execute 0)' do
166
+ let(:group_execute) {0}
167
+ it {should == '-'}
168
+ end
169
+ context '(execute 1)' do
170
+ let(:group_execute) {1}
171
+ it {should == 'x'}
172
+ end
173
+ end
174
+
175
+ context '(setgid 1)' do
176
+ let(:setgid) {1}
177
+ context '(execute 0)' do
178
+ let(:group_execute) {0}
179
+ it {should == 'S'}
180
+ end
181
+ context '(execute 1)' do
182
+ let(:group_execute) {1}
183
+ it {should == 's'}
184
+ end
185
+ end
186
+
187
+ end
188
+
189
+ describe 'other read' do
190
+ subject {letters[6..6]}
191
+ context '(0)' do
192
+ let(:other_read) {0}
193
+ it {should == '-'}
194
+ end
195
+ context '(1)' do
196
+ let(:other_read) {1}
197
+ it {should == 'r'}
198
+ end
199
+ end
200
+
201
+ describe 'other write' do
202
+ subject {letters[7..7]}
203
+ context '(0)' do
204
+ let(:other_write) {0}
205
+ it {should == '-'}
206
+ end
207
+ context '(1)' do
208
+ let(:other_write) {1}
209
+ it {should == 'w'}
210
+ end
211
+ end
212
+
213
+ describe 'other execute' do
214
+
215
+ subject {letters[8..8]}
216
+
217
+ context '(sticky 0)' do
218
+ let(:sticky) {0}
219
+ context '(execute 0)' do
220
+ let(:other_execute) {0}
221
+ it {should == '-'}
222
+ end
223
+ context '(execute 1)' do
224
+ let(:other_execute) {1}
225
+ it {should == 'x'}
226
+ end
227
+ end
228
+
229
+ context '(sticky 1)' do
230
+ let(:sticky) {1}
231
+ context '(execute 0)' do
232
+ let(:other_execute) {0}
233
+ it {should == 'T'}
234
+ end
235
+ context '(execute 1)' do
236
+ let(:other_execute) {1}
237
+ it {should == 't'}
238
+ end
239
+ end
240
+
241
+ end
242
+
243
+ end
244
+
245
+ describe '.format_time' do
246
+
247
+ let(:mtime) {Time.mktime(2013, 6, 1, 13, 14, 15)}
248
+
249
+ around(:each) { |block| Timecop.freeze(now, &block) }
250
+ subject {Ls.format_time(mtime)}
251
+
252
+ context '(recent)' do
253
+ let(:now) {mtime}
254
+ it {should == 'Jun 1 13:14'}
255
+ end
256
+
257
+ context '(old)' do
258
+ let(:now) {Time.mktime(2014, 1, 1, 0, 0, 0)}
259
+ it {should == 'Jun 1 2013'}
260
+ end
261
+
262
+ context '(future)' do
263
+ let(:now) {Time.mktime(2013, 1, 1, 0, 0, 0)}
264
+ it {should == 'Jun 1 2013'}
265
+ end
266
+
267
+ end
268
+
269
+ end
270
+ end