1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/spec/rubyspec/language/metaclass_spec.rb
eregon 95e8c48dd3 Add in-tree mspec and ruby/spec
* For easier modifications of ruby/spec by MRI developers.
* .gitignore: track changes under spec.
* spec/mspec, spec/rubyspec: add in-tree mspec and ruby/spec.
  These files can therefore be updated like any other file in MRI.
  Instructions are provided in spec/README.
  [Feature #13156] [ruby-core:79246]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58595 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-05-07 12:04:49 +00:00

143 lines
3.5 KiB
Ruby

require File.expand_path('../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/class', __FILE__)
require File.expand_path('../fixtures/metaclass', __FILE__)
describe "self in a metaclass body (class << obj)" do
it "is TrueClass for true" do
class << true; self; end.should == TrueClass
end
it "is FalseClass for false" do
class << false; self; end.should == FalseClass
end
it "is NilClass for nil" do
class << nil; self; end.should == NilClass
end
it "raises a TypeError for numbers" do
lambda { class << 1; self; end }.should raise_error(TypeError)
end
it "raises a TypeError for symbols" do
lambda { class << :symbol; self; end }.should raise_error(TypeError)
end
it "is a singleton Class instance" do
cls = class << mock('x'); self; end
cls.is_a?(Class).should == true
cls.should_not equal(Object)
end
end
describe "A constant on a metaclass" do
before :each do
@object = Object.new
class << @object
CONST = self
end
end
it "can be accessed after the metaclass body is reopened" do
class << @object
CONST.should == self
end
end
it "can be accessed via self::CONST" do
class << @object
self::CONST.should == self
end
end
it "can be accessed via const_get" do
class << @object
const_get(:CONST).should == self
end
end
it "is not defined on the object's class" do
@object.class.const_defined?(:CONST).should be_false
end
it "is not defined in the metaclass opener's scope" do
class << @object
CONST
end
lambda { CONST }.should raise_error(NameError)
end
it "cannot be accessed via object::CONST" do
lambda do
@object::CONST
end.should raise_error(TypeError)
end
it "raises a NameError for anonymous_module::CONST" do
@object = Class.new
class << @object
CONST = 100
end
lambda do
@object::CONST
end.should raise_error(NameError)
end
it "appears in the metaclass constant list" do
constants = class << @object; constants; end
constants.should include(:CONST)
end
it "does not appear in the object's class constant list" do
@object.class.constants.should_not include(:CONST)
end
it "is not preserved when the object is duped" do
@object = @object.dup
lambda do
class << @object; CONST; end
end.should raise_error(NameError)
end
it "is preserved when the object is cloned" do
@object = @object.clone
class << @object
CONST.should_not be_nil
end
end
end
describe "calling methods on the metaclass" do
it "calls a method on the metaclass" do
MetaClassSpecs::A.cheese.should == 'edam'
MetaClassSpecs::B.cheese.should == 'stilton'
end
it "calls a method on the instance's metaclass" do
b = MetaClassSpecs::B.new
b_meta = MetaClassSpecs.metaclass_of b
b_meta.send(:define_method, :cheese) {'cheshire'}
b.cheese.should == 'cheshire'
end
it "calls a method in deeper chains of metaclasses" do
b = MetaClassSpecs::B.new
b_meta = MetaClassSpecs.metaclass_of b
b_meta_meta = MetaClassSpecs.metaclass_of b_meta
b_meta_meta.send(:define_method, :cheese) {'gouda'}
b_meta.cheese.should == 'gouda'
b_meta_meta_meta = MetaClassSpecs.metaclass_of b_meta_meta
b_meta_meta_meta.send(:define_method, :cheese) {'wensleydale'}
b_meta_meta.cheese.should == 'wensleydale'
end
it "calls a method defined on the metaclass of the metaclass" do
d_meta = MetaClassSpecs::D.singleton_class
d_meta.ham.should == 'iberico'
end
end