summaryrefslogtreecommitdiff
path: root/spec/ruby/core/kernel/singleton_class_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/kernel/singleton_class_spec.rb')
-rw-r--r--spec/ruby/core/kernel/singleton_class_spec.rb29
1 files changed, 29 insertions, 0 deletions
diff --git a/spec/ruby/core/kernel/singleton_class_spec.rb b/spec/ruby/core/kernel/singleton_class_spec.rb
index 4865e29c10..23c400f9bd 100644
--- a/spec/ruby/core/kernel/singleton_class_spec.rb
+++ b/spec/ruby/core/kernel/singleton_class_spec.rb
@@ -1,3 +1,4 @@
+# truffleruby_primitives: true
require_relative '../../spec_helper'
describe "Kernel#singleton_class" do
@@ -42,4 +43,32 @@ describe "Kernel#singleton_class" do
obj.freeze
obj.singleton_class.frozen?.should be_true
end
+
+ context "for an IO object with a replaced singleton class" do
+ it "looks up singleton methods from the fresh singleton class after an object instance got a new one" do
+ proxy = -> io { io.foo }
+ if RUBY_ENGINE == 'truffleruby'
+ # We need an inline cache with only this object seen, the best way to do that is to use a Primitive
+ sclass = -> io { Primitive.singleton_class(io) }
+ else
+ sclass = -> io { io.singleton_class }
+ end
+
+ io = File.new(__FILE__)
+ io.define_singleton_method(:foo) { "old" }
+ sclass1 = sclass.call(io)
+ proxy.call(io).should == "old"
+
+ # IO#reopen is the only method which can replace an object's singleton class
+ io2 = File.new(__FILE__)
+ io.reopen(io2)
+ io.define_singleton_method(:foo) { "new" }
+ sclass2 = sclass.call(io)
+ sclass2.should_not.equal?(sclass1)
+ proxy.call(io).should == "new"
+ ensure
+ io2.close
+ io.close
+ end
+ end
end