diff options
author | eregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-09-20 20:18:52 +0000 |
---|---|---|
committer | eregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-09-20 20:18:52 +0000 |
commit | 1d15d5f08032acf1b7bceacbb450d617ff6e0931 (patch) | |
tree | a3785a79899302bc149e4a6e72f624ac27dc1f10 /spec/ruby/core/objectspace/define_finalizer_spec.rb | |
parent | 75bfc6440d595bf339007f4fb280fd4d743e89c1 (diff) | |
download | ruby-1d15d5f08032acf1b7bceacbb450d617ff6e0931.tar.gz |
Move spec/rubyspec to spec/ruby for consistency
* Other ruby implementations use the spec/ruby directory.
[Misc #13792] [ruby-core:82287]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/ruby/core/objectspace/define_finalizer_spec.rb')
-rw-r--r-- | spec/ruby/core/objectspace/define_finalizer_spec.rb | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/spec/ruby/core/objectspace/define_finalizer_spec.rb b/spec/ruby/core/objectspace/define_finalizer_spec.rb new file mode 100644 index 0000000000..969e8b16b0 --- /dev/null +++ b/spec/ruby/core/objectspace/define_finalizer_spec.rb @@ -0,0 +1,101 @@ +require File.expand_path('../../../spec_helper', __FILE__) +require File.expand_path('../fixtures/classes', __FILE__) + +# NOTE: A call to define_finalizer does not guarantee that the +# passed proc or callable will be called at any particular time. +# It is highly questionable whether these aspects of ObjectSpace +# should be spec'd at all. +describe "ObjectSpace.define_finalizer" do + it "raises an ArgumentError if the action does not respond to call" do + lambda { + ObjectSpace.define_finalizer("", mock("ObjectSpace.define_finalizer no #call")) + }.should raise_error(ArgumentError) + end + + it "accepts an object and a proc" do + handler = lambda { |obj| obj } + ObjectSpace.define_finalizer("garbage", handler).should == [0, handler] + end + + it "accepts an object and a callable" do + handler = mock("callable") + def handler.call(obj) end + ObjectSpace.define_finalizer("garbage", handler).should == [0, handler] + end + + it "raises ArgumentError trying to define a finalizer on a non-reference" do + lambda { + ObjectSpace.define_finalizer(:blah) { 1 } + }.should raise_error(ArgumentError) + end + + # see [ruby-core:24095] + with_feature :fork do + it "calls finalizer on process termination" do + rd, wr = IO.pipe + pid = Process.fork do + rd.close + handler = ObjectSpaceFixtures.scoped(wr) + obj = "Test" + ObjectSpace.define_finalizer(obj, handler) + exit 0 + end + + wr.close + begin + rd.read.should == "finalized" + ensure + rd.close + Process.wait pid + end + end + + it "calls finalizer at exit even if it is self-referencing" do + rd, wr = IO.pipe + pid = Process.fork do + rd.close + obj = "Test" + handler = Proc.new { wr.write "finalized"; wr.close } + ObjectSpace.define_finalizer(obj, handler) + exit 0 + end + + wr.close + begin + rd.read.should == "finalized" + ensure + rd.close + Process.wait pid + end + end + + # These specs are defined under the fork specs because there is no + # deterministic way to force finalizers to be run, except process exit, so + # we rely on that. + it "allows multiple finalizers with different 'callables' to be defined" do + rd1, wr1 = IO.pipe + rd2, wr2 = IO.pipe + + pid = Kernel::fork do + rd1.close + rd2.close + obj = mock("ObjectSpace.define_finalizer multiple") + + ObjectSpace.define_finalizer(obj, Proc.new { wr1.write "finalized1"; wr1.close }) + ObjectSpace.define_finalizer(obj, Proc.new { wr2.write "finalized2"; wr2.close }) + + exit 0 + end + + wr1.close + wr2.close + + rd1.read.should == "finalized1" + rd2.read.should == "finalized2" + + rd1.close + rd2.close + Process.wait pid + end + end +end |