io-like 0.3.0 → 0.3.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.
- data/.yardopts +1 -0
- data/LICENSE +22 -57
- data/{LICENSE.rubyspec → LICENSE-rubyspec} +0 -0
- data/{NEWS → NEWS.md} +10 -5
- data/README.md +269 -0
- data/Rakefile +228 -0
- data/ruby.1.8.mspec +7 -0
- data/spec/binmode_spec.rb +29 -0
- data/spec/close_read_spec.rb +64 -0
- data/spec/close_spec.rb +36 -0
- data/spec/close_write_spec.rb +61 -0
- data/spec/closed_spec.rb +16 -0
- data/spec/each_byte_spec.rb +38 -0
- data/spec/each_line_spec.rb +11 -0
- data/spec/each_spec.rb +11 -0
- data/spec/eof_spec.rb +11 -0
- data/spec/fixtures/classes.rb +96 -0
- data/spec/fixtures/gets.txt +9 -0
- data/spec/fixtures/numbered_lines.txt +5 -0
- data/spec/fixtures/one_byte.txt +1 -0
- data/spec/fixtures/paragraphs.txt +7 -0
- data/spec/fixtures/readlines.txt +6 -0
- data/spec/flush_spec.rb +8 -0
- data/spec/getc_spec.rb +44 -0
- data/spec/gets_spec.rb +212 -0
- data/spec/isatty_spec.rb +6 -0
- data/spec/lineno_spec.rb +84 -0
- data/spec/output_spec.rb +47 -0
- data/spec/pos_spec.rb +53 -0
- data/spec/print_spec.rb +97 -0
- data/spec/printf_spec.rb +24 -0
- data/spec/putc_spec.rb +57 -0
- data/spec/puts_spec.rb +99 -0
- data/spec/read_spec.rb +162 -0
- data/spec/readchar_spec.rb +49 -0
- data/spec/readline_spec.rb +60 -0
- data/spec/readlines_spec.rb +140 -0
- data/spec/readpartial_spec.rb +92 -0
- data/spec/rewind_spec.rb +56 -0
- data/spec/seek_spec.rb +72 -0
- data/spec/shared/each.rb +204 -0
- data/spec/shared/eof.rb +116 -0
- data/spec/shared/pos.rb +39 -0
- data/spec/shared/tty.rb +12 -0
- data/spec/shared/write.rb +53 -0
- data/spec/sync_spec.rb +56 -0
- data/spec/sysread_spec.rb +87 -0
- data/spec/sysseek_spec.rb +68 -0
- data/spec/syswrite_spec.rb +60 -0
- data/spec/tell_spec.rb +7 -0
- data/spec/to_io_spec.rb +19 -0
- data/spec/tty_spec.rb +6 -0
- data/spec/ungetc_spec.rb +118 -0
- data/spec/write_spec.rb +61 -0
- data/spec_helper.rb +49 -0
- metadata +223 -32
- data/CONTRIBUTORS +0 -15
- data/GPL +0 -676
- data/HACKING +0 -123
- data/LEGAL +0 -56
- data/MANIFEST +0 -10
- data/README +0 -150
data/spec/printf_spec.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/fixtures/classes'
|
3
|
+
|
4
|
+
describe "IO::Like#printf" do
|
5
|
+
before :each do
|
6
|
+
@io = IO.new(STDOUT.fileno, 'w')
|
7
|
+
@iowrapper = WritableIOWrapper.open(@io)
|
8
|
+
@iowrapper.sync = true
|
9
|
+
end
|
10
|
+
|
11
|
+
after :each do
|
12
|
+
@iowrapper.close unless @iowrapper.closed?
|
13
|
+
end
|
14
|
+
|
15
|
+
it "writes the #sprintf formatted string to the file descriptor" do
|
16
|
+
lambda do
|
17
|
+
@io.printf("%s\n", "look ma, no hands")
|
18
|
+
end.should output_to_fd("look ma, no hands\n", @io)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "raises IOError on closed stream" do
|
22
|
+
lambda { IOSpecs.closed_file.printf("stuff") }.should raise_error(IOError)
|
23
|
+
end
|
24
|
+
end
|
data/spec/putc_spec.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/fixtures/classes'
|
3
|
+
|
4
|
+
describe "IO::Like#putc" do
|
5
|
+
before :each do
|
6
|
+
@filename = tmp('IO_Like__putc_test')
|
7
|
+
@file = File.open(@filename, 'w')
|
8
|
+
@file.sync = true
|
9
|
+
@iowrapper = WritableIOWrapper.open(@file)
|
10
|
+
@iowrapper.sync = true
|
11
|
+
end
|
12
|
+
|
13
|
+
after :each do
|
14
|
+
@iowrapper.close unless @iowrapper.closed?
|
15
|
+
@file.close unless @file.closed?
|
16
|
+
File.unlink @filename
|
17
|
+
end
|
18
|
+
|
19
|
+
it "returns a reference to the object" do
|
20
|
+
@iowrapper.putc('a').should == 'a'
|
21
|
+
@iowrapper.putc(128).should == 128
|
22
|
+
end
|
23
|
+
|
24
|
+
it "writes the first byte of a String" do
|
25
|
+
@iowrapper.putc("foo")
|
26
|
+
File.read(@filename).should == 'f'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "writes the first byte of an object's string representation" do
|
30
|
+
(obj = mock('test')).should_receive(:to_int).and_return(261)
|
31
|
+
@iowrapper.putc(obj)
|
32
|
+
File.read(@filename).should == "\005"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "writes Numerics that fit in a C char" do
|
36
|
+
@iowrapper.putc(-128)
|
37
|
+
@iowrapper.putc(0)
|
38
|
+
@iowrapper.putc(255)
|
39
|
+
|
40
|
+
File.read(@filename).should == "\200\000\377"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "write the first byte of Numerics that don't fit in a C char" do
|
44
|
+
@iowrapper.putc(-129)
|
45
|
+
@iowrapper.putc(256)
|
46
|
+
|
47
|
+
File.read(@filename).should == "\177\000"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "checks if the stream is writable" do
|
51
|
+
lambda { IOSpecs.readable_iowrapper.putc('a') }.should raise_error(IOError)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "raises IOError on closed stream" do
|
55
|
+
lambda { IOSpecs.closed_file.putc('a') }.should raise_error(IOError)
|
56
|
+
end
|
57
|
+
end
|
data/spec/puts_spec.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/fixtures/classes'
|
3
|
+
|
4
|
+
# TODO: need to find a better way to test this. Too fragile to set expectations
|
5
|
+
# to each write call. Only care that all the characters are sent not the number
|
6
|
+
# or write calls. Also, these tests do not make sure the ordering of the write calls
|
7
|
+
# are correct.
|
8
|
+
describe "IO::Like#puts" do
|
9
|
+
before :each do
|
10
|
+
@old_record_separator = $\
|
11
|
+
@old_field_separator = $,
|
12
|
+
@filename = tmp('IO_Like__print_test')
|
13
|
+
@file = File.open(@filename, 'w')
|
14
|
+
@file.sync = true
|
15
|
+
@iowrapper = WritableIOWrapper.open(@file)
|
16
|
+
@iowrapper.sync = true
|
17
|
+
end
|
18
|
+
|
19
|
+
after :each do
|
20
|
+
$\ = @old_record_separator
|
21
|
+
$, = @old_field_separator
|
22
|
+
@iowrapper.close unless @iowrapper.closed?
|
23
|
+
@file.close unless @file.closed?
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns nil" do
|
27
|
+
@iowrapper.puts('hello').should == nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "writes just a newline when given no args" do
|
31
|
+
@iowrapper.puts()
|
32
|
+
File.read(@filename).should == "\n"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "writes just a newline when given just a newline" do
|
36
|
+
@iowrapper.puts("\n")
|
37
|
+
File.read(@filename).should == "\n"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "writes nil with a newline when given nil as an arg" do
|
41
|
+
@iowrapper.puts(nil)
|
42
|
+
File.read(@filename).should == "nil\n"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "coerces arguments to strings using to_s" do
|
46
|
+
data = 'abcdefgh9876'
|
47
|
+
(obj = mock('test')).should_receive(:to_s).and_return(data)
|
48
|
+
@iowrapper.puts(obj)
|
49
|
+
File.read(@filename).should == "#{data}\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "writes each arg if given several" do
|
53
|
+
data1 = 'abcdefgh9876'
|
54
|
+
data2 = '12345678zyxw'
|
55
|
+
@iowrapper.puts(data1, data2)
|
56
|
+
File.read(@filename).should == "#{data1}\n#{data2}\n"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "flattens a nested array before writing it" do
|
60
|
+
data = ['abcdefgh9876', '12345678zyxw']
|
61
|
+
@iowrapper.puts(data)
|
62
|
+
File.read(@filename).should == "#{data[0]}\n#{data[1]}\n"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "writes [...] for a recursive array arg" do
|
66
|
+
data = []
|
67
|
+
data << 1 << data << 2
|
68
|
+
@iowrapper.puts(data)
|
69
|
+
File.read(@filename).should == "#{data[0]}\n[...]\n#{data[2]}\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "writes a newline after objects that do not end in newlines" do
|
73
|
+
data = 'abcdefgh9876'
|
74
|
+
@iowrapper.puts(data)
|
75
|
+
File.read(@filename).should == "#{data}\n"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "does not write a newline after objects that end in newlines" do
|
79
|
+
data = "abcdefgh9876\n"
|
80
|
+
@iowrapper.puts(data)
|
81
|
+
File.read(@filename).should == data
|
82
|
+
end
|
83
|
+
|
84
|
+
it "ignores the $\ separator global" do
|
85
|
+
$\ = ":"
|
86
|
+
data1 = 'abcdefgh9876'
|
87
|
+
data2 = '12345678zyxw'
|
88
|
+
@iowrapper.puts(data1, data2)
|
89
|
+
File.read(@filename).should == "#{data1}\n#{data2}\n"
|
90
|
+
end
|
91
|
+
|
92
|
+
it "raises IOError on read-only stream" do
|
93
|
+
lambda { IOSpecs.readable_iowrapper.puts }.should raise_error(IOError)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "raises IOError on closed stream" do
|
97
|
+
lambda { IOSpecs.closed_file.puts }.should raise_error(IOError)
|
98
|
+
end
|
99
|
+
end
|
data/spec/read_spec.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/fixtures/classes'
|
3
|
+
|
4
|
+
describe "IO::Like#read" do
|
5
|
+
before :each do
|
6
|
+
@filename = tmp('IO_Like__read_test')
|
7
|
+
@contents = "1234567890"
|
8
|
+
File.open(@filename, "w") { |io| io.write(@contents) }
|
9
|
+
|
10
|
+
@file = File.open(@filename, "r+")
|
11
|
+
@iowrapper = IOWrapper.open(@file)
|
12
|
+
end
|
13
|
+
|
14
|
+
after :each do
|
15
|
+
@iowrapper.close unless @iowrapper.closed?
|
16
|
+
@file.close unless @file.closed?
|
17
|
+
File.delete(@filename) if File.exists?(@filename)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "can be read from consecutively" do
|
21
|
+
@iowrapper.read(1).should == '1'
|
22
|
+
@iowrapper.read(2).should == '23'
|
23
|
+
@iowrapper.read(3).should == '456'
|
24
|
+
@iowrapper.read(4).should == '7890'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "can read lots of data" do
|
28
|
+
data = "\xaa" * (8096 * 2 + 1024) # HACK IO::BufferSize
|
29
|
+
File.open(@filename, 'w') { |io| io.write(data) }
|
30
|
+
actual = nil
|
31
|
+
File.open(@filename, 'r') { |io| actual = io.read }
|
32
|
+
|
33
|
+
actual.length.should == data.length
|
34
|
+
actual.split('').all? { |c| c == "\xaa" }.should == true
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can read lots of data with length" do
|
38
|
+
read_length = 8096 * 2 + 1024 # HACK IO::BufferSize
|
39
|
+
data = "\xaa" * (read_length + 8096) # HACK same
|
40
|
+
File.open(@filename, 'w') { |io| io.write(data) }
|
41
|
+
actual = nil
|
42
|
+
File.open(@filename, 'r') { |io| actual = io.read(read_length) }
|
43
|
+
|
44
|
+
actual.length.should == read_length
|
45
|
+
actual.split('').all? { |c| c == "\xaa" }.should == true
|
46
|
+
end
|
47
|
+
|
48
|
+
it "consumes zero bytes when reading zero bytes" do
|
49
|
+
pre_pos = @iowrapper.pos
|
50
|
+
|
51
|
+
@iowrapper.read(0).should == ''
|
52
|
+
@iowrapper.getc.chr.should == '1'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "is at end-of-file when everything has been read" do
|
56
|
+
@iowrapper.read
|
57
|
+
@iowrapper.eof?.should == true
|
58
|
+
end
|
59
|
+
|
60
|
+
it "reads the contents of a file" do
|
61
|
+
@iowrapper.read.should == @contents
|
62
|
+
end
|
63
|
+
|
64
|
+
it "places the specified number of bytes in the buffer" do
|
65
|
+
buf = ""
|
66
|
+
@iowrapper.read(5, buf)
|
67
|
+
|
68
|
+
buf.should == "12345"
|
69
|
+
end
|
70
|
+
|
71
|
+
it "expands the buffer when too small" do
|
72
|
+
buf = "ABCDE"
|
73
|
+
@iowrapper.read(nil, buf)
|
74
|
+
|
75
|
+
buf.should == @contents
|
76
|
+
end
|
77
|
+
|
78
|
+
it "overwrites the buffer" do
|
79
|
+
buf = "ABCDEFGHIJ"
|
80
|
+
@iowrapper.read(nil, buf)
|
81
|
+
|
82
|
+
buf.should == @contents
|
83
|
+
end
|
84
|
+
|
85
|
+
it "truncates the buffer when too big" do
|
86
|
+
buf = "ABCDEFGHIJKLMNO"
|
87
|
+
@iowrapper.read(nil, buf)
|
88
|
+
buf.should == @contents
|
89
|
+
|
90
|
+
@iowrapper.rewind
|
91
|
+
buf = "ABCDEFGHIJKLMNO"
|
92
|
+
@iowrapper.read(5, buf)
|
93
|
+
buf.should == @contents[0..4]
|
94
|
+
end
|
95
|
+
|
96
|
+
it "returns the given buffer" do
|
97
|
+
buf = ""
|
98
|
+
|
99
|
+
@iowrapper.read(nil, buf).object_id.should == buf.object_id
|
100
|
+
end
|
101
|
+
|
102
|
+
it "coerces the second argument to string and uses it as a buffer" do
|
103
|
+
buf = "ABCDE"
|
104
|
+
obj = mock("buff")
|
105
|
+
obj.should_receive(:to_str).any_number_of_times.and_return(buf)
|
106
|
+
|
107
|
+
@iowrapper.read(15, obj).object_id.should_not == obj.object_id
|
108
|
+
buf.should == @contents
|
109
|
+
end
|
110
|
+
|
111
|
+
it "returns an empty string at end-of-file" do
|
112
|
+
@iowrapper.read
|
113
|
+
@iowrapper.read.should == ''
|
114
|
+
end
|
115
|
+
|
116
|
+
it "reads the contents of a file when more bytes are specified" do
|
117
|
+
@iowrapper.read(@contents.length + 1).should == @contents
|
118
|
+
end
|
119
|
+
|
120
|
+
it "reads all data available before a SystemCallError is raised" do
|
121
|
+
# Overrride @file.sysread to raise SystemCallError every other time it's
|
122
|
+
# called.
|
123
|
+
class << @file
|
124
|
+
alias :sysread_orig :sysread
|
125
|
+
def sysread(length)
|
126
|
+
if @error_raised then
|
127
|
+
@error_raised = false
|
128
|
+
sysread_orig(length)
|
129
|
+
else
|
130
|
+
@error_raised = true
|
131
|
+
raise SystemCallError, 'Test Error'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
lambda { @iowrapper.read }.should raise_error(SystemCallError)
|
137
|
+
@iowrapper.read.should == @contents
|
138
|
+
end
|
139
|
+
|
140
|
+
it "returns an empty string when the current pos is bigger than the content size" do
|
141
|
+
@iowrapper.pos = 1000
|
142
|
+
@iowrapper.read.should == ''
|
143
|
+
end
|
144
|
+
|
145
|
+
it "returns nil at end-of-file with a length" do
|
146
|
+
@iowrapper.read
|
147
|
+
@iowrapper.read(1).should == nil
|
148
|
+
end
|
149
|
+
|
150
|
+
it "with length argument returns nil when the current pos is bigger than the content size" do
|
151
|
+
@iowrapper.pos = 1000
|
152
|
+
@iowrapper.read(1).should == nil
|
153
|
+
end
|
154
|
+
|
155
|
+
it "raises IOError on write-only stream" do
|
156
|
+
lambda { IOSpecs.writable_iowrapper.read }.should raise_error(IOError)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "raises IOError on closed stream" do
|
160
|
+
lambda { IOSpecs.closed_file.read }.should raise_error(IOError)
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/fixtures/classes'
|
3
|
+
|
4
|
+
describe "IO::Like#readchar" do
|
5
|
+
before :each do
|
6
|
+
@file_name = File.dirname(__FILE__) + '/fixtures/readlines.txt'
|
7
|
+
@io = File.open(@file_name, 'r')
|
8
|
+
@iowrapper = IOWrapper.open(@io)
|
9
|
+
end
|
10
|
+
|
11
|
+
after :each do
|
12
|
+
@iowrapper.close unless @iowrapper.closed?
|
13
|
+
@io.close unless @io.closed?
|
14
|
+
end
|
15
|
+
|
16
|
+
it "returns the next byte from the stream" do
|
17
|
+
@io.readchar.should == 86
|
18
|
+
@io.readchar.should == 111
|
19
|
+
@io.readchar.should == 105
|
20
|
+
# read the rest of line
|
21
|
+
@io.readline.should == "ci la ligne une.\n"
|
22
|
+
@io.readchar.should == 81
|
23
|
+
end
|
24
|
+
|
25
|
+
it "raises EOFError when invoked at the end of the stream" do
|
26
|
+
# read entire content
|
27
|
+
@io.read
|
28
|
+
lambda { @io.readchar }.should raise_error(EOFError)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "raises EOFError when reaches the end of the stream" do
|
32
|
+
lambda { loop { @io.readchar } }.should raise_error(EOFError)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "raises EOFError on empty stream" do
|
36
|
+
path = tmp('empty.txt')
|
37
|
+
File.open(path, "w+") do |empty|
|
38
|
+
IOWrapper.open(empty) do |iowrapper|
|
39
|
+
lambda { iowrapper.readchar }.should raise_error(EOFError)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
File.unlink(path)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "raises IOError on closed stream" do
|
47
|
+
lambda { IOSpecs.closed_file.readchar }.should raise_error(IOError)
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require File.dirname(__FILE__) + '/fixtures/classes'
|
3
|
+
|
4
|
+
describe "IO::Like#readline" do
|
5
|
+
before :each do
|
6
|
+
testfile = File.dirname(__FILE__) + '/fixtures/gets.txt'
|
7
|
+
@contents = File.read(testfile)
|
8
|
+
@io = File.open(testfile, 'r')
|
9
|
+
@iowrapper = IOWrapper.open(@io)
|
10
|
+
end
|
11
|
+
|
12
|
+
after :each do
|
13
|
+
@iowrapper.close unless @iowrapper.closed?
|
14
|
+
@io.close unless @io.closed?
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns the next line on the stream" do
|
18
|
+
@iowrapper.readline.should == "Voici la ligne une.\n"
|
19
|
+
@iowrapper.readline.should == "Qui è la linea due.\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "goes back to first position after a rewind" do
|
23
|
+
@iowrapper.readline.should == "Voici la ligne une.\n"
|
24
|
+
@iowrapper.rewind
|
25
|
+
@iowrapper.readline.should == "Voici la ligne une.\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "is modified by the cursor position" do
|
29
|
+
@iowrapper.seek(1)
|
30
|
+
@iowrapper.readline.should == "oici la ligne une.\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "reads and returns all data available before a SystemCallError is raised when the separator is nil" do
|
34
|
+
# Overrride @io.sysread to raise SystemCallError every other time it's
|
35
|
+
# called.
|
36
|
+
class << @io
|
37
|
+
alias :sysread_orig :sysread
|
38
|
+
def sysread(length)
|
39
|
+
if @error_raised then
|
40
|
+
@error_raised = false
|
41
|
+
sysread_orig(length)
|
42
|
+
else
|
43
|
+
@error_raised = true
|
44
|
+
raise SystemCallError, 'Test Error'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
lambda { @iowrapper.readline(nil) }.should raise_error(SystemCallError)
|
50
|
+
@iowrapper.readline(nil).should == @contents
|
51
|
+
end
|
52
|
+
|
53
|
+
it "raises EOFError on end of stream" do
|
54
|
+
lambda { loop { @iowrapper.readline } }.should raise_error(EOFError)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "raises IOError on closed stream" do
|
58
|
+
lambda { IOSpecs.closed_file.readline }.should raise_error(IOError)
|
59
|
+
end
|
60
|
+
end
|