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
135
136
137
138
139
|
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "IO#sysread on a file" do
before :each do
@file_name = tmp("IO_sysread_file") + $$.to_s
File.open(@file_name, "w") do |f|
# write some stuff
f.write("012345678901234567890123456789\nabcdef")
end
@file = File.open(@file_name, "r+")
end
after :each do
@file.close
rm_r @file_name
end
it "reads the specified number of bytes from the file" do
@file.sysread(15).should == "012345678901234"
end
it "reads the specified number of bytes from the file to the buffer" do
buf = +"" # empty buffer
@file.sysread(15, buf).should == buf
buf.should == "012345678901234"
@file.rewind
buf = +"ABCDE" # small buffer
@file.sysread(15, buf).should == buf
buf.should == "012345678901234"
@file.rewind
buf = +"ABCDE" * 5 # large buffer
@file.sysread(15, buf).should == buf
buf.should == "012345678901234"
end
it "coerces the second argument to string and uses it as a buffer" do
buf = +"ABCDE"
(obj = mock("buff")).should_receive(:to_str).any_number_of_times.and_return(buf)
@file.sysread(15, obj).should == buf
buf.should == "012345678901234"
end
it "advances the position of the file by the specified number of bytes" do
@file.sysread(15)
@file.sysread(5).should == "56789"
end
it "raises an error when called after buffered reads" do
@file.readline
-> { @file.sysread(5) }.should raise_error(IOError)
end
it "reads normally even when called immediately after a buffered IO#read" do
@file.read(15)
@file.sysread(5).should == "56789"
end
it "does not raise error if called after IO#read followed by IO#write" do
@file.read(5)
@file.write("abcde")
-> { @file.sysread(5) }.should_not raise_error(IOError)
end
it "does not raise error if called after IO#read followed by IO#syswrite" do
@file.read(5)
@file.syswrite("abcde")
-> { @file.sysread(5) }.should_not raise_error(IOError)
end
it "reads updated content after the flushed buffered IO#write" do
@file.write("abcde")
@file.flush
@file.sysread(5).should == "56789"
File.open(@file_name) do |f|
f.sysread(10).should == "abcde56789"
end
end
it "raises IOError on closed stream" do
-> { IOSpecs.closed_io.sysread(5) }.should raise_error(IOError)
end
it "immediately returns an empty string if the length argument is 0" do
@file.sysread(0).should == ""
end
it "immediately returns the given buffer if the length argument is 0" do
buffer = +"existing content"
@file.sysread(0, buffer).should == buffer
buffer.should == "existing content"
end
it "discards the existing buffer content upon successful read" do
buffer = +"existing content"
@file.sysread(11, buffer).should.equal?(buffer)
buffer.should == "01234567890"
end
it "discards the existing buffer content upon error" do
buffer = +"existing content"
@file.seek(0, :END)
-> { @file.sysread(1, buffer) }.should raise_error(EOFError)
buffer.should be_empty
end
it "preserves the encoding of the given buffer" do
buffer = ''.encode(Encoding::ISO_8859_1)
string = @file.sysread(10, buffer)
buffer.encoding.should == Encoding::ISO_8859_1
end
end
describe "IO#sysread" do
before do
@read, @write = IO.pipe
end
after do
@read.close
@write.close
end
it "returns a smaller string if less than size bytes are available" do
@write.syswrite "ab"
@read.sysread(3).should == "ab"
end
guard_not -> { platform_is :windows and ruby_version_is ""..."3.2" } do # https://bugs.ruby-lang.org/issues/18880
it "raises ArgumentError when length is less than 0" do
-> { @read.sysread(-1) }.should raise_error(ArgumentError)
end
end
end
|