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.rb452
1 files changed, 352 insertions, 100 deletions
diff --git a/spec/ruby/optional/capi/kernel_spec.rb b/spec/ruby/optional/capi/kernel_spec.rb
index d1e3e03582..62eb21448b 100644
--- a/spec/ruby/optional/capi/kernel_spec.rb
+++ b/spec/ruby/optional/capi/kernel_spec.rb
@@ -1,12 +1,21 @@
require_relative 'spec_helper'
+require_relative 'fixtures/kernel'
kernel_path = load_extension("kernel")
+class CApiKernelSpecs::Exc < StandardError
+end
+exception_class = CApiKernelSpecs::Exc
+
describe "C-API Kernel function" do
before :each do
@s = CApiKernelSpecs.new
end
+ after :each do
+ @s.rb_errinfo.should == nil
+ end
+
describe "rb_block_given_p" do
it "returns false if no block is passed" do
@s.should_not.rb_block_given_p
@@ -19,7 +28,7 @@ describe "C-API Kernel function" do
describe "rb_need_block" do
it "raises a LocalJumpError if no block is given" do
- -> { @s.rb_need_block }.should raise_error(LocalJumpError)
+ -> { @s.rb_need_block }.should.raise(LocalJumpError)
end
it "does not raise a LocalJumpError if a block is given" do
@@ -44,7 +53,7 @@ describe "C-API Kernel function" do
it "calls the method with no function callback and no block" do
ary = [1, 3, 5]
- @s.rb_block_call_no_func(ary).should be_kind_of(Enumerator)
+ @s.rb_block_call_no_func(ary).should.is_a?(Enumerator)
end
it "calls the method with no function callback and a block" do
@@ -56,7 +65,7 @@ describe "C-API Kernel function" do
it "can pass extra data to the function" do
ary = [3]
- @s.rb_block_call_extra_data(ary).should equal(ary)
+ @s.rb_block_call_extra_data(ary).should.equal?(ary)
end
end
@@ -69,14 +78,30 @@ describe "C-API Kernel function" do
describe "rb_raise" do
it "raises an exception" do
- -> { @s.rb_raise({}) }.should raise_error(TypeError)
+ -> { @s.rb_raise({}) }.should.raise(TypeError)
end
it "terminates the function at the point it was called" do
h = {}
- -> { @s.rb_raise(h) }.should raise_error(TypeError)
+ -> { @s.rb_raise(h) }.should.raise(TypeError)
h[:stage].should == :before
end
+
+ it "re-raises a rescued exception" do
+ -> do
+ begin
+ raise StandardError, "aaa"
+ rescue Exception
+ begin
+ @s.rb_raise({})
+ rescue TypeError
+ end
+
+ # should raise StandardError "aaa"
+ raise
+ end
+ end.should.raise(StandardError, "aaa")
+ end
end
describe "rb_throw" do
@@ -100,7 +125,7 @@ describe "C-API Kernel function" do
end
it "raises an ArgumentError if there is no catch block for the symbol" do
- -> { @s.rb_throw(nil) }.should raise_error(ArgumentError)
+ -> { @s.rb_throw(nil) }.should.raise(ArgumentError)
end
end
@@ -126,31 +151,21 @@ describe "C-API Kernel function" do
end
it "raises an ArgumentError if there is no catch block for the symbol" do
- -> { @s.rb_throw(nil) }.should raise_error(ArgumentError)
+ -> { @s.rb_throw(nil) }.should.raise(ArgumentError)
end
end
describe "rb_warn" do
- before :each do
- @stderr, $stderr = $stderr, IOStub.new
- @verbose = $VERBOSE
- end
-
- after :each do
- $stderr = @stderr
- $VERBOSE = @verbose
- end
-
it "prints a message to $stderr if $VERBOSE evaluates to true" do
- $VERBOSE = true
- @s.rb_warn("This is a warning")
- $stderr.should =~ /This is a warning/
+ -> {
+ @s.rb_warn("This is a warning")
+ }.should complain(/warning: This is a warning/, verbose: true)
end
it "prints a message to $stderr if $VERBOSE evaluates to false" do
- $VERBOSE = false
- @s.rb_warn("This is a warning")
- $stderr.should =~ /This is a warning/
+ -> {
+ @s.rb_warn("This is a warning")
+ }.should complain(/warning: This is a warning/, verbose: false)
end
end
@@ -158,13 +173,13 @@ describe "C-API Kernel function" do
it "raises an exception from the value of errno" do
-> do
@s.rb_sys_fail("additional info")
- end.should raise_error(SystemCallError, /additional info/)
+ end.should.raise(SystemCallError, /additional info/)
end
it "can take a NULL message" do
-> do
@s.rb_sys_fail(nil)
- end.should raise_error(Errno::EPERM)
+ end.should.raise(Errno::EPERM)
end
end
@@ -172,13 +187,35 @@ describe "C-API Kernel function" do
it "raises an exception from the given error" do
-> do
@s.rb_syserr_fail(Errno::EINVAL::Errno, "additional info")
- end.should raise_error(Errno::EINVAL, /additional info/)
+ end.should.raise(Errno::EINVAL, "Invalid argument - additional info")
end
it "can take a NULL message" do
-> do
@s.rb_syserr_fail(Errno::EINVAL::Errno, nil)
- end.should raise_error(Errno::EINVAL)
+ end.should.raise(Errno::EINVAL, "Invalid argument")
+ end
+
+ it "uses some kind of string as message when errno is unknown" do
+ -> { @s.rb_syserr_fail(-10, nil) }.should.raise(SystemCallError, /[[:graph:]]+/)
+ end
+ end
+
+ describe "rb_syserr_fail_str" do
+ it "raises an exception from the given error" do
+ -> do
+ @s.rb_syserr_fail_str(Errno::EINVAL::Errno, "additional info")
+ end.should.raise(Errno::EINVAL, "Invalid argument - additional info")
+ end
+
+ it "can take nil as a message" do
+ -> do
+ @s.rb_syserr_fail_str(Errno::EINVAL::Errno, nil)
+ end.should.raise(Errno::EINVAL, "Invalid argument")
+ end
+
+ it "uses some kind of string as message when errno is unknown" do
+ -> { @s.rb_syserr_fail_str(-10, nil) }.should.raise(SystemCallError, /[[:graph:]]+/)
end
end
@@ -194,7 +231,7 @@ describe "C-API Kernel function" do
end
it "raises LocalJumpError when no block is given" do
- -> { @s.rb_yield(1) }.should raise_error(LocalJumpError)
+ -> { @s.rb_yield(1) }.should.raise(LocalJumpError)
end
it "rb_yield to a block that breaks does not raise an error" do
@@ -205,10 +242,8 @@ describe "C-API Kernel function" do
@s.rb_yield(1) { break 73 }.should == 73
end
- platform_is_not :"solaris2.10" do # NOTE: i386-pc-solaris2.10
- it "rb_yield through a callback to a block that breaks with a value returns the value" do
- @s.rb_yield_indirected(1) { break 73 }.should == 73
- end
+ it "rb_yield through a callback to a block that breaks with a value returns the value" do
+ @s.rb_yield_indirected(1) { break 73 }.should == 73
end
it "rb_yield to block passed to enumerator" do
@@ -234,7 +269,7 @@ describe "C-API Kernel function" do
end
it "raises LocalJumpError when no block is given" do
- -> { @s.rb_yield_splat([1, 2]) }.should raise_error(LocalJumpError)
+ -> { @s.rb_yield_splat([1, 2]) }.should.raise(LocalJumpError)
end
end
@@ -266,7 +301,7 @@ describe "C-API Kernel function" do
end
it "raises LocalJumpError when no block is given" do
- -> { @s.rb_yield_splat([1, 2]) }.should raise_error(LocalJumpError)
+ -> { @s.rb_yield_splat([1, 2]) }.should.raise(LocalJumpError)
end
end
@@ -294,30 +329,37 @@ describe "C-API Kernel function" do
it "will allow cleanup code to run after a raise" do
proof = [] # Hold proof of work performed after the yield.
-> do
- @s.rb_protect_yield(77, proof) { |x| raise NameError}
- end.should raise_error(NameError)
+ @s.rb_protect_yield(77, proof) { |x| raise NameError }
+ end.should.raise(NameError)
proof[0].should == 23
end
it "will return nil if an error was raised" do
proof = [] # Hold proof of work performed after the yield.
-> do
- @s.rb_protect_yield(77, proof) { |x| raise NameError}
- end.should raise_error(NameError)
+ @s.rb_protect_yield(77, proof) { |x| raise NameError }
+ end.should.raise(NameError)
proof[0].should == 23
proof[1].should == nil
end
it "accepts NULL as status and returns nil if it failed" do
@s.rb_protect_null_status(42) { |x| x + 1 }.should == 43
- @s.rb_protect_null_status(42) { |x| raise }.should == nil
+ @s.rb_protect_null_status(42) { |x| raise NameError }.should == nil
+ @s.rb_errinfo().should.is_a? NameError
+ ensure
+ @s.rb_set_errinfo(nil)
end
- it "populates errinfo with the captured exception" do
+ it "populates rb_errinfo() with the captured exception" do
proof = []
- @s.rb_protect_errinfo(77, proof) { |x| raise NameError }.class.should == NameError
+ @s.rb_protect_ignore_status(77, proof) { |x| raise NameError }
+ @s.rb_errinfo().should.is_a? NameError
+ # Note: on CRuby $! is the NameError here, but not clear if that is desirable or bug
proof[0].should == 23
proof[1].should == nil
+ ensure
+ @s.rb_set_errinfo(nil)
end
end
@@ -333,7 +375,7 @@ describe "C-API Kernel function" do
proof = []
-> do
@s.rb_eval_string_protect('raise RuntimeError', proof)
- end.should raise_error(RuntimeError)
+ end.should.raise(RuntimeError)
proof.should == [23, nil]
end
end
@@ -374,16 +416,28 @@ describe "C-API Kernel function" do
end
it "raises an exception if passed function raises an exception other than StandardError" do
- -> { @s.rb_rescue(@exc_error_proc, nil, @rescue_proc_returns_arg, nil) }.should raise_error(Exception)
+ -> { @s.rb_rescue(@exc_error_proc, nil, @rescue_proc_returns_arg, nil) }.should.raise(Exception)
end
it "raises an exception if any exception is raised inside the 'rescue function'" do
- -> { @s.rb_rescue(@std_error_proc, nil, @std_error_proc, nil) }.should raise_error(StandardError)
+ -> { @s.rb_rescue(@std_error_proc, nil, @std_error_proc, nil) }.should.raise(StandardError)
end
- it "makes $! available only during the 'rescue function' execution" do
- @s.rb_rescue(@std_error_proc, nil, -> *_ { $! }, nil).class.should == StandardError
+ it "sets $! and rb_errinfo() during the 'rescue function' execution" do
+ @s.rb_rescue(-> *_ { raise exception_class, '' }, nil, -> _, exc {
+ exc.should.is_a?(exception_class)
+ $!.should.equal?(exc)
+ @s.rb_errinfo.should.equal?(exc)
+ }, nil)
+
+ @s.rb_rescue(-> _ { @s.rb_raise({}) }, nil, -> _, exc {
+ exc.should.is_a?(TypeError)
+ $!.should.equal?(exc)
+ @s.rb_errinfo.should.equal?(exc)
+ }, nil)
+
$!.should == nil
+ @s.rb_errinfo.should == nil
end
it "returns the break value if the passed function yields to a block with a break" do
@@ -401,7 +455,7 @@ describe "C-API Kernel function" do
describe "rb_rescue2" do
it "only rescues if one of the passed exceptions is raised" do
- proc = -> x { x }
+ proc = -> x, _exc { x }
arg_error_proc = -> *_ { raise ArgumentError, '' }
run_error_proc = -> *_ { raise RuntimeError, '' }
type_error_proc = -> *_ { raise Exception, 'custom error' }
@@ -409,13 +463,30 @@ describe "C-API Kernel function" do
@s.rb_rescue2(run_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError).should == :exc
-> {
@s.rb_rescue2(type_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError)
- }.should raise_error(Exception, 'custom error')
+ }.should.raise(Exception, 'custom error')
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/)
+ }.should.raise(TypeError, /class or module required/)
+ end
+
+ it "sets $! and rb_errinfo() during the 'rescue function' execution" do
+ @s.rb_rescue2(-> *_ { raise exception_class, '' }, :no_exc, -> _, exc {
+ exc.should.is_a?(exception_class)
+ $!.should.equal?(exc)
+ @s.rb_errinfo.should.equal?(exc)
+ }, :exc, exception_class, ScriptError)
+
+ @s.rb_rescue2(-> *_ { @s.rb_raise({}) }, :no_exc, -> _, exc {
+ exc.should.is_a?(TypeError)
+ $!.should.equal?(exc)
+ @s.rb_errinfo.should.equal?(exc)
+ }, :exc, TypeError, ArgumentError)
+
+ $!.should == nil
+ @s.rb_errinfo.should == nil
end
end
@@ -434,12 +505,12 @@ describe "C-API Kernel function" do
throw :thrown_value
ScratchPad << :after_throw
end
- @s.rb_catch("thrown_value", proc).should be_nil
+ @s.rb_catch("thrown_value", proc).should == nil
ScratchPad.recorded.should == [:before_throw]
end
it "raises an ArgumentError if the throw symbol isn't caught" do
- -> { @s.rb_catch("foo", -> { throw :bar }) }.should raise_error(ArgumentError)
+ -> { @s.rb_catch("foo", -> { throw :bar }) }.should.raise(ArgumentError)
end
end
@@ -460,12 +531,46 @@ describe "C-API Kernel function" do
throw @tag
ScratchPad << :after_throw
end
- @s.rb_catch_obj(@tag, proc).should be_nil
+ @s.rb_catch_obj(@tag, proc).should == nil
ScratchPad.recorded.should == [:before_throw]
end
it "raises an ArgumentError if the throw symbol isn't caught" do
- -> { @s.rb_catch("foo", -> { throw :bar }) }.should raise_error(ArgumentError)
+ -> { @s.rb_catch("foo", -> { throw :bar }) }.should.raise(ArgumentError)
+ end
+ end
+
+ describe "rb_category_warn" do
+ it "emits a warning into stderr" do
+ Warning[:deprecated] = true
+
+ -> {
+ @s.rb_category_warn_deprecated
+ }.should complain(/warning: foo/, verbose: true)
+ end
+
+ it "supports printf format modifiers" do
+ Warning[:deprecated] = true
+
+ -> {
+ @s.rb_category_warn_deprecated_with_integer_extra_value(42)
+ }.should complain(/warning: foo 42/, verbose: true)
+ end
+
+ it "does not emits a warning when a category is disabled" do
+ Warning[:deprecated] = false
+
+ -> {
+ @s.rb_category_warn_deprecated
+ }.should_not complain(verbose: true)
+ end
+
+ it "does not emits a warning when $VERBOSE is nil" do
+ Warning[:deprecated] = true
+
+ -> {
+ @s.rb_category_warn_deprecated
+ }.should_not complain(verbose: nil)
end
end
@@ -485,16 +590,37 @@ describe "C-API Kernel function" do
it "executes passed 'ensure function' when an exception is raised" do
foo = nil
- raise_proc = -> { raise '' }
+ raise_proc = -> _ { raise exception_class }
ensure_proc = -> x { foo = x }
- @s.rb_ensure(raise_proc, nil, ensure_proc, :foo) rescue nil
+ -> {
+ @s.rb_ensure(raise_proc, nil, ensure_proc, :foo)
+ }.should.raise(exception_class)
foo.should == :foo
end
+ it "sets $! and rb_errinfo() during the 'ensure function' execution" do
+ -> {
+ @s.rb_ensure(-> _ { raise exception_class }, nil, -> _ {
+ $!.should.is_a?(exception_class)
+ @s.rb_errinfo.should.is_a?(exception_class)
+ }, nil)
+ }.should.raise(exception_class)
+
+ -> {
+ @s.rb_ensure(-> _ { @s.rb_raise({}) }, nil, -> _ {
+ $!.should.is_a?(TypeError)
+ @s.rb_errinfo.should.is_a?(TypeError)
+ }, nil)
+ }.should.raise(TypeError)
+
+ $!.should == nil
+ @s.rb_errinfo.should == nil
+ end
+
it "raises the same exception raised inside passed function" do
raise_proc = -> *_ { raise RuntimeError, 'foo' }
proc = -> *_ { }
- -> { @s.rb_ensure(raise_proc, nil, proc, nil) }.should raise_error(RuntimeError, 'foo')
+ -> { @s.rb_ensure(raise_proc, nil, proc, nil) }.should.raise(RuntimeError, 'foo')
end
end
@@ -502,12 +628,38 @@ 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
+
+ ruby_version_is ""..."4.0" do
+ 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
end
describe "rb_block_proc" do
it "converts the implicit block into a proc" do
proc = @s.rb_block_proc { 1+1 }
- proc.should be_kind_of(Proc)
+ proc.should.is_a?(Proc)
proc.call.should == 2
proc.should_not.lambda?
end
@@ -515,7 +667,7 @@ describe "C-API Kernel function" do
it "passes through an existing lambda and does not convert to a proc" do
b = -> { 1+1 }
proc = @s.rb_block_proc(&b)
- proc.should equal(b)
+ proc.should.equal?(b)
proc.call.should == 2
proc.should.lambda?
end
@@ -524,7 +676,7 @@ describe "C-API Kernel function" do
describe "rb_block_lambda" do
it "converts the implicit block into a lambda" do
proc = @s.rb_block_lambda { 1+1 }
- proc.should be_kind_of(Proc)
+ proc.should.is_a?(Proc)
proc.call.should == 2
proc.should.lambda?
end
@@ -532,7 +684,7 @@ describe "C-API Kernel function" do
it "passes through an existing Proc and does not convert to a lambda" do
b = proc { 1+1 }
proc = @s.rb_block_lambda(&b)
- proc.should equal(b)
+ proc.should.equal?(b)
proc.call.should == 2
proc.should_not.lambda?
end
@@ -551,6 +703,12 @@ describe "C-API Kernel function" do
end
end
+ describe "ruby_vm_at_exit" do
+ it "runs a C function after the VM is terminated" do
+ ruby_exe("require #{kernel_path.inspect}; CApiKernelSpecs.new.ruby_vm_at_exit").should == "ruby_vm_at_exit hook ran\n"
+ end
+ end
+
describe "rb_f_sprintf" do
it "returns a string according to format and arguments" do
@s.rb_f_sprintf(["%d %f %s", 10, 2.5, "test"]).should == "10 2.500000 test"
@@ -561,7 +719,7 @@ describe "C-API Kernel function" do
it "returns a caller backtrace" do
backtrace = @s.rb_make_backtrace
lines = backtrace.select {|l| l =~ /#{__FILE__}/ }
- lines.should_not be_empty
+ lines.should_not.empty?
end
end
@@ -578,47 +736,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
+
+ it "calls a protected method" do
+ object = CApiKernelSpecs::ClassWithProtectedMethod.new
+ @s.rb_funcallv(object, :protected_method, []).should == :protected
+ end
+ 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}], {}]
+ 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
- -> {
- @s.rb_funcallv_kw(self, :m, [42])
- }.should raise_error(TypeError, 'no implicit conversion of Integer into Hash')
+ 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(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
@@ -637,7 +813,7 @@ describe "C-API Kernel function" do
end
it "does not call a private method" do
- -> { @s.rb_funcallv_public(@obj, :method_private) }.should raise_error(NoMethodError, /private/)
+ -> { @s.rb_funcallv_public(@obj, :method_private) }.should.raise(NoMethodError, /private/)
end
end
@@ -657,21 +833,97 @@ 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(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(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(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(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
+
+ describe "rb_str_format" do
+ it "returns a string according to format and arguments" do
+ @s.rb_str_format(3, [10, 2.5, "test"], "%d %f %s").should == "10 2.500000 test"
end
end
end