ftpd 0.2.2 → 0.3.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.
@@ -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