io-like 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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,116 @@
1
+ require File.dirname(__FILE__) + '/../fixtures/classes'
2
+
3
+ describe :io_like__eof, :shared => true do
4
+ before :each do
5
+ @filename = File.dirname(__FILE__) + '/../fixtures/readlines.txt'
6
+ @file = File.open(@filename, 'r')
7
+ @iowrapper = ReadableIOWrapper.open(@file)
8
+ end
9
+
10
+ after :each do
11
+ @iowrapper.close unless @iowrapper.closed?
12
+ @file.close unless @file.closed?
13
+ end
14
+
15
+ it "returns false when not at end of file" do
16
+ @iowrapper.send(@method).should == false
17
+ @iowrapper.read(1)
18
+ @iowrapper.send(@method).should == false
19
+ end
20
+
21
+ it "returns true after reading with read with no parameters" do
22
+ @iowrapper.read
23
+ @iowrapper.send(@method).should == true
24
+ end
25
+
26
+ it "returns true after reading with read" do
27
+ @iowrapper.read(File.size(@filename))
28
+ @iowrapper.send(@method).should == true
29
+ end
30
+
31
+ it "returns true after reading with sysread" do
32
+ @iowrapper.sysread(File.size(@filename))
33
+ @iowrapper.send(@method).should == true
34
+ end
35
+
36
+ it "returns true after reading with readlines" do
37
+ @iowrapper.readlines
38
+ @iowrapper.send(@method).should == true
39
+ end
40
+
41
+ it "returns true on just opened empty stream" do
42
+ path = tmp('empty.txt')
43
+ File.open(path, "w") { |empty| } # ensure it exists
44
+ File.open(path) do |empty|
45
+ ReadableIOWrapper.open(empty) do |iowrapper|
46
+ iowrapper.send(@method).should == true
47
+ end
48
+ end
49
+ File.delete(path)
50
+ end
51
+
52
+ it "returns false on just opened non-empty stream" do
53
+ @iowrapper.send(@method).should == false
54
+ end
55
+
56
+ it "should not consume the data from the stream" do
57
+ @iowrapper.send(@method).should == false
58
+ @iowrapper.getc.should == 86
59
+ end
60
+
61
+ it "raises IOError on closed stream" do
62
+ lambda { IOSpecs.closed_file.send(@method) }.should raise_error(IOError)
63
+ end
64
+
65
+ it "raises IOError on stream not opened for reading" do
66
+ IOSpecs.writable_iowrapper do |iowrapper|
67
+ lambda { iowrapper.send(@method) }.should raise_error(IOError)
68
+ end
69
+ end
70
+
71
+ it "raises IOError on stream closed for reading by close_read" do
72
+ @iowrapper.close_read
73
+ lambda { @iowrapper.send(@method) }.should raise_error(IOError)
74
+ end
75
+
76
+ it "returns true on one-byte stream after single-byte read" do
77
+ File.open(File.dirname(__FILE__) + '/../fixtures/one_byte.txt') do |one_byte|
78
+ WritableIOWrapper.open(one_byte) do |iowrapper|
79
+ one_byte.read(1)
80
+ one_byte.send(@method).should == true
81
+ end
82
+ end
83
+ end
84
+
85
+ it "returns true on receiving side of Pipe when writing side is closed" do
86
+ r, w = IO.pipe
87
+ iowrapper_r = ReadableIOWrapper.open(r)
88
+ iowrapper_w = WritableIOWrapper.open(w)
89
+ iowrapper_w.close
90
+ w.close
91
+
92
+ iowrapper_r.send(@method).should == true
93
+
94
+ iowrapper_r.close
95
+ r.close
96
+ end
97
+
98
+ it "returns false on receiving side of Pipe when writing side wrote some data" do
99
+ r, w = IO.pipe
100
+ iowrapper_r = ReadableIOWrapper.open(r)
101
+ iowrapper_w = WritableIOWrapper.open(w)
102
+ iowrapper_w.sync = true
103
+
104
+ iowrapper_w.puts "hello"
105
+ iowrapper_r.send(@method).should == false
106
+ iowrapper_w.close
107
+ w.close
108
+
109
+ iowrapper_r.send(@method).should == false
110
+ iowrapper_r.read
111
+ iowrapper_r.send(@method).should == true
112
+
113
+ iowrapper_r.close
114
+ r.close
115
+ end
116
+ end
@@ -0,0 +1,39 @@
1
+ describe :io_like__pos, :shared => true do
2
+ before :each do
3
+ @fname = tmp('IO_Like__pos_test')
4
+ File.open(@fname, 'w') { |f| f.write("123") }
5
+ end
6
+
7
+ after :each do
8
+ File.unlink(@fname)
9
+ end
10
+
11
+ it "gets the offset" do
12
+ IOSpecs.readable_iowrapper do |iowrapper|
13
+ iowrapper.send(@method).should == 0
14
+ iowrapper.read(1)
15
+ iowrapper.send(@method).should == 1
16
+ iowrapper.read(2)
17
+ iowrapper.send(@method).should == 3
18
+ end
19
+ end
20
+
21
+ it "raises IOError on closed stream" do
22
+ lambda { IOSpecs.closed_file.send(@method) }.should raise_error(IOError)
23
+ end
24
+
25
+ # BOGUS EXPECTATION
26
+ # This fails for File and IO. It used to pass because the end of file was not
27
+ # actually reached with just 2 bytes read from the file.
28
+ #it "resets #eof?" do
29
+ # File.open(@fname) do |f|
30
+ # ReadableIOWrapper.open(f) do |iowrapper|
31
+ # iowrapper.read(1)
32
+ # iowrapper.read(1)
33
+ # iowrapper.eof?.should == true
34
+ # iowrapper.send(@method)
35
+ # iowrapper.eof?.should == false
36
+ # end
37
+ # end
38
+ #end
39
+ end
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + '/../fixtures/classes'
2
+
3
+ describe :io_like__tty, :shared => true do
4
+ it "returns false if this stream is open" do
5
+ IOSpecs.readable_iowrapper { |io| io.send(@method) }.should == false
6
+ IOSpecs.writable_iowrapper { |io| io.send(@method) }.should == false
7
+ end
8
+
9
+ it "raises IOError on closed stream" do
10
+ lambda { IOSpecs.closed_file.send(@method) }.should raise_error(IOError)
11
+ end
12
+ end
@@ -0,0 +1,53 @@
1
+ require File.dirname(__FILE__) + '/../fixtures/classes'
2
+
3
+ describe :io_like__write, :shared => true do
4
+ before :each do
5
+ @filename = tmp("IO_Like__shared_write_test")
6
+ @content = "012345678901234567890123456789"
7
+ File.open(@filename, "w") { |f| f.write(@content) }
8
+ @file = File.open(@filename, "r+")
9
+ @iowrapper = IOWrapper.open(@file)
10
+ end
11
+
12
+ after :each do
13
+ @iowrapper.close unless @iowrapper.closed?
14
+ @file.close unless @file.closed?
15
+ File.delete(@filename)
16
+ end
17
+
18
+ it "coerces the argument to a string using to_s" do
19
+ (obj = mock('test')).should_receive(:to_s).and_return('a string')
20
+ @iowrapper.send(@method, obj)
21
+ end
22
+
23
+ it "does not warn if called after IO#read" do
24
+ @iowrapper.read(5)
25
+ lambda { @iowrapper.send(@method, "fghij") }.should_not complain
26
+ end
27
+
28
+ it "writes to the current position after IO#read" do
29
+ @iowrapper.read(5)
30
+ @iowrapper.send(@method, "abcd")
31
+ @iowrapper.rewind
32
+ @iowrapper.read.should == "01234abcd901234567890123456789"
33
+ end
34
+
35
+ it "advances the file position by the count of given bytes" do
36
+ @iowrapper.send(@method, "abcde")
37
+ @iowrapper.read(10).should == "5678901234"
38
+ end
39
+
40
+ it "raises IOError on read-only stream if writing more than zero bytes" do
41
+ lambda do
42
+ IOSpecs.readable_iowrapper do |iowrapper|
43
+ iowrapper.send(@method, "abcde")
44
+ end
45
+ end.should raise_error(IOError)
46
+ end
47
+
48
+ it "raises IOError on closed stream if writing more than zero bytes" do
49
+ lambda do
50
+ IOSpecs.closed_file.send(@method, "abcde")
51
+ end.should raise_error(IOError)
52
+ end
53
+ end
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/fixtures/classes'
3
+
4
+ describe "IO::Like#sync=" do
5
+ before :each do
6
+ @file = File.dirname(__FILE__) + '/fixtures/readlines.txt'
7
+ @f = File.open(@file)
8
+ @iowrapper = ReadableIOWrapper.open(@f)
9
+ end
10
+
11
+ after :each do
12
+ @iowrapper.close unless @iowrapper.closed?
13
+ @f.close unless @f.closed?
14
+ end
15
+
16
+ it "sets the sync mode to true or false" do
17
+ @iowrapper.sync = true
18
+ @iowrapper.sync.should == true
19
+ @iowrapper.sync = false
20
+ @iowrapper.sync.should == false
21
+ end
22
+
23
+ it "accepts non-boolean arguments" do
24
+ @iowrapper.sync = 10
25
+ @iowrapper.sync.should == true
26
+ @iowrapper.sync = nil
27
+ @iowrapper.sync.should == false
28
+ @iowrapper.sync = Object.new
29
+ @iowrapper.sync.should == true
30
+ end
31
+
32
+ it "raises IOError on closed stream" do
33
+ lambda { IOSpecs.closed_file.sync = true }.should raise_error(IOError)
34
+ end
35
+ end
36
+
37
+ describe "IO::Like#sync" do
38
+ before :each do
39
+ @file = File.dirname(__FILE__) + '/fixtures/readlines.txt'
40
+ @f = File.open(@file)
41
+ @iowrapper = ReadableIOWrapper.open(@f)
42
+ end
43
+
44
+ after :each do
45
+ @iowrapper.close unless @iowrapper.closed?
46
+ @f.close unless @f.closed?
47
+ end
48
+
49
+ it "returns the current sync mode" do
50
+ @iowrapper.sync.should == false
51
+ end
52
+
53
+ it "raises IOError on closed stream" do
54
+ lambda { IOSpecs.closed_file.sync }.should raise_error(IOError)
55
+ end
56
+ end
@@ -0,0 +1,87 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/fixtures/classes'
3
+
4
+ describe "IO::Like#sysread on a file" do
5
+ before :each do
6
+ @filename = tmp("IO_Like___sysread_file") + $$.to_s
7
+ @contents = "012345678901234567890123456789"
8
+ File.open(@filename, "w") { |f| f.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 "reads the specified number of bytes from the file" do
21
+ @iowrapper.sysread(15).should == @contents.slice(0, 15)
22
+ end
23
+
24
+ it "reads the specified number of bytes from the file to the buffer" do
25
+ buf = "" # empty buffer
26
+ @iowrapper.sysread(15, buf).should == buf
27
+ buf.should == @contents.slice(0, 15)
28
+
29
+ @iowrapper.rewind
30
+
31
+ buf = "ABCDE" # small buffer
32
+ @iowrapper.sysread(15, buf).should == buf
33
+ buf.should == @contents.slice(0, 15)
34
+
35
+ @iowrapper.rewind
36
+
37
+ buf = "ABCDE" * 5 # large buffer
38
+ @iowrapper.sysread(15, buf).should == buf
39
+ buf.should == @contents.slice(0, 15)
40
+ end
41
+
42
+ it "coerces the second argument to string and uses it as a buffer" do
43
+ buf = "ABCDE"
44
+ (obj = mock("buff")).should_receive(:to_str).and_return(buf)
45
+ @iowrapper.sysread(15, obj).should == buf
46
+ buf.should == @contents.slice(0, 15)
47
+ end
48
+
49
+ it "advances the position of the file by the specified number of bytes" do
50
+ @iowrapper.sysread(15)
51
+ @iowrapper.sysread(5).should == @contents.slice(15, 5)
52
+ end
53
+
54
+ it "raises IOError when called immediately after a buffered IO#read" do
55
+ @iowrapper.read(15)
56
+ lambda { @iowrapper.sysread(5) }.should raise_error(IOError)
57
+ end
58
+
59
+ it "does not raise IOError if called after IO#read followed by IO#write" do
60
+ @iowrapper.read(5)
61
+ @iowrapper.write("abcde")
62
+ lambda { @iowrapper.sysread(5) }.should_not raise_error(IOError)
63
+ end
64
+
65
+ it "does not raise IOError if called after IO#read followed by IO#syswrite" do
66
+ @iowrapper.read(5)
67
+ @iowrapper.syswrite("abcde")
68
+ lambda { @iowrapper.sysread(5) }.should_not raise_error(IOError)
69
+ end
70
+
71
+ it "reads updated content after the flushed buffered IO#write" do
72
+ @iowrapper.write("abcde")
73
+ @iowrapper.flush
74
+ @iowrapper.sysread(5).should == @contents.slice(5, 5)
75
+ File.open(@filename) do |f|
76
+ f.sysread(10).should == "abcde56789"
77
+ end
78
+ end
79
+
80
+ it "raises IOError on write-only stream" do
81
+ lambda { IOSpecs.writable_iowrapper.sysread(5) }.should raise_error(IOError)
82
+ end
83
+
84
+ it "raises IOError on closed stream" do
85
+ lambda { IOSpecs.closed_file.sysread(5) }.should raise_error(IOError)
86
+ end
87
+ end
@@ -0,0 +1,68 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/fixtures/classes'
3
+
4
+ describe "IO::Like#sysseek on a file" do
5
+ # TODO: This should be made more generic with seek spec
6
+ before :each do
7
+ @file = File.open(File.dirname(__FILE__) + '/fixtures/readlines.txt', 'r')
8
+ @iowrapper = IOWrapper.open(@file)
9
+ end
10
+
11
+ after :each do
12
+ @iowrapper.close unless @iowrapper.closed?
13
+ @file.close unless @file.closed?
14
+ end
15
+
16
+ it "moves the read position relative to the current position with SEEK_CUR" do
17
+ @iowrapper.sysseek(10, IO::SEEK_CUR)
18
+ @iowrapper.readline.should == "igne une.\n"
19
+ end
20
+
21
+ it "raises an error when called after buffered reads" do
22
+ @iowrapper.readline
23
+ lambda { @iowrapper.sysseek(-5, IO::SEEK_CUR) }.should raise_error(IOError)
24
+ end
25
+
26
+ it "warns if called immediately after a buffered IO#write" do
27
+ begin
28
+ # copy contents to a separate file
29
+ tmpfile = File.open(tmp("tmp_IO_sysseek"), "w")
30
+ wrapper = IOWrapper.open(tmpfile)
31
+ wrapper.write(@iowrapper.read)
32
+ wrapper.seek(0, File::SEEK_SET)
33
+
34
+ wrapper.write("abcde")
35
+ lambda { wrapper.sysseek(10) }.should complain(/sysseek/)
36
+ ensure
37
+ wrapper.close
38
+ File.unlink(tmpfile.path)
39
+ end
40
+ end
41
+
42
+ it "moves the read position relative to the start with SEEK_SET" do
43
+ @iowrapper.sysseek(42, IO::SEEK_SET)
44
+ @iowrapper.readline.should == "quí está la línea tres.\n"
45
+ end
46
+
47
+ it "moves the read position relative to the end with SEEK_END" do
48
+ @iowrapper.sysseek(1, IO::SEEK_END)
49
+
50
+ # this is the safest way of checking the EOF when
51
+ # sys-* methods are invoked
52
+ lambda { @iowrapper.sysread(1) }.should raise_error(EOFError)
53
+
54
+ @iowrapper.sysseek(-25, IO::SEEK_END)
55
+ @iowrapper.sysread(7).should == "cinco.\n"
56
+ end
57
+
58
+ it "can handle any numerical argument without breaking and can seek past EOF" do
59
+ @iowrapper.sysseek(1.2).should == 1
60
+ @iowrapper.sysseek(2**10).should == 1024
61
+ @iowrapper.sysseek(2**32).should == 4294967296
62
+ lambda { @iowrapper.sysseek(2**128) }.should raise_error(RangeError)
63
+ end
64
+
65
+ it "raises IOError on closed stream" do
66
+ lambda { IOSpecs.closed_file.sysseek(0) }.should raise_error(IOError)
67
+ end
68
+ end
@@ -0,0 +1,60 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ require File.dirname(__FILE__) + '/fixtures/classes'
3
+ require File.dirname(__FILE__) + '/shared/write'
4
+
5
+ describe "IO::Like#syswrite" do
6
+ before :each do
7
+ @filename = tmp("IO_Like__syswrite_test")
8
+ @content = "012345678901234567890123456789"
9
+ File.open(@filename, "w") { |f| f.syswrite(@content) }
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)
18
+ end
19
+
20
+ it "returns the number of bytes written" do
21
+ @iowrapper.syswrite('').should == 0
22
+ @iowrapper.syswrite('abcde').should == 5
23
+ end
24
+
25
+ it "writes all of the string's bytes but does not buffer them" do
26
+ written = @iowrapper.syswrite("abcde")
27
+ written.should == 5
28
+ File.open(@filename) do |file|
29
+ file.sysread(10).should == "abcde56789"
30
+ file.seek(0)
31
+ @iowrapper.flush
32
+ file.sysread(10).should == "abcde56789"
33
+ end
34
+ end
35
+
36
+ not_compliant_on :rubinius do
37
+ it "warns if called immediately after a buffered IO#write" do
38
+ @iowrapper.write("abcde")
39
+ lambda { @iowrapper.syswrite("fghij") }.should complain(/syswrite/)
40
+ end
41
+ end
42
+
43
+ it "does not warn if called after IO#write with intervening IO#sysread" do
44
+ @iowrapper.write("abcde")
45
+ @iowrapper.sysread(5)
46
+ lambda { @iowrapper.syswrite("fghij") }.should_not complain
47
+ end
48
+
49
+ it "writes to the actual file position when called after buffered IO#read" do
50
+ @iowrapper.read(5)
51
+ @iowrapper.syswrite("abcde")
52
+ File.open(@filename) do |file|
53
+ file.sysread(10).should == "01234abcde"
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "IO::Like#syswrite" do
59
+ it_behaves_like :io_like__write, :syswrite
60
+ end