memfs 0.5.0 → 2.0.0
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.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +19 -0
- data/.github/workflows/ci.yml +64 -0
- data/.gitignore +1 -0
- data/.rspec +2 -2
- data/.rubocop.yml +81 -12
- data/CHANGELOG.md +41 -10
- data/Gemfile +19 -0
- data/Guardfile +5 -3
- data/README.md +7 -6
- data/Rakefile +4 -2
- data/bin/_guard-core +16 -0
- data/bin/coverage_summary +51 -0
- data/bin/guard +16 -0
- data/bin/rake +16 -0
- data/bin/rspec +16 -0
- data/bin/rubocop +16 -0
- data/lib/memfs/dir.rb +86 -21
- data/lib/memfs/fake/directory.rb +31 -3
- data/lib/memfs/fake/entry.rb +41 -25
- data/lib/memfs/fake/file/content.rb +6 -5
- data/lib/memfs/fake/file.rb +6 -5
- data/lib/memfs/fake/symlink.rb +2 -0
- data/lib/memfs/file/stat.rb +21 -14
- data/lib/memfs/file.rb +92 -77
- data/lib/memfs/file_system.rb +17 -12
- data/lib/memfs/filesystem_access.rb +2 -0
- data/lib/memfs/io.rb +183 -153
- data/lib/memfs/version.rb +3 -1
- data/lib/memfs.rb +112 -5
- data/memfs.gemspec +0 -14
- data/spec/fileutils_spec.rb +86 -58
- data/spec/memfs/dir_spec.rb +175 -27
- data/spec/memfs/fake/directory_spec.rb +8 -4
- data/spec/memfs/fake/entry_spec.rb +16 -10
- data/spec/memfs/fake/file/content_spec.rb +1 -1
- data/spec/memfs/fake/file_spec.rb +1 -1
- data/spec/memfs/fake/symlink_spec.rb +3 -3
- data/spec/memfs/file/stat_spec.rb +30 -15
- data/spec/memfs/file_spec.rb +271 -104
- data/spec/memfs/file_system_spec.rb +20 -19
- data/spec/memfs_spec.rb +67 -2
- data/spec/spec_helper.rb +40 -23
- metadata +17 -135
- data/.travis.yml +0 -6
data/spec/memfs/file_spec.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
1
3
|
require 'spec_helper'
|
|
2
4
|
require 'pathname'
|
|
3
5
|
|
|
4
6
|
module MemFs
|
|
5
|
-
describe File do
|
|
7
|
+
::RSpec.describe File do
|
|
6
8
|
subject { described_class.new('/test-file') }
|
|
7
9
|
let(:write_subject) { described_class.new('/test-file', 'w') }
|
|
8
10
|
|
|
@@ -15,7 +17,6 @@ module MemFs
|
|
|
15
17
|
described_class.symlink '/no-file', '/no-link'
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
|
|
19
20
|
it 'implements Enumerable' do
|
|
20
21
|
expect(described_class.ancestors).to include Enumerable
|
|
21
22
|
end
|
|
@@ -25,6 +26,10 @@ module MemFs
|
|
|
25
26
|
expect(MemFs::File::SEPARATOR).to eq '/'
|
|
26
27
|
end
|
|
27
28
|
|
|
29
|
+
it 'exposes PATH_SEPARATOR' do
|
|
30
|
+
expect(MemFs::File::PATH_SEPARATOR).to eq '/'
|
|
31
|
+
end
|
|
32
|
+
|
|
28
33
|
it 'expose ALT_SEPARATOR' do
|
|
29
34
|
expect(MemFs::File::ALT_SEPARATOR).to be_nil
|
|
30
35
|
end
|
|
@@ -35,20 +40,20 @@ module MemFs
|
|
|
35
40
|
|
|
36
41
|
it 'converts a pathname to an absolute pathname' do
|
|
37
42
|
path = described_class.absolute_path('./test-file')
|
|
38
|
-
expect(path).to eq '/test-dir/test-file'
|
|
43
|
+
expect(path).to eq expected_path('/test-dir/test-file')
|
|
39
44
|
end
|
|
40
45
|
|
|
41
46
|
context 'when +dir_string+ is given' do
|
|
42
47
|
it 'uses it as the starting point' do
|
|
43
48
|
path = described_class.absolute_path('./test-file', '/no-dir')
|
|
44
|
-
expect(path).to eq '/no-dir/test-file'
|
|
49
|
+
expect(path).to eq expected_path('/no-dir/test-file')
|
|
45
50
|
end
|
|
46
51
|
end
|
|
47
52
|
|
|
48
53
|
context "when the given pathname starts with a '~'" do
|
|
49
54
|
it 'does not expanded' do
|
|
50
55
|
path = described_class.absolute_path('~/test-file')
|
|
51
|
-
expect(path).to eq '/test-dir/~/test-file'
|
|
56
|
+
expect(path).to eq expected_path('/test-dir/~/test-file')
|
|
52
57
|
end
|
|
53
58
|
end
|
|
54
59
|
end
|
|
@@ -74,6 +79,27 @@ module MemFs
|
|
|
74
79
|
end
|
|
75
80
|
end
|
|
76
81
|
|
|
82
|
+
describe '.birthtime' do
|
|
83
|
+
it 'returns creation time for the named file as a Time object' do
|
|
84
|
+
expect(described_class.birthtime('/test-file')).to be_a Time
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'raises an error if the entry does not exist' do
|
|
88
|
+
expect { described_class.birthtime('/no-file') }.to raise_error Errno::ENOENT
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context 'when the entry is a symlink' do
|
|
92
|
+
let(:time) { Time.now - 500_000 }
|
|
93
|
+
|
|
94
|
+
it 'returns the creation time of the last target of the link chain' do
|
|
95
|
+
_fs.find!('/test-file').birthtime = time
|
|
96
|
+
described_class.symlink '/test-link', '/test-link2'
|
|
97
|
+
|
|
98
|
+
expect(described_class.birthtime('/test-link2')).to eq time
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
77
103
|
describe '.blockdev?' do
|
|
78
104
|
context 'when the name file exists' do
|
|
79
105
|
context 'and it is a block device' do
|
|
@@ -150,17 +176,17 @@ module MemFs
|
|
|
150
176
|
|
|
151
177
|
describe '.chmod' do
|
|
152
178
|
it 'changes permission bits on the named file' do
|
|
153
|
-
described_class.chmod
|
|
179
|
+
described_class.chmod 0o777, '/test-file'
|
|
154
180
|
|
|
155
181
|
mode = described_class.stat('/test-file').mode
|
|
156
|
-
expect(mode).to be
|
|
182
|
+
expect(mode).to be 0o100777
|
|
157
183
|
end
|
|
158
184
|
|
|
159
185
|
it 'changes permission bits on the named files (in list)' do
|
|
160
|
-
described_class.chmod
|
|
186
|
+
described_class.chmod 0o777, '/test-file', '/test-file2'
|
|
161
187
|
|
|
162
188
|
mode = described_class.stat('/test-file2').mode
|
|
163
|
-
expect(mode).to be
|
|
189
|
+
expect(mode).to be 0o100777
|
|
164
190
|
end
|
|
165
191
|
end
|
|
166
192
|
|
|
@@ -205,7 +231,7 @@ module MemFs
|
|
|
205
231
|
|
|
206
232
|
it 'ignores -1 user id' do
|
|
207
233
|
expect {
|
|
208
|
-
described_class.chown
|
|
234
|
+
described_class.chown(-1, 42, '/test-file')
|
|
209
235
|
}.to_not change { described_class.stat('/test-file').uid }
|
|
210
236
|
end
|
|
211
237
|
|
|
@@ -303,6 +329,12 @@ module MemFs
|
|
|
303
329
|
end
|
|
304
330
|
end
|
|
305
331
|
|
|
332
|
+
describe '.empty?' do
|
|
333
|
+
subject { described_class }
|
|
334
|
+
|
|
335
|
+
it_behaves_like 'aliased method', :empty?, :zero?
|
|
336
|
+
end
|
|
337
|
+
|
|
306
338
|
describe '.executable?' do
|
|
307
339
|
let(:access) { 0 }
|
|
308
340
|
let(:gid) { 0 }
|
|
@@ -458,20 +490,20 @@ module MemFs
|
|
|
458
490
|
_fs.chdir '/'
|
|
459
491
|
|
|
460
492
|
expanded_path = described_class.expand_path('test-file')
|
|
461
|
-
expect(expanded_path).to eq '/test-file'
|
|
493
|
+
expect(expanded_path).to eq expected_path('/test-file')
|
|
462
494
|
end
|
|
463
495
|
|
|
464
496
|
it 'references path from the current working directory' do
|
|
465
497
|
_fs.chdir '/test-dir'
|
|
466
498
|
|
|
467
499
|
expanded_path = described_class.expand_path('test-file')
|
|
468
|
-
expect(expanded_path).to eq '/test-dir/test-file'
|
|
500
|
+
expect(expanded_path).to eq expected_path('/test-dir/test-file')
|
|
469
501
|
end
|
|
470
502
|
|
|
471
503
|
context 'when +dir_string+ is provided' do
|
|
472
504
|
it 'uses +dir_string+ as the stating point' do
|
|
473
505
|
expanded_path = described_class.expand_path('test-file', '/test')
|
|
474
|
-
expect(expanded_path).to eq '/test/test-file'
|
|
506
|
+
expect(expanded_path).to eq expected_path('/test/test-file')
|
|
475
507
|
end
|
|
476
508
|
end
|
|
477
509
|
end
|
|
@@ -499,9 +531,16 @@ module MemFs
|
|
|
499
531
|
end
|
|
500
532
|
|
|
501
533
|
context 'when the period is the last character in path' do
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
534
|
+
if MemFs.ruby_version_gte?('2.7') && !MemFs.windows?
|
|
535
|
+
it 'returns a period' do
|
|
536
|
+
extname = described_class.extname('test-subject.')
|
|
537
|
+
expect(extname).to eq '.'
|
|
538
|
+
end
|
|
539
|
+
else
|
|
540
|
+
it 'returns an empty string' do
|
|
541
|
+
extname = described_class.extname('test-subject.')
|
|
542
|
+
expect(extname).to eq ''
|
|
543
|
+
end
|
|
505
544
|
end
|
|
506
545
|
end
|
|
507
546
|
end
|
|
@@ -555,21 +594,21 @@ module MemFs
|
|
|
555
594
|
|
|
556
595
|
describe '.ftype' do
|
|
557
596
|
context 'when the named entry is a regular file' do
|
|
558
|
-
it
|
|
597
|
+
it 'returns "file"' do
|
|
559
598
|
ftype = described_class.ftype('/test-file')
|
|
560
599
|
expect(ftype).to eq 'file'
|
|
561
600
|
end
|
|
562
601
|
end
|
|
563
602
|
|
|
564
603
|
context 'when the named entry is a directory' do
|
|
565
|
-
it
|
|
604
|
+
it 'returns "directory"' do
|
|
566
605
|
ftype = described_class.ftype('/test-dir')
|
|
567
606
|
expect(ftype).to eq 'directory'
|
|
568
607
|
end
|
|
569
608
|
end
|
|
570
609
|
|
|
571
610
|
context 'when the named entry is a block device' do
|
|
572
|
-
it
|
|
611
|
+
it 'returns "blockSpecial"' do
|
|
573
612
|
_fs.touch '/block-file'
|
|
574
613
|
file = _fs.find('/block-file')
|
|
575
614
|
file.block_device = true
|
|
@@ -580,7 +619,7 @@ module MemFs
|
|
|
580
619
|
end
|
|
581
620
|
|
|
582
621
|
context 'when the named entry is a character device' do
|
|
583
|
-
it
|
|
622
|
+
it 'returns "characterSpecial"' do
|
|
584
623
|
_fs.touch '/character-file'
|
|
585
624
|
file = _fs.find('/character-file')
|
|
586
625
|
file.character_device = true
|
|
@@ -591,7 +630,7 @@ module MemFs
|
|
|
591
630
|
end
|
|
592
631
|
|
|
593
632
|
context 'when the named entry is a symlink' do
|
|
594
|
-
it
|
|
633
|
+
it 'returns "link"' do
|
|
595
634
|
ftype = described_class.ftype('/test-link')
|
|
596
635
|
expect(ftype).to eq 'link'
|
|
597
636
|
end
|
|
@@ -600,7 +639,7 @@ module MemFs
|
|
|
600
639
|
# fifo and socket not handled for now
|
|
601
640
|
|
|
602
641
|
context 'when the named entry has no specific type' do
|
|
603
|
-
it
|
|
642
|
+
it 'returns "unknown"' do
|
|
604
643
|
root = _fs.find '/'
|
|
605
644
|
root.add_entry Fake::Entry.new('test-entry')
|
|
606
645
|
|
|
@@ -623,7 +662,7 @@ module MemFs
|
|
|
623
662
|
|
|
624
663
|
context 'and the effective user group does not own of the file' do
|
|
625
664
|
it 'returns false' do
|
|
626
|
-
described_class.chown
|
|
665
|
+
described_class.chown 9999, 9999, '/test-file'
|
|
627
666
|
|
|
628
667
|
grpowned = File.grpowned?('/test-file')
|
|
629
668
|
expect(grpowned).to be false
|
|
@@ -700,6 +739,30 @@ module MemFs
|
|
|
700
739
|
end
|
|
701
740
|
end
|
|
702
741
|
end
|
|
742
|
+
|
|
743
|
+
context 'when given a File object instead of a path' do
|
|
744
|
+
it 'returns true when the File object refers to the same file' do
|
|
745
|
+
file = described_class.new('/test-file', 'r')
|
|
746
|
+
expect(described_class.identical?(file, '/test-file')).to be true
|
|
747
|
+
file.close
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
it 'returns true when both arguments are File objects for the same file' do
|
|
751
|
+
file1 = described_class.new('/test-file', 'r')
|
|
752
|
+
file2 = described_class.new('/test-file', 'r')
|
|
753
|
+
expect(described_class.identical?(file1, file2)).to be true
|
|
754
|
+
file1.close
|
|
755
|
+
file2.close
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
it 'returns false when both File objects refer to different files' do
|
|
759
|
+
file1 = described_class.new('/test-file', 'r')
|
|
760
|
+
file2 = described_class.new('/test-file2', 'r')
|
|
761
|
+
expect(described_class.identical?(file1, file2)).to be false
|
|
762
|
+
file1.close
|
|
763
|
+
file2.close
|
|
764
|
+
end
|
|
765
|
+
end
|
|
703
766
|
end
|
|
704
767
|
|
|
705
768
|
describe '.join' do
|
|
@@ -712,24 +775,24 @@ module MemFs
|
|
|
712
775
|
describe '.lchmod' do
|
|
713
776
|
context 'when the named file is a regular file' do
|
|
714
777
|
it 'acts like chmod' do
|
|
715
|
-
described_class.lchmod
|
|
778
|
+
described_class.lchmod 0o777, '/test-file'
|
|
716
779
|
|
|
717
780
|
mode = described_class.stat('/test-file').mode
|
|
718
|
-
expect(mode).to be
|
|
781
|
+
expect(mode).to be 0o100777
|
|
719
782
|
end
|
|
720
783
|
end
|
|
721
784
|
|
|
722
785
|
context 'when the named file is a symlink' do
|
|
723
786
|
it 'changes permission bits on the symlink' do
|
|
724
|
-
described_class.lchmod
|
|
787
|
+
described_class.lchmod 0o777, '/test-link'
|
|
725
788
|
|
|
726
789
|
mode = described_class.lstat('/test-link').mode
|
|
727
|
-
expect(mode).to be
|
|
790
|
+
expect(mode).to be 0o100777
|
|
728
791
|
end
|
|
729
792
|
|
|
730
|
-
it
|
|
793
|
+
it 'does not change permission bits on the link’s target' do
|
|
731
794
|
old_mode = described_class.stat('/test-file').mode
|
|
732
|
-
described_class.lchmod
|
|
795
|
+
described_class.lchmod 0o777, '/test-link'
|
|
733
796
|
|
|
734
797
|
mode = described_class.stat('/test-file').mode
|
|
735
798
|
expect(mode).to eq old_mode
|
|
@@ -791,18 +854,45 @@ module MemFs
|
|
|
791
854
|
is_symlink = described_class.lstat('/test-link').symlink?
|
|
792
855
|
expect(is_symlink).to be true
|
|
793
856
|
end
|
|
857
|
+
end
|
|
858
|
+
end
|
|
794
859
|
|
|
795
|
-
|
|
796
|
-
|
|
860
|
+
describe '.new' do
|
|
861
|
+
it 'resets the file position to the beginning' do
|
|
862
|
+
described_class.open('/test-file', 'w') { |f| f.write 'hello' }
|
|
863
|
+
|
|
864
|
+
contents = described_class.open('/test-file', 'r', &:read)
|
|
865
|
+
expect(contents).to eq('hello')
|
|
866
|
+
|
|
867
|
+
contents = described_class.open('/test-file', 'r', &:read)
|
|
868
|
+
expect(contents).to eq('hello')
|
|
869
|
+
end
|
|
870
|
+
|
|
871
|
+
context 'when only the filename is provided' do
|
|
872
|
+
context 'and the file exists' do
|
|
873
|
+
it 'returns the open file' do
|
|
874
|
+
file = described_class.new('/test-file')
|
|
875
|
+
expect(file).to be_a(MemFs::File)
|
|
876
|
+
end
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
context 'and the file does not exist' do
|
|
880
|
+
it 'raises an exception' do
|
|
797
881
|
expect {
|
|
798
|
-
described_class.
|
|
799
|
-
}.
|
|
882
|
+
described_class.new('missing-file')
|
|
883
|
+
}.to raise_error(Errno::ENOENT)
|
|
884
|
+
end
|
|
885
|
+
end
|
|
886
|
+
|
|
887
|
+
context 'when the file is a symlink and its target does not exist' do
|
|
888
|
+
it 'raises an exception' do
|
|
889
|
+
expect {
|
|
890
|
+
described_class.new('/no-link')
|
|
891
|
+
}.to raise_error(Errno::ENOENT)
|
|
800
892
|
end
|
|
801
893
|
end
|
|
802
894
|
end
|
|
803
|
-
end
|
|
804
895
|
|
|
805
|
-
describe '.new' do
|
|
806
896
|
context 'when the mode is provided' do
|
|
807
897
|
context 'and it is an integer' do
|
|
808
898
|
subject { described_class.new('/test-file', File::RDWR) }
|
|
@@ -820,7 +910,8 @@ module MemFs
|
|
|
820
910
|
|
|
821
911
|
it 'sets the write+create+truncate mode for "w"' do
|
|
822
912
|
subject = described_class.new('/test-file', 'w')
|
|
823
|
-
expect(subject.send(:opening_mode)).to
|
|
913
|
+
expect(subject.send(:opening_mode)).to \
|
|
914
|
+
eq File::CREAT | File::TRUNC | File::WRONLY
|
|
824
915
|
end
|
|
825
916
|
|
|
826
917
|
it 'sets the read+write mode for "r+"' do
|
|
@@ -830,17 +921,20 @@ module MemFs
|
|
|
830
921
|
|
|
831
922
|
it 'sets the read+write+create+truncate mode for "w+"' do
|
|
832
923
|
subject = described_class.new('/test-file', 'w+')
|
|
833
|
-
expect(subject.send(:opening_mode)).to
|
|
924
|
+
expect(subject.send(:opening_mode)).to \
|
|
925
|
+
eq File::CREAT | File::TRUNC | File::RDWR
|
|
834
926
|
end
|
|
835
927
|
|
|
836
928
|
it 'sets the write+create+append mode for "a"' do
|
|
837
929
|
subject = described_class.new('/test-file', 'a')
|
|
838
|
-
expect(subject.send(:opening_mode)).to
|
|
930
|
+
expect(subject.send(:opening_mode)).to \
|
|
931
|
+
eq File::CREAT | File::APPEND | File::WRONLY
|
|
839
932
|
end
|
|
840
933
|
|
|
841
934
|
it 'sets the read+write+create+append mode for "a+"' do
|
|
842
935
|
subject = described_class.new('/test-file', 'a+')
|
|
843
|
-
expect(subject.send(:opening_mode)).to
|
|
936
|
+
expect(subject.send(:opening_mode)).to \
|
|
937
|
+
eq File::CREAT | File::APPEND | File::RDWR
|
|
844
938
|
end
|
|
845
939
|
|
|
846
940
|
it 'handles the :bom option' do
|
|
@@ -848,6 +942,16 @@ module MemFs
|
|
|
848
942
|
expect(subject.send(:opening_mode)).to eq File::RDONLY
|
|
849
943
|
end
|
|
850
944
|
|
|
945
|
+
it 'handles the :utf-8 option' do
|
|
946
|
+
subject = described_class.new('/test-file', 'r:utf-8')
|
|
947
|
+
expect(subject.send(:opening_mode)).to eq File::RDONLY
|
|
948
|
+
end
|
|
949
|
+
|
|
950
|
+
it 'handles the :UTF-8 option' do
|
|
951
|
+
subject = described_class.new('/test-file', 'r:UTF-8')
|
|
952
|
+
expect(subject.send(:opening_mode)).to eq File::RDONLY
|
|
953
|
+
end
|
|
954
|
+
|
|
851
955
|
it 'handles the |utf-8 option' do
|
|
852
956
|
subject = described_class.new('/test-file', 'r|utf-8')
|
|
853
957
|
expect(subject.send(:opening_mode)).to eq File::RDONLY
|
|
@@ -889,7 +993,9 @@ module MemFs
|
|
|
889
993
|
|
|
890
994
|
context 'when too many arguments are given' do
|
|
891
995
|
it 'raises an exception' do
|
|
892
|
-
expect {
|
|
996
|
+
expect {
|
|
997
|
+
described_class.new(1, 2, 3, 4)
|
|
998
|
+
}.to raise_error(ArgumentError)
|
|
893
999
|
end
|
|
894
1000
|
end
|
|
895
1001
|
end
|
|
@@ -907,7 +1013,7 @@ module MemFs
|
|
|
907
1013
|
|
|
908
1014
|
context 'and the effective user does not own of the file' do
|
|
909
1015
|
it 'returns false' do
|
|
910
|
-
described_class.chown
|
|
1016
|
+
described_class.chown 9999, 9999, '/test-file'
|
|
911
1017
|
|
|
912
1018
|
owned = File.owned?('/test-file')
|
|
913
1019
|
expect(owned).to be false
|
|
@@ -989,18 +1095,18 @@ module MemFs
|
|
|
989
1095
|
|
|
990
1096
|
context 'when the last argument is a hash' do
|
|
991
1097
|
it 'passes the contained options to +open+' do
|
|
992
|
-
expect(described_class).to
|
|
993
|
-
|
|
994
|
-
|
|
1098
|
+
expect(described_class).to \
|
|
1099
|
+
receive(:open)
|
|
1100
|
+
.with('/test-file', File::RDONLY, { encoding: 'UTF-8' })
|
|
1101
|
+
.and_return(subject)
|
|
995
1102
|
|
|
996
1103
|
described_class.read '/test-file', encoding: 'UTF-8'
|
|
997
1104
|
end
|
|
998
1105
|
|
|
999
1106
|
context 'when it contains the +open_args+ key' do
|
|
1000
1107
|
it 'takes precedence over the other options' do
|
|
1001
|
-
expect(described_class).to
|
|
1002
|
-
|
|
1003
|
-
.and_return(subject)
|
|
1108
|
+
expect(described_class).to \
|
|
1109
|
+
receive(:open).with('/test-file', 'r').and_return(subject)
|
|
1004
1110
|
|
|
1005
1111
|
described_class.read '/test-file', mode: 'w', open_args: ['r']
|
|
1006
1112
|
end
|
|
@@ -1152,7 +1258,7 @@ module MemFs
|
|
|
1152
1258
|
context 'when the path does not contain any symlink or useless dots' do
|
|
1153
1259
|
it 'returns the path itself' do
|
|
1154
1260
|
path = described_class.realdirpath('/test-file')
|
|
1155
|
-
expect(path).to eq '/test-file'
|
|
1261
|
+
expect(path).to eq expected_path('/test-file')
|
|
1156
1262
|
end
|
|
1157
1263
|
end
|
|
1158
1264
|
|
|
@@ -1160,14 +1266,14 @@ module MemFs
|
|
|
1160
1266
|
context 'and the symlink is a middle part' do
|
|
1161
1267
|
it 'returns the path with the symlink dereferrenced' do
|
|
1162
1268
|
path = described_class.realdirpath('/test-dir/sub-dir-link/test-file')
|
|
1163
|
-
expect(path).to eq '/test-dir/sub-dir/test-file'
|
|
1269
|
+
expect(path).to eq expected_path('/test-dir/sub-dir/test-file')
|
|
1164
1270
|
end
|
|
1165
1271
|
end
|
|
1166
1272
|
|
|
1167
1273
|
context 'and the symlink is the last part' do
|
|
1168
1274
|
it 'returns the path with the symlink dereferrenced' do
|
|
1169
1275
|
path = described_class.realdirpath('/test-dir/sub-dir-link')
|
|
1170
|
-
expect(path).to eq '/test-dir/sub-dir'
|
|
1276
|
+
expect(path).to eq expected_path('/test-dir/sub-dir')
|
|
1171
1277
|
end
|
|
1172
1278
|
end
|
|
1173
1279
|
end
|
|
@@ -1175,7 +1281,7 @@ module MemFs
|
|
|
1175
1281
|
context 'when the path contains useless dots' do
|
|
1176
1282
|
it 'returns the path with the useless dots interpolated' do
|
|
1177
1283
|
path = described_class.realdirpath('/test-dir/../test-dir/./sub-dir/test-file')
|
|
1178
|
-
expect(path).to eq '/test-dir/sub-dir/test-file'
|
|
1284
|
+
expect(path).to eq expected_path('/test-dir/sub-dir/test-file')
|
|
1179
1285
|
end
|
|
1180
1286
|
end
|
|
1181
1287
|
|
|
@@ -1184,14 +1290,14 @@ module MemFs
|
|
|
1184
1290
|
it 'uses the current working directory has base directory' do
|
|
1185
1291
|
_fs.chdir '/test-dir'
|
|
1186
1292
|
path = described_class.realdirpath('../test-dir/./sub-dir/test-file')
|
|
1187
|
-
expect(path).to eq '/test-dir/sub-dir/test-file'
|
|
1293
|
+
expect(path).to eq expected_path('/test-dir/sub-dir/test-file')
|
|
1188
1294
|
end
|
|
1189
1295
|
end
|
|
1190
1296
|
|
|
1191
1297
|
context 'and +dir_string+ is provided' do
|
|
1192
1298
|
it 'uses the given directory has base directory' do
|
|
1193
1299
|
path = described_class.realdirpath('../test-dir/./sub-dir/test-file', '/test-dir')
|
|
1194
|
-
expect(path).to eq '/test-dir/sub-dir/test-file'
|
|
1300
|
+
expect(path).to eq expected_path('/test-dir/sub-dir/test-file')
|
|
1195
1301
|
end
|
|
1196
1302
|
end
|
|
1197
1303
|
end
|
|
@@ -1204,7 +1310,7 @@ module MemFs
|
|
|
1204
1310
|
|
|
1205
1311
|
it 'uses the name of the target in the resulting path' do
|
|
1206
1312
|
path = described_class.realdirpath('/test-dir/sub-dir/test-link')
|
|
1207
|
-
expect(path).to eq '/test-dir/sub-dir/test'
|
|
1313
|
+
expect(path).to eq expected_path('/test-dir/sub-dir/test')
|
|
1208
1314
|
end
|
|
1209
1315
|
end
|
|
1210
1316
|
end
|
|
@@ -1212,7 +1318,7 @@ module MemFs
|
|
|
1212
1318
|
context 'when the last part of the given path does not exist' do
|
|
1213
1319
|
it 'uses its name in the resulting path' do
|
|
1214
1320
|
path = described_class.realdirpath('/test-dir/sub-dir/test')
|
|
1215
|
-
expect(path).to eq '/test-dir/sub-dir/test'
|
|
1321
|
+
expect(path).to eq expected_path('/test-dir/sub-dir/test')
|
|
1216
1322
|
end
|
|
1217
1323
|
end
|
|
1218
1324
|
|
|
@@ -1220,7 +1326,7 @@ module MemFs
|
|
|
1220
1326
|
it 'raises an exception' do
|
|
1221
1327
|
expect {
|
|
1222
1328
|
described_class.realdirpath '/no-dir/test-file'
|
|
1223
|
-
}.to raise_error
|
|
1329
|
+
}.to raise_error Errno::ENOENT
|
|
1224
1330
|
end
|
|
1225
1331
|
end
|
|
1226
1332
|
end
|
|
@@ -1235,7 +1341,7 @@ module MemFs
|
|
|
1235
1341
|
context 'when the path does not contain any symlink or useless dots' do
|
|
1236
1342
|
it 'returns the path itself' do
|
|
1237
1343
|
path = described_class.realpath('/test-file')
|
|
1238
|
-
expect(path).to eq '/test-file'
|
|
1344
|
+
expect(path).to eq expected_path('/test-file')
|
|
1239
1345
|
end
|
|
1240
1346
|
end
|
|
1241
1347
|
|
|
@@ -1243,14 +1349,14 @@ module MemFs
|
|
|
1243
1349
|
context 'and the symlink is a middle part' do
|
|
1244
1350
|
it 'returns the path with the symlink dereferrenced' do
|
|
1245
1351
|
path = described_class.realpath('/test-dir/sub-dir-link/test-file')
|
|
1246
|
-
expect(path).to eq '/test-dir/sub-dir/test-file'
|
|
1352
|
+
expect(path).to eq expected_path('/test-dir/sub-dir/test-file')
|
|
1247
1353
|
end
|
|
1248
1354
|
end
|
|
1249
1355
|
|
|
1250
1356
|
context 'and the symlink is the last part' do
|
|
1251
1357
|
it 'returns the path with the symlink dereferrenced' do
|
|
1252
1358
|
path = described_class.realpath('/test-dir/sub-dir-link')
|
|
1253
|
-
expect(path).to eq '/test-dir/sub-dir'
|
|
1359
|
+
expect(path).to eq expected_path('/test-dir/sub-dir')
|
|
1254
1360
|
end
|
|
1255
1361
|
end
|
|
1256
1362
|
end
|
|
@@ -1258,7 +1364,7 @@ module MemFs
|
|
|
1258
1364
|
context 'when the path contains useless dots' do
|
|
1259
1365
|
it 'returns the path with the useless dots interpolated' do
|
|
1260
1366
|
path = described_class.realpath('/test-dir/../test-dir/./sub-dir/test-file')
|
|
1261
|
-
expect(path).to eq '/test-dir/sub-dir/test-file'
|
|
1367
|
+
expect(path).to eq expected_path('/test-dir/sub-dir/test-file')
|
|
1262
1368
|
end
|
|
1263
1369
|
end
|
|
1264
1370
|
|
|
@@ -1268,14 +1374,14 @@ module MemFs
|
|
|
1268
1374
|
_fs.chdir '/test-dir'
|
|
1269
1375
|
|
|
1270
1376
|
path = described_class.realpath('../test-dir/./sub-dir/test-file')
|
|
1271
|
-
expect(path).to eq '/test-dir/sub-dir/test-file'
|
|
1377
|
+
expect(path).to eq expected_path('/test-dir/sub-dir/test-file')
|
|
1272
1378
|
end
|
|
1273
1379
|
end
|
|
1274
1380
|
|
|
1275
1381
|
context 'and +dir_string+ is provided' do
|
|
1276
1382
|
it 'uses the given directory has base directory' do
|
|
1277
1383
|
path = described_class.realpath('../test-dir/./sub-dir/test-file', '/test-dir')
|
|
1278
|
-
expect(path).to eq '/test-dir/sub-dir/test-file'
|
|
1384
|
+
expect(path).to eq expected_path('/test-dir/sub-dir/test-file')
|
|
1279
1385
|
end
|
|
1280
1386
|
end
|
|
1281
1387
|
end
|
|
@@ -1284,7 +1390,7 @@ module MemFs
|
|
|
1284
1390
|
it 'raises an exception' do
|
|
1285
1391
|
expect {
|
|
1286
1392
|
described_class.realpath '/no-dir/test-file'
|
|
1287
|
-
}.to raise_error
|
|
1393
|
+
}.to raise_error Errno::ENOENT
|
|
1288
1394
|
end
|
|
1289
1395
|
end
|
|
1290
1396
|
end
|
|
@@ -1307,7 +1413,7 @@ module MemFs
|
|
|
1307
1413
|
context 'when the named file exists' do
|
|
1308
1414
|
context 'and the named file has the setgid bit set' do
|
|
1309
1415
|
it 'returns true' do
|
|
1310
|
-
_fs.chmod
|
|
1416
|
+
_fs.chmod 0o2000, '/test-file'
|
|
1311
1417
|
|
|
1312
1418
|
setgid = File.setgid?('/test-file')
|
|
1313
1419
|
expect(setgid).to be true
|
|
@@ -1316,6 +1422,8 @@ module MemFs
|
|
|
1316
1422
|
|
|
1317
1423
|
context 'and the named file does not have the setgid bit set' do
|
|
1318
1424
|
it 'returns false' do
|
|
1425
|
+
_fs.chmod 0o644, '/test-file'
|
|
1426
|
+
|
|
1319
1427
|
setgid = File.setgid?('/test-file')
|
|
1320
1428
|
expect(setgid).not_to be true
|
|
1321
1429
|
end
|
|
@@ -1334,7 +1442,7 @@ module MemFs
|
|
|
1334
1442
|
context 'when the named file exists' do
|
|
1335
1443
|
context 'and the named file has the setuid bit set' do
|
|
1336
1444
|
it 'returns true' do
|
|
1337
|
-
_fs.chmod
|
|
1445
|
+
_fs.chmod 0o4000, '/test-file'
|
|
1338
1446
|
|
|
1339
1447
|
setuid = File.setuid?('/test-file')
|
|
1340
1448
|
expect(setuid).to be true
|
|
@@ -1343,6 +1451,8 @@ module MemFs
|
|
|
1343
1451
|
|
|
1344
1452
|
context 'and the named file does not have the setuid bit set' do
|
|
1345
1453
|
it 'returns false' do
|
|
1454
|
+
_fs.chmod 0o644, '/test-file'
|
|
1455
|
+
|
|
1346
1456
|
setuid = File.setuid?('/test-file')
|
|
1347
1457
|
expect(setuid).not_to be true
|
|
1348
1458
|
end
|
|
@@ -1441,10 +1551,10 @@ module MemFs
|
|
|
1441
1551
|
end
|
|
1442
1552
|
|
|
1443
1553
|
it 'always returns a new object' do
|
|
1444
|
-
|
|
1445
|
-
|
|
1554
|
+
stat1 = described_class.stat('/test-file')
|
|
1555
|
+
stat2 = described_class.stat('/test-file')
|
|
1446
1556
|
|
|
1447
|
-
expect(
|
|
1557
|
+
expect(stat2).not_to be stat1
|
|
1448
1558
|
end
|
|
1449
1559
|
end
|
|
1450
1560
|
|
|
@@ -1452,14 +1562,15 @@ module MemFs
|
|
|
1452
1562
|
context 'when the named file exists' do
|
|
1453
1563
|
it 'returns true if the named file has the sticky bit set' do
|
|
1454
1564
|
_fs.touch '/test-file'
|
|
1455
|
-
_fs.chmod
|
|
1565
|
+
_fs.chmod 0o1777, '/test-file'
|
|
1456
1566
|
|
|
1457
1567
|
sticky = File.sticky?('/test-file')
|
|
1458
1568
|
expect(sticky).to be true
|
|
1459
1569
|
end
|
|
1460
1570
|
|
|
1461
|
-
it
|
|
1571
|
+
it 'returns false if the named file hasn’t the sticky bit set' do
|
|
1462
1572
|
_fs.touch '/test-file'
|
|
1573
|
+
_fs.chmod 0o666, '/test-file'
|
|
1463
1574
|
|
|
1464
1575
|
sticky = File.sticky?('/test-file')
|
|
1465
1576
|
expect(sticky).to be false
|
|
@@ -1540,33 +1651,37 @@ module MemFs
|
|
|
1540
1651
|
|
|
1541
1652
|
context 'when the named file does not exist' do
|
|
1542
1653
|
it 'raises an exception' do
|
|
1543
|
-
expect {
|
|
1654
|
+
expect {
|
|
1655
|
+
described_class.truncate '/no-file', 5
|
|
1656
|
+
}.to raise_error Errno::ENOENT
|
|
1544
1657
|
end
|
|
1545
1658
|
end
|
|
1546
1659
|
|
|
1547
1660
|
context 'when the given size is negative' do
|
|
1548
1661
|
it 'it raises an exception' do
|
|
1549
|
-
expect {
|
|
1662
|
+
expect {
|
|
1663
|
+
described_class.truncate '/test-file', -1
|
|
1664
|
+
}.to raise_error TypeError
|
|
1550
1665
|
end
|
|
1551
1666
|
end
|
|
1552
1667
|
end
|
|
1553
1668
|
|
|
1554
1669
|
describe '.umask' do
|
|
1555
|
-
before { described_class.umask
|
|
1670
|
+
before { described_class.umask 0o022 }
|
|
1556
1671
|
|
|
1557
1672
|
it 'returns the current umask value for this process' do
|
|
1558
|
-
expect(described_class.umask).to be
|
|
1673
|
+
expect(described_class.umask).to be 0o022
|
|
1559
1674
|
end
|
|
1560
1675
|
|
|
1561
1676
|
context 'when the optional argument is given' do
|
|
1562
1677
|
it 'sets the umask to that value' do
|
|
1563
|
-
described_class.umask
|
|
1564
|
-
expect(described_class.umask).to be
|
|
1678
|
+
described_class.umask 0o777
|
|
1679
|
+
expect(described_class.umask).to be 0o777
|
|
1565
1680
|
end
|
|
1566
1681
|
|
|
1567
1682
|
it 'return the previous value' do
|
|
1568
|
-
previous_umask = described_class.umask(
|
|
1569
|
-
expect(previous_umask).to be
|
|
1683
|
+
previous_umask = described_class.umask(0o777)
|
|
1684
|
+
expect(previous_umask).to be 0o022
|
|
1570
1685
|
end
|
|
1571
1686
|
end
|
|
1572
1687
|
end
|
|
@@ -1803,6 +1918,54 @@ module MemFs
|
|
|
1803
1918
|
end
|
|
1804
1919
|
end
|
|
1805
1920
|
|
|
1921
|
+
describe '.write' do
|
|
1922
|
+
it 'writes the string to the given file' do
|
|
1923
|
+
described_class.write('/test-file', 'test')
|
|
1924
|
+
read_content = described_class.read('/test-file')
|
|
1925
|
+
expect(read_content).to eq 'test'
|
|
1926
|
+
end
|
|
1927
|
+
|
|
1928
|
+
context 'when +offset+ is provided' do
|
|
1929
|
+
it 'writes the string to the given file when offset is 0' do
|
|
1930
|
+
described_class.write('/test-file', 'test', 0)
|
|
1931
|
+
read_content = described_class.read('/test-file')
|
|
1932
|
+
expect(read_content).to eq 'test'
|
|
1933
|
+
end
|
|
1934
|
+
|
|
1935
|
+
it 'writes the string to the given file when offset is nil' do
|
|
1936
|
+
described_class.write('/test-file', 'test', nil)
|
|
1937
|
+
read_content = described_class.read('/test-file')
|
|
1938
|
+
expect(read_content).to eq 'test'
|
|
1939
|
+
end
|
|
1940
|
+
|
|
1941
|
+
it 'starts writing from the offset' do
|
|
1942
|
+
skip('Offsets not yet implemented in IO.write')
|
|
1943
|
+
described_class.write('/test-file', 'test')
|
|
1944
|
+
described_class.write('/test-file', 'test', 2)
|
|
1945
|
+
read_content = described_class.read('/test-file')
|
|
1946
|
+
expect(read_content).to eq 'tetest'
|
|
1947
|
+
end
|
|
1948
|
+
|
|
1949
|
+
it 'raises an error if offset is negative' do
|
|
1950
|
+
expect {
|
|
1951
|
+
described_class.write('/test-file', 'foo', -1)
|
|
1952
|
+
}.to raise_error Errno::EINVAL
|
|
1953
|
+
end
|
|
1954
|
+
|
|
1955
|
+
it 'raises an error if offset is a boolean' do
|
|
1956
|
+
expect {
|
|
1957
|
+
described_class.write '/test-file', 'foo', false
|
|
1958
|
+
}.to raise_error TypeError
|
|
1959
|
+
end
|
|
1960
|
+
|
|
1961
|
+
it 'raises an error if offset is a string' do
|
|
1962
|
+
expect {
|
|
1963
|
+
described_class.write '/test-file', 'foo', 'offset'
|
|
1964
|
+
}.to raise_error TypeError
|
|
1965
|
+
end
|
|
1966
|
+
end
|
|
1967
|
+
end
|
|
1968
|
+
|
|
1806
1969
|
describe '.zero?' do
|
|
1807
1970
|
context 'when the named file exists' do
|
|
1808
1971
|
context 'and has a zero size' do
|
|
@@ -1906,7 +2069,7 @@ module MemFs
|
|
|
1906
2069
|
end
|
|
1907
2070
|
|
|
1908
2071
|
describe '#autoclose?' do
|
|
1909
|
-
it
|
|
2072
|
+
it 'returns true by default' do
|
|
1910
2073
|
expect(subject.autoclose?).to be true
|
|
1911
2074
|
end
|
|
1912
2075
|
|
|
@@ -1938,7 +2101,7 @@ module MemFs
|
|
|
1938
2101
|
expect(subject.binmode?).to be true
|
|
1939
2102
|
end
|
|
1940
2103
|
|
|
1941
|
-
it
|
|
2104
|
+
it 'sets the file encoding to ASCII-8BIT' do
|
|
1942
2105
|
subject.binmode
|
|
1943
2106
|
|
|
1944
2107
|
encoding = subject.external_encoding
|
|
@@ -1947,7 +2110,7 @@ module MemFs
|
|
|
1947
2110
|
end
|
|
1948
2111
|
|
|
1949
2112
|
describe '#binmode?' do
|
|
1950
|
-
it
|
|
2113
|
+
it 'returns false by default' do
|
|
1951
2114
|
expect(subject.binmode?).to be false
|
|
1952
2115
|
end
|
|
1953
2116
|
|
|
@@ -1960,6 +2123,12 @@ module MemFs
|
|
|
1960
2123
|
end
|
|
1961
2124
|
end
|
|
1962
2125
|
|
|
2126
|
+
describe '#birthtime' do
|
|
2127
|
+
it 'returns a Time object' do
|
|
2128
|
+
expect(subject.birthtime).to be_a Time
|
|
2129
|
+
end
|
|
2130
|
+
end
|
|
2131
|
+
|
|
1963
2132
|
describe '#bytes' do
|
|
1964
2133
|
it_behaves_like 'aliased method', :bytes, :each_byte
|
|
1965
2134
|
end
|
|
@@ -1970,14 +2139,14 @@ module MemFs
|
|
|
1970
2139
|
|
|
1971
2140
|
describe '#chmod' do
|
|
1972
2141
|
it 'changes permission bits on the file' do
|
|
1973
|
-
subject.chmod
|
|
2142
|
+
subject.chmod 0o777
|
|
1974
2143
|
|
|
1975
2144
|
mode = subject.stat.mode
|
|
1976
|
-
expect(mode).to be
|
|
2145
|
+
expect(mode).to be 0o100777
|
|
1977
2146
|
end
|
|
1978
2147
|
|
|
1979
2148
|
it 'returns zero' do
|
|
1980
|
-
returned_value = subject.chmod(
|
|
2149
|
+
returned_value = subject.chmod(0o777)
|
|
1981
2150
|
expect(returned_value).to be_zero
|
|
1982
2151
|
end
|
|
1983
2152
|
end
|
|
@@ -2023,7 +2192,7 @@ module MemFs
|
|
|
2023
2192
|
|
|
2024
2193
|
it 'ignores -1 user id' do
|
|
2025
2194
|
expect {
|
|
2026
|
-
subject.chown
|
|
2195
|
+
subject.chown(-1, 42)
|
|
2027
2196
|
}.to_not change { subject.stat.uid }
|
|
2028
2197
|
end
|
|
2029
2198
|
|
|
@@ -2097,7 +2266,7 @@ module MemFs
|
|
|
2097
2266
|
expect(subject.close_on_exec?).to be true
|
|
2098
2267
|
end
|
|
2099
2268
|
|
|
2100
|
-
context
|
|
2269
|
+
context 'when the close-on-exec flag is set to false' do
|
|
2101
2270
|
before { subject.close_on_exec = false }
|
|
2102
2271
|
|
|
2103
2272
|
it 'returns false' do
|
|
@@ -2186,7 +2355,7 @@ module MemFs
|
|
|
2186
2355
|
context 'when the file is not open for reading' do
|
|
2187
2356
|
it 'raises an exception' do
|
|
2188
2357
|
expect {
|
|
2189
|
-
write_subject.each_byte {
|
|
2358
|
+
write_subject.each_byte {}
|
|
2190
2359
|
}.to raise_error IOError
|
|
2191
2360
|
end
|
|
2192
2361
|
|
|
@@ -2223,7 +2392,7 @@ module MemFs
|
|
|
2223
2392
|
context 'when the file is not open for reading' do
|
|
2224
2393
|
it 'raises an exception' do
|
|
2225
2394
|
expect {
|
|
2226
|
-
write_subject.each_char {
|
|
2395
|
+
write_subject.each_char {}
|
|
2227
2396
|
}.to raise_error IOError
|
|
2228
2397
|
end
|
|
2229
2398
|
|
|
@@ -2313,6 +2482,12 @@ module MemFs
|
|
|
2313
2482
|
end
|
|
2314
2483
|
end
|
|
2315
2484
|
|
|
2485
|
+
describe '#fileno' do
|
|
2486
|
+
it 'raises an exception' do
|
|
2487
|
+
expect { subject.fileno }.to raise_exception(NotImplementedError)
|
|
2488
|
+
end
|
|
2489
|
+
end
|
|
2490
|
+
|
|
2316
2491
|
describe '#flock' do
|
|
2317
2492
|
it 'returns zero' do
|
|
2318
2493
|
returned_value = subject.flock(File::LOCK_EX)
|
|
@@ -2325,19 +2500,11 @@ module MemFs
|
|
|
2325
2500
|
expect(subject.lstat).to be_a File::Stat
|
|
2326
2501
|
end
|
|
2327
2502
|
|
|
2328
|
-
|
|
2329
|
-
|
|
2503
|
+
context 'when the given file is a symlink' do
|
|
2504
|
+
subject { described_class.new('/test-link') }
|
|
2330
2505
|
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
end
|
|
2334
|
-
|
|
2335
|
-
context 'when the named file is a symlink' do
|
|
2336
|
-
context 'and its target does not exist' do
|
|
2337
|
-
it 'ignores errors' do
|
|
2338
|
-
file = described_class.new('/no-link')
|
|
2339
|
-
expect { file.lstat }.not_to raise_error
|
|
2340
|
-
end
|
|
2506
|
+
it 'does not follow the last symbolic link' do
|
|
2507
|
+
expect(subject.lstat).to be_symlink
|
|
2341
2508
|
end
|
|
2342
2509
|
end
|
|
2343
2510
|
end
|
|
@@ -2507,7 +2674,7 @@ module MemFs
|
|
|
2507
2674
|
expect(content).to eq "test\n"
|
|
2508
2675
|
end
|
|
2509
2676
|
|
|
2510
|
-
it
|
|
2677
|
+
it 'does not override the file’s content' do
|
|
2511
2678
|
write_subject.puts 'test'
|
|
2512
2679
|
write_subject.puts 'test'
|
|
2513
2680
|
write_subject.close
|
|
@@ -2562,7 +2729,7 @@ module MemFs
|
|
|
2562
2729
|
|
|
2563
2730
|
context 'when a buffer is given' do
|
|
2564
2731
|
it 'fills the buffer with the read content' do
|
|
2565
|
-
buffer =
|
|
2732
|
+
buffer = +''
|
|
2566
2733
|
subject.read 2, buffer
|
|
2567
2734
|
|
|
2568
2735
|
expect(buffer).to eq random_string[0, 2]
|
|
@@ -2599,7 +2766,7 @@ module MemFs
|
|
|
2599
2766
|
|
|
2600
2767
|
context 'when +whence+ is IO::SEEK_END' do
|
|
2601
2768
|
it 'seeks to +amount+ plus end of stream' do
|
|
2602
|
-
subject.seek
|
|
2769
|
+
subject.seek(-1, ::IO::SEEK_END)
|
|
2603
2770
|
|
|
2604
2771
|
expect(subject.pos).to be 4
|
|
2605
2772
|
end
|
|
@@ -2621,7 +2788,7 @@ module MemFs
|
|
|
2621
2788
|
|
|
2622
2789
|
context 'if the position ends up to be less than zero' do
|
|
2623
2790
|
it 'raises an exception' do
|
|
2624
|
-
expect { subject.seek
|
|
2791
|
+
expect { subject.seek(-1) }.to raise_error Errno::EINVAL
|
|
2625
2792
|
end
|
|
2626
2793
|
end
|
|
2627
2794
|
end
|