memfs 0.0.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.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +128 -0
- data/Rakefile +6 -0
- data/lib/fileutils.rb +1738 -0
- data/lib/memfs/dir.rb +33 -0
- data/lib/memfs/fake/directory.rb +51 -0
- data/lib/memfs/fake/entry.rb +73 -0
- data/lib/memfs/fake/file/content.rb +47 -0
- data/lib/memfs/fake/file.rb +36 -0
- data/lib/memfs/fake/symlink.rb +32 -0
- data/lib/memfs/file/stat.rb +48 -0
- data/lib/memfs/file.rb +284 -0
- data/lib/memfs/file_system.rb +157 -0
- data/lib/memfs/filesystem_access.rb +7 -0
- data/lib/memfs/version.rb +3 -0
- data/lib/memfs.rb +100 -0
- data/memfs.gemspec +29 -0
- data/spec/fileutils_spec.rb +961 -0
- data/spec/memfs/dir_spec.rb +104 -0
- data/spec/memfs/fake/directory_spec.rb +115 -0
- data/spec/memfs/fake/entry_spec.rb +140 -0
- data/spec/memfs/fake/file/content_spec.rb +154 -0
- data/spec/memfs/fake/file_spec.rb +37 -0
- data/spec/memfs/fake/symlink_spec.rb +43 -0
- data/spec/memfs/file/stat_spec.rb +209 -0
- data/spec/memfs/file_spec.rb +928 -0
- data/spec/memfs/file_system_spec.rb +393 -0
- data/spec/memfs_spec.rb +54 -0
- data/spec/spec_helper.rb +20 -0
- metadata +203 -0
| @@ -0,0 +1,928 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module MemFs
         | 
| 4 | 
            +
              describe File do
         | 
| 5 | 
            +
                subject { MemFs::File }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                let(:file) { subject.new('/test-file') }
         | 
| 8 | 
            +
                let(:random_string) { ('a'..'z').to_a.sample(10).join }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                before :each do
         | 
| 11 | 
            +
                  fs.mkdir '/test-dir'
         | 
| 12 | 
            +
                  fs.touch '/test-file', '/test-file2'
         | 
| 13 | 
            +
                  subject.symlink '/test-file', '/test-link'
         | 
| 14 | 
            +
                  subject.symlink '/no-file', '/no-link'
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                describe '.atime' do
         | 
| 18 | 
            +
                  it "returns the last access time for the named file as a Time object" do
         | 
| 19 | 
            +
                    expect(subject.atime('/test-file')).to be_a(Time)
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  it "raises an error if the entry does not exist" do
         | 
| 23 | 
            +
                    expect { subject.atime('/no-file') }.to raise_error(Errno::ENOENT)
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  context "when the entry is a symlink" do
         | 
| 27 | 
            +
                    let(:time) { Time.now - 500000 }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    it "returns the last access time of the last target of the link chain" do
         | 
| 30 | 
            +
                      fs.find!('/test-file').atime = time
         | 
| 31 | 
            +
                      subject.symlink('/test-link', '/test-link2')
         | 
| 32 | 
            +
                      expect(subject.atime('/test-link2')).to eq(time)
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                describe ".basename" do
         | 
| 38 | 
            +
                  it "returns the last component of the filename given in +file_name+" do
         | 
| 39 | 
            +
                    expect(subject.basename('/path/to/file.txt')).to eq('file.txt')
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  context "when +suffix+ is given" do
         | 
| 43 | 
            +
                    context "when it is present at the end of +file_name+" do
         | 
| 44 | 
            +
                      it "removes the +suffix+ from the filename basename" do
         | 
| 45 | 
            +
                        expect(subject.basename('/path/to/file.txt', '.txt')).to eq('file')
         | 
| 46 | 
            +
                      end
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                describe '.chmod' do
         | 
| 52 | 
            +
                  it "changes permission bits on the named file" do
         | 
| 53 | 
            +
                    subject.chmod(0777, '/test-file')
         | 
| 54 | 
            +
                    expect(subject.stat('/test-file').mode).to eq(0100777)
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  it "changes permission bits on the named files (in list)" do
         | 
| 58 | 
            +
                    subject.chmod(0777, '/test-file', '/test-file2')
         | 
| 59 | 
            +
                    expect(subject.stat('/test-file2').mode).to eq(0100777)
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                describe ".chown" do
         | 
| 64 | 
            +
                  it "changes the owner of the named file to the given numeric owner id" do
         | 
| 65 | 
            +
                    subject.chown(42, nil, '/test-file')
         | 
| 66 | 
            +
                    expect(subject.stat('/test-file').uid).to eq(42)
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  it "changes owner on the named files (in list)" do
         | 
| 70 | 
            +
                    subject.chown(42, nil, '/test-file', '/test-file2')
         | 
| 71 | 
            +
                    expect(subject.stat('/test-file2').uid).to eq(42)
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  it "changes the group of the named file to the given numeric group id" do
         | 
| 75 | 
            +
                    subject.chown(nil, 42, '/test-file')
         | 
| 76 | 
            +
                    expect(subject.stat('/test-file').gid).to eq(42)
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  it "returns the number of files" do
         | 
| 80 | 
            +
                    expect(subject.chown(42, 42, '/test-file', '/test-file2')).to eq(2)
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  it "ignores nil user id" do
         | 
| 84 | 
            +
                    previous_uid = subject.stat('/test-file').uid
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                    subject.chown(nil, 42, '/test-file')
         | 
| 87 | 
            +
                    expect(subject.stat('/test-file').uid).to eq(previous_uid)
         | 
| 88 | 
            +
                  end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  it "ignores nil group id" do
         | 
| 91 | 
            +
                    previous_gid = subject.stat('/test-file').gid
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                    subject.chown(42, nil, '/test-file')
         | 
| 94 | 
            +
                    expect(subject.stat('/test-file').gid).to eq(previous_gid)
         | 
| 95 | 
            +
                  end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  it "ignores -1 user id" do
         | 
| 98 | 
            +
                    previous_uid = subject.stat('/test-file').uid
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                    subject.chown(-1, 42, '/test-file')
         | 
| 101 | 
            +
                    expect(subject.stat('/test-file').uid).to eq(previous_uid)
         | 
| 102 | 
            +
                  end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  it "ignores -1 group id" do
         | 
| 105 | 
            +
                    previous_gid = subject.stat('/test-file').gid
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                    subject.chown(42, -1, '/test-file')
         | 
| 108 | 
            +
                    expect(subject.stat('/test-file').gid).to eq(previous_gid)
         | 
| 109 | 
            +
                  end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  context "when the named entry is a symlink" do
         | 
| 112 | 
            +
                    it "changes the owner on the last target of the link chain" do
         | 
| 113 | 
            +
                      subject.chown(42, nil, '/test-link')
         | 
| 114 | 
            +
                      expect(subject.stat('/test-file').uid).to eq(42)
         | 
| 115 | 
            +
                    end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                    it "changes the group on the last target of the link chain" do
         | 
| 118 | 
            +
                      subject.chown(nil, 42, '/test-link')
         | 
| 119 | 
            +
                      expect(subject.stat('/test-file').gid).to eq(42)
         | 
| 120 | 
            +
                    end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                    it "does not change the owner of the symlink" do
         | 
| 123 | 
            +
                      subject.chown(42, nil, '/test-link')
         | 
| 124 | 
            +
                      expect(subject.lstat('/test-link').uid).not_to eq(42)
         | 
| 125 | 
            +
                    end
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                    it "does not change the group of the symlink" do
         | 
| 128 | 
            +
                      subject.chown(nil, 42, '/test-link')
         | 
| 129 | 
            +
                      expect(subject.lstat('/test-link').gid).not_to eq(42)
         | 
| 130 | 
            +
                    end
         | 
| 131 | 
            +
                  end
         | 
| 132 | 
            +
                end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                describe ".delete" do
         | 
| 135 | 
            +
                  it_behaves_like 'aliased method', :delete, :unlink
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                describe '.directory?' do
         | 
| 139 | 
            +
                  context "when the named entry is a directory" do
         | 
| 140 | 
            +
                    it "returns true" do
         | 
| 141 | 
            +
                      expect(subject.directory?('/test-dir')).to be_true
         | 
| 142 | 
            +
                    end
         | 
| 143 | 
            +
                  end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                  context "when the named entry is not a directory" do
         | 
| 146 | 
            +
                    it "returns false" do
         | 
| 147 | 
            +
                      expect(subject.directory?('/test-file')).to be_false
         | 
| 148 | 
            +
                    end
         | 
| 149 | 
            +
                  end
         | 
| 150 | 
            +
                end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                describe ".dirname" do
         | 
| 153 | 
            +
                  it "returns all components of the filename given in +file_name+ except the last one" do
         | 
| 154 | 
            +
                    expect(subject.dirname('/path/to/some/file.txt')).to eq('/path/to/some')
         | 
| 155 | 
            +
                  end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                  it "returns / if file_name is /" do
         | 
| 158 | 
            +
                    expect(subject.dirname('/')).to eq('/')
         | 
| 159 | 
            +
                  end
         | 
| 160 | 
            +
                end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                describe ".exists?" do
         | 
| 163 | 
            +
                  it "returns true if the file exists" do
         | 
| 164 | 
            +
                    expect(subject.exists?('/test-file')).to be_true
         | 
| 165 | 
            +
                  end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                  it "returns false if the file does not exist" do
         | 
| 168 | 
            +
                    expect(subject.exists?('/no-file')).to be_false
         | 
| 169 | 
            +
                  end
         | 
| 170 | 
            +
                end
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                describe ".exist?" do
         | 
| 173 | 
            +
                  it_behaves_like 'aliased method', :exist?, :exists?
         | 
| 174 | 
            +
                end
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                describe ".expand_path" do
         | 
| 177 | 
            +
                  it "converts a pathname to an absolute pathname" do
         | 
| 178 | 
            +
                    fs.chdir('/')
         | 
| 179 | 
            +
                    expect(subject.expand_path('test-file')).to eq("/test-file")
         | 
| 180 | 
            +
                  end
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                  it "references path from the current working directory" do
         | 
| 183 | 
            +
                    fs.chdir('/test-dir')
         | 
| 184 | 
            +
                    expect(subject.expand_path('test-file')).to eq("/test-dir/test-file")
         | 
| 185 | 
            +
                  end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                  context "when +dir_string+ is provided" do
         | 
| 188 | 
            +
                    it "uses +dir_string+ as the stating point" do
         | 
| 189 | 
            +
                      expect(subject.expand_path('test-file', '/test')).to eq("/test/test-file")
         | 
| 190 | 
            +
                    end
         | 
| 191 | 
            +
                  end
         | 
| 192 | 
            +
                end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                describe ".file?" do
         | 
| 195 | 
            +
                  context "when the named file exists" do
         | 
| 196 | 
            +
                    context "and it is a regular file" do
         | 
| 197 | 
            +
                      it "returns true" do
         | 
| 198 | 
            +
                        expect(subject.file?('/test-file')).to be_true
         | 
| 199 | 
            +
                      end
         | 
| 200 | 
            +
                    end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                    context "and it is not a regular file" do
         | 
| 203 | 
            +
                      it "returns false" do
         | 
| 204 | 
            +
                        expect(subject.file?('/test-dir')).to be_false
         | 
| 205 | 
            +
                      end
         | 
| 206 | 
            +
                    end
         | 
| 207 | 
            +
                  end
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                  context "when the named file does not exist" do
         | 
| 210 | 
            +
                    it "returns false" do
         | 
| 211 | 
            +
                      expect(subject.file?('/no-file')).to be_false
         | 
| 212 | 
            +
                    end
         | 
| 213 | 
            +
                  end
         | 
| 214 | 
            +
                end
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                describe ".identical?" do
         | 
| 217 | 
            +
                  before :each do
         | 
| 218 | 
            +
                    subject.open('/test-file', 'w') { |f| f.puts 'test' }
         | 
| 219 | 
            +
                    subject.open('/test-file2', 'w') { |f| f.puts 'test' }
         | 
| 220 | 
            +
                    subject.symlink '/test-file', '/test-file-link'
         | 
| 221 | 
            +
                    subject.symlink '/test-file', '/test-file-link2'
         | 
| 222 | 
            +
                    subject.symlink '/test-file2', '/test-file2-link'
         | 
| 223 | 
            +
                  end
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                  context "when two paths represent the same path" do
         | 
| 226 | 
            +
                    it "returns true" do
         | 
| 227 | 
            +
                      expect(subject.identical?('/test-file', '/test-file')).to be_true
         | 
| 228 | 
            +
                    end
         | 
| 229 | 
            +
                  end
         | 
| 230 | 
            +
             | 
| 231 | 
            +
                  context "when two paths do not represent the same file" do
         | 
| 232 | 
            +
                    it "returns false" do
         | 
| 233 | 
            +
                      expect(subject.identical?('/test-file', '/test-file2')).to be_false
         | 
| 234 | 
            +
                    end
         | 
| 235 | 
            +
                  end
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                  context "when one of the paths does not exist" do
         | 
| 238 | 
            +
                    it "returns false" do
         | 
| 239 | 
            +
                      expect(subject.identical?('/test-file', '/no-file')).to be_false
         | 
| 240 | 
            +
                    end
         | 
| 241 | 
            +
                  end
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                  context "when a path is a symlink" do
         | 
| 244 | 
            +
                    context "and the linked file is the same as the other path" do
         | 
| 245 | 
            +
                      it "returns true" do
         | 
| 246 | 
            +
                        expect(subject.identical?('/test-file', '/test-file-link')).to be_true
         | 
| 247 | 
            +
                      end
         | 
| 248 | 
            +
                    end
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                    context "and the linked file is different from the other path" do
         | 
| 251 | 
            +
                      it "returns false" do
         | 
| 252 | 
            +
                        expect(subject.identical?('/test-file2', '/test-file-link')).to be_false
         | 
| 253 | 
            +
                      end
         | 
| 254 | 
            +
                    end
         | 
| 255 | 
            +
                  end
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                  context "when the two paths are symlinks" do
         | 
| 258 | 
            +
                    context "and both links point to the same file" do
         | 
| 259 | 
            +
                      it "returns true" do
         | 
| 260 | 
            +
                        expect(subject.identical?('/test-file-link', '/test-file-link2')).to be_true
         | 
| 261 | 
            +
                      end
         | 
| 262 | 
            +
                    end
         | 
| 263 | 
            +
             | 
| 264 | 
            +
                    context "and both links do not point to the same file" do
         | 
| 265 | 
            +
                      it "returns false" do
         | 
| 266 | 
            +
                        expect(subject.identical?('/test-file-link', '/test-file2-link')).to be_false
         | 
| 267 | 
            +
                      end
         | 
| 268 | 
            +
                    end
         | 
| 269 | 
            +
                  end
         | 
| 270 | 
            +
                end
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                describe ".join" do
         | 
| 273 | 
            +
                  it "Returns a new string formed by joining the strings using File::SEPARATOR" do
         | 
| 274 | 
            +
                    expect(subject.join('a', 'b', 'c')).to eq('a/b/c')
         | 
| 275 | 
            +
                  end
         | 
| 276 | 
            +
                end
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                describe ".lchmod" do
         | 
| 279 | 
            +
                  context "when the named file is a regular file" do
         | 
| 280 | 
            +
                    it "acts like chmod" do
         | 
| 281 | 
            +
                      subject.lchmod(0777, '/test-file')
         | 
| 282 | 
            +
                      expect(subject.stat('/test-file').mode).to eq(0100777)
         | 
| 283 | 
            +
                    end
         | 
| 284 | 
            +
                  end
         | 
| 285 | 
            +
             | 
| 286 | 
            +
                  context "when the named file is a symlink" do
         | 
| 287 | 
            +
                    it "changes permission bits on the symlink" do
         | 
| 288 | 
            +
                      subject.lchmod(0777, '/test-link')
         | 
| 289 | 
            +
                      expect(subject.lstat('/test-link').mode).to eq(0100777)
         | 
| 290 | 
            +
                    end
         | 
| 291 | 
            +
             | 
| 292 | 
            +
                    it "does not change permission bits on the link's target" do
         | 
| 293 | 
            +
                      mode = subject.stat('/test-file').mode
         | 
| 294 | 
            +
                      subject.lchmod(0777, '/test-link')
         | 
| 295 | 
            +
                      expect(subject.stat('/test-file').mode).to eq(mode)
         | 
| 296 | 
            +
                    end
         | 
| 297 | 
            +
                  end
         | 
| 298 | 
            +
                end
         | 
| 299 | 
            +
             | 
| 300 | 
            +
                describe ".link" do
         | 
| 301 | 
            +
                  before :each do
         | 
| 302 | 
            +
                    subject.open('/test-file', 'w') { |f| f.puts 'test' }
         | 
| 303 | 
            +
                  end
         | 
| 304 | 
            +
             | 
| 305 | 
            +
                  it "creates a new name for an existing file using a hard link" do
         | 
| 306 | 
            +
                    subject.link('/test-file', '/new-file')
         | 
| 307 | 
            +
                    expect(subject.read('/new-file')).to eq(subject.read('/test-file'))
         | 
| 308 | 
            +
                  end
         | 
| 309 | 
            +
             | 
| 310 | 
            +
                  it "returns zero" do
         | 
| 311 | 
            +
                    expect(subject.link('/test-file', '/new-file')).to eq(0)
         | 
| 312 | 
            +
                  end
         | 
| 313 | 
            +
             | 
| 314 | 
            +
                  context "when +old_name+ does not exist" do
         | 
| 315 | 
            +
                    it "raises an exception" do
         | 
| 316 | 
            +
                      expect {
         | 
| 317 | 
            +
                        subject.link('/no-file', '/nowhere')
         | 
| 318 | 
            +
                      }.to raise_error(Errno::ENOENT)
         | 
| 319 | 
            +
                    end
         | 
| 320 | 
            +
                  end
         | 
| 321 | 
            +
             | 
| 322 | 
            +
                  context "when +new_name+ already exists" do
         | 
| 323 | 
            +
                    it "raises an exception" do
         | 
| 324 | 
            +
                      subject.open('/test-file2', 'w') { |f| f.puts 'test2' }
         | 
| 325 | 
            +
                      expect {
         | 
| 326 | 
            +
                        subject.link('/test-file', '/test-file2')
         | 
| 327 | 
            +
                      }.to raise_error(SystemCallError)
         | 
| 328 | 
            +
                    end
         | 
| 329 | 
            +
                  end
         | 
| 330 | 
            +
                end
         | 
| 331 | 
            +
             | 
| 332 | 
            +
                describe '.lstat' do
         | 
| 333 | 
            +
                  it "returns a File::Stat object for the named file" do
         | 
| 334 | 
            +
                    expect(subject.lstat('/test-file')).to be_a(File::Stat)
         | 
| 335 | 
            +
                  end
         | 
| 336 | 
            +
             | 
| 337 | 
            +
                  context "when the named file does not exist" do
         | 
| 338 | 
            +
                    it "raises an exception" do
         | 
| 339 | 
            +
                      expect { subject.lstat('/no-file') }.to raise_error(Errno::ENOENT)
         | 
| 340 | 
            +
                    end
         | 
| 341 | 
            +
                  end
         | 
| 342 | 
            +
             | 
| 343 | 
            +
                  context "when the named file is a symlink" do
         | 
| 344 | 
            +
                    it "does not follow the last symbolic link" do
         | 
| 345 | 
            +
                      expect(subject.lstat('/test-link').symlink?).to be_true
         | 
| 346 | 
            +
                    end
         | 
| 347 | 
            +
             | 
| 348 | 
            +
                    context "and its target does not exist" do
         | 
| 349 | 
            +
                      it "ignores errors" do
         | 
| 350 | 
            +
                        expect {
         | 
| 351 | 
            +
                          subject.lstat('/no-link')
         | 
| 352 | 
            +
                        }.not_to raise_error(Errno::ENOENT)
         | 
| 353 | 
            +
                      end
         | 
| 354 | 
            +
                    end
         | 
| 355 | 
            +
                  end
         | 
| 356 | 
            +
                end
         | 
| 357 | 
            +
             | 
| 358 | 
            +
                describe '.new' do
         | 
| 359 | 
            +
                  context "when the mode is provided" do
         | 
| 360 | 
            +
                    context "and it is an integer" do
         | 
| 361 | 
            +
                      it "sets the mode to the integer value" do
         | 
| 362 | 
            +
                        file = subject.new('/test-file', File::RDWR)
         | 
| 363 | 
            +
                        expect(file.opening_mode).to eq(File::RDWR)
         | 
| 364 | 
            +
                      end
         | 
| 365 | 
            +
                    end
         | 
| 366 | 
            +
             | 
| 367 | 
            +
                    context "and it is a string" do
         | 
| 368 | 
            +
                      it "sets the mode to the integer value" do
         | 
| 369 | 
            +
                        file = subject.new('/test-file', 'r+')
         | 
| 370 | 
            +
                        expect(file.opening_mode).to eq(File::RDWR)
         | 
| 371 | 
            +
                      end
         | 
| 372 | 
            +
                    end
         | 
| 373 | 
            +
             | 
| 374 | 
            +
                    context "and it specifies that the file must be created" do
         | 
| 375 | 
            +
                      context "and the file already exists" do
         | 
| 376 | 
            +
                        it "changes the mtime of the file" do
         | 
| 377 | 
            +
                          fs.should_receive(:touch).with('/test-file')
         | 
| 378 | 
            +
                          subject.new('/test-file', 'w')
         | 
| 379 | 
            +
                        end
         | 
| 380 | 
            +
                      end
         | 
| 381 | 
            +
                    end
         | 
| 382 | 
            +
                  end
         | 
| 383 | 
            +
             | 
| 384 | 
            +
                  context "when no argument is given" do
         | 
| 385 | 
            +
                    it "raises an exception" do
         | 
| 386 | 
            +
                      expect { subject.new }.to raise_error(ArgumentError)
         | 
| 387 | 
            +
                    end
         | 
| 388 | 
            +
                  end
         | 
| 389 | 
            +
             | 
| 390 | 
            +
                  context "when too many arguments are given" do
         | 
| 391 | 
            +
                    it "raises an exception" do
         | 
| 392 | 
            +
                      expect { subject.new(1,2,3,4) }.to raise_error(ArgumentError)
         | 
| 393 | 
            +
                    end
         | 
| 394 | 
            +
                  end
         | 
| 395 | 
            +
                end
         | 
| 396 | 
            +
             | 
| 397 | 
            +
                describe '.path' do
         | 
| 398 | 
            +
                  context "when the path is a string" do
         | 
| 399 | 
            +
                    let(:path) { '/some/path' }
         | 
| 400 | 
            +
             | 
| 401 | 
            +
                    it "returns the string representation of the path" do
         | 
| 402 | 
            +
                      expect(subject.path(path)).to eq('/some/path')
         | 
| 403 | 
            +
                    end
         | 
| 404 | 
            +
                  end
         | 
| 405 | 
            +
             | 
| 406 | 
            +
                  context "when the path is a Pathname" do
         | 
| 407 | 
            +
                    let(:path) { Pathname.new('/some/path') }
         | 
| 408 | 
            +
             | 
| 409 | 
            +
                    it "returns the string representation of the path" do
         | 
| 410 | 
            +
                      expect(subject.path(path)).to eq('/some/path')
         | 
| 411 | 
            +
                    end
         | 
| 412 | 
            +
                  end
         | 
| 413 | 
            +
                end
         | 
| 414 | 
            +
             | 
| 415 | 
            +
                describe ".read" do
         | 
| 416 | 
            +
                  before :each do
         | 
| 417 | 
            +
                    subject.open('/test-file', 'w') { |f| f.puts "test" }
         | 
| 418 | 
            +
                  end
         | 
| 419 | 
            +
             | 
| 420 | 
            +
                  it "reads the content of the given file" do
         | 
| 421 | 
            +
                    expect(subject.read('/test-file')).to eq("test\n")
         | 
| 422 | 
            +
                  end
         | 
| 423 | 
            +
             | 
| 424 | 
            +
                  context "when +lenght+ is provided" do
         | 
| 425 | 
            +
                    it "reads only +length+ characters" do
         | 
| 426 | 
            +
                      expect(subject.read('/test-file', 2)).to eq('te')
         | 
| 427 | 
            +
                    end
         | 
| 428 | 
            +
             | 
| 429 | 
            +
                    context "when +length+ is bigger than the file size" do
         | 
| 430 | 
            +
                      it "reads until the end of the file" do
         | 
| 431 | 
            +
                        expect(subject.read('/test-file', 1000)).to eq("test\n")
         | 
| 432 | 
            +
                      end
         | 
| 433 | 
            +
                    end
         | 
| 434 | 
            +
                  end
         | 
| 435 | 
            +
             | 
| 436 | 
            +
                  context "when +offset+ is provided" do
         | 
| 437 | 
            +
                    it "starts reading from the offset" do
         | 
| 438 | 
            +
                      expect(subject.read('/test-file', 2, 1)).to eq('es')
         | 
| 439 | 
            +
                    end
         | 
| 440 | 
            +
             | 
| 441 | 
            +
                    it "raises an error if offset is negative" do
         | 
| 442 | 
            +
                      expect {
         | 
| 443 | 
            +
                        subject.read('/test-file', 2, -1)
         | 
| 444 | 
            +
                      }.to raise_error(Errno::EINVAL)
         | 
| 445 | 
            +
                    end
         | 
| 446 | 
            +
                  end
         | 
| 447 | 
            +
             | 
| 448 | 
            +
                  context "when the last argument is a hash" do
         | 
| 449 | 
            +
                    it "passes the contained options to +open+" do
         | 
| 450 | 
            +
                      subject.should_receive(:open)
         | 
| 451 | 
            +
                          .with('/test-file', File::RDONLY, encoding: 'UTF-8')
         | 
| 452 | 
            +
                          .and_return(file)
         | 
| 453 | 
            +
                      subject.read('/test-file', encoding: 'UTF-8')
         | 
| 454 | 
            +
                    end
         | 
| 455 | 
            +
             | 
| 456 | 
            +
                    context "when it contains the +open_args+ key" do
         | 
| 457 | 
            +
                      it "takes precedence over the other options" do
         | 
| 458 | 
            +
                        subject.should_receive(:open)
         | 
| 459 | 
            +
                            .with('/test-file', 'r')
         | 
| 460 | 
            +
                            .and_return(file)
         | 
| 461 | 
            +
                        subject.read('/test-file', mode: 'w', open_args: ['r'])
         | 
| 462 | 
            +
                      end
         | 
| 463 | 
            +
                    end
         | 
| 464 | 
            +
                  end
         | 
| 465 | 
            +
                end
         | 
| 466 | 
            +
             | 
| 467 | 
            +
                describe ".readlink" do
         | 
| 468 | 
            +
                  it "returns the name of the file referenced by the given link" do
         | 
| 469 | 
            +
                    expect(subject.readlink('/test-link')).to eq('/test-file')
         | 
| 470 | 
            +
                  end
         | 
| 471 | 
            +
                end
         | 
| 472 | 
            +
             | 
| 473 | 
            +
                describe ".rename" do
         | 
| 474 | 
            +
                  it "renames the given file to the new name" do
         | 
| 475 | 
            +
                    subject.rename('/test-file', '/test-file2')
         | 
| 476 | 
            +
                    expect(subject.exists?('/test-file2')).to be_true
         | 
| 477 | 
            +
                  end
         | 
| 478 | 
            +
             | 
| 479 | 
            +
                  it "returns zero" do
         | 
| 480 | 
            +
                    expect(subject.rename('/test-file', '/test-file2')).to eq(0)
         | 
| 481 | 
            +
                  end
         | 
| 482 | 
            +
                end
         | 
| 483 | 
            +
             | 
| 484 | 
            +
                describe ".size" do
         | 
| 485 | 
            +
                  it "returns the size of the file" do
         | 
| 486 | 
            +
                    subject.open('/test-file', 'w') { |f| f.puts random_string }
         | 
| 487 | 
            +
                    expect(subject.size('/test-file')).to eq(random_string.size + 1)
         | 
| 488 | 
            +
                  end
         | 
| 489 | 
            +
                end
         | 
| 490 | 
            +
             | 
| 491 | 
            +
                describe '.stat' do
         | 
| 492 | 
            +
                  it "returns a File::Stat object for the named file" do
         | 
| 493 | 
            +
                    expect(subject.stat('/test-file')).to be_a(File::Stat)
         | 
| 494 | 
            +
                  end
         | 
| 495 | 
            +
             | 
| 496 | 
            +
                  it "follows the last symbolic link" do
         | 
| 497 | 
            +
                    expect(subject.stat('/test-link').symlink?).to be_false
         | 
| 498 | 
            +
                  end
         | 
| 499 | 
            +
             | 
| 500 | 
            +
                  context "when the named file does not exist" do
         | 
| 501 | 
            +
                    it "raises an exception" do
         | 
| 502 | 
            +
                      expect { subject.stat('/no-file') }.to raise_error(Errno::ENOENT)
         | 
| 503 | 
            +
                    end
         | 
| 504 | 
            +
                  end
         | 
| 505 | 
            +
             | 
| 506 | 
            +
                  context "when the named file is a symlink" do
         | 
| 507 | 
            +
                    context "and its target does not exist" do
         | 
| 508 | 
            +
                      it "raises an exception" do
         | 
| 509 | 
            +
                        expect { subject.stat('/no-link') }.to raise_error(Errno::ENOENT)
         | 
| 510 | 
            +
                      end
         | 
| 511 | 
            +
                    end
         | 
| 512 | 
            +
                  end
         | 
| 513 | 
            +
             | 
| 514 | 
            +
                  it "always returns a new object" do
         | 
| 515 | 
            +
                    stat = subject.stat('/test-file')
         | 
| 516 | 
            +
                    expect(subject.stat('/test-file')).not_to be(stat)
         | 
| 517 | 
            +
                  end
         | 
| 518 | 
            +
                end
         | 
| 519 | 
            +
             | 
| 520 | 
            +
                describe '.symlink' do
         | 
| 521 | 
            +
                  it "creates a symbolic link named new_name" do
         | 
| 522 | 
            +
                    expect(subject.symlink?('/test-link')).to be_true
         | 
| 523 | 
            +
                  end
         | 
| 524 | 
            +
             | 
| 525 | 
            +
                  it "creates a symbolic link that points to an entry named old_name" do
         | 
| 526 | 
            +
                    expect(fs.find!('/test-link').target).to eq('/test-file')
         | 
| 527 | 
            +
                  end
         | 
| 528 | 
            +
             | 
| 529 | 
            +
                  context "when the target does not exist" do
         | 
| 530 | 
            +
                    it "creates a symbolic link" do
         | 
| 531 | 
            +
                      expect(subject.symlink?('/no-link')).to be_true
         | 
| 532 | 
            +
                    end
         | 
| 533 | 
            +
                  end
         | 
| 534 | 
            +
             | 
| 535 | 
            +
                  it "returns 0" do
         | 
| 536 | 
            +
                    expect(subject.symlink('/test-file', '/new-link')).to eq(0)
         | 
| 537 | 
            +
                  end
         | 
| 538 | 
            +
                end
         | 
| 539 | 
            +
             | 
| 540 | 
            +
                describe '.symlink?' do
         | 
| 541 | 
            +
                  context "when the named entry is a symlink" do
         | 
| 542 | 
            +
                    it "returns true" do
         | 
| 543 | 
            +
                      expect(subject.symlink?('/test-link')).to be_true
         | 
| 544 | 
            +
                    end
         | 
| 545 | 
            +
                  end
         | 
| 546 | 
            +
             | 
| 547 | 
            +
                  context "when the named entry is not a symlink" do
         | 
| 548 | 
            +
                    it "returns false" do
         | 
| 549 | 
            +
                      expect(subject.symlink?('/test-file')).to be_false
         | 
| 550 | 
            +
                    end
         | 
| 551 | 
            +
                  end
         | 
| 552 | 
            +
             | 
| 553 | 
            +
                  context "when the named entry does not exist" do
         | 
| 554 | 
            +
                    it "returns false" do
         | 
| 555 | 
            +
                      expect(subject.symlink?('/no-file')).to be_false
         | 
| 556 | 
            +
                    end
         | 
| 557 | 
            +
                  end
         | 
| 558 | 
            +
                end
         | 
| 559 | 
            +
             | 
| 560 | 
            +
                describe '.umask' do
         | 
| 561 | 
            +
                  before :each do
         | 
| 562 | 
            +
                    subject.umask(0022)
         | 
| 563 | 
            +
                  end
         | 
| 564 | 
            +
             | 
| 565 | 
            +
                  it "returns the current umask value for this process" do
         | 
| 566 | 
            +
                    expect(subject.umask).to eq(0022)
         | 
| 567 | 
            +
                  end
         | 
| 568 | 
            +
             | 
| 569 | 
            +
                  context "when the optional argument is given" do
         | 
| 570 | 
            +
                    it "sets the umask to that value" do
         | 
| 571 | 
            +
                      subject.umask 0777
         | 
| 572 | 
            +
                      expect(subject.umask).to eq(0777)
         | 
| 573 | 
            +
                    end
         | 
| 574 | 
            +
             | 
| 575 | 
            +
                    it "return the previous value" do
         | 
| 576 | 
            +
                      expect(subject.umask(0777)).to eq(0022)
         | 
| 577 | 
            +
                    end
         | 
| 578 | 
            +
                  end
         | 
| 579 | 
            +
                end
         | 
| 580 | 
            +
             | 
| 581 | 
            +
                describe ".unlink" do
         | 
| 582 | 
            +
                  it "deletes the named file" do
         | 
| 583 | 
            +
                    subject.unlink('/test-file')
         | 
| 584 | 
            +
                    expect(subject.exists?('/test-file')).to be_false
         | 
| 585 | 
            +
                  end
         | 
| 586 | 
            +
             | 
| 587 | 
            +
                  it "returns the number of names passed as arguments" do
         | 
| 588 | 
            +
                    expect(subject.unlink('/test-file', '/test-file2')).to eq(2)
         | 
| 589 | 
            +
                  end
         | 
| 590 | 
            +
             | 
| 591 | 
            +
                  context "when multiple file names are given" do
         | 
| 592 | 
            +
                    it "deletes the named files" do
         | 
| 593 | 
            +
                      subject.unlink('/test-file', '/test-file2')
         | 
| 594 | 
            +
                      expect(subject.exists?('/test-file2')).to be_false
         | 
| 595 | 
            +
                    end
         | 
| 596 | 
            +
                  end
         | 
| 597 | 
            +
             | 
| 598 | 
            +
                  context "when the entry is a directory" do
         | 
| 599 | 
            +
                    it "raises an exception" do
         | 
| 600 | 
            +
                      expect { subject.unlink('/test-dir') }.to raise_error(Errno::EPERM)
         | 
| 601 | 
            +
                    end
         | 
| 602 | 
            +
                  end
         | 
| 603 | 
            +
                end
         | 
| 604 | 
            +
             | 
| 605 | 
            +
                describe '.utime' do
         | 
| 606 | 
            +
                  let(:time) { Time.now - 500000 }
         | 
| 607 | 
            +
             | 
| 608 | 
            +
                  it "sets the access time of each named file to the first argument" do
         | 
| 609 | 
            +
                    subject.utime(time, time, '/test-file')
         | 
| 610 | 
            +
                    expect(subject.atime('/test-file')).to eq(time)
         | 
| 611 | 
            +
                  end
         | 
| 612 | 
            +
             | 
| 613 | 
            +
                  it "sets the modification time of each named file to the second argument" do
         | 
| 614 | 
            +
                    subject.utime(time, time, '/test-file')
         | 
| 615 | 
            +
                    expect(subject.mtime('/test-file')).to eq(time)
         | 
| 616 | 
            +
                  end
         | 
| 617 | 
            +
             | 
| 618 | 
            +
                  it "returns the number of file names in the argument list" do
         | 
| 619 | 
            +
                    expect(subject.utime(time, time, '/test-file', '/test-file2')).to eq(2)
         | 
| 620 | 
            +
                  end
         | 
| 621 | 
            +
             | 
| 622 | 
            +
                  it "raises en error if the entry does not exist" do
         | 
| 623 | 
            +
                    expect {
         | 
| 624 | 
            +
                      subject.utime(time, time, '/no-file')
         | 
| 625 | 
            +
                    }.to raise_error(Errno::ENOENT)
         | 
| 626 | 
            +
                  end
         | 
| 627 | 
            +
                end
         | 
| 628 | 
            +
             | 
| 629 | 
            +
                describe '#chmod' do
         | 
| 630 | 
            +
                  it "changes permission bits on the file" do
         | 
| 631 | 
            +
                    file.chmod(0777)
         | 
| 632 | 
            +
                    expect(file.stat.mode).to eq(0100777)
         | 
| 633 | 
            +
                  end
         | 
| 634 | 
            +
             | 
| 635 | 
            +
                  it "returns zero" do
         | 
| 636 | 
            +
                    expect(file.chmod(0777)).to eq(0)
         | 
| 637 | 
            +
                  end
         | 
| 638 | 
            +
                end
         | 
| 639 | 
            +
             | 
| 640 | 
            +
                describe "#chown" do
         | 
| 641 | 
            +
                  it "changes the owner of the named file to the given numeric owner id" do
         | 
| 642 | 
            +
                    file.chown(42, nil)
         | 
| 643 | 
            +
                    expect(file.stat.uid).to be(42)
         | 
| 644 | 
            +
                  end
         | 
| 645 | 
            +
             | 
| 646 | 
            +
                  it "changes owner on the named files (in list)" do
         | 
| 647 | 
            +
                    file.chown(42)
         | 
| 648 | 
            +
                    expect(file.stat.uid).to be(42)
         | 
| 649 | 
            +
                  end
         | 
| 650 | 
            +
             | 
| 651 | 
            +
                  it "changes the group of the named file to the given numeric group id" do
         | 
| 652 | 
            +
                    file.chown(nil, 42)
         | 
| 653 | 
            +
                    expect(file.stat.gid).to be(42)
         | 
| 654 | 
            +
                  end
         | 
| 655 | 
            +
             | 
| 656 | 
            +
                  it "returns zero" do
         | 
| 657 | 
            +
                    expect(file.chown(42, 42)).to eq(0)
         | 
| 658 | 
            +
                  end
         | 
| 659 | 
            +
             | 
| 660 | 
            +
                  it "ignores nil user id" do
         | 
| 661 | 
            +
                    previous_uid = file.stat.uid
         | 
| 662 | 
            +
             | 
| 663 | 
            +
                    file.chown(nil, 42)
         | 
| 664 | 
            +
                    expect(file.stat.uid).to eq(previous_uid)
         | 
| 665 | 
            +
                  end
         | 
| 666 | 
            +
             | 
| 667 | 
            +
                  it "ignores nil group id" do
         | 
| 668 | 
            +
                    previous_gid = file.stat.gid
         | 
| 669 | 
            +
             | 
| 670 | 
            +
                    file.chown(42, nil)
         | 
| 671 | 
            +
                    expect(file.stat.gid).to eq(previous_gid)
         | 
| 672 | 
            +
                  end
         | 
| 673 | 
            +
             | 
| 674 | 
            +
                  it "ignores -1 user id" do
         | 
| 675 | 
            +
                    previous_uid = file.stat.uid
         | 
| 676 | 
            +
             | 
| 677 | 
            +
                    file.chown(-1, 42)
         | 
| 678 | 
            +
                    expect(file.stat.uid).to eq(previous_uid)
         | 
| 679 | 
            +
                  end
         | 
| 680 | 
            +
             | 
| 681 | 
            +
                  it "ignores -1 group id" do
         | 
| 682 | 
            +
                    previous_gid = file.stat.gid
         | 
| 683 | 
            +
             | 
| 684 | 
            +
                    file.chown(42, -1)
         | 
| 685 | 
            +
                    expect(file.stat.gid).to eq(previous_gid)
         | 
| 686 | 
            +
                  end
         | 
| 687 | 
            +
             | 
| 688 | 
            +
                  context "when the named entry is a symlink" do
         | 
| 689 | 
            +
                    let(:symlink) { subject.new('/test-link') }
         | 
| 690 | 
            +
             | 
| 691 | 
            +
                    it "changes the owner on the last target of the link chain" do
         | 
| 692 | 
            +
                      symlink.chown(42, nil)
         | 
| 693 | 
            +
                      expect(file.stat.uid).to be(42)
         | 
| 694 | 
            +
                    end
         | 
| 695 | 
            +
             | 
| 696 | 
            +
                    it "changes the group on the last target of the link chain" do
         | 
| 697 | 
            +
                      symlink.chown(nil, 42)
         | 
| 698 | 
            +
                      expect(file.stat.gid).to be(42)
         | 
| 699 | 
            +
                    end
         | 
| 700 | 
            +
             | 
| 701 | 
            +
                    it "does not change the owner of the symlink" do
         | 
| 702 | 
            +
                      symlink.chown(42, nil)
         | 
| 703 | 
            +
                      expect(symlink.lstat.uid).not_to be(42)
         | 
| 704 | 
            +
                    end
         | 
| 705 | 
            +
             | 
| 706 | 
            +
                    it "does not change the group of the symlink" do
         | 
| 707 | 
            +
                      symlink.chown(nil, 42)
         | 
| 708 | 
            +
                      expect(symlink.lstat.gid).not_to be(42)
         | 
| 709 | 
            +
                    end
         | 
| 710 | 
            +
                  end
         | 
| 711 | 
            +
                end
         | 
| 712 | 
            +
             | 
| 713 | 
            +
                describe "#close" do
         | 
| 714 | 
            +
                  it "closes the file stream" do
         | 
| 715 | 
            +
                    file = subject.open('/test-file')
         | 
| 716 | 
            +
                    file.close
         | 
| 717 | 
            +
                    expect(file).to be_closed
         | 
| 718 | 
            +
                  end
         | 
| 719 | 
            +
                end
         | 
| 720 | 
            +
             | 
| 721 | 
            +
                describe "#closed?" do
         | 
| 722 | 
            +
                  it "returns true when the file is closed" do
         | 
| 723 | 
            +
                    file = subject.open('/test-file')
         | 
| 724 | 
            +
                    file.close
         | 
| 725 | 
            +
                    expect(file.closed?).to be_true
         | 
| 726 | 
            +
                  end
         | 
| 727 | 
            +
             | 
| 728 | 
            +
                  it "returns false when the file is open" do
         | 
| 729 | 
            +
                    file = subject.open('/test-file')
         | 
| 730 | 
            +
                    expect(file.closed?).to be_false
         | 
| 731 | 
            +
                    file.close
         | 
| 732 | 
            +
                  end
         | 
| 733 | 
            +
                end
         | 
| 734 | 
            +
             | 
| 735 | 
            +
                describe '#lstat' do
         | 
| 736 | 
            +
                  it "returns the File::Stat object of the file" do
         | 
| 737 | 
            +
                    expect(file.lstat).to be_a(File::Stat)
         | 
| 738 | 
            +
                  end
         | 
| 739 | 
            +
             | 
| 740 | 
            +
                  it "does not follow the last symbolic link" do
         | 
| 741 | 
            +
                    file = subject.new('/test-link')
         | 
| 742 | 
            +
                    expect(file.lstat).to be_symlink
         | 
| 743 | 
            +
                  end
         | 
| 744 | 
            +
             | 
| 745 | 
            +
                  context "when the named file is a symlink" do
         | 
| 746 | 
            +
                    context "and its target does not exist" do
         | 
| 747 | 
            +
                      it "ignores errors" do
         | 
| 748 | 
            +
                        file = subject.new('/no-link')
         | 
| 749 | 
            +
                        expect { file.lstat }.not_to raise_error(Errno::ENOENT)
         | 
| 750 | 
            +
                      end
         | 
| 751 | 
            +
                    end
         | 
| 752 | 
            +
                  end
         | 
| 753 | 
            +
                end
         | 
| 754 | 
            +
             | 
| 755 | 
            +
                describe "#path" do
         | 
| 756 | 
            +
                  it "returns the path of the file" do
         | 
| 757 | 
            +
                    file = subject.new('/test-file')
         | 
| 758 | 
            +
                    expect(file.path).to eq('/test-file')
         | 
| 759 | 
            +
                  end
         | 
| 760 | 
            +
                end
         | 
| 761 | 
            +
             | 
| 762 | 
            +
                describe "#pos" do
         | 
| 763 | 
            +
                  before :each do
         | 
| 764 | 
            +
                    subject.open('/test-file', 'w') { |f| f.puts 'test' }
         | 
| 765 | 
            +
                  end
         | 
| 766 | 
            +
             | 
| 767 | 
            +
                  it "returns zero when the file was just opened" do
         | 
| 768 | 
            +
                    expect(file.pos).to be_zero
         | 
| 769 | 
            +
                  end
         | 
| 770 | 
            +
             | 
| 771 | 
            +
                  it "returns the reading offset when some of the file has been read" do
         | 
| 772 | 
            +
                    file.read(2)
         | 
| 773 | 
            +
                    expect(file.pos).to eq(2)
         | 
| 774 | 
            +
                  end
         | 
| 775 | 
            +
                end
         | 
| 776 | 
            +
             | 
| 777 | 
            +
                describe "#puts" do
         | 
| 778 | 
            +
                  it "appends content to the file" do
         | 
| 779 | 
            +
                    file = subject.new('/test-file', 'w')
         | 
| 780 | 
            +
                    file.puts "test"
         | 
| 781 | 
            +
                    file.close
         | 
| 782 | 
            +
                    expect(file.content.to_s).to eq("test\n")
         | 
| 783 | 
            +
                  end
         | 
| 784 | 
            +
             | 
| 785 | 
            +
                  it "does not override the file's content" do
         | 
| 786 | 
            +
                    file = subject.new('/test-file', 'w')
         | 
| 787 | 
            +
                    file.puts "test"
         | 
| 788 | 
            +
                    file.puts "test"
         | 
| 789 | 
            +
                    file.close
         | 
| 790 | 
            +
                    expect(file.content.to_s).to eq("test\ntest\n")
         | 
| 791 | 
            +
                  end
         | 
| 792 | 
            +
             | 
| 793 | 
            +
                  it "raises an exception if the file is not writable" do
         | 
| 794 | 
            +
                    file = subject.new('/test-file')
         | 
| 795 | 
            +
                    expect { file.puts "test" }.to raise_error(IOError)
         | 
| 796 | 
            +
                  end
         | 
| 797 | 
            +
                end
         | 
| 798 | 
            +
             | 
| 799 | 
            +
                describe "#read" do
         | 
| 800 | 
            +
                  before :each do
         | 
| 801 | 
            +
                    subject.open('/test-file', 'w') { |f| f.puts random_string }
         | 
| 802 | 
            +
                  end
         | 
| 803 | 
            +
             | 
| 804 | 
            +
                  context "when no length is given" do
         | 
| 805 | 
            +
                    it "returns the content of the named file" do
         | 
| 806 | 
            +
                      expect(file.read).to eq(random_string + "\n")
         | 
| 807 | 
            +
                    end
         | 
| 808 | 
            +
             | 
| 809 | 
            +
                    it "returns an empty string if called a second time" do
         | 
| 810 | 
            +
                      file.read
         | 
| 811 | 
            +
                      expect(file.read).to be_empty
         | 
| 812 | 
            +
                    end
         | 
| 813 | 
            +
                  end
         | 
| 814 | 
            +
             | 
| 815 | 
            +
                  context "when a length is given" do
         | 
| 816 | 
            +
                    it "returns a string of the given length" do
         | 
| 817 | 
            +
                      expect(file.read(2)).to eq(random_string[0, 2])
         | 
| 818 | 
            +
                    end
         | 
| 819 | 
            +
             | 
| 820 | 
            +
                    it "returns nil when there is nothing more to read" do
         | 
| 821 | 
            +
                      file.read(1000)
         | 
| 822 | 
            +
                      expect(file.read(1000)).to be_nil
         | 
| 823 | 
            +
                    end
         | 
| 824 | 
            +
                  end
         | 
| 825 | 
            +
             | 
| 826 | 
            +
                  context "when a buffer is given" do
         | 
| 827 | 
            +
                    it "fills the buffer with the read content" do
         | 
| 828 | 
            +
                      buffer = String.new
         | 
| 829 | 
            +
                      file.read(2, buffer)
         | 
| 830 | 
            +
                      expect(buffer).to eq(random_string[0, 2])
         | 
| 831 | 
            +
                    end
         | 
| 832 | 
            +
                  end
         | 
| 833 | 
            +
                end
         | 
| 834 | 
            +
             | 
| 835 | 
            +
                describe "#seek" do
         | 
| 836 | 
            +
                  before :each do
         | 
| 837 | 
            +
                    subject.open('/test-file', 'w') { |f| f.puts 'test' }
         | 
| 838 | 
            +
                  end
         | 
| 839 | 
            +
             | 
| 840 | 
            +
                  it "returns zero" do
         | 
| 841 | 
            +
                    expect(file.seek(1)).to eq(0)
         | 
| 842 | 
            +
                  end
         | 
| 843 | 
            +
             | 
| 844 | 
            +
                  context "when +whence+ is not provided" do
         | 
| 845 | 
            +
                    it "seeks to the absolute location given by +amount+" do
         | 
| 846 | 
            +
                      file.seek(3)
         | 
| 847 | 
            +
                      expect(file.pos).to eq(3)
         | 
| 848 | 
            +
                    end
         | 
| 849 | 
            +
                  end
         | 
| 850 | 
            +
             | 
| 851 | 
            +
                  context "when +whence+ is IO::SEEK_CUR" do
         | 
| 852 | 
            +
                    it "seeks to +amount+ plus current position" do
         | 
| 853 | 
            +
                      file.read(1)
         | 
| 854 | 
            +
                      file.seek(1, IO::SEEK_CUR)
         | 
| 855 | 
            +
                      expect(file.pos).to eq(2)
         | 
| 856 | 
            +
                    end
         | 
| 857 | 
            +
                  end
         | 
| 858 | 
            +
             | 
| 859 | 
            +
                  context "when +whence+ is IO::SEEK_END" do
         | 
| 860 | 
            +
                    it "seeks to +amount+ plus end of stream" do
         | 
| 861 | 
            +
                      file.seek(-1, IO::SEEK_END)
         | 
| 862 | 
            +
                      expect(file.pos).to eq(4)
         | 
| 863 | 
            +
                    end
         | 
| 864 | 
            +
                  end
         | 
| 865 | 
            +
             | 
| 866 | 
            +
                  context "when +whence+ is IO::SEEK_SET" do
         | 
| 867 | 
            +
                    it "seeks to the absolute location given by +amount+" do
         | 
| 868 | 
            +
                      file.seek(3, IO::SEEK_SET)
         | 
| 869 | 
            +
                      expect(file.pos).to eq(3)
         | 
| 870 | 
            +
                    end
         | 
| 871 | 
            +
                  end
         | 
| 872 | 
            +
             | 
| 873 | 
            +
                  context "when +whence+ is invalid" do
         | 
| 874 | 
            +
                    it "raises an exception" do
         | 
| 875 | 
            +
                      expect { file.seek(0, 42) }.to raise_error(Errno::EINVAL)
         | 
| 876 | 
            +
                    end
         | 
| 877 | 
            +
                  end
         | 
| 878 | 
            +
             | 
| 879 | 
            +
                  context "if the position ends up to be less than zero" do
         | 
| 880 | 
            +
                    it "raises an exception" do
         | 
| 881 | 
            +
                      expect { file.seek(-1) }.to raise_error(Errno::EINVAL)
         | 
| 882 | 
            +
                    end
         | 
| 883 | 
            +
                  end
         | 
| 884 | 
            +
                end
         | 
| 885 | 
            +
             | 
| 886 | 
            +
                describe "#size" do
         | 
| 887 | 
            +
                  it "returns the size of the file" do
         | 
| 888 | 
            +
                    subject.open('/test-file', 'w') { |f| f.puts random_string }
         | 
| 889 | 
            +
                    expect(subject.new('/test-file').size).to eq(random_string.size + 1)
         | 
| 890 | 
            +
                  end
         | 
| 891 | 
            +
                end
         | 
| 892 | 
            +
             | 
| 893 | 
            +
                describe "#stat" do
         | 
| 894 | 
            +
                  it "returns the +Stat+ object of the file" do
         | 
| 895 | 
            +
                    file = subject.new('/test-file')
         | 
| 896 | 
            +
                    file.stat == subject.stat('/test-file')
         | 
| 897 | 
            +
                  end
         | 
| 898 | 
            +
                end
         | 
| 899 | 
            +
             | 
| 900 | 
            +
                describe "#write" do
         | 
| 901 | 
            +
                  it "writes the given string to file" do
         | 
| 902 | 
            +
                    subject.open('/test-file', 'w') { |f| f.write "test" }
         | 
| 903 | 
            +
                    expect(subject.read('/test-file')).to eq("test")
         | 
| 904 | 
            +
                  end
         | 
| 905 | 
            +
             | 
| 906 | 
            +
                  it "returns the number of bytes written" do
         | 
| 907 | 
            +
                    file = subject.open('/test-file', 'w')
         | 
| 908 | 
            +
                    expect(file.write('test')).to eq(4)
         | 
| 909 | 
            +
                    file.close
         | 
| 910 | 
            +
                  end
         | 
| 911 | 
            +
             | 
| 912 | 
            +
                  context "when the file is not opened for writing" do
         | 
| 913 | 
            +
                    it "raises an exception" do
         | 
| 914 | 
            +
                      file = subject.open('/test-file')
         | 
| 915 | 
            +
                      expect { file.write('test') }.to raise_error(IOError)
         | 
| 916 | 
            +
                      file.close
         | 
| 917 | 
            +
                    end
         | 
| 918 | 
            +
                  end
         | 
| 919 | 
            +
             | 
| 920 | 
            +
                  context "when the argument is not a string" do
         | 
| 921 | 
            +
                    it "will be converted to a string using to_s" do
         | 
| 922 | 
            +
                      subject.open('/test-file', 'w') { |f| f.write 42 }
         | 
| 923 | 
            +
                      expect(subject.read('/test-file')).to eq('42')
         | 
| 924 | 
            +
                    end
         | 
| 925 | 
            +
                  end
         | 
| 926 | 
            +
                end
         | 
| 927 | 
            +
              end
         | 
| 928 | 
            +
            end
         |