filepath 0.4 → 0.5

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,24 +43,6 @@ class FilePathList
43
43
  return FilePathList.new(remaining_entries)
44
44
  end
45
45
 
46
- def exclude(pattern = nil, &block)
47
- if block_given?
48
- select { |e| !block.call(e) }
49
- else
50
- select { |e| !(e =~ pattern) }
51
- end
52
- end
53
-
54
- def select(pattern = nil, &block)
55
- if !block_given?
56
- block = proc { |e| e =~ pattern }
57
- end
58
-
59
- remaining_entries = @entries.select { |e| block.call(e) }
60
-
61
- return FilePathList.new(remaining_entries)
62
- end
63
-
64
46
  def <<(extra_path)
65
47
  return FilePathList.new(@entries + [extra_path.as_path])
66
48
  end
@@ -137,10 +119,40 @@ class FilePathList
137
119
 
138
120
  define_array_method :each
139
121
 
140
- define_array_method :map
122
+ define_array_method :all?
123
+
124
+ define_array_method :any?
125
+
126
+ define_array_method :none?
141
127
 
142
128
  define_array_method :size
143
129
  end
144
130
 
131
+ module EntriesMethods
132
+ def map(&block)
133
+ mapped_entries = @entries.map(&block)
134
+ return FilePathList.new(mapped_entries)
135
+ end
136
+
137
+ def select(pattern = nil, &block)
138
+ if !block_given?
139
+ block = proc { |e| e =~ pattern }
140
+ end
141
+
142
+ remaining_entries = @entries.select { |e| block.call(e) }
143
+
144
+ return FilePathList.new(remaining_entries)
145
+ end
146
+
147
+ def exclude(pattern = nil, &block)
148
+ if block_given?
149
+ select { |e| !block.call(e) }
150
+ else
151
+ select { |e| !(e =~ pattern) }
152
+ end
153
+ end
154
+ end
155
+
145
156
  include ArrayMethods
157
+ include EntriesMethods
146
158
  end
@@ -27,15 +27,15 @@ describe FilePath do
27
27
  ]
28
28
  test_data.each do |base, extra, result|
29
29
  it "concatenates `#{base}` and `#{extra}` (as String) into `#{result}`" do
30
- p = FilePath.new(base) / extra
31
- p.should == result
30
+ ph = FilePath.new(base) / extra
31
+ ph.should == result
32
32
  end
33
33
  end
34
34
 
35
35
  test_data.each do |base, extra, result|
36
36
  it "concatenates `#{base}` and `#{extra}` (as FilePath) into `#{result}`" do
37
- p = FilePath.new(base) / FilePath.new(extra)
38
- p.should == result
37
+ ph = FilePath.new(base) / FilePath.new(extra)
38
+ ph.should == result
39
39
  end
40
40
  end
41
41
  end
@@ -69,13 +69,14 @@ describe FilePath do
69
69
  ['/foo/bar', 'bar'],
70
70
  ['foo', 'foo'],
71
71
  ['/', ''],
72
+ ['a/b/../../', ''],
72
73
  ['/foo/bar/.', 'bar'],
73
74
  ['a/b/../c', 'c'],
74
75
  ]
75
76
  test_data.each do |path, result|
76
77
  it "says that `#{result}` is the filename of `#{path}`" do
77
- p = FilePath.new(path)
78
- p.filename.should == result
78
+ ph = FilePath.new(path)
79
+ ph.filename.should == result
79
80
  end
80
81
  end
81
82
  end
@@ -90,8 +91,8 @@ describe FilePath do
90
91
  ]
91
92
  test_data.each do |path, result|
92
93
  it "says that `#{result}` is the parent dir of `#{path}`" do
93
- p = FilePath.new(path)
94
- p.parent_dir.should == result
94
+ ph = FilePath.new(path)
95
+ ph.parent_dir.should == result
95
96
  end
96
97
  end
97
98
  end
@@ -108,8 +109,8 @@ describe FilePath do
108
109
  ]
109
110
  test_data.each do |path, base, result|
110
111
  it "says that `#{path}` relative to `#{base}` is `#{result}`" do
111
- p = FilePath.new(path)
112
- p.relative_to(base).should == result
112
+ ph = FilePath.new(path)
113
+ ph.relative_to(base).should == result
113
114
  end
114
115
  end
115
116
 
@@ -121,8 +122,8 @@ describe FilePath do
121
122
  ]
122
123
  test_data2.each do |path, base|
123
124
  it "raise an exception because `#{path}` and `#{base}` have different prefixes" do
124
- p = FilePath.new(path)
125
- expect { p.relative_to(base) }.to raise_error(ArgumentError)
125
+ ph = FilePath.new(path)
126
+ expect { ph.relative_to(base) }.to raise_error(ArgumentError)
126
127
  end
127
128
  end
128
129
  end
@@ -137,13 +138,13 @@ describe FilePath do
137
138
  ]
138
139
  test_data.each do |path, base, result|
139
140
  it "says that `#{path}` relative to the file `#{base}` is `#{result}`" do
140
- p = FilePath.new(path)
141
- p.relative_to_file(base).should == result
141
+ ph = FilePath.new(path)
142
+ ph.relative_to_file(base).should == result
142
143
  end
143
144
  end
144
145
  end
145
146
 
146
- describe "#replace_filename" do
147
+ describe "#with_filename" do
147
148
  test_data = [
148
149
  ['foo/bar', 'quux', 'foo/quux'],
149
150
  ['foo/baz/..', 'quux', 'quux'],
@@ -151,8 +152,8 @@ describe FilePath do
151
152
  ]
152
153
  test_data.each do |base, new, result|
153
154
  it "changes `#{base}` + `#{new}` into `#{result}`" do
154
- p = FilePath.new(base)
155
- p.replace_filename(new).should == result
155
+ ph = FilePath.new(base)
156
+ ph.with_filename(new).should == result
156
157
  end
157
158
  end
158
159
  end
@@ -214,7 +215,7 @@ describe FilePath do
214
215
  end
215
216
  end
216
217
 
217
- describe "#replace_extension(String)" do
218
+ describe "#with_extension(String)" do
218
219
  test_data = [
219
220
  ['foo.bar', 'foo.baz'],
220
221
  ['foo.', 'foo.baz'],
@@ -224,13 +225,13 @@ describe FilePath do
224
225
  ]
225
226
  test_data.each do |path, result|
226
227
  it "replaces `#{path}` with `baz` into `#{result}`" do
227
- new = FilePath.new(path).replace_extension('baz')
228
+ new = FilePath.new(path).with_extension('baz')
228
229
  new.basename.to_s.should == result
229
230
  end
230
231
  end
231
232
  end
232
233
 
233
- describe "#remove_extension" do
234
+ describe "#without_extension" do
234
235
  test_data = [
235
236
  ['foo.bar', 'foo'],
236
237
  ['foo.', 'foo'],
@@ -240,7 +241,7 @@ describe FilePath do
240
241
  ]
241
242
  test_data.each do |path, result|
242
243
  it "turns `#{path}` into `#{result}`" do
243
- new = FilePath.new(path).remove_extension
244
+ new = FilePath.new(path).without_extension
244
245
  new.basename.to_s.should == result
245
246
  end
246
247
  end
@@ -304,6 +305,7 @@ describe FilePath do
304
305
  ['/', '/'],
305
306
  ['/..', '/'],
306
307
  ['/../../../a', '/a'],
308
+ ['a/b/../..', '.'],
307
309
  ]
308
310
  test_data.each do |path, result|
309
311
  it "turns `#{path}` into `#{result}`" do
@@ -312,11 +314,43 @@ describe FilePath do
312
314
  end
313
315
  end
314
316
 
317
+ describe "#each_segment" do
318
+ it "goes through all the segments of an absolute path" do
319
+ steps = []
320
+ FilePath.new("/a/b/c").each_segment do |seg|
321
+ steps << seg
322
+ end
323
+
324
+ steps.should have(4).items
325
+ steps[0].should eq("/")
326
+ steps[1].should eq("a")
327
+ steps[2].should eq("b")
328
+ steps[3].should eq("c")
329
+ end
330
+
331
+ it "goes through all the segments of a relative path" do
332
+ steps = []
333
+ FilePath.new("a/b/c").each_segment do |seg|
334
+ steps << seg
335
+ end
336
+
337
+ steps.should have(3).items
338
+ steps[0].should eq("a")
339
+ steps[1].should eq("b")
340
+ steps[2].should eq("c")
341
+ end
342
+
343
+ it "returns the path itself" do
344
+ path = FilePath.new("/a/b/c/")
345
+ path.each_segment { }.should be(path)
346
+ end
347
+ end
348
+
315
349
  describe "#ascend" do
316
350
  it "goes through all the segments of an absolute path" do
317
351
  steps = []
318
- FilePath.new("/a/b/c").ascend do |p|
319
- steps << p
352
+ FilePath.new("/a/b/c").ascend do |seg|
353
+ steps << seg
320
354
  end
321
355
 
322
356
  steps.should have(4).items
@@ -328,8 +362,8 @@ describe FilePath do
328
362
 
329
363
  it "goes through all the segments of a relative path" do
330
364
  steps = []
331
- FilePath.new("a/b/c").ascend do |p|
332
- steps << p
365
+ FilePath.new("a/b/c").ascend do |seg|
366
+ steps << seg
333
367
  end
334
368
 
335
369
  steps.should have(3).items
@@ -347,8 +381,8 @@ describe FilePath do
347
381
  describe "#descend" do
348
382
  it "goes through all the segments of an absolute path" do
349
383
  steps = []
350
- FilePath.new("/a/b/c").descend do |p|
351
- steps << p
384
+ FilePath.new("/a/b/c").descend do |seg|
385
+ steps << seg
352
386
  end
353
387
 
354
388
  steps.should have(4).items
@@ -360,8 +394,8 @@ describe FilePath do
360
394
 
361
395
  it "goes through all the segments of a relative path" do
362
396
  steps = []
363
- FilePath.new("a/b/c").descend do |p|
364
- steps << p
397
+ FilePath.new("a/b/c").descend do |seg|
398
+ steps << seg
365
399
  end
366
400
 
367
401
  steps.should have(3).items
@@ -414,8 +448,8 @@ describe FilePath do
414
448
  ]
415
449
  test_data.each do |ver1, ver2|
416
450
  it "says that `#{ver1}` is equivalent to `#{ver2}`" do
417
- p = FilePath.new(ver1)
418
- p.should == ver2
451
+ ph = FilePath.new(ver1)
452
+ ph.should == ver2
419
453
  end
420
454
  end
421
455
  end
@@ -450,6 +484,23 @@ describe FilePath do
450
484
  end
451
485
  end
452
486
 
487
+ describe "#<=>" do
488
+ test_data = [
489
+ ['a/', 'b'],
490
+ ['/a', 'a'],
491
+ ['../b', 'a'],
492
+ ]
493
+ test_data.each do |path1, path2|
494
+ it "says that `#{path1}` precedes `#{path2}`" do
495
+ p1 = path1.as_path
496
+ p2 = path2.as_path
497
+
498
+ order = p1 <=> p2
499
+ order.should == -1
500
+ end
501
+ end
502
+ end
503
+
453
504
  describe "#hash" do
454
505
  it "has the same value for similar paths" do
455
506
  p1 = '/foo/bar'.as_path
@@ -474,29 +525,63 @@ describe FilePath do
474
525
  end
475
526
  end
476
527
 
477
- describe FilePath::PathResolution do
478
- describe "#absolute_path" do
479
- test_data = [
480
- ['d1/l11', File.expand_path('d1/l11', FIXTURES_DIR), FIXTURES_DIR],
481
- ['/foo/bar', '/foo/bar', '.'],
482
- ]
483
- test_data.each do |path, abs_path, cwd|
484
- it "resolves <#{path}> to <#{abs_path}> (in #{cwd})" do
485
- Dir.chdir(cwd) do # FIXME
486
- FilePath.new(path).absolute_path.should == abs_path
487
- end
488
- end
528
+ describe FilePath::MetadataInfo do
529
+ describe "#stat" do
530
+ it "returns a stat for the file" do
531
+ (@root / 'd1').stat.should be_directory
532
+ (@root / 'f1').stat.size.should be_zero
533
+ end
534
+
535
+ it "follows links" do
536
+ (@root / 'd1' / 'l11').stat.should == '/dev/null'.as_path.stat
537
+ end
538
+
539
+ it "raises Errno::ENOENT for non-existing files" do
540
+ expect { (@root / 'foobar').stat }.to raise_error(Errno::ENOENT)
489
541
  end
490
542
  end
491
543
 
492
- describe "#real_path" do
493
- it "resolves <d1/l11> to </dev/null>" do
494
- (@root / 'd1' / 'l11').real_path.should == '/dev/null'
544
+ describe "#lstat" do
545
+ it "does not follow links" do
546
+ link_lstat = (@root / 'd1' / 'l11').lstat
547
+
548
+ link_lstat.should_not eq('/dev/null'.as_path.stat)
549
+ link_lstat.should be_symlink
550
+ end
551
+ end
552
+ end
553
+
554
+ describe FilePath::MetadataChanges do
555
+ describe "#chtime" do
556
+ it "change mtime" do
557
+ ph = @root / 'f1'
558
+ orig_mtime = ph.mtime
559
+
560
+ ph.chtime(Time.now, 0)
561
+ ph.mtime.to_i.should eq(0)
562
+
563
+ ph.chtime(Time.now, orig_mtime)
564
+ ph.mtime.should eq(orig_mtime)
565
+ end
566
+ end
567
+
568
+ describe "#chmod" do
569
+ it "changes file permissions" do
570
+ ph = @root / 'f1'
571
+ orig_mode = ph.stat.mode
572
+
573
+ ph.should be_readable
574
+
575
+ ph.chmod(000)
576
+ ph.should_not be_readable
577
+
578
+ ph.chmod(orig_mode)
579
+ ph.should be_readable
495
580
  end
496
581
  end
497
582
  end
498
583
 
499
- describe FilePath::FileInfo do
584
+ describe FilePath::MetadataTests do
500
585
  describe "#file?" do
501
586
  it "says that `f1` is a file" do
502
587
  (@root / 'f1').should be_file
@@ -506,7 +591,7 @@ describe FilePath do
506
591
  (@root / 'd1' / 'l11').should_not be_file
507
592
  end
508
593
 
509
- it "says that the root directory is not a file" do
594
+ it "says that the fixture root directory is not a file" do
510
595
  @root.should_not be_file
511
596
  end
512
597
  end
@@ -520,7 +605,7 @@ describe FilePath do
520
605
  (@root / 'd1' / 'l11').should be_link
521
606
  end
522
607
 
523
- it "says that the root directory is not a link" do
608
+ it "says that the fixture root directory is not a link" do
524
609
  @root.should_not be_link
525
610
  end
526
611
  end
@@ -534,11 +619,39 @@ describe FilePath do
534
619
  (@root / 'd1' / 'l11').should_not be_directory
535
620
  end
536
621
 
537
- it "says that the root directory is file" do
622
+ it "says that the fixture root directory is a directory" do
538
623
  @root.should be_directory
539
624
  end
540
625
  end
541
626
 
627
+ describe "#pipe?" do
628
+ it "says that `p1` is a pipe" do
629
+ (@root / 'p1').should be_pipe
630
+ end
631
+
632
+ it "says that `f1` is not a pipe" do
633
+ (@root / 'f1').should_not be_pipe
634
+ end
635
+
636
+ it "says that the fixture root directory is not a pipe" do
637
+ @root.should_not be_pipe
638
+ end
639
+ end
640
+
641
+ describe "#socket?" do
642
+ it "says that `s1` is a socket" do
643
+ (@root / 's1').should be_socket
644
+ end
645
+
646
+ it "says that `f1` is not a socket" do
647
+ (@root / 'f1').should_not be_socket
648
+ end
649
+
650
+ it "says that the fixture root directory is not a socket" do
651
+ @root.should_not be_socket
652
+ end
653
+ end
654
+
542
655
  describe "#hidden?" do
543
656
  hidden_paths = [
544
657
  '.foorc',
@@ -563,18 +676,40 @@ describe FilePath do
563
676
  end
564
677
  end
565
678
 
566
- describe FilePath::FileManipulationMethods do
567
- describe "#touch" do
568
- let(:ph) { @root / 'd1' / 'test-touch' }
569
-
570
- before(:each) do
571
- ph.should_not exist
679
+ describe FilePath::FilesystemInfo do
680
+ describe "#absolute_path" do
681
+ test_data = [
682
+ ['d1/l11', File.expand_path('d1/l11', FIXTURES_DIR), FIXTURES_DIR],
683
+ ['/foo/bar', '/foo/bar', '.'],
684
+ ]
685
+ test_data.each do |path, abs_path, cwd|
686
+ it "resolves <#{path}> to <#{abs_path}> (in #{cwd})" do
687
+ Dir.chdir(cwd) do # FIXME
688
+ FilePath.new(path).absolute_path.should == abs_path
689
+ end
690
+ end
572
691
  end
692
+ end
573
693
 
574
- after(:each) do
575
- File.delete(ph) if File.exists?(ph)
694
+ describe "#real_path" do
695
+ it "resolves <d1/l11> to </dev/null>" do
696
+ (@root / 'd1' / 'l11').real_path.should == '/dev/null'
576
697
  end
698
+ end
699
+ end
700
+
701
+ describe FilePath::FilesystemChanges do
702
+ let(:ph) { @root / 'd1' / 'test-file' }
703
+
704
+ before(:each) do
705
+ ph.should_not exist
706
+ end
707
+
708
+ after(:each) do
709
+ File.delete(ph) if File.exists?(ph)
710
+ end
577
711
 
712
+ describe "#touch" do
578
713
  it "creates an empty file" do
579
714
  ph.touch
580
715
  ph.should exist
@@ -601,7 +736,225 @@ describe FilePath do
601
736
  end
602
737
  end
603
738
 
604
- describe FilePath::DirectoryMethods do
739
+ describe FilePath::FilesystemTests do
740
+ describe "mountpoint?" do
741
+ it "says that </proc> is a mount point" do
742
+ "/proc".as_path.should be_mountpoint
743
+ end
744
+
745
+ it "says that this RSpec file is not a mount point" do
746
+ __FILE__.as_path.should_not be_mountpoint
747
+ end
748
+
749
+ it "says that an non-existing file is not a mount point" do
750
+ "/foo/bar".as_path.should_not be_mountpoint
751
+ end
752
+
753
+ it "says that </> is a mount point" do
754
+ "/".as_path.should be_mountpoint
755
+ end
756
+ end
757
+ end
758
+
759
+ describe FilePath::ContentInfo do
760
+ let(:ph) { @root / 'd1' / 'test-file' }
761
+
762
+ before(:each) do
763
+ ph.should_not exist
764
+ end
765
+
766
+ after(:each) do
767
+ File.delete(ph) if File.exists?(ph)
768
+ end
769
+
770
+ describe "#read" do
771
+ let(:content) { "a"*20 + "b"*10 + "c"*5 }
772
+
773
+ before(:each) do
774
+ ph.open('w') { |f| f << content }
775
+ end
776
+
777
+ it "reads the complete content of a file" do
778
+ c = ph.read
779
+ c.should == content
780
+ end
781
+
782
+ it "reads the content in chunks of arbitrary sizes" do
783
+ sum = ""
784
+ len = 8
785
+
786
+ num_chunks = (content.length.to_f / len).ceil
787
+ num_chunks.times do |i|
788
+ c = ph.read(len, len*i)
789
+ sum += c
790
+ c.should == content[len*i, len]
791
+ end
792
+
793
+ sum.should == content
794
+ end
795
+ end
796
+
797
+ describe "#readlines" do
798
+ let(:line) { "abcd12" }
799
+ let(:lines) { Array.new(3) { line } }
800
+
801
+ it "reads all the lines in the file" do
802
+ ph.open('w') { |file| file << lines.join("\n") }
803
+ readlines = ph.readlines
804
+
805
+ readlines.should have(3).lines
806
+ readlines.all? { |l| l.chomp.should == line }
807
+ end
808
+
809
+ it "read lines separated by arbitrary separators" do
810
+ sep = ','
811
+
812
+ ph.open('w') { |file| file << lines.join(sep) }
813
+ readlines = ph.readlines(sep)
814
+
815
+ readlines.should have(3).lines
816
+ readlines[0..-2].all? { |l| l.should == line + sep}
817
+ readlines.last.should == line
818
+ end
819
+ end
820
+
821
+ describe "#size" do
822
+ before(:each) do
823
+ ph.touch
824
+ end
825
+
826
+ it "says that an empty file contains 0 bytes" do
827
+ ph.size.should be_zero
828
+ end
829
+
830
+ it "reports the size of a non-empty file" do
831
+ ph.size.should be_zero
832
+
833
+ ph.open("a") { |f| f << "abc" }
834
+ ph.size.should eq(3)
835
+
836
+ ph.open("a") { |f| f << "defg" }
837
+ ph.size.should eq(3+4)
838
+ end
839
+ end
840
+ end
841
+
842
+ describe FilePath::ContentChanges do
843
+ let(:ph) { @root / 'd1' / 'test-file' }
844
+ let(:content) { "a"*20 + "b"*10 + "c"*5 }
845
+
846
+ before(:each) do
847
+ ph.should_not exist
848
+ end
849
+
850
+ after(:each) do
851
+ File.delete(ph) if File.exists?(ph)
852
+ end
853
+
854
+ describe "#open" do
855
+ before(:each) do
856
+ ph.touch
857
+ end
858
+
859
+ it "opens files" do
860
+ file = ph.open
861
+ file.should be_a(File)
862
+ end
863
+
864
+ it "opens files in read-only mode" do
865
+ ph.open do |file|
866
+ expect { file << "abc" }.to raise_error(IOError)
867
+ end
868
+ end
869
+
870
+ it "opens files in read-write mode" do
871
+ ph.open('w') do |file|
872
+ file << "abc"
873
+ end
874
+
875
+ ph.size.should == 3
876
+ end
877
+ end
878
+
879
+ describe "#write" do
880
+ it "writes data passed as argument" do
881
+ ph.write(content)
882
+
883
+ ph.read.should == content
884
+ end
885
+
886
+ it "overwrites an existing file" do
887
+ ph.write(content * 2)
888
+ ph.size.should eq(content.length * 2)
889
+
890
+ ph.write(content)
891
+ ph.size.should eq(content.length)
892
+
893
+ ph.read.should == content
894
+ end
895
+ end
896
+
897
+ describe "#append" do
898
+ it "appends data to an existing file" do
899
+ ph.write(content)
900
+ ph.append(content)
901
+
902
+ ph.size.should eq(content.length * 2)
903
+ ph.read.should == content * 2
904
+ end
905
+ end
906
+
907
+ describe "#truncate" do
908
+ before(:each) do
909
+ ph.open('w') { |f| f << content }
910
+ end
911
+
912
+ it "truncates a file to 0 bytes" do
913
+ ph.size.should_not be_zero
914
+ ph.truncate
915
+ ph.size.should be_zero
916
+ end
917
+
918
+ it "truncates a file to an arbitrary size" do
919
+ ph.size.should_not be_zero
920
+ ph.truncate(2)
921
+ ph.size.should == 2
922
+ end
923
+ end
924
+ end
925
+
926
+ describe FilePath::ContentTests do
927
+ let(:ph) { @root / 'd1' / 'test-file' }
928
+
929
+ before(:each) do
930
+ ph.should_not exist
931
+ end
932
+
933
+ after(:each) do
934
+ File.delete(ph) if File.exists?(ph)
935
+ end
936
+
937
+ describe "#empty?" do
938
+ before(:each) do
939
+ ph.touch
940
+ end
941
+
942
+ it "says that an empty file is empty" do
943
+ ph.should be_empty
944
+ end
945
+
946
+ it "says that a non-empyt file is not empty" do
947
+ ph.open('w') { |f| f << "abc" }
948
+ ph.should_not be_empty
949
+ end
950
+
951
+ it "says that </dev/null> is empty" do
952
+ '/dev/null'.as_path.should be_empty
953
+ end
954
+ end
955
+ end
956
+
957
+ describe FilePath::SearchMethods do
605
958
  describe "#entries" do
606
959
  it "raises when path is not a directory" do
607
960
  expect { (@root / 'f1').entries(:files) }.to raise_error(Errno::ENOTDIR)
@@ -612,14 +965,14 @@ describe FilePath do
612
965
  it "finds all paths matching a glob string" do
613
966
  list = @root.find('*1')
614
967
 
615
- list.should have(6).items
968
+ list.should have(8).items
616
969
  list.each { |path| path.should =~ /1/ }
617
970
  end
618
971
 
619
972
  it "finds all paths matching a Regex" do
620
973
  list = @root.find(/2/)
621
974
 
622
- list.should have(5).items
975
+ list.should have(6).items
623
976
  list.each { |path| path.should =~ /2/ }
624
977
  end
625
978
 
@@ -677,6 +1030,8 @@ describe FilePath do
677
1030
  end
678
1031
  end
679
1032
  end
1033
+
1034
+ describe FilePath::EnvironmentInfo
680
1035
  end
681
1036
 
682
1037
  describe String do