summaryrefslogtreecommitdiff
path: root/spec/ruby/core/objectspace
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/objectspace')
-rw-r--r--spec/ruby/core/objectspace/_id2ref_spec.rb87
-rw-r--r--spec/ruby/core/objectspace/add_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/call_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/define_finalizer_spec.rb83
-rw-r--r--spec/ruby/core/objectspace/each_object_spec.rb46
-rw-r--r--spec/ruby/core/objectspace/finalizers_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/garbage_collect_spec.rb4
-rw-r--r--spec/ruby/core/objectspace/remove_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/undefine_finalizer_spec.rb30
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/clear_spec.rb25
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/delete_spec.rb71
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb123
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb101
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb5
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb32
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb28
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/key_spec.rb61
-rw-r--r--spec/ruby/core/objectspace/weakmap/delete_spec.rb42
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/each.rb2
19 files changed, 477 insertions, 283 deletions
diff --git a/spec/ruby/core/objectspace/_id2ref_spec.rb b/spec/ruby/core/objectspace/_id2ref_spec.rb
index c088ae2743..a9fd526b7d 100644
--- a/spec/ruby/core/objectspace/_id2ref_spec.rb
+++ b/spec/ruby/core/objectspace/_id2ref_spec.rb
@@ -1,52 +1,65 @@
require_relative '../../spec_helper'
-describe "ObjectSpace._id2ref" do
- it "converts an object id to a reference to the object" do
- s = "I am a string"
- r = ObjectSpace._id2ref(s.object_id)
- r.should == s
+ruby_version_is "4.0" do
+ describe "ObjectSpace._id2ref" do
+ it "is deprecated" do
+ id = nil.object_id
+ -> {
+ ObjectSpace._id2ref(id)
+ }.should complain(/warning: ObjectSpace\._id2ref is deprecated/)
+ end
end
+end
- it "retrieves true by object_id" do
- ObjectSpace._id2ref(true.object_id).should == true
- end
+ruby_version_is ""..."4.0" do
+ describe "ObjectSpace._id2ref" do
+ it "converts an object id to a reference to the object" do
+ s = "I am a string"
+ r = ObjectSpace._id2ref(s.object_id)
+ r.should == s
+ end
- it "retrieves false by object_id" do
- ObjectSpace._id2ref(false.object_id).should == false
- end
+ it "retrieves true by object_id" do
+ ObjectSpace._id2ref(true.object_id).should == true
+ end
- it "retrieves nil by object_id" do
- ObjectSpace._id2ref(nil.object_id).should == nil
- end
+ it "retrieves false by object_id" do
+ ObjectSpace._id2ref(false.object_id).should == false
+ end
- it "retrieves a small Integer by object_id" do
- ObjectSpace._id2ref(1.object_id).should == 1
- ObjectSpace._id2ref((-42).object_id).should == -42
- end
+ it "retrieves nil by object_id" do
+ ObjectSpace._id2ref(nil.object_id).should == nil
+ end
- it "retrieves a large Integer by object_id" do
- obj = 1 << 88
- ObjectSpace._id2ref(obj.object_id).should.equal?(obj)
- end
+ it "retrieves a small Integer by object_id" do
+ ObjectSpace._id2ref(1.object_id).should == 1
+ ObjectSpace._id2ref((-42).object_id).should == -42
+ end
- it "retrieves a Symbol by object_id" do
- ObjectSpace._id2ref(:sym.object_id).should.equal?(:sym)
- end
+ it "retrieves a large Integer by object_id" do
+ obj = 1 << 88
+ ObjectSpace._id2ref(obj.object_id).should.equal?(obj)
+ end
- it "retrieves a String by object_id" do
- obj = "str"
- ObjectSpace._id2ref(obj.object_id).should.equal?(obj)
- end
+ it "retrieves a Symbol by object_id" do
+ ObjectSpace._id2ref(:sym.object_id).should.equal?(:sym)
+ end
- it "retrieves a frozen literal String by object_id" do
- ObjectSpace._id2ref("frozen string literal _id2ref".freeze.object_id).should.equal?("frozen string literal _id2ref".freeze)
- end
+ it "retrieves a String by object_id" do
+ obj = "str"
+ ObjectSpace._id2ref(obj.object_id).should.equal?(obj)
+ end
- it "retrieves an Encoding by object_id" do
- ObjectSpace._id2ref(Encoding::UTF_8.object_id).should.equal?(Encoding::UTF_8)
- end
+ it "retrieves a frozen literal String by object_id" do
+ ObjectSpace._id2ref("frozen string literal _id2ref".freeze.object_id).should.equal?("frozen string literal _id2ref".freeze)
+ end
+
+ it "retrieves an Encoding by object_id" do
+ ObjectSpace._id2ref(Encoding::UTF_8.object_id).should.equal?(Encoding::UTF_8)
+ end
- it 'raises RangeError when an object could not be found' do
- proc { ObjectSpace._id2ref(1 << 60) }.should raise_error(RangeError)
+ it 'raises RangeError when an object could not be found' do
+ proc { ObjectSpace._id2ref(1 << 60) }.should.raise(RangeError)
+ end
end
end
diff --git a/spec/ruby/core/objectspace/add_finalizer_spec.rb b/spec/ruby/core/objectspace/add_finalizer_spec.rb
deleted file mode 100644
index 3540ac0413..0000000000
--- a/spec/ruby/core/objectspace/add_finalizer_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.add_finalizer" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/call_finalizer_spec.rb b/spec/ruby/core/objectspace/call_finalizer_spec.rb
deleted file mode 100644
index 6dce92ddd6..0000000000
--- a/spec/ruby/core/objectspace/call_finalizer_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.call_finalizer" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/define_finalizer_spec.rb b/spec/ruby/core/objectspace/define_finalizer_spec.rb
index 6be83e518e..5441cb4a21 100644
--- a/spec/ruby/core/objectspace/define_finalizer_spec.rb
+++ b/spec/ruby/core/objectspace/define_finalizer_spec.rb
@@ -13,7 +13,7 @@ describe "ObjectSpace.define_finalizer" do
it "raises an ArgumentError if the action does not respond to call" do
-> {
ObjectSpace.define_finalizer(Object.new, mock("ObjectSpace.define_finalizer no #call"))
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
it "accepts an object and a proc" do
@@ -42,7 +42,7 @@ describe "ObjectSpace.define_finalizer" do
it "raises ArgumentError trying to define a finalizer on a non-reference" do
-> {
ObjectSpace.define_finalizer(:blah) { 1 }
- }.should raise_error(ArgumentError)
+ }.should.raise(ArgumentError)
end
# see [ruby-core:24095]
@@ -52,12 +52,12 @@ describe "ObjectSpace.define_finalizer" do
Proc.new { puts "finalizer run" }
end
handler = scoped
- obj = "Test"
+ obj = +"Test"
ObjectSpace.define_finalizer(obj, handler)
exit 0
RUBY
- ruby_exe(code, :args => "2>&1").should include("finalizer run\n")
+ ruby_exe(code, :args => "2>&1").should.include?("finalizer run\n")
end
it "warns if the finalizer has the object as the receiver" do
@@ -73,7 +73,7 @@ describe "ObjectSpace.define_finalizer" do
exit 0
RUBY
- ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n")
+ ruby_exe(code, :args => "2>&1").should.include?("warning: finalizer references object to be finalized\n")
end
it "warns if the finalizer is a method bound to the receiver" do
@@ -90,7 +90,7 @@ describe "ObjectSpace.define_finalizer" do
exit 0
RUBY
- ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n")
+ ruby_exe(code, :args => "2>&1").should.include?("warning: finalizer references object to be finalized\n")
end
it "warns if the finalizer was a block in the receiver" do
@@ -106,18 +106,18 @@ describe "ObjectSpace.define_finalizer" do
exit 0
RUBY
- ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n")
+ ruby_exe(code, :args => "2>&1").should.include?("warning: finalizer references object to be finalized\n")
end
it "calls a finalizer at exit even if it is self-referencing" do
code = <<-RUBY
- obj = "Test"
+ obj = +"Test"
handler = Proc.new { puts "finalizer run" }
ObjectSpace.define_finalizer(obj, handler)
exit 0
RUBY
- ruby_exe(code).should include("finalizer run\n")
+ ruby_exe(code).should.include?("finalizer run\n")
end
it "calls a finalizer at exit even if it is indirectly self-referencing" do
@@ -136,14 +136,14 @@ describe "ObjectSpace.define_finalizer" do
exit 0
RUBY
- ruby_exe(code, :args => "2>&1").should include("finalizer run\n")
+ ruby_exe(code, :args => "2>&1").should.include?("finalizer run\n")
end
it "calls a finalizer defined in a finalizer running at exit" do
code = <<-RUBY
- obj = "Test"
+ obj = +"Test"
handler = Proc.new do
- obj2 = "Test"
+ obj2 = +"Test"
handler2 = Proc.new { puts "finalizer 2 run" }
ObjectSpace.define_finalizer(obj2, handler2)
exit 0
@@ -152,11 +152,11 @@ describe "ObjectSpace.define_finalizer" do
exit 0
RUBY
- ruby_exe(code, :args => "2>&1").should include("finalizer 2 run\n")
+ ruby_exe(code, :args => "2>&1").should.include?("finalizer 2 run\n")
end
it "allows multiple finalizers with different 'callables' to be defined" do
- code = <<-RUBY
+ code = <<-'RUBY'
obj = Object.new
ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized1\n" })
@@ -168,25 +168,50 @@ describe "ObjectSpace.define_finalizer" do
ruby_exe(code).lines.sort.should == ["finalized1\n", "finalized2\n"]
end
- ruby_version_is "3.1" do
- describe "when $VERBOSE is not nil" do
- it "warns if an exception is raised in finalizer" do
- code = <<-RUBY
- ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
- RUBY
+ it "defines same finalizer only once" do
+ code = <<~RUBY
+ obj = Object.new
+ p = proc { |id| print "ok" }
+ ObjectSpace.define_finalizer(obj, p.dup)
+ ObjectSpace.define_finalizer(obj, p.dup)
+ RUBY
- ruby_exe(code, args: "2>&1").should include("warning: Exception in finalizer", "finalizing")
- end
+ ruby_exe(code).should == "ok"
+ end
+
+ it "returns the defined finalizer" do
+ obj = Object.new
+ p = proc { |id| }
+ p2 = p.dup
+
+ ret = ObjectSpace.define_finalizer(obj, p)
+ ret.should == [0, p]
+ ret[1].should.equal?(p)
+
+ ret = ObjectSpace.define_finalizer(obj, p2)
+ ret.should == [0, p]
+ ret[1].should.equal?(p)
+ end
+
+ describe "when $VERBOSE is not nil" do
+ it "warns if an exception is raised in finalizer" do
+ code = <<-RUBY
+ ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
+ RUBY
+
+ out = ruby_exe(code, args: "2>&1")
+ out.should.include?("warning: Exception in finalizer")
+ out.should.include?("finalizing")
end
+ end
- describe "when $VERBOSE is nil" do
- it "does not warn even if an exception is raised in finalizer" do
- code = <<-RUBY
- ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
- RUBY
+ describe "when $VERBOSE is nil" do
+ it "does not warn even if an exception is raised in finalizer" do
+ code = <<-RUBY
+ ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
+ RUBY
- ruby_exe(code, args: "2>&1", options: "-W0").should == ""
- end
+ ruby_exe(code, args: "2>&1", options: "-W0").should == ""
end
end
end
diff --git a/spec/ruby/core/objectspace/each_object_spec.rb b/spec/ruby/core/objectspace/each_object_spec.rb
index 09a582afaf..aee0fd629c 100644
--- a/spec/ruby/core/objectspace/each_object_spec.rb
+++ b/spec/ruby/core/objectspace/each_object_spec.rb
@@ -39,7 +39,7 @@ describe "ObjectSpace.each_object" do
new_obj = klass.new
counter = ObjectSpace.each_object(klass)
- counter.should be_an_instance_of(Enumerator)
+ counter.should.instance_of?(Enumerator)
counter.each{}.should == 1
# this is needed to prevent the new_obj from being GC'd too early
new_obj.should_not == nil
@@ -47,20 +47,20 @@ describe "ObjectSpace.each_object" do
it "finds an object stored in a global variable" do
$object_space_global_variable = ObjectSpaceFixtures::ObjectToBeFound.new(:global)
- ObjectSpaceFixtures.to_be_found_symbols.should include(:global)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:global)
end
it "finds an object stored in a top-level constant" do
- ObjectSpaceFixtures.to_be_found_symbols.should include(:top_level_constant)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:top_level_constant)
end
it "finds an object stored in a second-level constant" do
- ObjectSpaceFixtures.to_be_found_symbols.should include(:second_level_constant)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:second_level_constant)
end
it "finds an object stored in a local variable" do
local = ObjectSpaceFixtures::ObjectToBeFound.new(:local)
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local)
end
it "finds an object stored in a local variable captured in a block explicitly" do
@@ -69,7 +69,7 @@ describe "ObjectSpace.each_object" do
Proc.new { local_in_block }
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_block_explicit)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local_in_block_explicit)
end
it "finds an object stored in a local variable captured in a block implicitly" do
@@ -78,11 +78,11 @@ describe "ObjectSpace.each_object" do
Proc.new { }
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_block_implicit)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local_in_block_implicit)
end
it "finds an object stored in a local variable captured in by a method defined with a block" do
- ObjectSpaceFixtures.to_be_found_symbols.should include(:captured_by_define_method)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:captured_by_define_method)
end
it "finds an object stored in a local variable captured in a Proc#binding" do
@@ -91,7 +91,7 @@ describe "ObjectSpace.each_object" do
Proc.new { }.binding
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_proc_binding)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local_in_proc_binding)
end
it "finds an object stored in a local variable captured in a Kernel#binding" do
@@ -100,45 +100,45 @@ describe "ObjectSpace.each_object" do
binding
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_kernel_binding)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local_in_kernel_binding)
end
it "finds an object stored in a local variable set in a binding manually" do
b = binding
b.eval("local = ObjectSpaceFixtures::ObjectToBeFound.new(:local_in_manual_binding)")
- ObjectSpaceFixtures.to_be_found_symbols.should include(:local_in_manual_binding)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:local_in_manual_binding)
end
it "finds an object stored in an array" do
array = [ObjectSpaceFixtures::ObjectToBeFound.new(:array)]
- ObjectSpaceFixtures.to_be_found_symbols.should include(:array)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:array)
end
it "finds an object stored in a hash key" do
hash = {ObjectSpaceFixtures::ObjectToBeFound.new(:hash_key) => :value}
- ObjectSpaceFixtures.to_be_found_symbols.should include(:hash_key)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:hash_key)
end
it "finds an object stored in a hash value" do
hash = {a: ObjectSpaceFixtures::ObjectToBeFound.new(:hash_value)}
- ObjectSpaceFixtures.to_be_found_symbols.should include(:hash_value)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:hash_value)
end
it "finds an object stored in an instance variable" do
local = ObjectSpaceFixtures::ObjectWithInstanceVariable.new
- ObjectSpaceFixtures.to_be_found_symbols.should include(:instance_variable)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:instance_variable)
end
it "finds an object stored in a thread local" do
thread = Thread.new {}
thread.thread_variable_set(:object_space_thread_local, ObjectSpaceFixtures::ObjectToBeFound.new(:thread_local))
- ObjectSpaceFixtures.to_be_found_symbols.should include(:thread_local)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:thread_local)
thread.join
end
it "finds an object stored in a fiber local" do
Thread.current[:object_space_fiber_local] = ObjectSpaceFixtures::ObjectToBeFound.new(:fiber_local)
- ObjectSpaceFixtures.to_be_found_symbols.should include(:fiber_local)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:fiber_local)
end
it "finds an object captured in an at_exit handler" do
@@ -150,7 +150,7 @@ describe "ObjectSpace.each_object" do
end
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:at_exit)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:at_exit)
end
it "finds an object captured in finalizer" do
@@ -164,9 +164,9 @@ describe "ObjectSpace.each_object" do
})
}.call
- ObjectSpaceFixtures.to_be_found_symbols.should include(:finalizer)
+ ObjectSpaceFixtures.to_be_found_symbols.should.include?(:finalizer)
- alive.should_not be_nil
+ alive.should_not == nil
end
describe "on singleton classes" do
@@ -185,8 +185,8 @@ describe "ObjectSpace.each_object" do
end
it "walks singleton classes" do
- @sclass.should be_kind_of(@meta)
- ObjectSpace.each_object(@meta).to_a.should include(@sclass)
+ @sclass.should.is_a?(@meta)
+ ObjectSpace.each_object(@meta).to_a.should.include?(@sclass)
end
end
@@ -202,7 +202,7 @@ describe "ObjectSpace.each_object" do
expected = [ a, b, c, d ]
expected << c_sclass
- c_sclass.should be_kind_of(a.singleton_class)
+ c_sclass.should.is_a?(a.singleton_class)
b.extend Enumerable # included modules should not be walked
diff --git a/spec/ruby/core/objectspace/finalizers_spec.rb b/spec/ruby/core/objectspace/finalizers_spec.rb
deleted file mode 100644
index e7f20fc8a0..0000000000
--- a/spec/ruby/core/objectspace/finalizers_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.finalizers" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/garbage_collect_spec.rb b/spec/ruby/core/objectspace/garbage_collect_spec.rb
index 521eaa8785..d2db22e0aa 100644
--- a/spec/ruby/core/objectspace/garbage_collect_spec.rb
+++ b/spec/ruby/core/objectspace/garbage_collect_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "ObjectSpace.garbage_collect" do
it "can be invoked without any exceptions" do
- -> { ObjectSpace.garbage_collect }.should_not raise_error
+ -> { ObjectSpace.garbage_collect }.should_not.raise
end
it "accepts keyword arguments" do
@@ -11,7 +11,7 @@ describe "ObjectSpace.garbage_collect" do
end
it "ignores the supplied block" do
- -> { ObjectSpace.garbage_collect {} }.should_not raise_error
+ -> { ObjectSpace.garbage_collect {} }.should_not.raise
end
it "always returns nil" do
diff --git a/spec/ruby/core/objectspace/remove_finalizer_spec.rb b/spec/ruby/core/objectspace/remove_finalizer_spec.rb
deleted file mode 100644
index 0b2b8cf16b..0000000000
--- a/spec/ruby/core/objectspace/remove_finalizer_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.remove_finalizer" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/undefine_finalizer_spec.rb b/spec/ruby/core/objectspace/undefine_finalizer_spec.rb
index 11d43121f8..98ffc6a986 100644
--- a/spec/ruby/core/objectspace/undefine_finalizer_spec.rb
+++ b/spec/ruby/core/objectspace/undefine_finalizer_spec.rb
@@ -1,5 +1,33 @@
require_relative '../../spec_helper'
describe "ObjectSpace.undefine_finalizer" do
- it "needs to be reviewed for spec completeness"
+ it "removes finalizers for an object" do
+ code = <<~RUBY
+ obj = Object.new
+ ObjectSpace.define_finalizer(obj, proc { |id| puts "hello" })
+ ObjectSpace.undefine_finalizer(obj)
+ RUBY
+
+ ruby_exe(code).should.empty?
+ end
+
+ it "should not remove finalizers for a frozen object" do
+ code = <<~RUBY
+ obj = Object.new
+ ObjectSpace.define_finalizer(obj, proc { |id| print "ok" })
+ obj.freeze
+ begin
+ ObjectSpace.undefine_finalizer(obj)
+ rescue
+ end
+ RUBY
+
+ ruby_exe(code).should == "ok"
+ end
+
+ it "should raise when removing finalizers for a frozen object" do
+ obj = Object.new
+ obj.freeze
+ -> { ObjectSpace.undefine_finalizer(obj) }.should.raise(FrozenError)
+ end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/clear_spec.rb b/spec/ruby/core/objectspace/weakkeymap/clear_spec.rb
new file mode 100644
index 0000000000..b1804ec9b0
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/clear_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakKeyMap#clear" do
+ it "removes all the entries" do
+ m = ObjectSpace::WeakKeyMap.new
+
+ key = Object.new
+ value = Object.new
+ m[key] = value
+
+ key2 = Object.new
+ value2 = Object.new
+ m[key2] = value2
+
+ m.clear
+
+ m.key?(key).should == false
+ m.key?(key2).should == false
+ end
+
+ it "returns self" do
+ m = ObjectSpace::WeakKeyMap.new
+ m.clear.should.equal?(m)
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb b/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb
index 6e534b8ea8..ad32c2c75e 100644
--- a/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb
@@ -1,40 +1,49 @@
require_relative '../../../spec_helper'
-ruby_version_is '3.3' do
- describe "ObjectSpace::WeakKeyMap#delete" do
- it "removes the entry and returns the deleted value" do
- m = ObjectSpace::WeakKeyMap.new
- key = Object.new
- value = Object.new
- m[key] = value
-
- m.delete(key).should == value
- m.key?(key).should == false
- end
+describe "ObjectSpace::WeakKeyMap#delete" do
+ it "removes the entry and returns the deleted value" do
+ m = ObjectSpace::WeakKeyMap.new
+ key = Object.new
+ value = Object.new
+ m[key] = value
- it "uses equality semantic" do
- m = ObjectSpace::WeakKeyMap.new
- key = "foo".upcase
- value = Object.new
- m[key] = value
+ m.delete(key).should == value
+ m.key?(key).should == false
+ end
- m.delete("foo".upcase).should == value
- m.key?(key).should == false
- end
+ it "uses equality semantic" do
+ m = ObjectSpace::WeakKeyMap.new
+ key = "foo".upcase
+ value = Object.new
+ m[key] = value
- it "calls supplied block if the key is not found" do
- key = Object.new
- m = ObjectSpace::WeakKeyMap.new
- return_value = m.delete(key) do |yielded_key|
- yielded_key.should == key
- 5
- end
- return_value.should == 5
- end
+ m.delete("foo".upcase).should == value
+ m.key?(key).should == false
+ end
- it "returns nil if the key is not found when no block is given" do
- m = ObjectSpace::WeakMap.new
- m.delete(Object.new).should == nil
+ it "calls supplied block if the key is not found" do
+ key = Object.new
+ m = ObjectSpace::WeakKeyMap.new
+ return_value = m.delete(key) do |yielded_key|
+ yielded_key.should == key
+ 5
end
+ return_value.should == 5
+ end
+
+ it "returns nil if the key is not found when no block is given" do
+ m = ObjectSpace::WeakKeyMap.new
+ m.delete(Object.new).should == nil
+ end
+
+ it "returns nil when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map.delete(1).should == nil
+ map.delete(1.0).should == nil
+ map.delete(:a).should == nil
+ map.delete(true).should == nil
+ map.delete(false).should == nil
+ map.delete(nil).should == nil
end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb b/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb
index 862480cd02..53eff79c40 100644
--- a/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb
@@ -1,26 +1,105 @@
require_relative '../../../spec_helper'
+require_relative 'fixtures/classes'
-ruby_version_is "3.3" do
- describe "ObjectSpace::WeakKeyMap#[]" do
- it "is faithful to the map's content" do
- map = ObjectSpace::WeakKeyMap.new
- key1, key2 = %w[a b].map(&:upcase)
- ref1, ref2 = %w[x y]
- map[key1] = ref1
- map[key1].should == ref1
- map[key1] = ref1
- map[key1].should == ref1
- map[key2] = ref2
- map[key1].should == ref1
- map[key2].should == ref2
- end
-
- it "matches using equality semantics" do
- map = ObjectSpace::WeakKeyMap.new
- key1, key2 = %w[a a].map(&:upcase)
- ref = "x"
- map[key1] = ref
- map[key2].should == ref
- end
+describe "ObjectSpace::WeakKeyMap#[]" do
+ it "is faithful to the map's content" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
+ map[key1] = ref1
+ map[key1].should == ref1
+ map[key1] = ref1
+ map[key1].should == ref1
+ map[key2] = ref2
+ map[key1].should == ref1
+ map[key2].should == ref2
+ end
+
+ it "compares keys with #eql? semantics" do
+ map = ObjectSpace::WeakKeyMap.new
+ key = [1.0]
+ map[key] = "x"
+ map[[1]].should == nil
+ map[[1.0]].should == "x"
+ key.should == [1.0] # keep the key alive until here to keep the map entry
+
+ map = ObjectSpace::WeakKeyMap.new
+ key = [1]
+ map[key] = "x"
+ map[[1.0]].should == nil
+ map[[1]].should == "x"
+ key.should == [1] # keep the key alive until here to keep the map entry
+
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a a].map(&:upcase)
+ ref = "x"
+ map[key1] = ref
+ map[key2].should == ref
+ end
+
+ it "compares key via #hash first" do
+ x = mock('0')
+ x.should_receive(:hash).and_return(0)
+
+ map = ObjectSpace::WeakKeyMap.new
+ key = 'foo'
+ map[key] = :bar
+ map[x].should == nil
+ end
+
+ it "does not compare keys with different #hash values via #eql?" do
+ x = mock('x')
+ x.should_not_receive(:eql?)
+ x.stub!(:hash).and_return(0)
+
+ y = mock('y')
+ y.should_not_receive(:eql?)
+ y.stub!(:hash).and_return(1)
+
+ map = ObjectSpace::WeakKeyMap.new
+ map[y] = 1
+ map[x].should == nil
+ end
+
+ it "compares keys with the same #hash value via #eql?" do
+ x = mock('x')
+ x.should_receive(:eql?).and_return(true)
+ x.stub!(:hash).and_return(42)
+
+ y = mock('y')
+ y.should_not_receive(:eql?)
+ y.stub!(:hash).and_return(42)
+
+ map = ObjectSpace::WeakKeyMap.new
+ map[y] = 1
+ map[x].should == 1
+ end
+
+ it "finds a value via an identical key even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.should_receive(:hash).at_least(1).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ map = ObjectSpace::WeakKeyMap.new
+ map[x] = :x
+ map[x].should == :x
+ end
+
+ it "supports keys with private #hash method" do
+ key = WeakKeyMapSpecs::KeyWithPrivateHash.new
+ map = ObjectSpace::WeakKeyMap.new
+ map[key] = 42
+ map[key].should == 42
+ end
+
+ it "returns nil and does not raise error when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map[1].should == nil
+ map[1.0].should == nil
+ map[:a].should == nil
+ map[true].should == nil
+ map[false].should == nil
+ map[nil].should == nil
end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb b/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
index 689509d820..cf59aebc6f 100644
--- a/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
@@ -1,71 +1,80 @@
require_relative '../../../spec_helper'
-ruby_version_is "3.3" do
- describe "ObjectSpace::WeakKeyMap#[]=" do
- def should_accept(map, key, value)
- (map[key] = value).should == value
- map.should.key?(key)
- map[key].should == value
- end
+describe "ObjectSpace::WeakKeyMap#[]=" do
+ def should_accept(map, key, value)
+ (map[key] = value).should == value
+ map.should.key?(key)
+ map[key].should == value
+ end
- def should_not_accept(map, key, value)
- -> { map[key] = value }.should raise_error(ArgumentError)
- end
+ it "is correct" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
+ should_accept(map, key1, ref1)
+ should_accept(map, key1, ref1)
+ should_accept(map, key2, ref2)
+ map[key1].should == ref1
+ end
- it "is correct" do
- map = ObjectSpace::WeakKeyMap.new
- key1, key2 = %w[a b].map(&:upcase)
- ref1, ref2 = %w[x y]
- should_accept(map, key1, ref1)
- should_accept(map, key1, ref1)
- should_accept(map, key2, ref2)
- map[key1].should == ref1
- end
+ it "requires the keys to implement #hash" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[BasicObject.new] = 1 }.should.raise(NoMethodError, /undefined method [`']hash' for an instance of BasicObject/)
+ end
- it "requires the keys to implement #hash" do
- map = ObjectSpace::WeakKeyMap.new
- -> { map[BasicObject.new] = 1 }.should raise_error(NoMethodError, "undefined method `hash' for an instance of BasicObject")
- end
+ it "accepts frozen keys or values" do
+ map = ObjectSpace::WeakKeyMap.new
+ x = Object.new
+ should_accept(map, x, true)
+ should_accept(map, x, false)
+ should_accept(map, x, 42)
+ should_accept(map, x, :foo)
- it "accepts frozen keys or values" do
- map = ObjectSpace::WeakKeyMap.new
- x = Object.new
- should_accept(map, x, true)
- should_accept(map, x, false)
- should_accept(map, x, 42)
- should_accept(map, x, :foo)
+ y = Object.new.freeze
+ should_accept(map, x, y)
+ should_accept(map, y, x)
+ end
+
+ it "does not duplicate and freeze String keys (like Hash#[]= does)" do
+ map = ObjectSpace::WeakKeyMap.new
+ key = +"a"
+ map[key] = 1
- y = Object.new.freeze
- should_accept(map, x, y)
- should_accept(map, y, x)
+ map.getkey("a").should.equal? key
+ map.getkey("a").should_not.frozen?
+
+ key.should == "a" # keep the key alive until here to keep the map entry
+ end
+
+ context "a key cannot be garbage collected" do
+ it "raises ArgumentError when Integer is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[1] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
end
- it "rejects symbols as keys" do
+ it "raises ArgumentError when Float is used as a key" do
map = ObjectSpace::WeakKeyMap.new
- should_not_accept(map, :foo, true)
- should_not_accept(map, rand.to_s.to_sym, true)
+ -> { map[1.0] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
end
- it "rejects integers as keys" do
+ it "raises ArgumentError when Symbol is used as a key" do
map = ObjectSpace::WeakKeyMap.new
- should_not_accept(map, 42, true)
- should_not_accept(map, 2 ** 68, true)
+ -> { map[:a] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
end
- it "rejects floats as keys" do
+ it "raises ArgumentError when true is used as a key" do
map = ObjectSpace::WeakKeyMap.new
- should_not_accept(map, 4.2, true)
+ -> { map[true] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
end
- it "rejects booleans as keys" do
+ it "raises ArgumentError when false is used as a key" do
map = ObjectSpace::WeakKeyMap.new
- should_not_accept(map, true, true)
- should_not_accept(map, false, true)
+ -> { map[false] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
end
- it "rejects nil as keys" do
+ it "raises ArgumentError when nil is used as a key" do
map = ObjectSpace::WeakKeyMap.new
- should_not_accept(map, nil, true)
+ -> { map[nil] = "x" }.should.raise(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
end
end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb b/spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb
new file mode 100644
index 0000000000..0fd04551b5
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb
@@ -0,0 +1,5 @@
+module WeakKeyMapSpecs
+ class KeyWithPrivateHash
+ private :hash
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb b/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb
index 3af0186f27..798a2e2cda 100644
--- a/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb
@@ -1,14 +1,26 @@
require_relative '../../../spec_helper'
-ruby_version_is "3.3" do
- describe "ObjectSpace::WeakKeyMap#getkey" do
- it "returns the existing equal key" do
- map = ObjectSpace::WeakKeyMap.new
- key1, key2 = %w[a a].map(&:upcase)
-
- map[key1] = true
- map.getkey(key2).should equal(key1)
- map.getkey("X").should == nil
- end
+describe "ObjectSpace::WeakKeyMap#getkey" do
+ it "returns the existing equal key" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a a].map(&:upcase)
+
+ map[key1] = true
+ map.getkey(key2).should.equal?(key1)
+ map.getkey("X").should == nil
+
+ key1.should == "A" # keep the key alive until here to keep the map entry
+ key2.should == "A" # keep the key alive until here to keep the map entry
+ end
+
+ it "returns nil when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map.getkey(1).should == nil
+ map.getkey(1.0).should == nil
+ map.getkey(:a).should == nil
+ map.getkey(true).should == nil
+ map.getkey(false).should == nil
+ map.getkey(nil).should == nil
end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb b/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb
index 557fbc8733..b6bb469158 100644
--- a/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb
@@ -1,17 +1,19 @@
require_relative '../../../spec_helper'
-ruby_version_is "3.3" do
- describe "ObjectSpace::WeakKeyMap#inspect" do
- it "only displays size in output" do
- map = ObjectSpace::WeakKeyMap.new
- key1, key2, key3 = "foo", "bar", "bar"
- map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=0>\z/
- map[key1] = 1
- map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=1>\z/
- map[key2] = 2
- map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=2>\z/
- map[key3] = 3
- map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=2>\z/
- end
+describe "ObjectSpace::WeakKeyMap#inspect" do
+ it "only displays size in output" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2, key3 = "foo", "bar", "bar"
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=0>\z/
+ map[key1] = 1
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=1>\z/
+ map[key2] = 2
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=2>\z/
+ map[key3] = 3
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=2>\z/
+
+ key1.should == "foo" # keep the key alive until here to keep the map entry
+ key2.should == "bar" # keep the key alive until here to keep the map entry
+ key3.should == "bar" # keep the key alive until here to keep the map entry
end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/key_spec.rb b/spec/ruby/core/objectspace/weakkeymap/key_spec.rb
index 2af9c2b8e7..e0b6866671 100644
--- a/spec/ruby/core/objectspace/weakkeymap/key_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/key_spec.rb
@@ -1,33 +1,42 @@
require_relative '../../../spec_helper'
-ruby_version_is "3.3" do
- describe "ObjectSpace::WeakKeyMap#key?" do
- it "recognizes keys in use" do
- map = ObjectSpace::WeakKeyMap.new
- key1, key2 = %w[a b].map(&:upcase)
- ref1, ref2 = %w[x y]
+describe "ObjectSpace::WeakKeyMap#key?" do
+ it "recognizes keys in use" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
- map[key1] = ref1
- map.key?(key1).should == true
- map[key1] = ref1
- map.key?(key1).should == true
- map[key2] = ref2
- map.key?(key2).should == true
- end
+ map[key1] = ref1
+ map.key?(key1).should == true
+ map[key1] = ref1
+ map.key?(key1).should == true
+ map[key2] = ref2
+ map.key?(key2).should == true
+ end
+
+ it "matches using equality semantics" do
+ map = ObjectSpace::WeakKeyMap.new
+ key1, key2 = %w[a a].map(&:upcase)
+ ref = "x"
+ map[key1] = ref
+ map.key?(key2).should == true
+ end
+
+ it "reports true if the pair exists and the value is nil" do
+ map = ObjectSpace::WeakKeyMap.new
+ key = Object.new
+ map[key] = nil
+ map.key?(key).should == true
+ end
- it "matches using equality semantics" do
- map = ObjectSpace::WeakKeyMap.new
- key1, key2 = %w[a a].map(&:upcase)
- ref = "x"
- map[key1] = ref
- map.key?(key2).should == true
- end
+ it "returns false when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
- it "reports true if the pair exists and the value is nil" do
- map = ObjectSpace::WeakKeyMap.new
- key = Object.new
- map[key] = nil
- map.key?(key).should == true
- end
+ map.key?(1).should == false
+ map.key?(1.0).should == false
+ map.key?(:a).should == false
+ map.key?(true).should == false
+ map.key?(false).should == false
+ map.key?(nil).should == false
end
end
diff --git a/spec/ruby/core/objectspace/weakmap/delete_spec.rb b/spec/ruby/core/objectspace/weakmap/delete_spec.rb
index 302de264fb..03beebbb83 100644
--- a/spec/ruby/core/objectspace/weakmap/delete_spec.rb
+++ b/spec/ruby/core/objectspace/weakmap/delete_spec.rb
@@ -1,30 +1,28 @@
require_relative '../../../spec_helper'
-ruby_version_is '3.3' do
- describe "ObjectSpace::WeakMap#delete" do
- it "removes the entry and returns the deleted value" do
- m = ObjectSpace::WeakMap.new
- key = Object.new
- value = Object.new
- m[key] = value
+describe "ObjectSpace::WeakMap#delete" do
+ it "removes the entry and returns the deleted value" do
+ m = ObjectSpace::WeakMap.new
+ key = Object.new
+ value = Object.new
+ m[key] = value
- m.delete(key).should == value
- m.key?(key).should == false
- end
+ m.delete(key).should == value
+ m.key?(key).should == false
+ end
- it "calls supplied block if the key is not found" do
- key = Object.new
- m = ObjectSpace::WeakMap.new
- return_value = m.delete(key) do |yielded_key|
- yielded_key.should == key
- 5
- end
- return_value.should == 5
+ it "calls supplied block if the key is not found" do
+ key = Object.new
+ m = ObjectSpace::WeakMap.new
+ return_value = m.delete(key) do |yielded_key|
+ yielded_key.should == key
+ 5
end
+ return_value.should == 5
+ end
- it "returns nil if the key is not found when no block is given" do
- m = ObjectSpace::WeakMap.new
- m.delete(Object.new).should == nil
- end
+ it "returns nil if the key is not found when no block is given" do
+ m = ObjectSpace::WeakMap.new
+ m.delete(Object.new).should == nil
end
end
diff --git a/spec/ruby/core/objectspace/weakmap/shared/each.rb b/spec/ruby/core/objectspace/weakmap/shared/each.rb
index 3d43a19347..771c416dde 100644
--- a/spec/ruby/core/objectspace/weakmap/shared/each.rb
+++ b/spec/ruby/core/objectspace/weakmap/shared/each.rb
@@ -5,6 +5,6 @@ describe :weakmap_each, shared: true do
ref = "x"
map.send(@method).should == map
map[key] = ref
- -> { map.send(@method) }.should raise_error(LocalJumpError)
+ -> { map.send(@method) }.should.raise(LocalJumpError)
end
end