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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
|
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "StringIO#reopen when passed [Object, Integer]" do
before :each do
@io = StringIO.new("example")
end
it "reopens self with the passed Object in the passed mode" do
@io.reopen("reopened", IO::RDONLY)
@io.closed_read?.should be_false
@io.closed_write?.should be_true
@io.string.should == "reopened"
@io.reopen(+"reopened, twice", IO::WRONLY)
@io.closed_read?.should be_true
@io.closed_write?.should be_false
@io.string.should == "reopened, twice"
@io.reopen(+"reopened, another time", IO::RDWR)
@io.closed_read?.should be_false
@io.closed_write?.should be_false
@io.string.should == "reopened, another time"
end
it "tries to convert the passed Object to a String using #to_str" do
obj = mock("to_str")
obj.should_receive(:to_str).and_return(+"to_str")
@io.reopen(obj, IO::RDWR)
@io.string.should == "to_str"
end
it "raises a TypeError when the passed Object can't be converted to a String" do
-> { @io.reopen(Object.new, IO::RDWR) }.should raise_error(TypeError)
end
it "raises an Errno::EACCES when trying to reopen self with a frozen String in write-mode" do
-> { @io.reopen("burn".freeze, IO::WRONLY) }.should raise_error(Errno::EACCES)
-> { @io.reopen("burn".freeze, IO::WRONLY | IO::APPEND) }.should raise_error(Errno::EACCES)
end
it "raises a FrozenError when trying to reopen self with a frozen String in truncate-mode" do
-> { @io.reopen("burn".freeze, IO::RDONLY | IO::TRUNC) }.should raise_error(FrozenError)
end
it "does not raise IOError when passed a frozen String in read-mode" do
@io.reopen("burn".freeze, IO::RDONLY)
@io.string.should == "burn"
end
end
describe "StringIO#reopen when passed [Object, Object]" do
before :each do
@io = StringIO.new("example")
end
it "reopens self with the passed Object in the passed mode" do
@io.reopen("reopened", "r")
@io.closed_read?.should be_false
@io.closed_write?.should be_true
@io.string.should == "reopened"
@io.reopen(+"reopened, twice", "r+")
@io.closed_read?.should be_false
@io.closed_write?.should be_false
@io.string.should == "reopened, twice"
@io.reopen(+"reopened, another", "w+")
@io.closed_read?.should be_false
@io.closed_write?.should be_false
@io.string.should == ""
@io.reopen(+"reopened, another time", "r+")
@io.closed_read?.should be_false
@io.closed_write?.should be_false
@io.string.should == "reopened, another time"
end
it "truncates the passed String when opened in truncate mode" do
@io.reopen(str = +"reopened", "w")
str.should == ""
end
it "tries to convert the passed Object to a String using #to_str" do
obj = mock("to_str")
obj.should_receive(:to_str).and_return("to_str")
@io.reopen(obj, "r")
@io.string.should == "to_str"
end
it "raises a TypeError when the passed Object can't be converted to a String using #to_str" do
-> { @io.reopen(Object.new, "r") }.should raise_error(TypeError)
end
it "resets self's position to 0" do
@io.read(5)
@io.reopen(+"reopened")
@io.pos.should eql(0)
end
it "resets self's line number to 0" do
@io.gets
@io.reopen(+"reopened")
@io.lineno.should eql(0)
end
it "tries to convert the passed mode Object to an Integer using #to_str" do
obj = mock("to_str")
obj.should_receive(:to_str).and_return("r")
@io.reopen("reopened", obj)
@io.closed_read?.should be_false
@io.closed_write?.should be_true
@io.string.should == "reopened"
end
it "raises an Errno::EACCES error when trying to reopen self with a frozen String in write-mode" do
-> { @io.reopen("burn".freeze, 'w') }.should raise_error(Errno::EACCES)
-> { @io.reopen("burn".freeze, 'w+') }.should raise_error(Errno::EACCES)
-> { @io.reopen("burn".freeze, 'a') }.should raise_error(Errno::EACCES)
-> { @io.reopen("burn".freeze, "r+") }.should raise_error(Errno::EACCES)
end
it "does not raise IOError if a frozen string is passed in read mode" do
@io.reopen("burn".freeze, "r")
@io.string.should == "burn"
end
end
describe "StringIO#reopen when passed [String]" do
before :each do
@io = StringIO.new("example")
end
it "reopens self with the passed String in read-write mode" do
@io.close
@io.reopen(+"reopened")
@io.closed_write?.should be_false
@io.closed_read?.should be_false
@io.string.should == "reopened"
end
it "resets self's position to 0" do
@io.read(5)
@io.reopen(+"reopened")
@io.pos.should eql(0)
end
it "resets self's line number to 0" do
@io.gets
@io.reopen(+"reopened")
@io.lineno.should eql(0)
end
end
describe "StringIO#reopen when passed [Object]" do
before :each do
@io = StringIO.new("example")
end
it "raises a TypeError when passed an Object that can't be converted to a StringIO" do
-> { @io.reopen(Object.new) }.should raise_error(TypeError)
end
it "does not try to convert the passed Object to a String using #to_str" do
obj = mock("not to_str")
obj.should_not_receive(:to_str)
-> { @io.reopen(obj) }.should raise_error(TypeError)
end
it "tries to convert the passed Object to a StringIO using #to_strio" do
obj = mock("to_strio")
obj.should_receive(:to_strio).and_return(StringIO.new(+"to_strio"))
@io.reopen(obj)
@io.string.should == "to_strio"
end
end
describe "StringIO#reopen when passed no arguments" do
before :each do
@io = StringIO.new("example\nsecond line")
end
it "resets self's mode to read-write" do
@io.close
@io.reopen
@io.closed_read?.should be_false
@io.closed_write?.should be_false
end
it "resets self's position to 0" do
@io.read(5)
@io.reopen
@io.pos.should eql(0)
end
it "resets self's line number to 0" do
@io.gets
@io.reopen
@io.lineno.should eql(0)
end
end
# NOTE: Some reopen specs disabled due to MRI bugs. See:
# http://rubyforge.org/tracker/index.php?func=detail&aid=13919&group_id=426&atid=1698
# for details.
describe "StringIO#reopen" do
before :each do
@io = StringIO.new(+'hello', 'a')
end
# TODO: find out if this is really a bug
it "reopens a stream when given a String argument" do
@io.reopen(+'goodbye').should == @io
@io.string.should == 'goodbye'
@io << 'x'
@io.string.should == 'xoodbye'
end
it "reopens a stream in append mode when flagged as such" do
@io.reopen(+'goodbye', 'a').should == @io
@io.string.should == 'goodbye'
@io << 'x'
@io.string.should == 'goodbyex'
end
it "reopens and truncate when reopened in write mode" do
@io.reopen(+'goodbye', 'wb').should == @io
@io.string.should == ''
@io << 'x'
@io.string.should == 'x'
end
it "truncates the given string, not a copy" do
str = +'goodbye'
@io.reopen(str, 'w')
@io.string.should == ''
str.should == ''
end
it "does not truncate the content even when the StringIO argument is in the truncate mode" do
orig_io = StringIO.new(+"Original StringIO", IO::RDWR|IO::TRUNC)
orig_io.write("BLAH") # make sure the content is not empty
@io.reopen(orig_io)
@io.string.should == "BLAH"
end
end
|