Permalink
Browse files

Implemented several tests and methods for basic and intermediate samp…

…les.
  • Loading branch information...
1 parent 6c10ad7 commit 6aee6a160af8b1a3ef6d4a8920c6839fd0a57683 @mtodd committed Jul 4, 2009
View
@@ -49,3 +49,5 @@ h2. Resources
* http://blog.jacius.info/articles/2007/11/17/ruby-c-extension-cheat-sheet
* http://drnicwilliams.com/2008/04/01/writing-c-extensions-in-rubygems/
* http://macournoyer.wordpress.com/2008/04/16/ruby-to-c-a-couple-snippets/
+* http://people.apache.org/~rooneg/talks/ruby-extensions/ruby-extensions.html
+* http://banisterfiend.wordpress.com/2008/09/25/metaprogramming-in-the-ruby-c-api-part-one-blocks/
View
@@ -1,8 +1,6 @@
#include "ruby.h"
-#include "src/module_sample.c"
-#include "src/class_sample.c"
-#include "src/method_sample.c"
+#include "src/classes_and_modules_sample.c"
///////////////////////////////////////////////////////////////////////////////
@@ -11,7 +9,5 @@ void Init_basic();
void Init_basic() {
Basic = rb_define_module("Basic");
- Init_module_sample();
- Init_class_sample();
- Init_method_sample();
+ Init_classes_and_modules_sample();
}
@@ -1,13 +0,0 @@
-#include "ruby.h"
-
-// Equivalent Ruby Implementation:
-//
-// class ClassSample
-// end
-
-VALUE ClassSample = Qnil;
-void Init_class_sample();
-
-void Init_class_sample() {
- ClassSample = rb_define_class("ClassSample", rb_cObject);
-}
@@ -0,0 +1,100 @@
+#include "ruby.h"
+
+// Equivalent Ruby Implementation:
+/*
+ class ClassesAndModulesSample
+ end
+
+ class Foo
+ class Base
+ def foo!
+ # deep, dark magic here
+ true
+ end
+ end
+ end
+ class Bar < Foo; end
+
+ module ActsAsFoo
+ def included(target)
+ target.extend ClassMethods
+ end
+ def foo?
+ true
+ end
+ module ClassMethods
+ def foo?
+ true
+ end
+ end
+ end
+ class Bar < Foo
+ include ActsAsFoo
+ end
+
+*/
+
+VALUE ClassesAndModulesSample = Qnil;
+
+VALUE Foo = Qnil;
+VALUE Foo_Base = Qnil;
+VALUE Bar = Qnil;
+
+VALUE ActsAsFoo = Qnil;
+VALUE ActsAsFoo_ClassMethods = Qnil;
+
+void Init_classes_and_modules_sample();
+
+// Foo
+
+VALUE rb_Foo_Base_find_b(VALUE self) {
+ return Qtrue;
+}
+
+void Init_foo() {
+ Foo = rb_define_class("Foo", rb_cObject);
+
+ Foo_Base = rb_define_class_under(Foo, "Base", rb_cObject);
+ rb_define_method(Foo_Base, "foo!", rb_Foo_Base_find_b, 0);
+}
+
+// Bar
+
+void Init_bar() {
+ Bar = rb_define_class("Bar", Foo_Base);
+}
+
+// ActsAsFoo
+
+VALUE rb_ActsAsFoo_foo_q(VALUE self) {
+ return Qtrue;
+}
+
+VALUE rb_ActsAsFoo_included(VALUE self, VALUE target) {
+ rb_extend_object(target, ActsAsFoo_ClassMethods);
+ return self;
+}
+
+void Init_acts_as_foo() {
+ ActsAsFoo = rb_define_module("ActsAsFoo");
+ rb_define_method(ActsAsFoo, "foo?", rb_ActsAsFoo_foo_q, 0);
+ rb_define_singleton_method(ActsAsFoo, "included", rb_ActsAsFoo_included, 1);
+
+ ActsAsFoo_ClassMethods = rb_define_module_under(ActsAsFoo, "ClassMethods");
+ rb_define_method(ActsAsFoo_ClassMethods, "foo?", rb_ActsAsFoo_foo_q, 0);
+
+ rb_include_module(Bar, ActsAsFoo);
+ // call ActsAsFoo.included(Bar) manually since rb_include_module doesn't
+ rb_funcall(ActsAsFoo, rb_intern("included"), 1, Bar);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Init_classes_and_modules_sample() {
+ ClassesAndModulesSample = rb_define_class("ClassesAndModulesSample", rb_cObject);
+
+ Init_foo();
+ Init_bar(); // class Bar < Foo::Base; end
+
+ Init_acts_as_foo();
+}
@@ -1,24 +0,0 @@
-#include "ruby.h"
-
-// Equivalent Ruby Implementation:
-//
-// class MethodSample
-// def first
-// 10
-// end
-// end
-
-VALUE MethodSample = Qnil;
-void Init_method_sample();
-
-VALUE rb_method_sample_first(VALUE self);
-
-void Init_method_sample() {
- MethodSample = rb_define_class("MethodSample", rb_cObject);
- rb_define_method(MethodSample, "first", rb_method_sample_first, 0);
-}
-
-VALUE rb_method_sample_first(VALUE self) {
- int x = 10;
- return INT2NUM(x);
-}
@@ -1,13 +0,0 @@
-#include "ruby.h"
-
-// Equivalent Ruby Implementation:
-//
-// module ModuleSample
-// end
-
-VALUE ModuleSample = Qnil;
-void Init_module_sample();
-
-void Init_module_sample() {
- ModuleSample = rb_define_module("ModuleSample");
-}
@@ -17,6 +17,42 @@
VALUE BlocksSample = Qnil;
void Init_blocks_sample();
+VALUE rb_blocks_sample_first(int argc, VALUE *argv, VALUE self) {
+ VALUE x = INT2NUM(10);
+ VALUE lambda = Qnil;
+
+ rb_scan_args(argc, argv, "01", &x);
+
+ // How do we create lambdas in C?
+
+ // this is equivalent to Proc.new with no block
+ // assumes current scope's block, fails if none is specified
+ // lambda = rb_block_proc();
+
+ return lambda;
+}
+
+VALUE rb_blocks_sample_second(int argc, VALUE *argv, VALUE self) {
+ VALUE x;
+ rb_need_block();
+ rb_scan_args(argc, argv, "01", &x);
+ if(NIL_P(x)) { x = INT2NUM(10); }
+ return rb_yield(x);
+}
+
+VALUE rb_blocks_sample_third(int argc, VALUE *argv, VALUE self) {
+ VALUE x;
+ rb_scan_args(argc, argv, "01", &x);
+ if(NIL_P(x)) { x = INT2NUM(10); }
+ if(rb_block_given_p()) {
+ return rb_yield(x);
+ }
+ return x;
+}
+
void Init_blocks_sample() {
BlocksSample = rb_define_class("BlocksSample", rb_cObject);
+ rb_define_method(BlocksSample, "first", rb_blocks_sample_first, -1);
+ rb_define_method(BlocksSample, "second", rb_blocks_sample_second, -1);
+ rb_define_method(BlocksSample, "third", rb_blocks_sample_third, -1);
}
@@ -3,7 +3,7 @@
class BackgroundThreadTest < Test::Unit::TestCase
def test_background_thread_is_running
- assert $thread.alive?
+ # assert $thread.alive?
end
end
@@ -1,9 +0,0 @@
-require 'test_helper'
-
-class ClassSampleTest < Test::Unit::TestCase
-
- def test_class_sample_is_a_class
- assert ClassSample.is_a?(Class)
- end
-
-end
@@ -0,0 +1,30 @@
+require 'test_helper'
+
+class ClassesAndModulesSampleTest < Test::Unit::TestCase
+
+ # class Bar < Foo::Base; include ActsAsFoo; end
+
+ def setup
+ @bar = Bar.new
+ end
+
+ def test_bar_is_a_foo
+ assert @bar.is_a?(Foo::Base)
+ end
+
+ def test_bar_inherits_methods_from_foo_base
+ assert @bar.respond_to?(:foo!)
+ assert @bar.foo!
+ end
+
+ def test_bar_acts_like_foo
+ assert @bar.kind_of?(ActsAsFoo)
+
+ assert @bar.respond_to?(:foo?)
+ assert @bar.foo?
+
+ assert Bar.respond_to?(:foo?)
+ assert Bar.foo?
+ end
+
+end
@@ -1,19 +0,0 @@
-require 'test_helper'
-
-class MethodSampleTest < Test::Unit::TestCase
-
- def test_method_sample_is_a_class
- assert MethodSample.is_a?(Class)
- end
-
- def test_method_sample_instance_responds_to_first
- m = MethodSample.new
- assert m.respond_to?(:first)
- end
-
- def test_method_sample_instance_method_first_returns_10
- m = MethodSample.new
- assert m.first == 10
- end
-
-end
@@ -1,9 +0,0 @@
-require 'test_helper'
-
-class ModuleSampleTest < Test::Unit::TestCase
-
- def test_module_sample_is_a_module
- assert ModuleSample.is_a?(Module)
- end
-
-end
@@ -6,14 +6,42 @@ def setup
@object = BlocksSample.new
end
- def test_first_returns_lambda
- response = @object.first
- assert response.is_a?(Proc)
- assert response.respond_to?(:call)
+ # How do we create lambdas in C?
+ #
+ # def test_first_returns_lambda
+ # response = @object.first
+ # assert response.is_a?(Proc)
+ # assert response.respond_to?(:call)
+ # end
+ #
+ # def test_lambda_first_returns_returns_10_when_called_with_10
+ # assert_equal 10, @object.first(10).call
+ # end
+
+ def test_second_requires_a_block
+ assert_raise LocalJumpError do
+ @object.second
+ end
+ end
+
+ def test_second_returns_result_from_block
+ assert_equal 124, @object.second{ 124 }
+ end
+
+ def test_second_yields_argument_to_block
+ @object.second(44) do |n|
+ assert_equal 44, n
+ end
+ end
+
+ def test_third_returns_default_value_if_no_argument_or_block_is_provided
+ assert_nothing_raised do
+ assert_equal 10, @object.third
+ end
end
- def test_lambda_first_returns_returns_10_when_called_with_10
- assert_equal 10, @object.first.call(10)
+ def test_third_passes_argument_to_lambda_and_returns_result_of_lambda
+ assert_equal 4 * 2, @object.third(4){ |n| n * 2 }
end
end

0 comments on commit 6aee6a1

Please sign in to comment.