diff options
Diffstat (limited to 'spec/ruby/optional/capi/class_spec.rb')
| -rw-r--r-- | spec/ruby/optional/capi/class_spec.rb | 270 |
1 files changed, 195 insertions, 75 deletions
diff --git a/spec/ruby/optional/capi/class_spec.rb b/spec/ruby/optional/capi/class_spec.rb index a25e80af60..07e9e42ad1 100644 --- a/spec/ruby/optional/capi/class_spec.rb +++ b/spec/ruby/optional/capi/class_spec.rb @@ -1,5 +1,6 @@ -require File.expand_path('../spec_helper', __FILE__) -require File.expand_path('../fixtures/class', __FILE__) +require_relative 'spec_helper' +require_relative 'fixtures/class' +require_relative '../../core/module/fixtures/classes' load_extension("class") compile_extension("class_under_autoload") @@ -10,7 +11,8 @@ autoload :ClassIdUnderAutoload, "#{object_path}/class_id_under_autoload_spec" describe :rb_path_to_class, shared: true do it "returns a class or module from a scoped String" do - @s.send(@method, "CApiClassSpecs::A::B").should equal(CApiClassSpecs::A::B) + @s.send(@method, "CApiClassSpecs::A::B").should.equal?(CApiClassSpecs::A::B) + @s.send(@method, "CApiClassSpecs::A::M").should.equal?(CApiClassSpecs::A::M) end it "resolves autoload constants" do @@ -18,19 +20,21 @@ describe :rb_path_to_class, shared: true do end it "raises an ArgumentError if a constant in the path does not exist" do - lambda { @s.send(@method, "CApiClassSpecs::NotDefined::B") }.should raise_error(ArgumentError) + -> { @s.send(@method, "CApiClassSpecs::NotDefined::B") }.should.raise(ArgumentError) end it "raises an ArgumentError if the final constant does not exist" do - lambda { @s.send(@method, "CApiClassSpecs::NotDefined") }.should raise_error(ArgumentError) + -> { @s.send(@method, "CApiClassSpecs::NotDefined") }.should.raise(ArgumentError) end it "raises a TypeError if the constant is not a class or module" do - lambda { @s.send(@method, "CApiClassSpecs::A::C") }.should raise_error(TypeError) + -> { + @s.send(@method, "CApiClassSpecs::A::C") + }.should.raise(TypeError, 'CApiClassSpecs::A::C does not refer to class/module') end it "raises an ArgumentError even if a constant in the path exists on toplevel" do - lambda { @s.send(@method, "CApiClassSpecs::Object") }.should raise_error(ArgumentError) + -> { @s.send(@method, "CApiClassSpecs::Object") }.should.raise(ArgumentError) end end @@ -39,26 +43,109 @@ describe "C-API Class function" do @s = CApiClassSpecs.new end + describe "rb_class_instance_methods" do + it "returns the public and protected methods of self and its ancestors" do + methods = @s.rb_class_instance_methods(ModuleSpecs::Basic) + methods.should.include?(:protected_module) + methods.should.include?(:public_module) + + methods = @s.rb_class_instance_methods(ModuleSpecs::Basic, true) + methods.should.include?(:protected_module) + methods.should.include?(:public_module) + end + + it "when passed false as a parameter, returns the instance methods of the class" do + methods = @s.rb_class_instance_methods(ModuleSpecs::Child, false) + methods.to_set.should >= Set[:protected_child, :public_child] + end + end + + describe "rb_class_public_instance_methods" do + it "returns a list of public methods in module and its ancestors" do + methods = @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild) + methods.should.include?(:public_3) + methods.should.include?(:public_2) + methods.should.include?(:public_1) + + methods = @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, true) + methods.should.include?(:public_3) + methods.should.include?(:public_2) + methods.should.include?(:public_1) + end + + it "when passed false as a parameter, should return only methods defined in that module" do + @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, false).should == [:public_1] + end + end + + describe "rb_class_protected_instance_methods" do + it "returns a list of protected methods in module and its ancestors" do + methods = @s.rb_class_protected_instance_methods(ModuleSpecs::CountsChild) + methods.should.include?(:protected_3) + methods.should.include?(:protected_2) + methods.should.include?(:protected_1) + + methods = @s.rb_class_protected_instance_methods(ModuleSpecs::CountsChild, true) + methods.should.include?(:protected_3) + methods.should.include?(:protected_2) + methods.should.include?(:protected_1) + end + + it "when passed false as a parameter, should return only methods defined in that module" do + @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, false).should == [:public_1] + end + end + + describe "rb_class_private_instance_methods" do + it "returns a list of private methods in module and its ancestors" do + @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild).should == ModuleSpecs::CountsChild.private_instance_methods + @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild, true).should == ModuleSpecs::CountsChild.private_instance_methods + end + + it "when passed false as a parameter, should return only methods defined in that module" do + methods = @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild, false) + methods.should == [:private_1] + end + end + describe "rb_class_new_instance" do it "allocates and initializes a new object" do - o = @s.rb_class_new_instance(0, nil, CApiClassSpecs::Alloc) + o = @s.rb_class_new_instance([], CApiClassSpecs::Alloc) o.class.should == CApiClassSpecs::Alloc - o.initialized.should be_true + o.initialized.should == true end it "passes arguments to the #initialize method" do - o = @s.rb_class_new_instance(2, [:one, :two], CApiClassSpecs::Alloc) + o = @s.rb_class_new_instance([:one, :two], CApiClassSpecs::Alloc) o.arguments.should == [:one, :two] end end + describe "rb_class_new_instance_kw" do + it "passes arguments and keywords to the #initialize method" do + obj = @s.rb_class_new_instance_kw([{pos: 1}, {kw: 2}], CApiClassSpecs::KeywordAlloc) + obj.args.should == [{pos: 1}] + obj.kwargs.should == {kw: 2} + + obj = @s.rb_class_new_instance_kw([{}], CApiClassSpecs::KeywordAlloc) + obj.args.should == [] + obj.kwargs.should == {} + end + + it "raises TypeError if the last argument is not a Hash" do + -> { + @s.rb_class_new_instance_kw([42], CApiClassSpecs::KeywordAlloc) + }.should.raise(TypeError, 'no implicit conversion of Integer into Hash') + end + end + describe "rb_include_module" do it "includes a module into a class" do c = Class.new o = c.new - lambda { o.included? }.should raise_error(NameError) + -> { o.included? }.should.raise(NameError) @s.rb_include_module(c, CApiClassSpecs::M) - o.included?.should be_true + o.included?.should == true end end @@ -70,12 +157,12 @@ describe "C-API Class function" do it "defines an attr_reader when passed true, false" do @s.rb_define_attr(CApiClassSpecs::Attr, :foo, true, false) @a.foo.should == 1 - lambda { @a.foo = 5 }.should raise_error(NameError) + -> { @a.foo = 5 }.should.raise(NameError) end it "defines an attr_writer when passed false, true" do @s.rb_define_attr(CApiClassSpecs::Attr, :bar, false, true) - lambda { @a.bar }.should raise_error(NameError) + -> { @a.bar }.should.raise(NameError) @a.bar = 5 @a.instance_variable_get(:@bar).should == 5 end @@ -95,6 +182,12 @@ describe "C-API Class function" do obj.call_super_method.should == :super_method end + it "calls the method in the superclass with the correct self" do + @s.define_call_super_method CApiClassSpecs::SubSelf, "call_super_method" + obj = CApiClassSpecs::SubSelf.new + obj.call_super_method.should.equal? obj + end + it "calls the method in the superclass through two native levels" do @s.define_call_super_method CApiClassSpecs::Sub, "call_super_method" @s.define_call_super_method CApiClassSpecs::SubSub, "call_super_method" @@ -109,7 +202,11 @@ describe "C-API Class function" do end it "returns a string for an anonymous class" do - @s.rb_class2name(Class.new).should be_kind_of(String) + @s.rb_class2name(Class.new).should.is_a?(String) + end + + it "returns a string beginning with # for an anonymous class" do + @s.rb_class2name(Struct.new(:x, :y).new(1, 2).class).should.start_with?('#') end end @@ -129,7 +226,7 @@ describe "C-API Class function" do end it "returns a string for an anonymous class" do - @s.rb_class_name(Class.new).should be_kind_of(String) + @s.rb_class_name(Class.new).should.is_a?(String) end end @@ -143,22 +240,22 @@ describe "C-API Class function" do describe "rb_cvar_defined" do it "returns false when the class variable is not defined" do - @s.rb_cvar_defined(CApiClassSpecs::CVars, "@@nocvar").should be_false + @s.rb_cvar_defined(CApiClassSpecs::CVars, "@@nocvar").should == false end it "returns true when the class variable is defined" do - @s.rb_cvar_defined(CApiClassSpecs::CVars, "@@cvar").should be_true + @s.rb_cvar_defined(CApiClassSpecs::CVars, "@@cvar").should == true end it "returns true if the class instance variable is defined" do - @s.rb_cvar_defined(CApiClassSpecs::CVars, "@c_ivar").should be_true + @s.rb_cvar_defined(CApiClassSpecs::CVars, "@c_ivar").should == true end end describe "rb_cv_set" do it "sets a class variable" do o = CApiClassSpecs::CVars.new - o.new_cv.should be_nil + o.new_cv.should == nil @s.rb_cv_set(CApiClassSpecs::CVars, "@@new_cv", 1) o.new_cv.should == 1 CApiClassSpecs::CVars.remove_class_variable :@@new_cv @@ -171,16 +268,16 @@ describe "C-API Class function" do end it "raises a NameError if the class variable is not defined" do - lambda { + -> { @s.rb_cv_get(CApiClassSpecs::CVars, "@@no_cvar") - }.should raise_error(NameError, /class variable @@no_cvar/) + }.should.raise(NameError, /class variable @@no_cvar/) end end describe "rb_cvar_set" do it "sets a class variable" do o = CApiClassSpecs::CVars.new - o.new_cvar.should be_nil + o.new_cvar.should == nil @s.rb_cvar_set(CApiClassSpecs::CVars, "@@new_cvar", 1) o.new_cvar.should == 1 CApiClassSpecs::CVars.remove_class_variable :@@new_cvar @@ -194,8 +291,8 @@ describe "C-API Class function" do end it "creates a subclass of the superclass" do - @cls.should be_kind_of(Class) - ClassSpecDefineClass.should equal(@cls) + @cls.should.is_a?(Class) + ClassSpecDefineClass.should.equal?(@cls) @cls.superclass.should == CApiClassSpecs::Super end @@ -210,23 +307,30 @@ describe "C-API Class function" do end it "raises a TypeError when given a non class object to superclass" do - lambda { + -> { @s.rb_define_class("ClassSpecDefineClass3", Module.new) - }.should raise_error(TypeError) + }.should.raise(TypeError) end it "raises a TypeError when given a mismatched class to superclass" do - lambda { + -> { @s.rb_define_class("ClassSpecDefineClass", Object) - }.should raise_error(TypeError) + }.should.raise(TypeError) + end + + it "raises a ArgumentError when given NULL as superclass" do + -> { + @s.rb_define_class("ClassSpecDefineClass4", nil) + }.should.raise(ArgumentError) end - ruby_version_is "2.4" do - it "raises a ArgumentError when given NULL as superclass" do - lambda { - @s.rb_define_class("ClassSpecDefineClass4", nil) - }.should raise_error(ArgumentError) - end + it "allows arbitrary names, including constant names not valid in Ruby" do + cls = @s.rb_define_class("_INVALID_CLASS", CApiClassSpecs::Super) + cls.name.should == "_INVALID_CLASS" + + -> { + Object.const_get(cls.name) + }.should.raise(NameError, /wrong constant name/) end end @@ -235,8 +339,8 @@ describe "C-API Class function" do cls = @s.rb_define_class_under(CApiClassSpecs, "ClassUnder1", CApiClassSpecs::Super) - cls.should be_kind_of(Class) - CApiClassSpecs::Super.should be_ancestor_of(CApiClassSpecs::ClassUnder1) + cls.should.is_a?(Class) + CApiClassSpecs::ClassUnder1.ancestors.should.include?(CApiClassSpecs::Super) end it "sets the class name" do @@ -251,48 +355,45 @@ describe "C-API Class function" do end it "raises a TypeError when given a non class object to superclass" do - lambda { @s.rb_define_class_under(CApiClassSpecs, + -> { @s.rb_define_class_under(CApiClassSpecs, "ClassUnder5", Module.new) - }.should raise_error(TypeError) - end - - ruby_version_is "2.3" do - it "raises a TypeError when given a mismatched class to superclass" do - CApiClassSpecs::ClassUnder6 = Class.new(CApiClassSpecs::Super) - lambda { @s.rb_define_class_under(CApiClassSpecs, - "ClassUnder6", - Class.new) - }.should raise_error(TypeError) - end + }.should.raise(TypeError) end - ruby_version_is ""..."2.3" do - it "raises a NameError when given a mismatched class to superclass" do - CApiClassSpecs::ClassUnder6 = Class.new(CApiClassSpecs::Super) - lambda { @s.rb_define_class_under(CApiClassSpecs, - "ClassUnder6", - Class.new) - }.should raise_error(NameError) - end + it "raises a TypeError when given a mismatched class to superclass" do + CApiClassSpecs::ClassUnder6 = Class.new(CApiClassSpecs::Super) + -> { @s.rb_define_class_under(CApiClassSpecs, + "ClassUnder6", + Class.new) + }.should.raise(TypeError) + ensure + CApiClassSpecs.send(:remove_const, :ClassUnder6) end it "defines a class for an existing Autoload" do ClassUnderAutoload.name.should == "ClassUnderAutoload" end - ruby_version_is "2.3" do - it "raises a TypeError if class is defined and its superclass mismatches the given one" do - lambda { @s.rb_define_class_under(CApiClassSpecs, "Sub", Object) }.should raise_error(TypeError) - end + it "raises a TypeError if class is defined and its superclass mismatches the given one" do + -> { @s.rb_define_class_under(CApiClassSpecs, "Sub", Object) }.should.raise(TypeError) + end + + it "allows arbitrary names, including constant names not valid in Ruby" do + cls = @s.rb_define_class_under(CApiClassSpecs, "_INVALID_CLASS", CApiClassSpecs::Super) + cls.name.should == "CApiClassSpecs::_INVALID_CLASS" + + -> { + CApiClassSpecs.const_get(cls.name) + }.should.raise(NameError, /wrong constant name/) end end describe "rb_define_class_id_under" do it "creates a subclass of the superclass contained in a module" do cls = @s.rb_define_class_id_under(CApiClassSpecs, :ClassIdUnder1, CApiClassSpecs::Super) - cls.should be_kind_of(Class) - CApiClassSpecs::Super.should be_ancestor_of(CApiClassSpecs::ClassIdUnder1) + cls.should.is_a?(Class) + CApiClassSpecs::ClassIdUnder1.ancestors.should.include?(CApiClassSpecs::Super) end it "sets the class name" do @@ -310,17 +411,24 @@ describe "C-API Class function" do ClassIdUnderAutoload.name.should == "ClassIdUnderAutoload" end - ruby_version_is "2.3" do - it "raises a TypeError if class is defined and its superclass mismatches the given one" do - lambda { @s.rb_define_class_id_under(CApiClassSpecs, :Sub, Object) }.should raise_error(TypeError) - end + it "raises a TypeError if class is defined and its superclass mismatches the given one" do + -> { @s.rb_define_class_id_under(CApiClassSpecs, :Sub, Object) }.should.raise(TypeError) + end + + it "allows arbitrary names, including constant names not valid in Ruby" do + cls = @s.rb_define_class_id_under(CApiClassSpecs, :_INVALID_CLASS2, CApiClassSpecs::Super) + cls.name.should == "CApiClassSpecs::_INVALID_CLASS2" + + -> { + CApiClassSpecs.const_get(cls.name) + }.should.raise(NameError, /wrong constant name/) end end describe "rb_define_class_variable" do it "sets a class variable" do o = CApiClassSpecs::CVars.new - o.rbdcv_cvar.should be_nil + o.rbdcv_cvar.should == nil @s.rb_define_class_variable(CApiClassSpecs::CVars, "@@rbdcv_cvar", 1) o.rbdcv_cvar.should == 1 CApiClassSpecs::CVars.remove_class_variable :@@rbdcv_cvar @@ -333,25 +441,25 @@ describe "C-API Class function" do end it "raises a NameError if the class variable is not defined" do - lambda { + -> { @s.rb_cvar_get(CApiClassSpecs::CVars, "@@no_cvar") - }.should raise_error(NameError, /class variable @@no_cvar/) + }.should.raise(NameError, /class variable @@no_cvar/) end end describe "rb_class_new" do - it "returns an new subclass of the superclass" do + it "returns a new subclass of the superclass" do subclass = @s.rb_class_new(CApiClassSpecs::NewClass) - CApiClassSpecs::NewClass.should be_ancestor_of(subclass) + subclass.ancestors.should.include?(CApiClassSpecs::NewClass) end it "raises a TypeError if passed Class as the superclass" do - lambda { @s.rb_class_new(Class) }.should raise_error(TypeError) + -> { @s.rb_class_new(Class) }.should.raise(TypeError) end it "raises a TypeError if passed a singleton class as the superclass" do metaclass = Object.new.singleton_class - lambda { @s.rb_class_new(metaclass) }.should raise_error(TypeError) + -> { @s.rb_class_new(metaclass) }.should.raise(TypeError) end end @@ -362,7 +470,7 @@ describe "C-API Class function" do end it "returns nil if the class has no superclass" do - @s.rb_class_superclass(BasicObject).should be_nil + @s.rb_class_superclass(BasicObject).should == nil end end @@ -383,4 +491,16 @@ describe "C-API Class function" do @s.rb_class_real(0).should == 0 end end + + describe "rb_class_get_superclass" do + it "returns parent class for a provided class" do + a = Class.new + @s.rb_class_get_superclass(Class.new(a)).should == a + end + + it "returns false when there is no parent class" do + @s.rb_class_get_superclass(BasicObject).should == false + @s.rb_class_get_superclass(Module.new).should == false + end + end end |
