summaryrefslogtreecommitdiff
path: root/spec/ruby/language/class_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/language/class_spec.rb')
-rw-r--r--spec/ruby/language/class_spec.rb103
1 files changed, 83 insertions, 20 deletions
diff --git a/spec/ruby/language/class_spec.rb b/spec/ruby/language/class_spec.rb
index d07454a3a7..6fb785fd56 100644
--- a/spec/ruby/language/class_spec.rb
+++ b/spec/ruby/language/class_spec.rb
@@ -17,6 +17,19 @@ describe "The class keyword" do
eval "class ClassSpecsKeywordWithoutSemicolon end"
ClassSpecsKeywordWithoutSemicolon.should be_an_instance_of(Class)
end
+
+ it "can redefine a class when called from a block" do
+ ClassSpecs::DEFINE_CLASS.call
+ A.should be_an_instance_of(Class)
+
+ Object.send(:remove_const, :A)
+ defined?(A).should be_nil
+
+ ClassSpecs::DEFINE_CLASS.call
+ A.should be_an_instance_of(Class)
+ ensure
+ Object.send(:remove_const, :A) if defined?(::A)
+ end
end
describe "A class definition" do
@@ -30,27 +43,34 @@ describe "A class definition" do
end
it "raises TypeError if constant given as class name exists and is not a Module" do
- lambda {
+ -> {
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)
it "raises TypeError if the constant qualifying the class is nil" do
- lambda {
+ -> {
class nil::Foo
end
}.should raise_error(TypeError)
end
it "raises TypeError if any constant qualifying the class is not a Module" do
- lambda {
+ -> {
class ClassSpecs::Number::MyClass
end
}.should raise_error(TypeError)
- lambda {
+ -> {
class ClassSpecsNumber::MyClass
end
}.should raise_error(TypeError)
@@ -64,7 +84,7 @@ describe "A class definition" do
module ClassSpecs
class SuperclassResetToSubclass < L
end
- lambda {
+ -> {
class SuperclassResetToSubclass < M
end
}.should raise_error(TypeError, /superclass mismatch/)
@@ -77,7 +97,7 @@ describe "A class definition" do
end
SuperclassReopenedBasicObject.superclass.should == A
- lambda {
+ -> {
class SuperclassReopenedBasicObject < BasicObject
end
}.should raise_error(TypeError, /superclass mismatch/)
@@ -92,7 +112,7 @@ describe "A class definition" do
end
SuperclassReopenedObject.superclass.should == A
- lambda {
+ -> {
class SuperclassReopenedObject < Object
end
}.should raise_error(TypeError, /superclass mismatch/)
@@ -117,7 +137,7 @@ describe "A class definition" do
class NoSuperclassSet
end
- lambda {
+ -> {
class NoSuperclassSet < String
end
}.should raise_error(TypeError, /superclass mismatch/)
@@ -127,7 +147,7 @@ describe "A class definition" do
it "allows using self as the superclass if self is a class" do
ClassSpecs::I::J.superclass.should == ClassSpecs::I
- lambda {
+ -> {
class ShouldNotWork < self; end
}.should raise_error(TypeError)
end
@@ -148,7 +168,7 @@ describe "A class definition" do
it "raises a TypeError if inheriting from a metaclass" do
obj = mock("metaclass super")
meta = obj.singleton_class
- lambda { class ClassSpecs::MetaclassSuper < meta; end }.should raise_error(TypeError)
+ -> { class ClassSpecs::MetaclassSuper < meta; end }.should raise_error(TypeError)
end
it "allows the declaration of class variables in the body" do
@@ -258,6 +278,8 @@ describe "A class definition" do
AnonWithConstant.name.should == 'AnonWithConstant'
klass.get_class_name.should == 'AnonWithConstant'
+ ensure
+ Object.send(:remove_const, :AnonWithConstant)
end
end
end
@@ -274,7 +296,7 @@ describe "A class definition extending an object (sclass)" do
end
it "raises a TypeError when trying to extend numbers" do
- lambda {
+ -> {
eval <<-CODE
class << 1
def xyz
@@ -285,12 +307,20 @@ describe "A class definition extending an object (sclass)" do
}.should raise_error(TypeError)
end
- ruby_version_is ""..."3.0" do
- it "allows accessing the block of the original scope" do
- suppress_warning do
- ClassSpecs.sclass_with_block { 123 }.should == 123
- end
- end
+ it "raises a TypeError when trying to extend non-Class" do
+ error_msg = /superclass must be a.* Class/
+ -> { class TestClass < ""; end }.should raise_error(TypeError, error_msg)
+ -> { class TestClass < 1; end }.should raise_error(TypeError, error_msg)
+ -> { class TestClass < :symbol; end }.should raise_error(TypeError, error_msg)
+ -> { class TestClass < mock('o'); end }.should raise_error(TypeError, error_msg)
+ -> { class TestClass < Module.new; end }.should raise_error(TypeError, error_msg)
+ -> { class TestClass < BasicObject.new; end }.should raise_error(TypeError, error_msg)
+ end
+
+ it "does not allow accessing the block of the original scope" do
+ -> {
+ ClassSpecs.sclass_with_block { 123 }
+ }.should raise_error(SyntaxError)
end
it "can use return to cause the enclosing method to return" do
@@ -310,11 +340,11 @@ describe "Reopening a class" do
end
it "raises a TypeError when superclasses mismatch" do
- lambda { class ClassSpecs::A < Array; end }.should raise_error(TypeError)
+ -> { class ClassSpecs::A < Array; end }.should raise_error(TypeError)
end
it "adds new methods to subclasses" do
- lambda { ClassSpecs::M.m }.should raise_error(NoMethodError)
+ -> { ClassSpecs::M.m }.should raise_error(NoMethodError)
class ClassSpecs::L
def self.m
1
@@ -323,6 +353,39 @@ describe "Reopening a class" do
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