summaryrefslogtreecommitdiff
path: root/test/ruby/test_class.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/ruby/test_class.rb')
-rw-r--r--test/ruby/test_class.rb157
1 files changed, 142 insertions, 15 deletions
diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb
index 5086e60398..8f12e06685 100644
--- a/test/ruby/test_class.rb
+++ b/test/ruby/test_class.rb
@@ -96,6 +96,13 @@ class TestClass < Test::Unit::TestCase
def test_superclass_of_basicobject
assert_equal(nil, BasicObject.superclass)
+
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ module Mod end
+ BasicObject.include(Mod)
+ assert_equal(nil, BasicObject.superclass)
+ end;
end
def test_module_function
@@ -252,6 +259,46 @@ class TestClass < Test::Unit::TestCase
assert_raise(TypeError) { BasicObject.dup }
end
+ def test_class_hierarchy_inside_initialize_dup_bug_21538
+ ancestors = sc_ancestors = nil
+ b = Class.new
+ b.define_singleton_method(:initialize_dup) do |x|
+ ancestors = self.ancestors
+ sc_ancestors = singleton_class.ancestors
+ super(x)
+ end
+
+ a = Class.new(b)
+
+ c = a.dup
+
+ expected_ancestors = [c, b, *Object.ancestors]
+ expected_sc_ancestors = [c.singleton_class, b.singleton_class, *Object.singleton_class.ancestors]
+ assert_equal expected_ancestors, ancestors
+ assert_equal expected_sc_ancestors, sc_ancestors
+ assert_equal expected_ancestors, c.ancestors
+ assert_equal expected_sc_ancestors, c.singleton_class.ancestors
+ end
+
+ def test_class_hierarchy_inside_initialize_clone_bug_21538
+ ancestors = sc_ancestors = nil
+ a = Class.new
+ a.define_singleton_method(:initialize_clone) do |x|
+ ancestors = self.ancestors
+ sc_ancestors = singleton_class.ancestors
+ super(x)
+ end
+
+ c = a.clone
+
+ expected_ancestors = [c, *Object.ancestors]
+ expected_sc_ancestors = [c.singleton_class, *Object.singleton_class.ancestors]
+ assert_equal expected_ancestors, ancestors
+ assert_equal expected_sc_ancestors, sc_ancestors
+ assert_equal expected_ancestors, c.ancestors
+ assert_equal expected_sc_ancestors, c.singleton_class.ancestors
+ end
+
def test_singleton_class
assert_raise(TypeError) { 1.extend(Module.new) }
assert_raise(TypeError) { 1.0.extend(Module.new) }
@@ -276,12 +323,8 @@ class TestClass < Test::Unit::TestCase
assert_raise(TypeError, bug6863) { Class.new(Class.allocate) }
allocator = Class.instance_method(:allocate)
- assert_raise_with_message(TypeError, /prohibited/) {
- allocator.bind(Rational).call
- }
- assert_raise_with_message(TypeError, /prohibited/) {
- allocator.bind_call(Rational)
- }
+ assert_nothing_raised { allocator.bind(Rational).call }
+ assert_nothing_raised { allocator.bind_call(Rational) }
end
def test_nonascii_name
@@ -309,6 +352,7 @@ class TestClass < Test::Unit::TestCase
def test_invalid_return_from_class_definition
assert_syntax_error("class C; return; end", /Invalid return/)
+ assert_syntax_error("class << Object; return; end", /Invalid return/)
end
def test_invalid_yield_from_class_definition
@@ -355,6 +399,17 @@ class TestClass < Test::Unit::TestCase
assert_equal(42, PrivateClass.new.foo)
end
+ def test_private_const_access
+ assert_raise_with_message NameError, /uninitialized/ do
+ begin
+ eval('class ::TestClass::PrivateClass; end')
+ rescue NameError
+ end
+
+ Object.const_get "NOT_AVAILABLE_CONST_NAME_#{__LINE__}"
+ end
+ end
+
StrClone = String.clone
Class.new(StrClone)
@@ -546,7 +601,7 @@ class TestClass < Test::Unit::TestCase
obj = Object.new
c = obj.singleton_class
obj.freeze
- assert_raise_with_message(FrozenError, /frozen object/) {
+ assert_raise_with_message(FrozenError, /frozen Object/) {
c.class_eval {def f; end}
}
end
@@ -681,9 +736,11 @@ class TestClass < Test::Unit::TestCase
def test_namescope_error_message
m = Module.new
o = m.module_eval "class A\u{3042}; self; end.new"
- assert_raise_with_message(TypeError, /A\u{3042}/) {
- o::Foo
- }
+ EnvUtil.with_default_internal(Encoding::UTF_8) do
+ assert_raise_with_message(TypeError, /A\u{3042}/) {
+ o::Foo
+ }
+ end
end
def test_redefinition_mismatch
@@ -702,9 +759,13 @@ class TestClass < Test::Unit::TestCase
assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}")
begin;
- Date = (class C\u{1f5ff}; self; end).new
+ module Bug
+ module Class
+ TestClassDefinedInC = (class C\u{1f5ff}; self; end).new
+ end
+ end
assert_raise_with_message(TypeError, /C\u{1f5ff}/) {
- require 'date'
+ require '-test-/class'
}
end;
end
@@ -771,15 +832,15 @@ class TestClass < Test::Unit::TestCase
c.attached_object
end
- assert_raise_with_message(TypeError, /`NilClass' is not a singleton class/) do
+ assert_raise_with_message(TypeError, /'NilClass' is not a singleton class/) do
nil.singleton_class.attached_object
end
- assert_raise_with_message(TypeError, /`FalseClass' is not a singleton class/) do
+ assert_raise_with_message(TypeError, /'FalseClass' is not a singleton class/) do
false.singleton_class.attached_object
end
- assert_raise_with_message(TypeError, /`TrueClass' is not a singleton class/) do
+ assert_raise_with_message(TypeError, /'TrueClass' is not a singleton class/) do
true.singleton_class.attached_object
end
end
@@ -818,4 +879,70 @@ CODE
klass.define_method(:bar) {}
assert_equal klass, klass.remove_method(:bar), '[Bug #19164]'
end
+
+ def test_method_table_assignment_just_after_class_init
+ assert_normal_exit "#{<<~"begin;"}\n#{<<~'end;'}", 'm_tbl assignment should be done only when Class object is not promoted'
+ begin;
+ GC.stress = true
+ class C; end
+ end;
+ end
+
+ def test_singleton_cc_invalidation
+ assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}")
+ begin;
+ class T
+ def hi
+ "hi"
+ end
+ end
+
+ t = T.new
+ t.singleton_class
+
+ def hello(t)
+ t.hi
+ end
+
+ 5.times do
+ hello(t) # populate inline cache on `t.singleton_class`.
+ end
+
+ class T
+ remove_method :hi # invalidate `t.singleton_class` ccs for `hi`
+ end
+
+ assert_raise NoMethodError do
+ hello(t)
+ end
+ end;
+ end
+
+ def test_safe_multi_ractor_subclasses_list_mutation
+ assert_ractor "#{<<~"begin;"}\n#{<<~'end;'}"
+ begin;
+ 4.times.map do
+ Ractor.new do
+ 20_000.times do
+ Object.new.singleton_class
+ end
+ end
+ end.each(&:join)
+ end;
+ end
+
+ def test_safe_multi_ractor_singleton_class_access
+ assert_ractor "#{<<~"begin;"}\n#{<<~'end;'}"
+ begin;
+ class A; end
+ 4.times.map do
+ Ractor.new do
+ a = A
+ 100.times do
+ a = a.singleton_class
+ end
+ end
+ end.each(&:join)
+ end;
+ end
end