filepath 0.4 → 0.5

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