-
-
Notifications
You must be signed in to change notification settings - Fork 395
Add initial specs for IO::Buffer #1297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
43635eb
a18d885
b8f5b80
b027cd1
ec3d184
001bdd5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| require_relative '../../../spec_helper' | ||
|
|
||
| describe "IO::Buffer#free" do | ||
| context "with a buffer created with .new" do | ||
| it "frees internal memory and nullifies the buffer" do | ||
| buffer = IO::Buffer.new(4) | ||
| buffer.free | ||
| buffer.null?.should be_true | ||
| end | ||
|
|
||
| it "frees mapped memory and nullifies the buffer" do | ||
| buffer = IO::Buffer.new(4, IO::Buffer::MAPPED) | ||
| buffer.free | ||
| buffer.null?.should be_true | ||
| end | ||
| end | ||
|
|
||
| context "with a file-backed buffer created with .map" do | ||
| it "frees mapped memory and nullifies the buffer" do | ||
| File.open(__FILE__, "r") do |file| | ||
| buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY) | ||
| buffer.free | ||
| buffer.null?.should be_true | ||
| end | ||
| end | ||
| end | ||
|
|
||
| context "with a String-backed buffer created with .for" do | ||
| context "without a block" do | ||
| it "disassociates the buffer from the string and nullifies the buffer" do | ||
| string = +"test" | ||
| buffer = IO::Buffer.for(string) | ||
| # Read-only buffer, can't modify the string. | ||
| buffer.free | ||
| buffer.null?.should be_true | ||
| end | ||
| end | ||
|
|
||
| context "with a block" do | ||
| it "disassociates the buffer from the string and nullifies the buffer" do | ||
| string = +"test" | ||
| IO::Buffer.for(string) do |buffer| | ||
| buffer.set_string("meat") | ||
| buffer.free | ||
| buffer.null?.should be_true | ||
| end | ||
| string.should == "meat" | ||
| end | ||
| end | ||
| end | ||
|
|
||
| ruby_version_is "3.3" do | ||
| context "with a String-backed buffer created with .string" do | ||
| it "disassociates the buffer from the string and nullifies the buffer" do | ||
| string = | ||
| IO::Buffer.string(4) do |buffer| | ||
| buffer.set_string("meat") | ||
| buffer.free | ||
| buffer.null?.should be_true | ||
| end | ||
| string.should == "meat" | ||
| end | ||
| end | ||
| end | ||
|
|
||
| it "can be called repeatedly without an error" do | ||
| buffer = IO::Buffer.new(4) | ||
| buffer.free | ||
| buffer.null?.should be_true | ||
| buffer.free | ||
| buffer.null?.should be_true | ||
| end | ||
|
|
||
| it "is disallowed while locked, raising IO::Buffer::LockedError" do | ||
| buffer = IO::Buffer.new(4) | ||
| buffer.locked do | ||
| -> { buffer.free }.should raise_error(IO::Buffer::LockedError, "Buffer is locked!") | ||
| end | ||
| buffer.free | ||
| buffer.null?.should be_true | ||
| end | ||
|
|
||
| context "with a slice of a buffer" do | ||
| it "nullifies the slice, not touching the buffer" do | ||
| buffer = IO::Buffer.new(4) | ||
| slice = buffer.slice(0, 2) | ||
|
|
||
| buffer.set_string("test") | ||
| slice.set_string("ea") | ||
| slice.free | ||
| slice.null?.should be_true | ||
| buffer.null?.should be_false | ||
| buffer.get_string.should == "east" | ||
|
|
||
| buffer.free | ||
| end | ||
|
|
||
| it "nullifies buffer, invalidating the slice" do | ||
| buffer = IO::Buffer.new(4) | ||
| slice = buffer.slice(0, 2) | ||
| buffer.free | ||
|
|
||
| slice.null?.should be_false | ||
| slice.valid?.should be_false | ||
| -> { slice.get_string }.should raise_error(IO::Buffer::InvalidatedError, "Buffer has been invalidated!") | ||
| end | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor: seems is duplicated in specs for |
||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,17 +13,13 @@ | |
| end | ||
| end | ||
|
|
||
| it "disallows freeing while locked, raising IO::Buffer::LockedError" do | ||
| it "disallows operations changing buffer itself, raising IO::Buffer::LockedError" do | ||
| @buffer = IO::Buffer.new(4) | ||
| @buffer.locked do | ||
| -> { @buffer.free }.should raise_error(IO::Buffer::LockedError, "Buffer is locked!") | ||
| end | ||
| end | ||
|
|
||
| it "disallows resizing while locked, raising IO::Buffer::LockedError" do | ||
| @buffer = IO::Buffer.new(4) | ||
| @buffer.locked do | ||
| -> { @buffer.resize(8) }.should raise_error(IO::Buffer::LockedError, "Cannot resize locked buffer!") | ||
| # See specs of individual methods for error messages. | ||
| -> { @buffer.free }.should raise_error(IO::Buffer::LockedError) | ||
| -> { @buffer.resize(8) }.should raise_error(IO::Buffer::LockedError) | ||
| -> { @buffer.transfer }.should raise_error(IO::Buffer::LockedError) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: it makes sense to specify exception messages everywhere
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor: I suppose other operations changing a buffer should be mentioned here as well (e.g. set_string or write). |
||
| end | ||
| end | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| require_relative '../../../spec_helper' | ||
|
|
||
| describe "IO::Buffer#resize" do | ||
| after :each do | ||
| @buffer&.free | ||
| @buffer = nil | ||
| end | ||
|
|
||
| context "with a buffer created with .new" do | ||
| it "resizes internal buffer, preserving type" do | ||
| @buffer = IO::Buffer.new(4) | ||
| @buffer.resize(IO::Buffer::PAGE_SIZE) | ||
| @buffer.size.should == IO::Buffer::PAGE_SIZE | ||
| @buffer.internal?.should be_true | ||
| @buffer.mapped?.should be_false | ||
| end | ||
|
|
||
| platform_is :linux do | ||
| it "resizes mapped buffer, preserving type" do | ||
| @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::MAPPED) | ||
| @buffer.resize(4) | ||
| @buffer.size.should == 4 | ||
| @buffer.internal?.should be_false | ||
| @buffer.mapped?.should be_true | ||
| end | ||
| end | ||
|
|
||
| platform_is_not :linux do | ||
| it "resizes mapped buffer, changing type to internal" do | ||
| @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::MAPPED) | ||
| @buffer.resize(4) | ||
| @buffer.size.should == 4 | ||
| @buffer.internal?.should be_true | ||
| @buffer.mapped?.should be_false | ||
| end | ||
| end | ||
| end | ||
|
|
||
| context "with a file-backed buffer created with .map" do | ||
| it "disallows resizing shared buffer, raising IO::Buffer::AccessError" do | ||
| File.open(__FILE__, "r+") do |file| | ||
| @buffer = IO::Buffer.map(file) | ||
| -> { @buffer.resize(10) }.should raise_error(IO::Buffer::AccessError, "Cannot resize external buffer!") | ||
| end | ||
| end | ||
|
|
||
| ruby_version_is "3.3" do | ||
| it "resizes private buffer, discarding excess contents" do | ||
| File.open(__FILE__, "r") do |file| | ||
| @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE) | ||
| @buffer.resize(10) | ||
| @buffer.size.should == 10 | ||
| @buffer.get_string.should == "require_re" | ||
| @buffer.resize(12) | ||
| @buffer.size.should == 12 | ||
| @buffer.get_string.should == "require_re\0\0" | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
| context "with a String-backed buffer created with .for" do | ||
| context "without a block" do | ||
| it "disallows resizing, raising IO::Buffer::AccessError" do | ||
| @buffer = IO::Buffer.for(+"test") | ||
| -> { @buffer.resize(10) }.should raise_error(IO::Buffer::AccessError, "Cannot resize external buffer!") | ||
| end | ||
| end | ||
|
|
||
| context "with a block" do | ||
| it "disallows resizing, raising IO::Buffer::AccessError" do | ||
| IO::Buffer.for(+'test') do |buffer| | ||
| -> { buffer.resize(10) }.should raise_error(IO::Buffer::AccessError, "Cannot resize external buffer!") | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
| ruby_version_is "3.3" do | ||
| context "with a String-backed buffer created with .string" do | ||
| it "disallows resizing, raising IO::Buffer::AccessError" do | ||
| IO::Buffer.string(4) do |buffer| | ||
| -> { buffer.resize(10) }.should raise_error(IO::Buffer::AccessError, "Cannot resize external buffer!") | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
| context "with a null buffer" do | ||
| it "allows resizing a 0-sized buffer, creating a regular buffer according to new size" do | ||
| @buffer = IO::Buffer.new(0) | ||
| @buffer.resize(IO::Buffer::PAGE_SIZE) | ||
| @buffer.size.should == IO::Buffer::PAGE_SIZE | ||
| @buffer.internal?.should be_false | ||
| @buffer.mapped?.should be_true | ||
| end | ||
|
|
||
| it "allows resizing after a free, creating a regular buffer according to new size" do | ||
| @buffer = IO::Buffer.for("test") | ||
| @buffer.free | ||
| @buffer.resize(10) | ||
| @buffer.size.should == 10 | ||
| @buffer.internal?.should be_true | ||
| @buffer.mapped?.should be_false | ||
| end | ||
| end | ||
|
|
||
| it "allows resizing to 0, freeing memory" do | ||
| @buffer = IO::Buffer.new(4) | ||
| @buffer.resize(0) | ||
| @buffer.null?.should be_true | ||
| end | ||
|
|
||
| it "can be called repeatedly" do | ||
| @buffer = IO::Buffer.new(4) | ||
| @buffer.resize(10) | ||
| @buffer.resize(27) | ||
| @buffer.resize(1) | ||
| @buffer.size.should == 1 | ||
| end | ||
|
|
||
| it "always clears extra memory" do | ||
| @buffer = IO::Buffer.new(4) | ||
| @buffer.set_string("test") | ||
| # This should not cause a re-allocation, just a technical resizing, | ||
| # even with very aggressive memory allocation. | ||
| @buffer.resize(2) | ||
| @buffer.resize(4) | ||
| @buffer.get_string.should == "te\0\0" | ||
| end | ||
|
|
||
| it "is disallowed while locked, raising IO::Buffer::LockedError" do | ||
| @buffer = IO::Buffer.new(4) | ||
| @buffer.locked do | ||
| -> { @buffer.resize(10) }.should raise_error(IO::Buffer::LockedError, "Cannot resize locked buffer!") | ||
| end | ||
| end | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. minor: seems a duplicate |
||
|
|
||
| it "raises ArgumentError if size is negative" do | ||
| @buffer = IO::Buffer.new(4) | ||
| -> { @buffer.resize(-1) }.should raise_error(ArgumentError, "Size can't be negative!") | ||
| end | ||
|
|
||
| it "raises TypeError if size is not an Integer" do | ||
| @buffer = IO::Buffer.new(4) | ||
| -> { @buffer.resize(nil) }.should raise_error(TypeError, "not an Integer") | ||
| -> { @buffer.resize(10.0) }.should raise_error(TypeError, "not an Integer") | ||
| end | ||
|
|
||
| context "with a slice of a buffer" do | ||
| # Current behavior of slice resizing seems unintended (it's undocumented, too). | ||
| # It either creates a completely new buffer, or breaks the slice on size 0. | ||
| it "needs to be reviewed for spec completeness" | ||
| end | ||
| end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: seems it's duplicated in specs for
#locked?.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and other dupes: I thought it would be better to over-spec than to select which file these interactions shoud be in 😅 I guess it would make sense to remove them from
#locked, as it's really a property of individual methods (like this https://github.com/ruby/ruby/blob/master/io_buffer.c#L1485)?