diff options
Diffstat (limited to 'spec/ruby/optional/capi/kernel_spec.rb')
-rw-r--r-- | spec/ruby/optional/capi/kernel_spec.rb | 189 |
1 files changed, 151 insertions, 38 deletions
diff --git a/spec/ruby/optional/capi/kernel_spec.rb b/spec/ruby/optional/capi/kernel_spec.rb index d1e3e03582..3b61d4f0f1 100644 --- a/spec/ruby/optional/capi/kernel_spec.rb +++ b/spec/ruby/optional/capi/kernel_spec.rb @@ -1,4 +1,5 @@ require_relative 'spec_helper' +require_relative 'fixtures/kernel' kernel_path = load_extension("kernel") @@ -502,6 +503,30 @@ describe "C-API Kernel function" do it "evaluates a string of ruby code" do @s.rb_eval_string("1+1").should == 2 end + + it "captures local variables when called within a method" do + a = 2 + @s.rb_eval_string("a+1").should == 3 + end + end + + describe "rb_eval_cmd_kw" do + it "evaluates a string of ruby code" do + @s.rb_eval_cmd_kw("1+1", [], 0).should == 2 + end + + it "calls a proc with the supplied arguments" do + @s.rb_eval_cmd_kw(-> *x { x.map { |i| i + 1 } }, [1, 3, 7], 0).should == [2, 4, 8] + end + + it "calls a proc with keyword arguments if kw_splat is non zero" do + a_proc = -> *x, **y { + res = x.map { |i| i + 1 } + y.each { |k, v| res << k; res << v } + res + } + @s.rb_eval_cmd_kw(a_proc, [1, 3, 7, {a: 1, b: 2, c: 3}], 1).should == [2, 4, 8, :a, 1, :b, 2, :c, 3] + end end describe "rb_block_proc" do @@ -578,47 +603,65 @@ describe "C-API Kernel function" do @s.rb_funcallv(self, :empty, []).should == 42 @s.rb_funcallv(self, :sum, [1, 2]).should == 3 end - end - ruby_version_is "3.0" do - describe "rb_funcallv_kw" do - it "passes keyword arguments to the callee" do - def m(*args, **kwargs) - [args, kwargs] - end + it "calls a private method" do + object = CApiKernelSpecs::ClassWithPrivateMethod.new + @s.rb_funcallv(object, :private_method, []).should == :private + end - @s.rb_funcallv_kw(self, :m, [{}]).should == [[], {}] - @s.rb_funcallv_kw(self, :m, [{a: 1}]).should == [[], {a: 1}] - @s.rb_funcallv_kw(self, :m, [{b: 2}, {a: 1}]).should == [[{b: 2}], {a: 1}] - @s.rb_funcallv_kw(self, :m, [{b: 2}, {}]).should == [[{b: 2}], {}] + it "calls a protected method" do + object = CApiKernelSpecs::ClassWithProtectedMethod.new + @s.rb_funcallv(object, :protected_method, []).should == :protected + end + end + + describe "rb_funcallv_kw" do + it "passes keyword arguments to the callee" do + def m(*args, **kwargs) + [args, kwargs] end - it "raises TypeError if the last argument is not a Hash" do - def m(*args, **kwargs) - [args, kwargs] - end + @s.rb_funcallv_kw(self, :m, [{}]).should == [[], {}] + @s.rb_funcallv_kw(self, :m, [{a: 1}]).should == [[], {a: 1}] + @s.rb_funcallv_kw(self, :m, [{b: 2}, {a: 1}]).should == [[{b: 2}], {a: 1}] + @s.rb_funcallv_kw(self, :m, [{b: 2}, {}]).should == [[{b: 2}], {}] + end + + it "calls a private method" do + object = CApiKernelSpecs::ClassWithPrivateMethod.new + @s.rb_funcallv_kw(object, :private_method, [{}]).should == :private + end + + it "calls a protected method" do + object = CApiKernelSpecs::ClassWithProtectedMethod.new + @s.rb_funcallv_kw(object, :protected_method, [{}]).should == :protected + end - -> { - @s.rb_funcallv_kw(self, :m, [42]) - }.should raise_error(TypeError, 'no implicit conversion of Integer into Hash') + it "raises TypeError if the last argument is not a Hash" do + def m(*args, **kwargs) + [args, kwargs] end + + -> { + @s.rb_funcallv_kw(self, :m, [42]) + }.should raise_error(TypeError, 'no implicit conversion of Integer into Hash') end + end - describe "rb_keyword_given_p" do - it "returns whether keywords were given to the C extension method" do - h = {a: 1} - empty = {} - @s.rb_keyword_given_p(a: 1).should == true - @s.rb_keyword_given_p("foo" => "bar").should == true - @s.rb_keyword_given_p(**h).should == true + describe "rb_keyword_given_p" do + it "returns whether keywords were given to the C extension method" do + h = {a: 1} + empty = {} + @s.rb_keyword_given_p(a: 1).should == true + @s.rb_keyword_given_p("foo" => "bar").should == true + @s.rb_keyword_given_p(**h).should == true - @s.rb_keyword_given_p(h).should == false - @s.rb_keyword_given_p().should == false - @s.rb_keyword_given_p(**empty).should == false + @s.rb_keyword_given_p(h).should == false + @s.rb_keyword_given_p().should == false + @s.rb_keyword_given_p(**empty).should == false - @s.rb_funcallv_kw(@s, :rb_keyword_given_p, [{a: 1}]).should == true - @s.rb_funcallv_kw(@s, :rb_keyword_given_p, [{}]).should == false - end + @s.rb_funcallv_kw(@s, :rb_keyword_given_p, [{a: 1}]).should == true + @s.rb_funcallv_kw(@s, :rb_keyword_given_p, [{}]).should == false end end @@ -657,21 +700,91 @@ describe "C-API Kernel function" do end describe 'rb_funcall_with_block' do - before :each do + it "calls a method with block" do @obj = Object.new class << @obj - def method_public; yield end - def method_private; yield end - private :method_private + def method_public(*args); [args, yield] end end + + @s.rb_funcall_with_block(@obj, :method_public, [1, 2], proc { :result }).should == [[1, 2], :result] end - it "calls a method with block" do - @s.rb_funcall_with_block(@obj, :method_public, proc { :result }).should == :result + it "does not call a private method" do + object = CApiKernelSpecs::ClassWithPrivateMethod.new + + -> { + @s.rb_funcall_with_block(object, :private_method, [], proc { }) + }.should raise_error(NoMethodError, /private/) + end + + it "does not call a protected method" do + object = CApiKernelSpecs::ClassWithProtectedMethod.new + + -> { + @s.rb_funcall_with_block(object, :protected_method, [], proc { }) + }.should raise_error(NoMethodError, /protected/) + end + end + + describe 'rb_funcall_with_block_kw' do + it "calls a method with keyword arguments and a block" do + @obj = Object.new + class << @obj + def method_public(*args, **kw, &block); [args, kw, block.call] end + end + + @s.rb_funcall_with_block_kw(@obj, :method_public, [1, 2, {a: 2}], proc { :result }).should == [[1, 2], {a: 2}, :result] end it "does not call a private method" do - -> { @s.rb_funcall_with_block(@obj, :method_private, proc { :result }) }.should raise_error(NoMethodError, /private/) + object = CApiKernelSpecs::ClassWithPrivateMethod.new + + -> { + @s.rb_funcall_with_block_kw(object, :private_method, [{}], proc { }) + }.should raise_error(NoMethodError, /private/) + end + + it "does not call a protected method" do + object = CApiKernelSpecs::ClassWithProtectedMethod.new + + -> { + @s.rb_funcall_with_block_kw(object, :protected_method, [{}], proc { }) + }.should raise_error(NoMethodError, /protected/) + end + end + + describe "rb_check_funcall" do + it "calls a method" do + @s.rb_check_funcall(1, :+, [2]).should == 3 + end + + it "returns Qundef if the method is not defined" do + obj = Object.new + @s.rb_check_funcall(obj, :foo, []).should == :Qundef + end + + it "uses #respond_to? to check if the method is defined" do + ScratchPad.record [] + obj = Object.new + def obj.respond_to?(name, priv) + ScratchPad << name + name == :foo || super + end + def obj.method_missing(name, *args) + name == :foo ? [name, 42] : super + end + @s.rb_check_funcall(obj, :foo, []).should == [:foo, 42] + ScratchPad.recorded.should == [:foo] + end + + it "calls a private method" do + object = CApiKernelSpecs::ClassWithPrivateMethod.new + @s.rb_check_funcall(object, :private_method, []).should == :private + end + + it "calls a protected method" do + object = CApiKernelSpecs::ClassWithProtectedMethod.new + @s.rb_check_funcall(object, :protected_method, []).should == :protected end end end |