file-find 0.4.4 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,634 @@
1
+ # frozen_string_literal: true
2
+
3
+ ######################################################################
4
+ # file_find_spec.rb
5
+ #
6
+ # Test case for the file-find library. You should run this via the
7
+ # 'rake spec' task.
8
+ ######################################################################
9
+ require 'rspec'
10
+ require 'file-find'
11
+ require 'sys-admin'
12
+ require 'tmpdir'
13
+ require 'pp' # Goofy workaround for FakeFS bug
14
+ require 'fakefs/spec_helpers'
15
+
16
+ RSpec.describe File::Find do
17
+ include FakeFS::SpecHelpers
18
+
19
+ let(:windows) { File::ALT_SEPARATOR }
20
+ let(:elevated) { windows and Win32::Security.elevated_security? }
21
+ let(:ruby_file) { 'file_find_test.rb' }
22
+ let(:doc_file) { 'file_find_test.doc' }
23
+
24
+ let(:rule) { described_class.new }
25
+ let(:txt_rule) { described_class.new(:name => '*.txt') }
26
+
27
+ before(:all) do
28
+ @loguser = Sys::Admin.get_user(Sys::Admin.get_login)
29
+ group = File::ALT_SEPARATOR ? 'Users' : @loguser.gid
30
+ @logroup = Sys::Admin.get_group(group)
31
+ end
32
+
33
+ context 'constants', :constants do
34
+ example 'version constant is set to expected value' do
35
+ expect(File::Find::VERSION).to eq('0.5.1')
36
+ expect(File::Find::VERSION).to be_frozen
37
+ end
38
+ end
39
+
40
+ context 'path', :path do
41
+ example 'path accessor basic functionality' do
42
+ expect(rule).to respond_to(:path)
43
+ expect(rule).to respond_to(:path=)
44
+ end
45
+
46
+ example 'path method returns expected value' do
47
+ expect(rule.path).to eq(Dir.pwd)
48
+ end
49
+ end
50
+
51
+ context 'options', :options do
52
+ example 'options accessor basic functionality' do
53
+ expect(rule).to respond_to(:options)
54
+ expect(rule).to respond_to(:options=)
55
+ end
56
+
57
+ example 'options method returns expected value' do
58
+ expect(txt_rule.options).to eq({:name => '*.txt'})
59
+ end
60
+ end
61
+
62
+ context 'atime', :atime do
63
+ before do
64
+ FileUtils.touch(ruby_file)
65
+ end
66
+
67
+ example 'atime accessor basic functionality' do
68
+ expect(rule).to respond_to(:atime)
69
+ expect(rule).to respond_to(:atime=)
70
+ end
71
+
72
+ example 'atime method returns expected default value' do
73
+ expect(rule.atime).to be_nil
74
+ end
75
+
76
+ example 'find with atime option works as expected' do
77
+ rule1 = described_class.new(:name => '*.rb', :atime => 0)
78
+ rule2 = described_class.new(:name => '*.rb', :atime => 1)
79
+
80
+ expect(rule1.find.empty?).to be false
81
+ expect(rule2.find.empty?).to be true
82
+ end
83
+ end
84
+
85
+ context 'ctime', :ctime do
86
+ before do
87
+ FileUtils.touch(ruby_file)
88
+ end
89
+
90
+ example 'ctime accessor basic functionality' do
91
+ expect(rule).to respond_to(:ctime)
92
+ expect(rule).to respond_to(:ctime=)
93
+ end
94
+
95
+ example 'ctime method returns expected default value' do
96
+ expect(rule.ctime).to be_nil
97
+ end
98
+
99
+ example 'find with ctime option works as expected' do
100
+ rule1 = described_class.new(:name => '*.rb', :ctime => 0)
101
+ rule2 = described_class.new(:name => '*.rb', :ctime => 1)
102
+
103
+ expect(rule1.find.empty?).to be false
104
+ expect(rule2.find.empty?).to be true
105
+ end
106
+ end
107
+
108
+ context 'find', :find do
109
+ example 'find method basic functionality' do
110
+ expect(rule).to respond_to(:find)
111
+ expect{ rule.find }.not_to raise_error
112
+ end
113
+
114
+ example 'find method returns expected value' do
115
+ expect(rule.find).to be_a(Array)
116
+ expect(rule.find{}).to be_nil
117
+ end
118
+ end
119
+
120
+ context 'filetest', :filetest do
121
+ before do
122
+ FileUtils.touch(doc_file, :mode => 0644)
123
+ end
124
+
125
+ example 'filetest accessor basic functionality' do
126
+ expect(rule).to respond_to(:filetest)
127
+ expect(rule).to respond_to(:filetest=)
128
+ expect{ rule.filetest }.not_to raise_error
129
+ end
130
+
131
+ example 'filetest method returns expected value' do
132
+ expect(rule.filetest).to be_a(Array)
133
+ end
134
+
135
+ example 'valid filetest options work as expected' do
136
+ expect{ described_class.new(:readable? => true) }.not_to raise_error
137
+ expect{ described_class.new(:writable? => true) }.not_to raise_error
138
+ end
139
+
140
+ example 'find method works with filetest option' do
141
+ rule = described_class.new(:name => '*.doc', :writable? => true)
142
+
143
+ expect(rule.find.map{ |f| File.basename(f) }).to eq([doc_file])
144
+ FileUtils.chmod(0444, doc_file)
145
+ expect(rule.find).to eq([])
146
+ end
147
+ end
148
+
149
+ context 'mtime', :mtime do
150
+ before do
151
+ FileUtils.touch(ruby_file)
152
+ end
153
+
154
+ example 'mtime accessor basic functionality' do
155
+ expect(rule).to respond_to(:mtime)
156
+ expect(rule).to respond_to(:mtime=)
157
+ end
158
+
159
+ example 'mtime method returns expected default value' do
160
+ expect(rule.mtime).to be_nil
161
+ end
162
+
163
+ example 'find with mtime option works as expected' do
164
+ rule1 = described_class.new(:name => '*.rb', :mtime => 0)
165
+ rule2 = described_class.new(:name => '*.rb', :mtime => 1)
166
+
167
+ expect(rule1.find.empty?).to be false
168
+ expect(rule2.find.empty?).to be true
169
+ end
170
+ end
171
+
172
+ context 'ftype', :ftype do
173
+ before do
174
+ FileUtils.touch(ruby_file)
175
+ end
176
+
177
+ example 'ftype accessor basic functionality' do
178
+ expect(rule).to respond_to(:ftype)
179
+ expect(rule).to respond_to(:ftype=)
180
+ end
181
+
182
+ example 'ftype method returns expected default value' do
183
+ expect(rule.ftype).to be_nil
184
+ end
185
+
186
+ example 'ftype method works as expected' do
187
+ rule1 = described_class.new(:name => '*.rb', :ftype => 'file')
188
+ rule2 = described_class.new(:name => '*.rb', :ftype => 'characterSpecial')
189
+
190
+ expect(rule1.find.empty?).to be false
191
+ expect(rule2.find.empty?).to be true
192
+ end
193
+ end
194
+
195
+ context 'group', :group do
196
+ before do
197
+ FileUtils.touch(doc_file)
198
+ end
199
+
200
+ example 'group accessor basic functionality' do
201
+ expect(rule).to respond_to(:group)
202
+ expect(rule).to respond_to(:group=)
203
+ end
204
+
205
+ example 'group method returns expected default value' do
206
+ expect(rule.group).to be_nil
207
+ end
208
+
209
+ # TODO: Update example for Windows
210
+ example 'find with numeric group id works as expected' do
211
+ skip 'group example skipped on MS Windows' if windows
212
+ rule = described_class.new(:name => '*.doc', :group => @loguser.gid)
213
+ expect(rule.find).to eq([File.expand_path(doc_file)])
214
+ end
215
+
216
+ # TODO: Update example for Windows
217
+ example 'find with string group id works as expected' do
218
+ skip 'group example skipped on MS Windows' if windows
219
+
220
+ rule = described_class.new(:name => '*.doc', :group => @logroup.name)
221
+ expect(rule.find).to eq([File.expand_path(doc_file)])
222
+ end
223
+
224
+ example 'find with bogus group returns empty results' do
225
+ skip 'group test skipped on MS Windows' if windows
226
+
227
+ rule1 = described_class.new(:name => '*.doc', :group => 'totallybogus')
228
+ rule2 = described_class.new(:name => '*.doc', :group => 99999999)
229
+ expect(rule1.find).to eq([])
230
+ expect(rule2.find).to eq([])
231
+ end
232
+ end
233
+
234
+ context 'inum', :inum do
235
+ example 'inum accessor basic functionality' do
236
+ expect(rule).to respond_to(:inum)
237
+ expect(rule).to respond_to(:inum=)
238
+ end
239
+
240
+ example 'inum method returns expected default value' do
241
+ expect(rule.inum).to be_nil
242
+ end
243
+ end
244
+
245
+ context 'follow', :follow do
246
+ example 'follow accessor basic functionality' do
247
+ expect(rule).to respond_to(:follow)
248
+ expect(rule).to respond_to(:follow=)
249
+ end
250
+
251
+ example 'follow method returns expected default value' do
252
+ expect(rule.follow).to be true
253
+ end
254
+ end
255
+
256
+ context 'links', :links do
257
+ before do
258
+ FileUtils.touch(ruby_file)
259
+ FileUtils.touch(doc_file)
260
+ end
261
+
262
+ example 'links accessor basic functionality' do
263
+ expect(rule).to respond_to(:links)
264
+ expect(rule).to respond_to(:links=)
265
+ end
266
+
267
+ example 'links method returns expected default value' do
268
+ expect(rule.links).to be_nil
269
+ end
270
+
271
+ example 'links method returns expected result' do
272
+ skip if windows && !elevated
273
+
274
+ rule1 = described_class.new(:name => '*.rb', :links => 2)
275
+ rule2 = described_class.new(:name => '*.doc', :links => 1)
276
+
277
+ expect(rule1.find).to eq([])
278
+ expect(rule2.find).to eq([File.expand_path(doc_file)])
279
+ end
280
+ end
281
+
282
+ context 'brackets', :brackets do
283
+ let(:file_rule){ described_class.new(:ftype => 'file', :path => ['/bracket']) }
284
+ let(:dir_rule){ described_class.new(:ftype => 'directory', :path => ['/bracket']) }
285
+
286
+ before do
287
+ allow(FakeFS::FileSystem).to receive(:find).and_call_original
288
+ allow(FakeFS::FileSystem).to receive(:find).with(anything, 0, false)
289
+ end
290
+
291
+ example 'find method works on dirs that contain brackets' do
292
+ skip 'dirs with brackets example skipped on MS Windows' if windows
293
+
294
+ # We use absolute paths here because of fakefs, which converts it anyway
295
+ bracket_files = ['/bracket/a[1]/a.foo', '/bracket/a [2] /b.foo', '/bracket/[a] b [c]/d.foo']
296
+ bracket_paths = ['/bracket/a[1]', '/bracket/a [2] ', '/bracket/[a] b [c]', '/bracket/[z] x']
297
+
298
+ bracket_paths.each{ |e| FakeFS::FileSystem.add(e) }
299
+ bracket_files.each{ |e| FileUtils.touch(e) }
300
+
301
+ file_results = file_rule.find
302
+ dir_results = dir_rule.find
303
+
304
+ expect(file_results).to match_array(bracket_files)
305
+ expect(dir_results).to match_array(bracket_paths)
306
+ end
307
+ end
308
+
309
+ context 'maxdepth', :maxdepth do
310
+ before do
311
+ FakeFS::FileSystem.add('a1/a2/a3')
312
+ rule.pattern = '*.foo'
313
+
314
+ FileUtils.touch('a1/a.foo')
315
+ FileUtils.touch('a1/a2/b.foo')
316
+ FileUtils.touch('a1/a2/c.foo')
317
+ FileUtils.touch('a1/a2/a3/d.foo')
318
+ FileUtils.touch('a1/a2/a3/e.foo')
319
+ FileUtils.touch('a1/a2/a3/f.foo')
320
+ end
321
+
322
+ example 'maxdepth_basic' do
323
+ expect(rule).to respond_to(:maxdepth)
324
+ expect(rule).to respond_to(:maxdepth=)
325
+ expect(rule.maxdepth).to be_nil
326
+ end
327
+
328
+ example 'find with maxdepth 1 returns expected results' do
329
+ rule.maxdepth = 1
330
+ expect(rule.find).to eq([])
331
+ end
332
+
333
+ example 'find with maxdepth 2 returns expected results' do
334
+ pending if windows
335
+ rule.maxdepth = 2
336
+ expect(rule.find.map{ |e| File.basename(e) }).to eq(['a.foo'])
337
+ end
338
+
339
+ example 'find with maxdepth 3 returns expected results' do
340
+ pending if windows
341
+ rule.maxdepth = 3
342
+ expect(rule.find.map{ |e| File.basename(e) }).to contain_exactly('a.foo', 'b.foo', 'c.foo')
343
+ end
344
+
345
+ example 'find with nil maxdepth option returns everything' do
346
+ pending if windows
347
+ rule.maxdepth = nil
348
+ results = ['a.foo', 'b.foo', 'c.foo', 'd.foo', 'e.foo', 'f.foo']
349
+ expect(rule.find.map{ |e| File.basename(e) }).to match_array(results)
350
+ end
351
+
352
+ example 'find with maxdepth 1 returns expected results for directories' do
353
+ rule.pattern = 'a3'
354
+ rule.maxdepth = 1
355
+ expect(rule.find).to eq([])
356
+ end
357
+
358
+ example 'find with maxdepth 2 returns expected results for directories' do
359
+ rule.pattern = 'a3'
360
+ rule.maxdepth = 2
361
+ expect(rule.find).to eq([])
362
+ end
363
+
364
+ example 'find with maxdepth 3 returns expected results for directories' do
365
+ pending if windows
366
+ rule.pattern = 'a3'
367
+ rule.maxdepth = 3
368
+ expect(rule.find.map{ |e| File.basename(e) }).to eq(['a3'])
369
+ end
370
+ end
371
+
372
+ context 'mindepth', :mindepth do
373
+ before do
374
+ FakeFS::FileSystem.add('a1/a2/a3')
375
+ rule.pattern = '*.min'
376
+
377
+ FileUtils.touch('z.min')
378
+ FileUtils.touch('a1/a.min')
379
+ FileUtils.touch('a1/a2/b.min')
380
+ FileUtils.touch('a1/a2/c.min')
381
+ FileUtils.touch('a1/a2/a3/d.min')
382
+ FileUtils.touch('a1/a2/a3/e.min')
383
+ FileUtils.touch('a1/a2/a3/f.min')
384
+ end
385
+
386
+ example 'mindepth accessor basic functionality' do
387
+ expect(rule).to respond_to(:mindepth)
388
+ expect(rule).to respond_to(:mindepth=)
389
+ expect(rule.mindepth).to be_nil
390
+ end
391
+
392
+ example 'mindepth method returns expected default value' do
393
+ expect(rule.mindepth).to be_nil
394
+ end
395
+
396
+ example 'find with mindepth option returns expected results at depth 0' do
397
+ pending if windows
398
+ rule.mindepth = 0
399
+ array = ['a.min', 'b.min', 'c.min', 'd.min', 'e.min', 'f.min', 'z.min']
400
+ expect(rule.find.map{ |e| File.basename(e) }).to match_array(array)
401
+ end
402
+
403
+ example 'find with mindepth option returns expected results at depth 1' do
404
+ pending if windows
405
+ rule.mindepth = 1
406
+ array = ['a.min', 'b.min', 'c.min', 'd.min', 'e.min', 'f.min', 'z.min']
407
+ expect(rule.find.map{ |e| File.basename(e) }).to match_array(array)
408
+ end
409
+
410
+ example 'find with mindepth option returns expected results at depth 2' do
411
+ pending if windows
412
+ rule.mindepth = 2
413
+ array = ['a.min', 'b.min', 'c.min', 'd.min', 'e.min', 'f.min']
414
+ expect(rule.find.map{ |e| File.basename(e) }).to match_array(array)
415
+ end
416
+
417
+ example 'find with mindepth option returns expected results at depth 3' do
418
+ pending if windows
419
+ rule.mindepth = 3
420
+ array = ['b.min', 'c.min', 'd.min', 'e.min', 'f.min']
421
+ expect(rule.find.map{ |e| File.basename(e) }).to match_array(array)
422
+ end
423
+
424
+ example 'find with mindepth option returns expected results at depth 4' do
425
+ pending if windows
426
+ rule.mindepth = 4
427
+ array = ['d.min', 'e.min', 'f.min']
428
+ expect(rule.find.map{ |e| File.basename(e) }).to match_array(array)
429
+ end
430
+
431
+ example 'find with mindepth option returns expected results at depth 5' do
432
+ rule.mindepth = 5
433
+ expect(rule.find.map{ |e| File.basename(e) }).to eq([])
434
+ end
435
+
436
+ example 'find with mindepth option returns expected results for directories' do
437
+ rule.pattern = 'a1'
438
+ rule.mindepth = 1
439
+
440
+ expect(rule.find.map{ |e| File.basename(e) }).to eq(['a1'])
441
+
442
+ rule.mindepth = 2
443
+ expect(rule.find).to eq([])
444
+
445
+ rule.mindepth = 3
446
+ expect(rule.find).to eq([])
447
+ end
448
+ end
449
+
450
+ context 'mount', :mount do
451
+ example 'mount accessor basic functionality' do
452
+ expect(rule).to respond_to(:mount)
453
+ expect(rule).to respond_to(:mount=)
454
+ end
455
+
456
+ example 'mount method returns expected default value' do
457
+ expect(rule.mount).to be_nil
458
+ end
459
+ end
460
+
461
+ context 'name', :name do
462
+ example 'name accessor basic functionality' do
463
+ expect(rule).to respond_to(:name)
464
+ expect(rule).to respond_to(:name=)
465
+ end
466
+
467
+ example 'name method returns expected default value' do
468
+ expect(txt_rule.name).to eq('*.txt')
469
+ end
470
+
471
+ example 'pattern is an alias for name' do
472
+ expect(rule.method(:name)).to eq(rule.method(:pattern))
473
+ expect(rule.method(:name=)).to eq(rule.method(:pattern=))
474
+ end
475
+ end
476
+
477
+ context 'perm', :perm do
478
+ let(:text_file1) { 'file_find_test1.txt' }
479
+ let(:text_file2) { 'file_find_test2.txt' }
480
+
481
+ before do
482
+ FileUtils.touch(ruby_file)
483
+ FileUtils.touch(text_file1)
484
+ FileUtils.touch(text_file2)
485
+ File.chmod(0464, ruby_file)
486
+ File.chmod(0644, text_file1)
487
+ File.chmod(0644, text_file2)
488
+ end
489
+
490
+ example 'perm accessor basic functionality' do
491
+ expect(rule).to respond_to(:perm)
492
+ expect(rule).to respond_to(:perm=)
493
+ end
494
+
495
+ example 'perm method returns expected default value' do
496
+ expect(rule.perm).to be_nil
497
+ end
498
+
499
+ example 'perm method returns expected results' do
500
+ results = described_class.new(:name => '*test1*', :perm => 0644).find
501
+
502
+ expect(results.length).to eq(1)
503
+ expect(File.basename(results.first)).to eq(text_file1)
504
+ end
505
+
506
+ example 'perm method works with symbolic permissions' do
507
+ skip 'symbolic perm spec skipped on MS Windows' if windows
508
+
509
+ results1 = described_class.new(:name => 'file*', :perm => 'g=rw').find
510
+ results2 = described_class.new(:name => 'file*', :perm => 'u=rw').find
511
+
512
+ expect(results1.length).to eq(1)
513
+ expect(results2.length).to eq(2)
514
+ expect(File.basename(results1.first)).to eq(ruby_file)
515
+ expect(results2.map{ |e| File.basename(e) }.sort).to eq([text_file1, text_file2])
516
+ end
517
+ end
518
+
519
+ context 'prune', :prune do
520
+ let(:prune_file) { 'file_find_test_prune.txt' }
521
+
522
+ before do
523
+ FileUtils.touch(prune_file)
524
+ end
525
+
526
+ example 'prune accessor basic functionality' do
527
+ expect(rule).to respond_to(:prune)
528
+ expect(rule).to respond_to(:prune=)
529
+ end
530
+
531
+ example 'prune method returns expected default value' do
532
+ expect(rule.prune).to be_nil
533
+ end
534
+
535
+ example 'find method with prune option works as expected' do
536
+ rule = described_class.new(:name => '*.txt', :prune => 'foo')
537
+ expect(File.basename(rule.find.first)).to eq(prune_file)
538
+ end
539
+ end
540
+
541
+ context 'size', :size do
542
+ example 'size accessor basic functionality' do
543
+ expect(rule).to respond_to(:size)
544
+ expect(rule).to respond_to(:size=)
545
+ end
546
+
547
+ example 'size method returns expected default value' do
548
+ expect(rule.size).to be_nil
549
+ end
550
+ end
551
+
552
+ context 'user', :user do
553
+ before do
554
+ FileUtils.touch(doc_file)
555
+ end
556
+
557
+ example 'user accessor basic functionality' do
558
+ expect(rule).to respond_to(:user)
559
+ expect(rule).to respond_to(:user=)
560
+ end
561
+
562
+ example 'user method returns expected default value' do
563
+ expect(rule.user).to be_nil
564
+ end
565
+
566
+ example 'user method works with numeric id as expected' do
567
+ pending if windows # TODO: Get this working on Windows
568
+
569
+ if windows && elevated
570
+ uid = @loguser.gid # Windows assigns the group if any member is an admin
571
+ else
572
+ uid = @loguser.uid
573
+ end
574
+
575
+ rule = described_class.new(:name => '*.doc', :user => uid)
576
+ expect(rule.find).to eq([File.expand_path(doc_file)])
577
+ end
578
+
579
+ example 'user method works with string as expected' do
580
+ pending if windows # TODO: Get this working on Windows
581
+
582
+ skip if windows && elevated
583
+ rule = described_class.new(:name => '*.doc', :user => @loguser.name)
584
+ expect(rule.find).to eq([File.expand_path(doc_file)])
585
+ end
586
+
587
+ example 'find method with user option using invalid user returns expected results' do
588
+ rule1 = described_class.new(:name => '*.doc', :user => 'totallybogus')
589
+ rule2 = described_class.new(:name => '*.doc', :user => 99999999)
590
+ expect(rule1.find).to eq([])
591
+ expect(rule2.find).to eq([])
592
+ end
593
+ end
594
+
595
+ context 'previous', :previous do
596
+ example 'previous method basic functionality' do
597
+ expect(rule).to respond_to(:previous)
598
+ end
599
+ end
600
+
601
+ example 'an error is raised if the path does not exist' do
602
+ expect{ described_class.new(:path => '/bogus/dir').find }.to raise_error(Errno::ENOENT)
603
+ end
604
+
605
+ example 'an error is raised if an invalid option is passed' do
606
+ expect{ described_class.new(:bogus => 1) }.to raise_error(ArgumentError)
607
+ expect{ described_class.new(:bogus? => true) }.to raise_error(ArgumentError)
608
+ end
609
+
610
+ context 'eloop', :eloop do
611
+ # Have to disable fakefs for this test because of bug: https://github.com/fakefs/fakefs/issues/459
612
+ before do
613
+ FakeFS.deactivate!
614
+ end
615
+
616
+ after do
617
+ FakeFS.activate!
618
+ end
619
+
620
+ # TODO: Update example for Windows
621
+ example 'eloop handling works as expected' do
622
+ skip 'eloop handling example skipped on MS Windows' if windows
623
+
624
+ Dir.chdir(Dir.mktmpdir) do
625
+ File.symlink('eloop0', 'eloop1')
626
+ File.symlink('eloop1', 'eloop0')
627
+ expected = ['./eloop0', './eloop1']
628
+
629
+ results = described_class.new(:path => '.', :follow => true).find
630
+ expect(results.sort).to eq(expected)
631
+ end
632
+ end
633
+ end
634
+ end
data.tar.gz.sig CHANGED
Binary file