1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
guard -> { platform_is_not :windows or ruby_version_is "3.3" } do
describe "IO#pread" do
before :each do
@fname = tmp("io_pread.txt")
@contents = "1234567890"
touch(@fname) { |f| f.write @contents }
@file = File.open(@fname, "r+")
end
after :each do
@file.close
rm_r @fname
end
it "accepts a length, and an offset" do
@file.pread(4, 0).should == "1234"
@file.pread(3, 4).should == "567"
end
it "accepts a length, an offset, and an output buffer" do
buffer = +"foo"
@file.pread(3, 4, buffer).should.equal?(buffer)
buffer.should == "567"
end
it "shrinks the buffer in case of less bytes read" do
buffer = +"foo"
@file.pread(1, 0, buffer)
buffer.should == "1"
end
it "grows the buffer in case of more bytes read" do
buffer = +"foo"
@file.pread(5, 0, buffer)
buffer.should == "12345"
end
it "preserves the encoding of the given buffer" do
buffer = ''.encode(Encoding::ISO_8859_1)
@file.pread(10, 0, buffer)
buffer.encoding.should == Encoding::ISO_8859_1
end
it "does not advance the file pointer" do
@file.pread(4, 0).should == "1234"
@file.read.should == "1234567890"
end
it "ignores the current offset" do
@file.pos = 3
@file.pread(4, 0).should == "1234"
end
it "returns an empty string for maxlen = 0" do
@file.pread(0, 4).should == ""
end
it "ignores the offset for maxlen = 0, even if it is out of file bounds" do
@file.pread(0, 400).should == ""
end
it "does not reset the buffer when reading with maxlen = 0" do
buffer = +"foo"
@file.pread(0, 4, buffer)
buffer.should == "foo"
@file.pread(0, 400, buffer)
buffer.should == "foo"
end
it "converts maxlen to Integer using #to_int" do
maxlen = mock('maxlen')
maxlen.should_receive(:to_int).and_return(4)
@file.pread(maxlen, 0).should == "1234"
end
it "converts offset to Integer using #to_int" do
offset = mock('offset')
offset.should_receive(:to_int).and_return(0)
@file.pread(4, offset).should == "1234"
end
it "converts a buffer to String using to_str" do
buffer = mock('buffer')
buffer.should_receive(:to_str).at_least(1).and_return(+"foo")
@file.pread(4, 0, buffer)
buffer.should_not.is_a?(String)
buffer.to_str.should == "1234"
end
it "raises TypeError if maxlen is not an Integer and cannot be coerced into Integer" do
maxlen = Object.new
-> { @file.pread(maxlen, 0) }.should raise_error(TypeError, 'no implicit conversion of Object into Integer')
end
it "raises TypeError if offset is not an Integer and cannot be coerced into Integer" do
offset = Object.new
-> { @file.pread(4, offset) }.should raise_error(TypeError, 'no implicit conversion of Object into Integer')
end
it "raises ArgumentError for negative values of maxlen" do
-> { @file.pread(-4, 0) }.should raise_error(ArgumentError, 'negative string size (or size too big)')
end
it "raised Errno::EINVAL for negative values of offset" do
-> { @file.pread(4, -1) }.should raise_error(Errno::EINVAL, /Invalid argument/)
end
it "raises TypeError if the buffer is not a String and cannot be coerced into String" do
buffer = Object.new
-> { @file.pread(4, 0, buffer) }.should raise_error(TypeError, 'no implicit conversion of Object into String')
end
it "raises EOFError if end-of-file is reached" do
-> { @file.pread(1, 10) }.should raise_error(EOFError)
end
it "raises IOError when file is not open in read mode" do
File.open(@fname, "w") do |file|
-> { file.pread(1, 1) }.should raise_error(IOError)
end
end
it "raises IOError when file is closed" do
file = File.open(@fname, "r+")
file.close
-> { file.pread(1, 1) }.should raise_error(IOError)
end
end
end
|