Skip to content

Commit bc2f82c

Browse files
committed
Add specs for IO::Buffer.for and .string, improve spec for #initialize
Also simplify specs for predicate methods, as flags are mostly set on buffer creation and tested accordingly.
1 parent c36ac5a commit bc2f82c

File tree

9 files changed

+297
-618
lines changed

9 files changed

+297
-618
lines changed

core/io/buffer/external_spec.rb

Lines changed: 9 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -6,103 +6,18 @@
66
@buffer = nil
77
end
88

9-
context "with a buffer created with .new" do
10-
it "is false for an internal buffer" do
11-
@buffer = IO::Buffer.new(4)
12-
@buffer.external?.should be_false
13-
end
14-
15-
it "is false for a mapped buffer" do
16-
@buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
17-
@buffer.external?.should be_false
18-
end
19-
end
20-
21-
context "with a file-backed buffer created with .map" do
22-
it "is true for a regular mapping" do
23-
File.open(__FILE__, "r") do |file|
24-
@buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
25-
@buffer.external?.should be_true
26-
end
27-
end
28-
29-
ruby_version_is "3.3" do
30-
it "is false for a private mapping" do
31-
File.open(__FILE__, "r") do |file|
32-
@buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY | IO::Buffer::PRIVATE)
33-
@buffer.external?.should be_false
34-
end
35-
end
36-
end
37-
end
38-
39-
context "with a String-backed buffer created with .for" do
40-
it "is true for a buffer created without a block" do
41-
@buffer = IO::Buffer.for("test")
42-
@buffer.external?.should be_true
43-
end
44-
45-
it "is true for a buffer created with a block" do
46-
IO::Buffer.for(+"test") do |buffer|
47-
buffer.external?.should be_true
48-
end
49-
end
9+
it "is true for a buffer with externally-managed memory" do
10+
@buffer = IO::Buffer.for("string")
11+
@buffer.external?.should be_true
5012
end
5113

52-
ruby_version_is "3.3" do
53-
context "with a String-backed buffer created with .string" do
54-
it "is true" do
55-
IO::Buffer.string(4) do |buffer|
56-
buffer.external?.should be_true
57-
end
58-
end
59-
end
14+
it "is false for a buffer with self-managed memory" do
15+
@buffer = IO::Buffer.new(12, IO::Buffer::MAPPED)
16+
@buffer.external?.should be_false
6017
end
6118

62-
# Always false for slices
63-
context "with a slice of a buffer" do
64-
context "created with .new" do
65-
it "is false when slicing an internal buffer" do
66-
@buffer = IO::Buffer.new(4)
67-
@buffer.slice.external?.should be_false
68-
end
69-
70-
it "is false when slicing a mapped buffer" do
71-
@buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
72-
@buffer.slice.external?.should be_false
73-
end
74-
end
75-
76-
context "created with .map" do
77-
it "is false" do
78-
File.open(__FILE__, "r") do |file|
79-
@buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
80-
@buffer.slice.external?.should be_false
81-
end
82-
end
83-
end
84-
85-
context "created with .for" do
86-
it "is false when slicing a buffer created without a block" do
87-
@buffer = IO::Buffer.for("test")
88-
@buffer.slice.external?.should be_false
89-
end
90-
91-
it "is false when slicing a buffer created with a block" do
92-
IO::Buffer.for(+"test") do |buffer|
93-
buffer.slice.external?.should be_false
94-
end
95-
end
96-
end
97-
98-
ruby_version_is "3.3" do
99-
context "created with .string" do
100-
it "is false" do
101-
IO::Buffer.string(4) do |buffer|
102-
buffer.slice.external?.should be_false
103-
end
104-
end
105-
end
106-
end
19+
it "is false for a null buffer" do
20+
@buffer = IO::Buffer.new(0)
21+
@buffer.external?.should be_false
10722
end
10823
end

core/io/buffer/for_spec.rb

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
require_relative '../../../spec_helper'
2+
3+
describe "IO::Buffer.for" do
4+
before :each do
5+
@string = +"för striñg"
6+
end
7+
8+
after :each do
9+
@buffer&.free
10+
@buffer = nil
11+
end
12+
13+
context "without a block" do
14+
it "copies string's contents, creating a separate read-only buffer" do
15+
@buffer = IO::Buffer.for(@string)
16+
17+
@buffer.size.should == @string.bytesize
18+
@buffer.get_string.should == @string.b
19+
20+
@string[0] = "d"
21+
@buffer.get_string(0, 1).should == "f".b
22+
23+
-> { @buffer.set_string("d") }.should raise_error(IO::Buffer::AccessError, "Buffer is not writable!")
24+
end
25+
26+
ruby_version_is ""..."3.3" do
27+
it "creates an external, read-only buffer" do
28+
@buffer = IO::Buffer.for(@string)
29+
30+
@buffer.should_not.internal?
31+
@buffer.should_not.mapped?
32+
@buffer.should.external?
33+
34+
@buffer.should_not.empty?
35+
@buffer.should_not.null?
36+
37+
@buffer.should_not.shared?
38+
@buffer.should.readonly?
39+
40+
@buffer.should_not.locked?
41+
@buffer.should.valid?
42+
end
43+
end
44+
45+
ruby_version_is "3.3" do
46+
it "creates an external, read-only buffer" do
47+
@buffer = IO::Buffer.for(@string)
48+
49+
@buffer.should_not.internal?
50+
@buffer.should_not.mapped?
51+
@buffer.should.external?
52+
53+
@buffer.should_not.empty?
54+
@buffer.should_not.null?
55+
56+
@buffer.should_not.shared?
57+
@buffer.should_not.private?
58+
@buffer.should.readonly?
59+
60+
@buffer.should_not.locked?
61+
@buffer.should.valid?
62+
end
63+
end
64+
end
65+
66+
context "with a block" do
67+
it "returns the last value in the block" do
68+
value =
69+
IO::Buffer.for(@string) do |buffer|
70+
buffer.size * 3
71+
end
72+
value.should == @string.bytesize * 3
73+
end
74+
75+
it "frees the buffer at the end of the block" do
76+
IO::Buffer.for(@string) do |buffer|
77+
@buffer = buffer
78+
@buffer.should_not.null?
79+
end
80+
@buffer.should.null?
81+
end
82+
83+
context "if string is not frozen" do
84+
it "creates a modifiable string-backed buffer" do
85+
IO::Buffer.for(@string) do |buffer|
86+
buffer.size.should == @string.bytesize
87+
buffer.get_string.should == @string.b
88+
89+
buffer.should_not.readonly?
90+
91+
buffer.set_string("ghost shell")
92+
@string.should == "ghost shellg"
93+
end
94+
end
95+
96+
it "locks the original string to prevent modification" do
97+
IO::Buffer.for(@string) do |_buffer|
98+
-> { @string[0] = "t" }.should raise_error(RuntimeError, "can't modify string; temporarily locked")
99+
end
100+
@string[1] = "u"
101+
@string.should == "fur striñg"
102+
end
103+
end
104+
105+
context "if string is frozen" do
106+
it "creates a read-only string-backed buffer" do
107+
IO::Buffer.for(@string.freeze) do |buffer|
108+
buffer.should.readonly?
109+
110+
-> { buffer.set_string("ghost shell") }.should raise_error(IO::Buffer::AccessError, "Buffer is not writable!")
111+
end
112+
end
113+
end
114+
end
115+
end

core/io/buffer/initialize_spec.rb

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,42 +12,62 @@
1212
@buffer.each(:U8).should.all? { |_offset, value| value.eql?(0) }
1313
end
1414

15-
it "creates a buffer with default state" do
16-
@buffer = IO::Buffer.new
17-
@buffer.should_not.shared?
18-
@buffer.should_not.readonly?
15+
ruby_version_is ""..."3.3" do
16+
it "creates a buffer with default state" do
17+
@buffer = IO::Buffer.new
18+
19+
@buffer.should_not.shared?
20+
@buffer.should_not.readonly?
21+
22+
@buffer.should_not.empty?
23+
@buffer.should_not.null?
24+
25+
@buffer.should_not.locked?
26+
@buffer.should.valid?
27+
end
28+
end
29+
30+
ruby_version_is "3.3" do
31+
it "creates a buffer with default state" do
32+
@buffer = IO::Buffer.new
1933

20-
@buffer.should_not.empty?
21-
@buffer.should_not.null?
34+
@buffer.should_not.external?
2235

23-
# This is run-time state, set by #locked.
24-
@buffer.should_not.locked?
36+
@buffer.should_not.shared?
37+
@buffer.should_not.private?
38+
@buffer.should_not.readonly?
39+
40+
@buffer.should_not.empty?
41+
@buffer.should_not.null?
42+
43+
@buffer.should_not.locked?
44+
@buffer.should.valid?
45+
end
2546
end
2647

2748
context "with size argument" do
2849
it "creates a new internal buffer if size is less than IO::Buffer::PAGE_SIZE" do
2950
size = IO::Buffer::PAGE_SIZE - 1
3051
@buffer = IO::Buffer.new(size)
3152
@buffer.size.should == size
53+
@buffer.should_not.empty?
54+
3255
@buffer.should.internal?
3356
@buffer.should_not.mapped?
34-
@buffer.should_not.empty?
3557
end
3658

3759
it "creates a new mapped buffer if size is greater than or equal to IO::Buffer::PAGE_SIZE" do
3860
size = IO::Buffer::PAGE_SIZE
3961
@buffer = IO::Buffer.new(size)
4062
@buffer.size.should == size
63+
@buffer.should_not.empty?
64+
4165
@buffer.should_not.internal?
4266
@buffer.should.mapped?
43-
@buffer.should_not.empty?
4467
end
4568

4669
it "creates a null buffer if size is 0" do
4770
@buffer = IO::Buffer.new(0)
48-
@buffer.size.should.zero?
49-
@buffer.should_not.internal?
50-
@buffer.should_not.mapped?
5171
@buffer.should.null?
5272
@buffer.should.empty?
5373
end
@@ -77,6 +97,29 @@
7797
@buffer.should_not.empty?
7898
end
7999

100+
it "allows extra flags" do
101+
@buffer = IO::Buffer.new(10, IO::Buffer::INTERNAL | IO::Buffer::SHARED | IO::Buffer::READONLY)
102+
@buffer.should.internal?
103+
@buffer.should.shared?
104+
@buffer.should.readonly?
105+
end
106+
107+
it "ignores flags if size is 0" do
108+
@buffer = IO::Buffer.new(0, 0xffff)
109+
@buffer.should.null?
110+
@buffer.should.empty?
111+
112+
@buffer.should_not.internal?
113+
@buffer.should_not.mapped?
114+
@buffer.should_not.external?
115+
116+
@buffer.should_not.shared?
117+
@buffer.should_not.readonly?
118+
119+
@buffer.should_not.locked?
120+
@buffer.should.valid?
121+
end
122+
80123
it "raises IO::Buffer::AllocationError if neither IO::Buffer::MAPPED nor IO::Buffer::INTERNAL is given" do
81124
-> { IO::Buffer.new(10, IO::Buffer::READONLY) }.should raise_error(IO::Buffer::AllocationError, "Could not allocate buffer!")
82125
-> { IO::Buffer.new(10, 0) }.should raise_error(IO::Buffer::AllocationError, "Could not allocate buffer!")

0 commit comments

Comments
 (0)