summaryrefslogtreecommitdiff
path: root/spec/ruby/optional/capi/kernel_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/optional/capi/kernel_spec.rb')
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb202
1 files changed, 186 insertions, 16 deletions
diff --git a/spec/ruby/optional/capi/kernel_spec.rb b/spec/ruby/optional/capi/kernel_spec.rb
index 758d944da9..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")
@@ -412,12 +413,10 @@ describe "C-API Kernel function" do
}.should raise_error(Exception, 'custom error')
end
- ruby_bug "#17305", ""..."2.7" do
- it "raises TypeError if one of the passed exceptions is not a Module" do
- -> {
- @s.rb_rescue2(-> *_ { raise RuntimeError, "foo" }, :no_exc, -> x { x }, :exc, Object.new, 42)
- }.should raise_error(TypeError, /class or module required/)
- end
+ it "raises TypeError if one of the passed exceptions is not a Module" do
+ -> {
+ @s.rb_rescue2(-> *_ { raise RuntimeError, "foo" }, :no_exc, -> x { x }, :exc, Object.new, 42)
+ }.should raise_error(TypeError, /class or module required/)
end
end
@@ -504,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
@@ -567,7 +590,82 @@ describe "C-API Kernel function" do
end
end
- describe "rb_funcall3" do
+ describe "rb_funcallv" do
+ def empty
+ 42
+ end
+
+ def sum(a, b)
+ a + b
+ end
+
+ it "calls a method" do
+ @s.rb_funcallv(self, :empty, []).should == 42
+ @s.rb_funcallv(self, :sum, [1, 2]).should == 3
+ end
+
+ it "calls a private method" do
+ object = CApiKernelSpecs::ClassWithPrivateMethod.new
+ @s.rb_funcallv(object, :private_method, []).should == :private
+ end
+
+ 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
+
+ @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
+
+ 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
+
+ @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
+ end
+
+ describe "rb_funcallv_public" do
before :each do
@obj = Object.new
class << @obj
@@ -578,10 +676,11 @@ describe "C-API Kernel function" do
end
it "calls a public method" do
- @s.rb_funcall3(@obj, :method_public).should == :method_public
+ @s.rb_funcallv_public(@obj, :method_public).should == :method_public
end
+
it "does not call a private method" do
- -> { @s.rb_funcall3(@obj, :method_private) }.should raise_error(NoMethodError, /private/)
+ -> { @s.rb_funcallv_public(@obj, :method_private) }.should raise_error(NoMethodError, /private/)
end
end
@@ -599,22 +698,93 @@ describe "C-API Kernel function" do
@s.rb_funcall_many_args(@obj, :many_args).should == 15.downto(1).to_a
end
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