From 5bc00883f9458988082d996e49cc3147cfdc65f4 Mon Sep 17 00:00:00 2001 From: Alexander Bulancov <6594487+trinistr@users.noreply.github.com> Date: Mon, 22 Dec 2025 01:56:12 +0300 Subject: [PATCH] Add more tests for reopening classes and modules --- core/module/fixtures/classes.rb | 2 +- language/class_spec.rb | 42 ++++++++++++++++++++++++++++++++- language/fixtures/module.rb | 9 ------- language/module_spec.rb | 32 +++++++++++++++++++++---- 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/core/module/fixtures/classes.rb b/core/module/fixtures/classes.rb index a434e7b0b8..964f64c593 100644 --- a/core/module/fixtures/classes.rb +++ b/core/module/fixtures/classes.rb @@ -1,6 +1,6 @@ module ModuleSpecs def self.without_test_modules(modules) - ignore = %w[MSpecRSpecAdapter PP::ObjectMixin ModuleSpecs::IncludedInObject MainSpecs::Module ConstantSpecs::ModuleA] + ignore = %w[MSpecRSpecAdapter PP::ObjectMixin MainSpecs::Module ConstantSpecs::ModuleA] modules.reject { |k| ignore.include?(k.name) } end diff --git a/language/class_spec.rb b/language/class_spec.rb index 0b770d69b5..6fb785fd56 100644 --- a/language/class_spec.rb +++ b/language/class_spec.rb @@ -46,7 +46,14 @@ class ClassSpecsKeywordWithSemicolon; end -> { class ClassSpecsNumber end - }.should raise_error(TypeError) + }.should raise_error(TypeError, /\AClassSpecsNumber is not a class/) + end + + it "raises TypeError if constant given as class name exists and is a Module but not a Class" do + -> { + class ClassSpecs + end + }.should raise_error(TypeError, /\AClassSpecs is not a class/) end # test case known to be detecting bugs (JRuby, MRI) @@ -346,6 +353,39 @@ def self.m ClassSpecs::M.m.should == 1 ClassSpecs::L.singleton_class.send(:remove_method, :m) end + + it "does not reopen a class included in Object" do + ruby_exe(<<~RUBY).should == "false" + module IncludedInObject + class IncludedClass + end + end + class Object + include IncludedInObject + end + class IncludedClass + end + print IncludedInObject::IncludedClass == Object::IncludedClass + RUBY + end + + it "does not reopen a class included in non-Object modules" do + ruby_exe(<<~RUBY).should == "false/false" + module Included + module IncludedClass; end + end + module M + include Included + module IncludedClass; end + end + class C + include Included + module IncludedClass; end + end + print Included::IncludedClass == M::IncludedClass, "/", + Included::IncludedClass == C::IncludedClass + RUBY + end end describe "class provides hooks" do diff --git a/language/fixtures/module.rb b/language/fixtures/module.rb index 33d323846e..75eee77791 100644 --- a/language/fixtures/module.rb +++ b/language/fixtures/module.rb @@ -12,13 +12,4 @@ class Klass module Anonymous end - - module IncludedInObject - module IncludedModuleSpecs - end - end -end - -class Object - include ModuleSpecs::IncludedInObject end diff --git a/language/module_spec.rb b/language/module_spec.rb index 4db00bd7fb..fba4aa8c6e 100644 --- a/language/module_spec.rb +++ b/language/module_spec.rb @@ -31,10 +31,34 @@ module ModuleSpecs; Reopened = true; end end it "does not reopen a module included in Object" do - module IncludedModuleSpecs; Reopened = true; end - ModuleSpecs::IncludedInObject::IncludedModuleSpecs.should_not == Object::IncludedModuleSpecs - ensure - IncludedModuleSpecs.send(:remove_const, :Reopened) + ruby_exe(<<~RUBY).should == "false" + module IncludedInObject + module IncludedModule; end + end + class Object + include IncludedInObject + end + module IncludedModule; end + print IncludedInObject::IncludedModule == Object::IncludedModule + RUBY + end + + it "does not reopen a module included in non-Object modules" do + ruby_exe(<<~RUBY).should == "false/false" + module Included + module IncludedModule; end + end + module M + include Included + module IncludedModule; end + end + class C + include Included + module IncludedModule; end + end + print Included::IncludedModule == M::IncludedModule, "/", + Included::IncludedModule == C::IncludedModule + RUBY end it "raises a TypeError if the constant is a Class" do