rubysl-stringio 1.0.0

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 (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +7 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +25 -0
  6. data/README.md +29 -0
  7. data/Rakefile +1 -0
  8. data/lib/rubysl/stringio.rb +2 -0
  9. data/lib/rubysl/stringio/stringio.rb +611 -0
  10. data/lib/rubysl/stringio/version.rb +5 -0
  11. data/lib/stringio.rb +1 -0
  12. data/rubysl-stringio.gemspec +24 -0
  13. data/spec/append_spec.rb +83 -0
  14. data/spec/binmode_spec.rb +8 -0
  15. data/spec/bytes_spec.rb +12 -0
  16. data/spec/chars_spec.rb +12 -0
  17. data/spec/close_read_spec.rb +30 -0
  18. data/spec/close_spec.rb +22 -0
  19. data/spec/close_write_spec.rb +30 -0
  20. data/spec/closed_read_spec.rb +11 -0
  21. data/spec/closed_spec.rb +15 -0
  22. data/spec/closed_write_spec.rb +11 -0
  23. data/spec/codepoints_spec.rb +11 -0
  24. data/spec/each_byte_spec.rb +10 -0
  25. data/spec/each_char_spec.rb +12 -0
  26. data/spec/each_codepoint_spec.rb +12 -0
  27. data/spec/each_line_spec.rb +14 -0
  28. data/spec/each_spec.rb +14 -0
  29. data/spec/eof_spec.rb +10 -0
  30. data/spec/external_encoding_spec.rb +12 -0
  31. data/spec/fcntl_spec.rb +7 -0
  32. data/spec/fileno_spec.rb +8 -0
  33. data/spec/fixtures/classes.rb +15 -0
  34. data/spec/flush_spec.rb +8 -0
  35. data/spec/fsync_spec.rb +8 -0
  36. data/spec/getbyte_spec.rb +25 -0
  37. data/spec/getc_spec.rb +31 -0
  38. data/spec/gets_spec.rb +245 -0
  39. data/spec/initialize_copy_spec.rb +95 -0
  40. data/spec/initialize_spec.rb +193 -0
  41. data/spec/internal_encoding_spec.rb +12 -0
  42. data/spec/isatty_spec.rb +6 -0
  43. data/spec/length_spec.rb +6 -0
  44. data/spec/lineno_spec.rb +29 -0
  45. data/spec/lines_spec.rb +16 -0
  46. data/spec/open_spec.rb +215 -0
  47. data/spec/path_spec.rb +15 -0
  48. data/spec/pid_spec.rb +7 -0
  49. data/spec/pos_spec.rb +27 -0
  50. data/spec/print_spec.rb +113 -0
  51. data/spec/printf_spec.rb +60 -0
  52. data/spec/putc_spec.rb +105 -0
  53. data/spec/puts_spec.rb +173 -0
  54. data/spec/read_nonblock_spec.rb +29 -0
  55. data/spec/read_spec.rb +62 -0
  56. data/spec/readbyte_spec.rb +21 -0
  57. data/spec/readchar_spec.rb +19 -0
  58. data/spec/readline_spec.rb +127 -0
  59. data/spec/readlines_spec.rb +124 -0
  60. data/spec/readpartial_spec.rb +29 -0
  61. data/spec/reopen_spec.rb +303 -0
  62. data/spec/rewind_spec.rb +23 -0
  63. data/spec/seek_spec.rb +75 -0
  64. data/spec/set_encoding_spec.rb +34 -0
  65. data/spec/shared/codepoints.rb +45 -0
  66. data/spec/shared/each.rb +162 -0
  67. data/spec/shared/each_byte.rb +60 -0
  68. data/spec/shared/each_char.rb +50 -0
  69. data/spec/shared/eof.rb +24 -0
  70. data/spec/shared/getc.rb +43 -0
  71. data/spec/shared/isatty.rb +5 -0
  72. data/spec/shared/length.rb +12 -0
  73. data/spec/shared/read.rb +186 -0
  74. data/spec/shared/readchar.rb +29 -0
  75. data/spec/shared/sysread.rb +27 -0
  76. data/spec/shared/tell.rb +12 -0
  77. data/spec/shared/write.rb +134 -0
  78. data/spec/size_spec.rb +6 -0
  79. data/spec/string_spec.rb +49 -0
  80. data/spec/stringio_spec.rb +8 -0
  81. data/spec/sync_spec.rb +18 -0
  82. data/spec/sysread_spec.rb +27 -0
  83. data/spec/syswrite_spec.rb +18 -0
  84. data/spec/tell_spec.rb +6 -0
  85. data/spec/truncate_spec.rb +69 -0
  86. data/spec/tty_spec.rb +6 -0
  87. data/spec/ungetbyte_spec.rb +88 -0
  88. data/spec/ungetc_spec.rb +98 -0
  89. data/spec/write_nonblock_spec.rb +20 -0
  90. data/spec/write_spec.rb +18 -0
  91. metadata +267 -0
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../fixtures/classes', __FILE__)
2
+
3
+ describe "StringIO#rewind" do
4
+ before(:each) do
5
+ @io = StringIO.new("hello\nworld")
6
+ @io.pos = 3
7
+ @io.lineno = 1
8
+ end
9
+
10
+ it "returns 0" do
11
+ @io.rewind.should eql(0)
12
+ end
13
+
14
+ it "resets the position" do
15
+ @io.rewind
16
+ @io.pos.should == 0
17
+ end
18
+
19
+ it "resets the line number" do
20
+ @io.rewind
21
+ @io.lineno.should == 0
22
+ end
23
+ end
data/spec/seek_spec.rb ADDED
@@ -0,0 +1,75 @@
1
+ require File.expand_path('../fixtures/classes', __FILE__)
2
+
3
+ describe "StringIO#seek" do
4
+ before(:each) do
5
+ @io = StringIO.new("12345678")
6
+ end
7
+
8
+ it "seeks from the current position when whence is IO::SEEK_CUR" do
9
+ @io.pos = 1
10
+ @io.seek(1, IO::SEEK_CUR)
11
+ @io.pos.should eql(2)
12
+
13
+ @io.seek(-1, IO::SEEK_CUR)
14
+ @io.pos.should eql(1)
15
+ end
16
+
17
+ it "seeks from the end of self when whence is IO::SEEK_END" do
18
+ @io.seek(3, IO::SEEK_END)
19
+ @io.pos.should eql(11) # Outside of the StringIO's content
20
+
21
+ @io.seek(-2, IO::SEEK_END)
22
+ @io.pos.should eql(6)
23
+ end
24
+
25
+ it "seeks to an absolute position when whence is IO::SEEK_SET" do
26
+ @io.seek(5, IO::SEEK_SET)
27
+ @io.pos.should == 5
28
+
29
+ @io.pos = 3
30
+ @io.seek(5, IO::SEEK_SET)
31
+ @io.pos.should == 5
32
+ end
33
+
34
+ it "raises an Errno::EINVAL error on negative amounts when whence is IO::SEEK_SET" do
35
+ lambda { @io.seek(-5, IO::SEEK_SET) }.should raise_error(Errno::EINVAL)
36
+ end
37
+
38
+ it "raises an Errno::EINVAL error on incorrect whence argument" do
39
+ lambda { @io.seek(0, 3) }.should raise_error(Errno::EINVAL)
40
+ lambda { @io.seek(0, -1) }.should raise_error(Errno::EINVAL)
41
+ lambda { @io.seek(0, 2**16) }.should raise_error(Errno::EINVAL)
42
+ lambda { @io.seek(0, -2**16) }.should raise_error(Errno::EINVAL)
43
+ end
44
+
45
+ it "tries to convert the passed Object to a String using #to_int" do
46
+ obj = mock("to_int")
47
+ obj.should_receive(:to_int).and_return(2)
48
+ @io.seek(obj)
49
+ @io.pos.should eql(2)
50
+ end
51
+
52
+ it "raises a TypeError when the passed Object can't be converted to an Integer" do
53
+ lambda { @io.seek(Object.new) }.should raise_error(TypeError)
54
+ end
55
+ end
56
+
57
+ describe "StringIO#seek when self is closed" do
58
+ before(:each) do
59
+ @io = StringIO.new("example")
60
+ @io.close
61
+ end
62
+
63
+ ruby_version_is "" ... "1.8.7" do
64
+ it "does not raise an IOError" do
65
+ @io.seek(5)
66
+ @io.pos.should eql(5)
67
+ end
68
+ end
69
+
70
+ ruby_version_is "1.8.7" do
71
+ it "raises an IOError" do
72
+ lambda { @io.seek(5) }.should raise_error(IOError)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,34 @@
1
+ require 'stringio'
2
+ require File.expand_path('../../../spec_helper', __FILE__)
3
+
4
+ ruby_version_is "1.9.2" do
5
+ describe "StringIO#set_encoding" do
6
+ before :each do
7
+ @default_external = Encoding.default_external
8
+ Encoding.default_external = Encoding::UTF_8
9
+ end
10
+
11
+ after :each do
12
+ Encoding.default_external = @default_external
13
+ end
14
+
15
+ it "sets the encoding of the underlying String to the specified encoding" do
16
+ io = StringIO.new
17
+ io.set_encoding Encoding::UTF_8
18
+ io.string.encoding.should == Encoding::UTF_8
19
+ end
20
+
21
+ it "sets the encoding of the underlying String to the named encoding" do
22
+ io = StringIO.new
23
+ io.set_encoding "UTF-8"
24
+ io.string.encoding.should == Encoding::UTF_8
25
+ end
26
+
27
+ it "sets the encoding of the underlying String to the default external encoding when passed nil" do
28
+ Encoding.default_external = Encoding::UTF_8
29
+ io = StringIO.new
30
+ io.set_encoding nil
31
+ io.string.encoding.should == Encoding::UTF_8
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,45 @@
1
+ # -*- encoding: utf-8 -*-
2
+ describe :stringio_codepoints, :shared => true do
3
+ before(:each) do
4
+ @io = StringIO.new("∂φ/∂x = gaîté")
5
+ @enum = @io.send(@method)
6
+ end
7
+
8
+ it "returns an Enumerator" do
9
+ @enum.should be_an_instance_of(enumerator_class)
10
+ end
11
+
12
+ it "yields each codepoint code in turn" do
13
+ @enum.to_a.should == [8706, 966, 47, 8706, 120, 32, 61, 32, 103, 97, 238, 116, 233]
14
+ end
15
+
16
+ it "yields each codepoint starting from the current position" do
17
+ @io.pos = 15
18
+ @enum.to_a.should == [238, 116, 233]
19
+ end
20
+
21
+ it "raises an error if reading invalid sequence" do
22
+ @io.pos = 1 # inside of a multibyte sequence
23
+ lambda { @enum.first }.should raise_error(ArgumentError)
24
+ end
25
+
26
+ it "raises an IOError if not readable" do
27
+ @io.close_read
28
+ lambda { @enum.to_a }.should raise_error(IOError)
29
+
30
+ io = StringIO.new("xyz", "w")
31
+ lambda { io.send(@method).to_a }.should raise_error(IOError)
32
+ end
33
+
34
+
35
+ it "calls the given block" do
36
+ r = []
37
+ @io.send(@method){|c| r << c }
38
+ r.should == [8706, 966, 47, 8706, 120, 32, 61, 32, 103, 97, 238, 116, 233]
39
+ end
40
+
41
+ it "returns self" do
42
+ @io.send(@method) {|l| l }.should equal(@io)
43
+ end
44
+
45
+ end
@@ -0,0 +1,162 @@
1
+ describe :stringio_each_separator, :shared => true do
2
+ before(:each) do
3
+ @io = StringIO.new("a b c d e\n1 2 3 4 5")
4
+ ScratchPad.record []
5
+ end
6
+
7
+ it "uses the passed argument as the line separator" do
8
+ seen = []
9
+ @io.send(@method, " ") {|s| seen << s}
10
+ seen.should == ["a ", "b ", "c ", "d ", "e\n1 ", "2 ", "3 ", "4 ", "5"]
11
+ end
12
+
13
+ it "does not change $_" do
14
+ $_ = "test"
15
+ @io.send(@method, " ") { |s| s}
16
+ $_.should == "test"
17
+ end
18
+
19
+ it "returns self" do
20
+ @io.send(@method) {|l| l }.should equal(@io)
21
+ end
22
+
23
+ ruby_version_is "1.9" do
24
+ it "returns at most limit characters when limit is positive" do
25
+ @io.send(@method, $/, 5) { |x| ScratchPad << x }
26
+ ScratchPad.recorded.should == ["a b c", " d e\n", "1 2 3", " 4 5"]
27
+ end
28
+
29
+ it "calls #to_str to convert a single argument to a String" do
30
+ sep = mock("stringio each sep")
31
+ sep.should_receive(:to_str).at_least(1).times.and_return($/)
32
+ sep.should_not_receive(:to_int)
33
+
34
+ @io.send(@method, sep) { |x| }
35
+ end
36
+
37
+ it "calls #to_int to convert a single argument if #to_str does not return a String" do
38
+ limit = mock("stringio each limit")
39
+ limit.should_receive(:to_str).at_least(1).times.and_return(nil)
40
+ limit.should_receive(:to_int).at_least(1).times.and_return(5)
41
+
42
+ @io.send(@method, limit) { |x| }
43
+ end
44
+
45
+ it "calls #to_int to convert the limit" do
46
+ limit = mock("stringio each limit")
47
+ limit.should_receive(:to_int).at_least(1).times.and_return(5)
48
+
49
+ @io.send(@method, limit) { |x| }
50
+ end
51
+
52
+ it "calls #to_int to convert the limit when passed separator and limit" do
53
+ limit = mock("stringio each limit")
54
+ limit.should_receive(:to_int).at_least(1).times.and_return(6)
55
+
56
+ @io.send(@method, $/, limit) { |x| }
57
+ end
58
+
59
+ it "raises an ArgumentError if length is 0 and #each is called on the Enumerator" do
60
+ enum = @io.send(@method, 0)
61
+ lambda { enum.each { } }.should raise_error(ArgumentError)
62
+ end
63
+
64
+ it "raises an ArgumentError if length is 0" do
65
+ lambda { @io.send(@method, 0) { } }.should raise_error(ArgumentError)
66
+ end
67
+ end
68
+
69
+ it "tries to convert the passed separator to a String using #to_str" do
70
+ obj = mock("to_str")
71
+ obj.stub!(:to_str).and_return(" ")
72
+
73
+ seen = []
74
+ @io.send(@method, obj) { |l| seen << l }
75
+ seen.should == ["a ", "b ", "c ", "d ", "e\n1 ", "2 ", "3 ", "4 ", "5"]
76
+ end
77
+
78
+ it "yields self's content starting from the current position when the passed separator is nil" do
79
+ seen = []
80
+ io = StringIO.new("1 2 1 2 1 2")
81
+ io.pos = 2
82
+ io.send(@method, nil) {|s| seen << s}
83
+ seen.should == ["2 1 2 1 2"]
84
+ end
85
+
86
+ ruby_bug "", "1.8.8" do
87
+ it "yields each paragraph when passed an empty String as separator" do
88
+ seen = []
89
+ io = StringIO.new("para1\n\npara2\n\n\npara3")
90
+ io.send(@method, "") {|s| seen << s}
91
+ seen.should == ["para1\n\n", "para2\n\n", "para3"]
92
+ end
93
+ end
94
+ end
95
+
96
+ describe :stringio_each_no_arguments, :shared => true do
97
+ before(:each) do
98
+ @io = StringIO.new("a b c d e\n1 2 3 4 5")
99
+ end
100
+
101
+ it "yields each line to the passed block" do
102
+ seen = []
103
+ @io.send(@method) {|s| seen << s }
104
+ seen.should == ["a b c d e\n", "1 2 3 4 5"]
105
+ end
106
+
107
+ it "yields each line starting from the current position" do
108
+ seen = []
109
+ @io.pos = 4
110
+ @io.send(@method) {|s| seen << s }
111
+ seen.should == ["c d e\n", "1 2 3 4 5"]
112
+ end
113
+
114
+ it "does not change $_" do
115
+ $_ = "test"
116
+ @io.send(@method) { |s| s}
117
+ $_.should == "test"
118
+ end
119
+
120
+ it "uses $/ as the default line separator" do
121
+ seen = []
122
+ begin
123
+ old_rs, $/ = $/, " "
124
+ @io.send(@method) {|s| seen << s }
125
+ seen.should eql(["a ", "b ", "c ", "d ", "e\n1 ", "2 ", "3 ", "4 ", "5"])
126
+ ensure
127
+ $/ = old_rs
128
+ end
129
+ end
130
+
131
+ it "returns self" do
132
+ @io.send(@method) {|l| l }.should equal(@io)
133
+ end
134
+
135
+ ruby_version_is "" ... "1.8.7" do
136
+ it "yields a LocalJumpError when passed no block" do
137
+ lambda { @io.send(@method) }.should raise_error(LocalJumpError)
138
+ end
139
+ end
140
+
141
+ ruby_version_is "1.8.7" do
142
+ it "returns an Enumerator when passed no block" do
143
+ enum = @io.send(@method)
144
+ enum.instance_of?(enumerator_class).should be_true
145
+
146
+ seen = []
147
+ enum.each { |b| seen << b }
148
+ seen.should == ["a b c d e\n", "1 2 3 4 5"]
149
+ end
150
+ end
151
+ end
152
+
153
+ describe :stringio_each_not_readable, :shared => true do
154
+ it "raises an IOError" do
155
+ io = StringIO.new("a b c d e", "w")
156
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
157
+
158
+ io = StringIO.new("a b c d e")
159
+ io.close_read
160
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
161
+ end
162
+ end
@@ -0,0 +1,60 @@
1
+ describe :stringio_each_byte, :shared => true do
2
+ before(:each) do
3
+ @io = StringIO.new("xyz")
4
+ end
5
+
6
+ it "yields each character code in turn" do
7
+ seen = []
8
+ @io.send(@method) { |b| seen << b }
9
+ seen.should == [120, 121, 122]
10
+ end
11
+
12
+ it "updates the position before each yield" do
13
+ seen = []
14
+ @io.send(@method) { |b| seen << @io.pos }
15
+ seen.should == [1, 2, 3]
16
+ end
17
+
18
+ it "does not yield if the current position is out of bounds" do
19
+ @io.pos = 1000
20
+ seen = nil
21
+ @io.send(@method) { |b| seen = b }
22
+ seen.should be_nil
23
+ end
24
+
25
+ ruby_version_is "" ... "1.8.7" do
26
+ it "returns nil" do
27
+ @io.send(@method) {}.should be_nil
28
+ end
29
+
30
+ it "yields a LocalJumpError when passed no block" do
31
+ lambda { @io.send(@method) }.should raise_error(LocalJumpError)
32
+ end
33
+ end
34
+
35
+ ruby_version_is "1.8.7" do
36
+ it "returns self" do
37
+ @io.send(@method) {}.should equal(@io)
38
+ end
39
+
40
+ it "returns an Enumerator when passed no block" do
41
+ enum = @io.send(@method)
42
+ enum.instance_of?(enumerator_class).should be_true
43
+
44
+ seen = []
45
+ enum.each { |b| seen << b }
46
+ seen.should == [120, 121, 122]
47
+ end
48
+ end
49
+ end
50
+
51
+ describe :stringio_each_byte_not_readable, :shared => true do
52
+ it "raises an IOError" do
53
+ io = StringIO.new("xyz", "w")
54
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
55
+
56
+ io = StringIO.new("xyz")
57
+ io.close_read
58
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
59
+ end
60
+ end
@@ -0,0 +1,50 @@
1
+ # -*- encoding: utf-8 -*-
2
+ describe :stringio_each_char, :shared => true do
3
+ before(:each) do
4
+ old_kcode, $KCODE = "UTF-8", $KCODE
5
+ @io = StringIO.new("xyz äöü")
6
+ $KCODE = old_kcode
7
+ end
8
+
9
+ it "yields each character code in turn" do
10
+ seen = []
11
+ @io.send(@method) { |c| seen << c }
12
+ seen.should == ["x", "y", "z", " ", "ä", "ö", "ü"]
13
+ end
14
+
15
+ ruby_version_is "" ... "1.8.7" do
16
+ it "returns nil" do
17
+ @io.send(@method) {}.should be_nil
18
+ end
19
+
20
+ it "yields a LocalJumpError when passed no block" do
21
+ lambda { @io.send(@method) }.should raise_error(LocalJumpError)
22
+ end
23
+ end
24
+
25
+ ruby_version_is "1.8.7" do
26
+ it "returns self" do
27
+ @io.send(@method) {}.should equal(@io)
28
+ end
29
+
30
+ it "returns an Enumerator when passed no block" do
31
+ enum = @io.send(@method)
32
+ enum.instance_of?(enumerator_class).should be_true
33
+
34
+ seen = []
35
+ enum.each { |c| seen << c }
36
+ seen.should == ["x", "y", "z", " ", "ä", "ö", "ü"]
37
+ end
38
+ end
39
+ end
40
+
41
+ describe :stringio_each_char_not_readable, :shared => true do
42
+ it "raises an IOError" do
43
+ io = StringIO.new("xyz", "w")
44
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
45
+
46
+ io = StringIO.new("xyz")
47
+ io.close_read
48
+ lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
49
+ end
50
+ end