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.
Files changed (62) hide show
  1. data/.yardopts +1 -0
  2. data/LICENSE +22 -57
  3. data/{LICENSE.rubyspec → LICENSE-rubyspec} +0 -0
  4. data/{NEWS → NEWS.md} +10 -5
  5. data/README.md +269 -0
  6. data/Rakefile +228 -0
  7. data/ruby.1.8.mspec +7 -0
  8. data/spec/binmode_spec.rb +29 -0
  9. data/spec/close_read_spec.rb +64 -0
  10. data/spec/close_spec.rb +36 -0
  11. data/spec/close_write_spec.rb +61 -0
  12. data/spec/closed_spec.rb +16 -0
  13. data/spec/each_byte_spec.rb +38 -0
  14. data/spec/each_line_spec.rb +11 -0
  15. data/spec/each_spec.rb +11 -0
  16. data/spec/eof_spec.rb +11 -0
  17. data/spec/fixtures/classes.rb +96 -0
  18. data/spec/fixtures/gets.txt +9 -0
  19. data/spec/fixtures/numbered_lines.txt +5 -0
  20. data/spec/fixtures/one_byte.txt +1 -0
  21. data/spec/fixtures/paragraphs.txt +7 -0
  22. data/spec/fixtures/readlines.txt +6 -0
  23. data/spec/flush_spec.rb +8 -0
  24. data/spec/getc_spec.rb +44 -0
  25. data/spec/gets_spec.rb +212 -0
  26. data/spec/isatty_spec.rb +6 -0
  27. data/spec/lineno_spec.rb +84 -0
  28. data/spec/output_spec.rb +47 -0
  29. data/spec/pos_spec.rb +53 -0
  30. data/spec/print_spec.rb +97 -0
  31. data/spec/printf_spec.rb +24 -0
  32. data/spec/putc_spec.rb +57 -0
  33. data/spec/puts_spec.rb +99 -0
  34. data/spec/read_spec.rb +162 -0
  35. data/spec/readchar_spec.rb +49 -0
  36. data/spec/readline_spec.rb +60 -0
  37. data/spec/readlines_spec.rb +140 -0
  38. data/spec/readpartial_spec.rb +92 -0
  39. data/spec/rewind_spec.rb +56 -0
  40. data/spec/seek_spec.rb +72 -0
  41. data/spec/shared/each.rb +204 -0
  42. data/spec/shared/eof.rb +116 -0
  43. data/spec/shared/pos.rb +39 -0
  44. data/spec/shared/tty.rb +12 -0
  45. data/spec/shared/write.rb +53 -0
  46. data/spec/sync_spec.rb +56 -0
  47. data/spec/sysread_spec.rb +87 -0
  48. data/spec/sysseek_spec.rb +68 -0
  49. data/spec/syswrite_spec.rb +60 -0
  50. data/spec/tell_spec.rb +7 -0
  51. data/spec/to_io_spec.rb +19 -0
  52. data/spec/tty_spec.rb +6 -0
  53. data/spec/ungetc_spec.rb +118 -0
  54. data/spec/write_spec.rb +61 -0
  55. data/spec_helper.rb +49 -0
  56. metadata +223 -32
  57. data/CONTRIBUTORS +0 -15
  58. data/GPL +0 -676
  59. data/HACKING +0 -123
  60. data/LEGAL +0 -56
  61. data/MANIFEST +0 -10
  62. data/README +0 -150
@@ -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
@@ -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
@@ -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
@@ -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