summaryrefslogtreecommitdiff
path: root/spec/ruby/optional
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/optional')
-rw-r--r--spec/ruby/optional/capi/ext/proc_spec.c59
-rw-r--r--spec/ruby/optional/capi/ext/thread_spec.c36
-rw-r--r--spec/ruby/optional/capi/proc_spec.rb27
-rw-r--r--spec/ruby/optional/capi/thread_spec.rb10
4 files changed, 132 insertions, 0 deletions
diff --git a/spec/ruby/optional/capi/ext/proc_spec.c b/spec/ruby/optional/capi/ext/proc_spec.c
index e0bd8b1bbc..1137f4156b 100644
--- a/spec/ruby/optional/capi/ext/proc_spec.c
+++ b/spec/ruby/optional/capi/ext/proc_spec.c
@@ -11,10 +11,63 @@ VALUE proc_spec_rb_proc_new_function(RB_BLOCK_CALL_FUNC_ARGLIST(args, dummy)) {
return rb_funcall(args, rb_intern("inspect"), 0);
}
+VALUE proc_spec_rb_proc_new_function_arg(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ return arg;
+}
+
+VALUE proc_spec_rb_proc_new_function_argc(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ return INT2FIX(argc);
+}
+
+VALUE proc_spec_rb_proc_new_function_argv_n(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ int n = FIX2INT(arg);
+ if (n < argc) {
+ return argv[n];
+ } else {
+ rb_exc_raise(rb_exc_new2(rb_eArgError, "Arg index out of bounds."));
+ }
+}
+
+VALUE proc_spec_rb_proc_new_function_callback_arg(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ return callback_arg;
+}
+
+VALUE proc_spec_rb_proc_new_function_blockarg(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ return blockarg;
+}
+
+VALUE proc_spec_rb_proc_new_function_block_given_p(VALUE arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg) {
+ return rb_block_given_p() ? Qtrue : Qfalse;
+}
+
VALUE proc_spec_rb_proc_new(VALUE self) {
return rb_proc_new(proc_spec_rb_proc_new_function, Qnil);
}
+VALUE proc_spec_rb_proc_new_arg(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_arg, Qnil);
+}
+
+VALUE proc_spec_rb_proc_new_argc(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_argc, Qnil);
+}
+
+VALUE proc_spec_rb_proc_new_argv_n(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_argv_n, Qnil);
+}
+
+VALUE proc_spec_rb_proc_new_callback_arg(VALUE self, VALUE arg) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_callback_arg, arg);
+}
+
+VALUE proc_spec_rb_proc_new_blockarg(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_blockarg, Qnil);
+}
+
+VALUE proc_spec_rb_proc_new_block_given_p(VALUE self) {
+ return rb_proc_new(proc_spec_rb_proc_new_function_block_given_p, Qnil);
+}
+
VALUE proc_spec_rb_proc_arity(VALUE self, VALUE prc) {
return INT2FIX(rb_proc_arity(prc));
}
@@ -62,6 +115,12 @@ VALUE proc_spec_rb_Proc_new(VALUE self, VALUE scenario) {
void Init_proc_spec(void) {
VALUE cls = rb_define_class("CApiProcSpecs", rb_cObject);
rb_define_method(cls, "rb_proc_new", proc_spec_rb_proc_new, 0);
+ rb_define_method(cls, "rb_proc_new_arg", proc_spec_rb_proc_new_arg, 0);
+ rb_define_method(cls, "rb_proc_new_argc", proc_spec_rb_proc_new_argc, 0);
+ rb_define_method(cls, "rb_proc_new_argv_n", proc_spec_rb_proc_new_argv_n, 0);
+ rb_define_method(cls, "rb_proc_new_callback_arg", proc_spec_rb_proc_new_callback_arg, 1);
+ rb_define_method(cls, "rb_proc_new_blockarg", proc_spec_rb_proc_new_blockarg, 0);
+ rb_define_method(cls, "rb_proc_new_block_given_p", proc_spec_rb_proc_new_block_given_p, 0);
rb_define_method(cls, "rb_proc_arity", proc_spec_rb_proc_arity, 1);
rb_define_method(cls, "rb_proc_call", proc_spec_rb_proc_call, 2);
rb_define_method(cls, "rb_Proc_new", proc_spec_rb_Proc_new, 1);
diff --git a/spec/ruby/optional/capi/ext/thread_spec.c b/spec/ruby/optional/capi/ext/thread_spec.c
index 21f98dec52..bab5fcc211 100644
--- a/spec/ruby/optional/capi/ext/thread_spec.c
+++ b/spec/ruby/optional/capi/ext/thread_spec.c
@@ -11,6 +11,10 @@
#define pipe(p) rb_w32_pipe(p)
#endif
+#ifndef _WIN32
+#include <pthread.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -131,6 +135,36 @@ static VALUE thread_spec_rb_thread_create(VALUE self, VALUE proc, VALUE arg) {
return rb_thread_create(thread_spec_call_proc, (void*)args);
}
+static VALUE thread_spec_ruby_native_thread_p(VALUE self) {
+ if (ruby_native_thread_p()) {
+ return Qtrue;
+ } else {
+ return Qfalse;
+ }
+}
+
+static VALUE false_result = Qfalse;
+static VALUE true_result = Qtrue;
+
+static void *new_thread_check(void *args) {
+ if (ruby_native_thread_p()) {
+ return &true_result;
+ } else {
+ return &false_result;
+ }
+}
+
+static VALUE thread_spec_ruby_native_thread_p_new_thread(VALUE self) {
+#ifndef _WIN32
+ pthread_t t;
+ VALUE *result = &true_result;
+ pthread_create(&t, NULL, new_thread_check, NULL);
+ pthread_join(t, (void **)&result);
+ return *result;
+#else
+ return Qfalse;
+#endif
+}
void Init_thread_spec(void) {
VALUE cls = rb_define_class("CApiThreadSpecs", rb_cObject);
@@ -143,6 +177,8 @@ void Init_thread_spec(void) {
rb_define_method(cls, "rb_thread_wakeup", thread_spec_rb_thread_wakeup, 1);
rb_define_method(cls, "rb_thread_wait_for", thread_spec_rb_thread_wait_for, 2);
rb_define_method(cls, "rb_thread_create", thread_spec_rb_thread_create, 2);
+ rb_define_method(cls, "ruby_native_thread_p", thread_spec_ruby_native_thread_p, 0);
+ rb_define_method(cls, "ruby_native_thread_p_new_thread", thread_spec_ruby_native_thread_p_new_thread, 0);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/proc_spec.rb b/spec/ruby/optional/capi/proc_spec.rb
index 6e797fdeb4..dab143fbe7 100644
--- a/spec/ruby/optional/capi/proc_spec.rb
+++ b/spec/ruby/optional/capi/proc_spec.rb
@@ -7,6 +7,8 @@ describe "C-API Proc function" do
before :each do
@p = CApiProcSpecs.new
@prc = @p.rb_proc_new
+ @prc2 = @p.rb_proc_new_argv_n
+ @prc3 = @p.rb_proc_new_argc
end
describe "rb_proc_new" do
@@ -15,6 +17,7 @@ describe "C-API Proc function" do
end
it "calls the C function wrapped by the Proc instance when sent #call" do
+ @p.rb_proc_new_arg.call().should == nil
@prc.call(:foo_bar).should == ":foo_bar"
@prc.call([:foo, :bar]).should == "[:foo, :bar]"
end
@@ -24,6 +27,30 @@ describe "C-API Proc function" do
@prc[[:foo, :bar]].should == "[:foo, :bar]"
end
+ it "calls the C function with the arg count in argc" do
+ @prc3.call().should == 0
+ @prc3.call(:foo).should == 1
+ @prc3.call(:foo, :bar).should == 2
+ end
+
+ it "calls the C function with arguments in argv" do
+ @prc2.call(1, :foo).should == :foo
+ @prc2.call(2, :foo, :bar).should == :bar
+ -> { @prc2.call(3, :foo, :bar) }.should raise_error(ArgumentError)
+ end
+
+ it "calls the C function with the block passed in blockarg" do
+ a_block = :foo.to_proc
+ @p.rb_proc_new_blockarg.call(&a_block).should == a_block
+ @p.rb_proc_new_blockarg.call().should == nil
+ end
+
+ it "calls the C function and yields to the block passed in blockarg" do
+ @p.rb_proc_new_block_given_p.call() do
+ end.should == false
+ @p.rb_proc_new_block_given_p.call().should == false
+ end
+
it "returns a Proc instance correctly described in #inspect without source location" do
@prc.inspect.should =~ /^#<Proc:([^ :@]*?)>$/
end
diff --git a/spec/ruby/optional/capi/thread_spec.rb b/spec/ruby/optional/capi/thread_spec.rb
index 30e29681eb..5cb46bbb7c 100644
--- a/spec/ruby/optional/capi/thread_spec.rb
+++ b/spec/ruby/optional/capi/thread_spec.rb
@@ -101,6 +101,16 @@ describe "C-API Thread function" do
end
end
+ describe "ruby_native_thread_p" do
+ it "returns non-zero for a ruby thread" do
+ @t.ruby_native_thread_p.should be_true
+ end
+
+ it "returns zero for a non ruby thread" do
+ @t.ruby_native_thread_p_new_thread.should be_false
+ end
+ end
+
describe "rb_thread_call_without_gvl" do
it "runs a C function with the global lock unlocked and can be woken by Thread#wakeup" do
thr = Thread.new do