[macruby-changes] [1495] MacRuby/branches/experimental

source_changes at macosforge.org source_changes at macosforge.org
Mon Apr 27 19:23:46 PDT 2009


Revision: 1495
          http://trac.macosforge.org/projects/ruby/changeset/1495
Author:   lsansonetti at apple.com
Date:     2009-04-27 19:23:44 -0700 (Mon, 27 Apr 2009)
Log Message:
-----------
implemented BridgeSupport constants, some work on Pointer, extracted the objc specs of method_spec.rb into method_objc_spec.rb, started working on pointer_spec.rb

Modified Paths:
--------------
    MacRuby/branches/experimental/objc.m
    MacRuby/branches/experimental/roxor.cpp
    MacRuby/branches/experimental/spec/macruby/method_spec.rb

Added Paths:
-----------
    MacRuby/branches/experimental/spec/macruby/objc_method_spec.rb
    MacRuby/branches/experimental/spec/macruby/pointer_spec.rb

Modified: MacRuby/branches/experimental/objc.m
===================================================================
--- MacRuby/branches/experimental/objc.m	2009-04-27 02:04:56 UTC (rev 1494)
+++ MacRuby/branches/experimental/objc.m	2009-04-28 02:23:44 UTC (rev 1495)
@@ -75,7 +75,7 @@
 static struct st_table *bs_inf_prot_imethods;
 static struct st_table *bs_cftypes;
 
-VALUE rb_cPointer;
+static VALUE rb_cPointer;
 
 struct RPointer
 {
@@ -517,6 +517,7 @@
 
 static void rb_objc_rval_to_ocval(VALUE, const char *, void **);
 
+#if 0
 static VALUE
 rb_pointer_new_with_type(VALUE recv, SEL sel, VALUE type)
 {
@@ -572,6 +573,7 @@
 
     return ret;
 }
+#endif
 
 static bool
 rb_objc_rval_copy_boxed_data(VALUE rval, bs_element_boxed_t *bs_boxed, void *ocval)
@@ -3264,11 +3266,13 @@
     rb_install_boxed_primitives();
 #endif
 
+#if 0
     rb_cPointer = rb_define_class("Pointer", rb_cObject);
     rb_undef_alloc_func(rb_cPointer);
     rb_objc_define_method(*(VALUE *)rb_cPointer, "new_with_type", rb_pointer_new_with_type, 1);
     rb_objc_define_method(rb_cPointer, "assign", rb_pointer_assign, 1);
     rb_objc_define_method(rb_cPointer, "[]", rb_pointer_aref, 1);
+#endif
 
     rb_ivar_type = rb_intern("@__objc_type__");
 

Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp	2009-04-27 02:04:56 UTC (rev 1494)
+++ MacRuby/branches/experimental/roxor.cpp	2009-04-28 02:23:44 UTC (rev 1495)
@@ -203,6 +203,8 @@
 	Function *compile_bs_struct_writer(rb_vm_bs_boxed_t *bs_boxed,
 		int field);
 	Function *compile_ffi_function(void *stub, void *imp, int argc);
+	Function *compile_to_rval_convertor(const char *type);
+	Function *compile_to_ocval_convertor(const char *type);
 
     private:
 	const char *fname;
@@ -477,6 +479,8 @@
 	std::map<Class, std::map<ID, int> *> ivar_slots;
 	std::map<SEL, GlobalVariable *> redefined_ops_gvars;
 	std::map<Class, struct rb_vm_outer *> outers;
+	std::map<std::string, void *> c_stubs, objc_stubs,
+	    to_rval_convertors, to_ocval_convertors;
 
     public:
 	static RoxorVM *current;
@@ -502,8 +506,6 @@
 	std::map<VALUE, rb_vm_catch_t *> catch_jmp_bufs;
 	std::vector<jmp_buf *> return_from_block_jmp_bufs;
 
-	std::map<std::string, void *> c_stubs, objc_stubs;
-
 	bs_parser_t *bs_parser;
 	std::map<std::string, rb_vm_bs_boxed_t *> bs_boxed;
 	std::map<std::string, bs_element_function_t *> bs_funcs;
@@ -516,6 +518,16 @@
 	rb_vm_bs_boxed_t *find_bs_struct(std::string type);
 	rb_vm_bs_boxed_t *find_bs_opaque(std::string type);
 
+	void *gen_stub(std::string types, int argc, bool is_objc);
+	void *gen_to_rval_convertor(std::string type);
+	void *gen_to_ocval_convertor(std::string type);
+
+	void insert_stub(const char *types, void *stub, bool is_objc) {
+	    std::map<std::string, void *> &m =
+		is_objc ? objc_stubs : c_stubs;
+	    m.insert(std::make_pair(types, stub));
+	}
+
 #if ROXOR_ULTRA_LAZY_JIT
 	std::map<SEL, std::map<Class, rb_vm_method_source_t *> *>
 	    method_sources;
@@ -7083,26 +7095,100 @@
     return rb_vm_call(obj, selMethodMissing, argc + 1, new_argv, false);
 }
 
-static void *
-vm_gen_stub(std::string types, int argc, bool is_objc)
+inline void *
+RoxorVM::gen_stub(std::string types, int argc, bool is_objc)
 {
-    std::map<std::string, void *> &stubs = 
-	is_objc ? GET_VM()->objc_stubs : GET_VM()->c_stubs;
+    std::map<std::string, void *> &stubs = is_objc ? objc_stubs : c_stubs;
     std::map<std::string, void *>::iterator iter = stubs.find(types);
     if (iter != stubs.end()) {
 	return iter->second;
     }
 
-    //printf("generating %s stub %s argc %d\n", is_objc ? "objc" : "c", types, argc);
-
     Function *f = RoxorCompiler::shared->compile_stub(types.c_str(), argc,
 	    is_objc);
-    void *stub = (void *)GET_VM()->compile(f);
+    void *stub = (void *)compile(f);
     stubs.insert(std::make_pair(types, stub));
 
     return stub;
 }
 
+Function *
+RoxorCompiler::compile_to_rval_convertor(const char *type)
+{
+    // VALUE foo(void *ocval);
+    Function *f = cast<Function>(module->getOrInsertFunction("",
+		Type::VoidTy, PtrTy, NULL));
+    Function::arg_iterator arg = f->arg_begin();
+    Value *ocval = arg++;
+
+    bb = BasicBlock::Create("EntryBlock", f);
+
+    const Type *llvm_type = convert_type(type); 
+    ocval = new BitCastInst(ocval, PointerType::getUnqual(llvm_type), "", bb);
+    ocval = new LoadInst(ocval, "", bb);
+
+    Value *rval = compile_conversion_to_ruby(type, llvm_type, ocval);
+
+    ReturnInst::Create(rval, bb);
+
+    return f;
+}
+
+inline void *
+RoxorVM::gen_to_rval_convertor(std::string type)
+{
+    std::map<std::string, void *>::iterator iter =
+	to_rval_convertors.find(type);
+    if (iter != to_rval_convertors.end()) {
+	return iter->second;
+    }
+
+    Function *f = RoxorCompiler::shared->compile_to_rval_convertor(
+	    type.c_str());
+    void *convertor = (void *)compile(f);
+    to_rval_convertors.insert(std::make_pair(type, convertor));
+    
+    return convertor; 
+}
+
+Function *
+RoxorCompiler::compile_to_ocval_convertor(const char *type)
+{
+    // void foo(VALUE rval, void **ocval);
+    Function *f = cast<Function>(module->getOrInsertFunction("",
+		Type::VoidTy, RubyObjTy, PtrTy, NULL));
+    Function::arg_iterator arg = f->arg_begin();
+    Value *rval = arg++;
+    Value *ocval = arg++;
+
+    bb = BasicBlock::Create("EntryBlock", f);
+
+    const Type *llvm_type = convert_type(type);
+    ocval = new BitCastInst(ocval, PointerType::getUnqual(llvm_type), "", bb);
+    compile_conversion_to_c(type, rval, ocval);
+
+    ReturnInst::Create(bb);
+
+    return f;
+}
+
+inline void *
+RoxorVM::gen_to_ocval_convertor(std::string type)
+{
+    std::map<std::string, void *>::iterator iter =
+	to_ocval_convertors.find(type);
+    if (iter != to_ocval_convertors.end()) {
+	return iter->second;
+    }
+
+    Function *f = RoxorCompiler::shared->compile_to_ocval_convertor(
+	    type.c_str());
+    void *convertor = (void *)compile(f);
+    to_ocval_convertors.insert(std::make_pair(type, convertor));
+    
+    return convertor; 
+}
+
 static inline void
 vm_gen_bs_func_types(bs_element_function_t *bs_func, std::string &types)
 {
@@ -7196,8 +7282,8 @@
 			    sel_getName(sel));
 		    abort();
 		}
-		ocache.stub = (rb_vm_objc_stub_t *)vm_gen_stub(types, argc,
-			true);
+		ocache.stub = (rb_vm_objc_stub_t *)GET_VM()->gen_stub(types, 
+			argc, true);
 	    }
 	}
 	else {
@@ -7235,8 +7321,8 @@
 		fcache.bs_function = bs_func;
 		fcache.imp = (IMP)dlsym(RTLD_DEFAULT, bs_func->name);
 		assert(fcache.imp != NULL);
-		fcache.stub = (rb_vm_c_stub_t *)vm_gen_stub(types, argc,
-			false);
+		fcache.stub = (rb_vm_c_stub_t *)GET_VM()->gen_stub(types,
+			argc, false);
 	    }
 	    else {
 		// Still nothing, then let's call #method_missing.
@@ -8568,9 +8654,8 @@
 		    bs_const->name);
 	}
 
-	// TODO
-	//rb_objc_ocval_to_rval(sym, bs_const->type, &v);
-	v = INT2FIX(42);
+	void *convertor = GET_VM()->gen_to_rval_convertor(bs_const->type);
+	v = ((VALUE (*)(void *))convertor)(sym);
 
 	CFMutableDictionaryRef iv_dict = rb_class_ivar_dict(rb_cObject);
 	assert(iv_dict != NULL);
@@ -8580,6 +8665,8 @@
     return v;
 }
 
+VALUE rb_cBoxed;
+
 extern "C"
 void
 rb_vm_check_arity(int given, int requested)
@@ -8983,8 +9070,61 @@
     return bs_boxed->bs_type == BS_ELEMENT_OPAQUE ? Qtrue : Qfalse;
 }
 
-VALUE rb_cBoxed;
+VALUE rb_cPointer;
 
+typedef struct {
+    VALUE type;
+    VALUE (*convert_to_rval)(void *);
+    void (*convert_to_ocval)(VALUE rval, void **);
+    void *val;
+} rb_vm_pointer_t;
+
+static VALUE
+rb_pointer_new(VALUE rcv, SEL sel, VALUE type)
+{
+    StringValuePtr(type);
+
+    rb_vm_pointer_t *ptr = (rb_vm_pointer_t *)xmalloc(sizeof(rb_vm_pointer_t));
+    GC_WB(&ptr->type, type);
+
+    const char *type_str = RSTRING_PTR(type);
+    ptr->convert_to_rval =
+	(VALUE (*)(void *))GET_VM()->gen_to_rval_convertor(type_str);
+    ptr->convert_to_ocval =
+	(void (*)(VALUE, void **))GET_VM()->gen_to_ocval_convertor(type_str);
+    ptr->val = NULL; // TODO
+
+    return Data_Wrap_Struct(rb_cPointer, NULL, NULL, ptr);
+}
+
+static VALUE
+rb_pointer_aref(VALUE rcv, SEL sel, VALUE idx)
+{
+    return Qnil;
+}
+
+static VALUE
+rb_pointer_asef(VALUE rcv, SEL sel, VALUE idx, VALUE val)
+{
+    return Qnil;
+}
+
+static VALUE
+rb_pointer_assign(VALUE rcv, SEL sel, VALUE val)
+{
+    return rb_pointer_asef(rcv, 0, FIX2INT(0), val);
+}
+
+static VALUE
+rb_pointer_type(VALUE rcv, SEL sel)
+{
+    rb_vm_pointer_t *ptr;
+
+    Data_Get_Struct(rcv, rb_vm_pointer_t, ptr);
+
+    return ptr->type;
+}
+
 extern "C"
 void
 Init_BridgeSupport(void)
@@ -8996,6 +9136,20 @@
 	    (void *)rb_boxed_is_opaque, 0);
     boxed_ivar_type = rb_intern("__octype__");
 
+    rb_cPointer = rb_define_class("Pointer", rb_cObject);
+    rb_objc_define_method(*(VALUE *)rb_cPointer, "new",
+	    (void *)rb_pointer_new, 1);
+    rb_objc_define_method(*(VALUE *)rb_cPointer, "new_with_type",
+	    (void *)rb_pointer_new, 1);
+    rb_objc_define_method(rb_cPointer, "[]",
+	    (void *)rb_pointer_aref, 1);
+    rb_objc_define_method(rb_cPointer, "[]=",
+	    (void *)rb_pointer_asef, 2);
+    rb_objc_define_method(rb_cPointer, "assign",
+	    (void *)rb_pointer_assign, 1);
+    rb_objc_define_method(rb_cPointer, "type",
+	    (void *)rb_pointer_type, 0);
+
     bs_const_magic_cookie = rb_str_new2("bs_const_magic_cookie");
     rb_objc_retain((void *)bs_const_magic_cookie);
 }
@@ -9475,7 +9629,8 @@
 	types.append(convert_ffi_type(RARRAY_AT(args, i)));
     } 
 
-    rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)vm_gen_stub(types, argc, false);
+    rb_vm_c_stub_t *stub = (rb_vm_c_stub_t *)GET_VM()->gen_stub(types, argc,
+	    false);
     Function *f = RoxorCompiler::shared->compile_ffi_function((void *)stub,
 	    sym, argc);
     IMP imp = GET_VM()->compile(f);
@@ -9507,8 +9662,8 @@
 static void
 setup_builtin_stubs(void)
 {
-    GET_VM()->objc_stubs.insert(std::make_pair("@@:", (void *)builtin_ostub1));
-    GET_VM()->objc_stubs.insert(std::make_pair("#@:", (void *)builtin_ostub1));
+    GET_VM()->insert_stub("@@:", (void *)builtin_ostub1, true);
+    GET_VM()->insert_stub("#@:", (void *)builtin_ostub1, true);
 }
 
 #if ROXOR_ULTRA_LAZY_JIT

Modified: MacRuby/branches/experimental/spec/macruby/method_spec.rb
===================================================================
--- MacRuby/branches/experimental/spec/macruby/method_spec.rb	2009-04-27 02:04:56 UTC (rev 1494)
+++ MacRuby/branches/experimental/spec/macruby/method_spec.rb	2009-04-28 02:23:44 UTC (rev 1495)
@@ -82,375 +82,6 @@
     def @o.isFoo; end
     @o.should_not have_method(:'foo?')
   end
-end
 
-framework 'Foundation'
-
-fixture_source = File.dirname(__FILE__) + '/fixtures/method.m'
-fixture_ext = '/tmp/method.bundle'
-if !File.exist?(fixture_ext) or File.mtime(fixture_source) > File.mtime(fixture_ext)
-=begin
-  # #system is currently broken
-  unless system("/usr/bin/gcc #{fixture_source} -o #{fixture_ext} -g -framework Foundation -dynamiclib -fobjc-gc -arch i386 -arch x86_64 -arch ppc")
-    $stderr.puts "cannot compile fixture source file `#{fixture_source}' - aborting"
-    exit 1
-  end
-=end
-  `/usr/bin/gcc #{fixture_source} -o #{fixture_ext} -g -framework Foundation -dynamiclib -fobjc-gc -arch i386 -arch x86_64 -arch ppc`
+  # TODO add overloading specs
 end
-require '/tmp/method'
-load_bridge_support_file File.dirname(__FILE__) + '/fixtures/method.bridgesupport'
-
-describe "A pure Objective-C method" do
-  before :each do
-    @o = TestMethod.new
-  end
-
-  it "can be called with #foo= if it matches the #setFoo pattern" do
-    o = []
-
-    # TODO Stopped here: This should be sufficient, but doesn't work.
-    # o.should have_method(:'setArray', true)
-    # o.should have_method(:'array=', true)
-
-    o.respond_to?(:'setArray').should == true
-    o.respond_to?(:'array=').should == true
-    o.array = [1, 2, 3]
-    o.should == [1, 2, 3]
-  end
-
-  it "can be called with #foo? if it matches the #isFoo pattern" do
-    o = NSBundle.mainBundle
-    o.respond_to?(:'isLoaded').should == true
-    o.respond_to?(:'loaded?').should == true
-    o.loaded?.should == true
-  end
-
-  it "is only exposed in #methods if the second argument is true" do
-    o = Object.new
-    o.methods.include?(:'performSelector').should == false
-    o.methods(true).include?(:'performSelector').should == false
-    o.methods(false).include?(:'performSelector').should == false
-    o.methods(true, true).include?(:'performSelector').should == true
-    o.methods(false, true).include?(:'performSelector').should == true
-  end
-
-  it "can be called on an immediate object" do
-    123.self.should == 123
-    true.self.should == true
-    false.self.should == false
-    nil.self.should == nil
-  end
-
-  it "returning void returns nil in Ruby" do
-    @o.methodReturningVoid.should == nil
-  end
-
-  it "returning nil returns nil in Ruby" do
-    @o.methodReturningNil.should == nil
-  end
-
-  it "returning self returns the same receiver object" do
-    @o.methodReturningSelf.should == @o
-    @o.methodReturningSelf.object_id == @o.object_id
-  end
-
-  it "returning kCFBooleanTrue returns true in Ruby" do
-    @o.methodReturningCFTrue.should == true
-    @o.methodReturningCFTrue.class.should == TrueClass
-  end
-
-  it "returning kCFBooleanFalse returns false in Ruby" do
-    @o.methodReturningCFFalse.should == false
-    @o.methodReturningCFFalse.class.should == FalseClass
-  end
-
-  it "returning kCFNull returns nil in Ruby" do
-    @o.methodReturningCFNull.should == nil
-    @o.methodReturningCFNull.class.should == NilClass
-  end
-
-  it "returning YES returns true in Ruby" do
-    @o.methodReturningYES.should == true
-  end
-
-  it "returning NO returns true in Ruby" do
-    @o.methodReturningNO.should == false
-  end
-
-  it "returning 'char' or 'unsigned char' returns a Fixnum in Ruby" do
-    @o.methodReturningChar.should == 42
-    @o.methodReturningChar2.should == -42
-    @o.methodReturningUnsignedChar.should == 42
-  end
- 
-  it "returning 'short' or 'unsigned short' returns a Fixnum in Ruby" do
-    @o.methodReturningShort.should == 42
-    @o.methodReturningShort2.should == -42
-    @o.methodReturningUnsignedShort.should == 42
-  end
-
-  it "returning 'int' or 'unsigned int' returns a Fixnum in Ruby" do
-    @o.methodReturningInt.should == 42
-    @o.methodReturningInt2.should == -42
-    @o.methodReturningUnsignedInt.should == 42
-  end
-
-  it "returning 'long' or 'unsigned long' returns a Fixnum if possible in Ruby" do
-    @o.methodReturningLong.should == 42
-    @o.methodReturningLong2.should == -42
-    @o.methodReturningUnsignedLong.should == 42
-  end
-
-  it "returning 'long' or 'unsigned long' returns a Bignum if it cannot fix in a Fixnum in Ruby" do
-    @o.methodReturningLong3.should ==
-      (RUBY_ARCH == 'x86_64' ? 4611686018427387904 : 1073741824)
-    @o.methodReturningLong3.class.should == Bignum
-    @o.methodReturningLong4.should ==
-      (RUBY_ARCH == 'x86_64' ? -4611686018427387905 : -1073741825)
-    @o.methodReturningLong4.class.should == Bignum
-    @o.methodReturningUnsignedLong2.should ==
-      (RUBY_ARCH == 'x86_64' ? 4611686018427387904 : 1073741824)
-    @o.methodReturningUnsignedLong2.class.should == Bignum
-  end
-
-  it "returning 'float' returns a Float in Ruby" do
-    @o.methodReturningFloat.should be_close(3.1415, 0.0001)
-    @o.methodReturningFloat.class.should == Float
-  end
-
-  it "returning 'double' returns a Float in Ruby" do
-    @o.methodReturningDouble.should be_close(3.1415, 0.0001)
-    @o.methodReturningDouble.class.should == Float
-  end
-
-  it "returning 'SEL' returns a Symbol or nil in Ruby" do
-    @o.methodReturningSEL.class.should == Symbol
-    @o.methodReturningSEL.should == :'foo:with:with:'
-    @o.methodReturningSEL2.class.should == NilClass
-    @o.methodReturningSEL2.should == nil
-  end
-
-  it "returning 'char *' returns a String or nil in Ruby" do
-    @o.methodReturningCharPtr.class.should == String
-    @o.methodReturningCharPtr.should == 'foo'
-    @o.methodReturningCharPtr2.class.should == NilClass
-    @o.methodReturningCharPtr2.should == nil
-  end
-
-  it "returning 'NSPoint' returns an NSPoint boxed object in Ruby" do
-    b = @o.methodReturningNSPoint
-    b.class.should == NSPoint
-    b.x.class.should == Float
-    b.x.should == 1.0
-    b.y.class.should == Float
-    b.y.should == 2.0
-  end
-
-  it "returning 'NSSize' returns an NSSize boxed object in Ruby" do
-    b = @o.methodReturningNSSize
-    b.class.should == NSSize
-    b.width.class.should == Float
-    b.width.should == 3.0
-    b.height.class.should == Float
-    b.height.should == 4.0
-  end
-
-  it "returning 'NSRect' returns an NSRect boxed object in Ruby" do
-    b = @o.methodReturningNSRect
-    b.class.should == NSRect
-    b.origin.class.should == NSPoint
-    b.origin.x.should == 1.0
-    b.origin.y.should == 2.0
-    b.size.class.should == NSSize
-    b.size.width.should == 3.0
-    b.size.height.should == 4.0
-  end
-
-  it "returning 'NSRange' returns an NSRange boxed object in Ruby" do
-    b = @o.methodReturningNSRange
-    b.class.should == NSRange
-    b.location.class.should == Fixnum
-    b.location.should == 0
-    b.length.class.should == Fixnum
-    b.length.should == 42
-  end
-
-  it "accepting the receiver as 'id' should receive the exact same object" do
-    @o.methodAcceptingSelf(@o).should == 1
-  end
-
-  it "accepting the receiver's class as 'id' should receive the exact same object" do
-    @o.methodAcceptingSelfClass(@o.class).should == 1
-  end
-
-  it "accepting 'nil' as 'id' should receive Objective-C's nil" do
-    @o.methodAcceptingNil(nil).should == 1
-  end
-
-  it "accepting 'true' as 'id; should receive CF's kCFBooleanTrue" do
-    @o.methodAcceptingTrue(true).should == 1
-  end
-
-  it "accepting 'false' as 'id' should receive CF's kCFBooleanFalse" do
-    @o.methodAcceptingFalse(false).should == 1
-  end
-
-  it "accepting a Fixnum as 'id' should receive a Fixnum boxed object" do
-    @o.methodAcceptingFixnum(42).should == 1
-  end
-
-  it "accepting nil or false as 'BOOL' should receive NO, any other object should receive YES" do
-    @o.methodAcceptingFalseBOOL(nil).should == 1
-    @o.methodAcceptingFalseBOOL(false).should == 1
-
-    @o.methodAcceptingTrueBOOL(true).should == 1
-    @o.methodAcceptingTrueBOOL(0).should == 1
-    @o.methodAcceptingTrueBOOL(123).should == 1
-    @o.methodAcceptingTrueBOOL('foo').should == 1
-    @o.methodAcceptingTrueBOOL(Object.new).should == 1
-  end
-
-  it "accepting a Fixnum-compatible object as 'char', 'unsigned char', 'short', 'unsigned short', 'int', 'unsigned int', 'long', 'unsigned long' should receive the converted data, or raise an exception" do
-    @o.methodAcceptingChar(42).should == 1
-    @o.methodAcceptingUnsignedChar(42).should == 1
-    @o.methodAcceptingShort(42).should == 1
-    @o.methodAcceptingUnsignedShort(42).should == 1
-    @o.methodAcceptingInt(42).should == 1
-    @o.methodAcceptingUnsignedInt(42).should == 1
-    @o.methodAcceptingLong(42).should == 1
-    @o.methodAcceptingUnsignedLong(42).should == 1
-
-    @o.methodAcceptingChar(42.0).should == 1
-    @o.methodAcceptingUnsignedChar(42.0).should == 1
-    @o.methodAcceptingShort(42.0).should == 1
-    @o.methodAcceptingUnsignedShort(42.0).should == 1
-    @o.methodAcceptingInt(42.0).should == 1
-    @o.methodAcceptingUnsignedInt(42.0).should == 1
-    @o.methodAcceptingLong(42.0).should == 1
-    @o.methodAcceptingUnsignedLong(42.0).should == 1
-
-    o2 = Object.new
-    def o2.to_i; 42; end
-
-    @o.methodAcceptingChar(o2).should == 1
-    @o.methodAcceptingUnsignedChar(o2).should == 1
-    @o.methodAcceptingShort(o2).should == 1
-    @o.methodAcceptingUnsignedShort(o2).should == 1
-    @o.methodAcceptingInt(o2).should == 1
-    @o.methodAcceptingUnsignedInt(o2).should == 1
-    @o.methodAcceptingLong(o2).should == 1
-    @o.methodAcceptingUnsignedLong(o2).should == 1
-
-    lambda { @o.methodAcceptingChar(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingUnsignedChar(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingShort(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingUnsignedShort(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingInt(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingUnsignedInt(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingLong(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingUnsignedLong(nil) }.should raise_error(TypeError)
-
-    lambda { @o.methodAcceptingChar(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingUnsignedChar(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingShort(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingUnsignedShort(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingInt(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingUnsignedInt(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingLong(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingUnsignedLong(Object.new) }.should raise_error(TypeError)
-  end
-
-  it "accepting a one-character string as 'char' or 'unsigned char' should receive the first character" do
-    @o.methodAcceptingChar('*').should == 1
-    @o.methodAcceptingUnsignedChar('*').should == 1
-  end
-
-  it "accepting a String, Symbol or nil as 'SEL' should receive the appropriate selector" do
-    @o.methodAcceptingSEL(:'foo:with:with:').should == 1
-    @o.methodAcceptingSEL('foo:with:with:').should == 1
-    @o.methodAcceptingSEL2(nil).should == 1
-
-    lambda { @o.methodAcceptingSEL(123) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingSEL(Object.new) }.should raise_error(TypeError)
-  end
-
-  it "accepting a Float-compatible object as 'float' or 'double' should receive the appropriate data" do
-    @o.methodAcceptingFloat(3.1415).should == 1 
-    @o.methodAcceptingDouble(3.1415).should == 1
-
-    o2 = Object.new
-    def o2.to_f; 3.1415; end
-
-    @o.methodAcceptingFloat(o2).should == 1 
-    @o.methodAcceptingDouble(o2).should == 1
-
-    lambda { @o.methodAcceptingFloat(nil) }.should raise_error(TypeError) 
-    lambda { @o.methodAcceptingDouble(nil) }.should raise_error(TypeError) 
-    lambda { @o.methodAcceptingFloat(Object.new) }.should raise_error(TypeError) 
-    lambda { @o.methodAcceptingDouble(Object.new) }.should raise_error(TypeError) 
-  end
-
-  it "accepting a String-compatible object as 'char *' should receive the appropriate data" do
-    @o.methodAcceptingCharPtr('foo').should == 1
-
-    o2 = Object.new
-    def o2.to_str; 'foo' end
-
-    @o.methodAcceptingCharPtr(o2).should == 1
-
-    lambda { @o.methodAcceptingCharPtr(123) }.should raise_error(TypeError) 
-    lambda { @o.methodAcceptingCharPtr([]) }.should raise_error(TypeError) 
-    lambda { @o.methodAcceptingCharPtr(Object.new) }.should raise_error(TypeError) 
-
-    @o.methodAcceptingCharPtr2(nil).should == 1
-  end
-
-  it "accepting an NSPoint, NSSize, NSRange or NSRect object as 'NSPoint', 'NSSize', 'NSRange' or 'NSRect' should receive the C structure" do
-    p = @o.methodReturningNSPoint
-    @o.methodAcceptingNSPoint(p).should == 1
-    p = @o.methodReturningNSSize
-    @o.methodAcceptingNSSize(p).should == 1
-    p = @o.methodReturningNSRect
-    @o.methodAcceptingNSRect(p).should == 1
-    p = @o.methodReturningNSRange
-    @o.methodAcceptingNSRange(p).should == 1
-
-    lambda { @o.methodAcceptingNSPoint(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSPoint(123) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSPoint(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSPoint(@o.methodReturningNSSize) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSSize(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSSize(123) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSSize(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSSize(@o.methodReturningNSPoint) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSRect(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSRect(123) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSRect(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSRect(@o.methodReturningNSPoint) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSRange(nil) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSRange(123) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSRange(Object.new) }.should raise_error(TypeError)
-    lambda { @o.methodAcceptingNSRange(@o.methodReturningNSPoint) }.should raise_error(TypeError)
-  end
-
-  it "accepting an Array of valid objects as a structure type should receive the C structure" do
-    @o.methodAcceptingNSPoint([1, 2]).should == 1
-    @o.methodAcceptingNSSize([3, 4]).should == 1
-    @o.methodAcceptingNSRect([[1, 2], [3, 4]]).should == 1
-    @o.methodAcceptingNSRect([1, 2, 3, 4]).should == 1
-    @o.methodAcceptingNSRange([0, 42]).should == 1
-
-    lambda { @o.methodAcceptingNSPoint([1]) }.should raise_error(ArgumentError)
-    lambda { @o.methodAcceptingNSPoint([1, 2, 3]) }.should raise_error(ArgumentError)
-    lambda { @o.methodAcceptingNSRect([1, 2, 3]) }.should raise_error(ArgumentError)
-    lambda { @o.methodAcceptingNSRect([1, 2, 3, 4, 5]) }.should raise_error(ArgumentError)
-    lambda { @o.methodAcceptingNSRect([[1, 2], [3]]) }.should raise_error(ArgumentError)
-    lambda { @o.methodAcceptingNSRect([[1, 2], [3, 4, 5]]) }.should raise_error(ArgumentError)
-  end
-
-  it "accepting various C types should receive these types as expected" do
-    @o.methodAcceptingInt(42, float:42, double:42, short:42, NSPoint:[42, 42],
-                          NSRect:[42, 42, 42, 42], char:42).should == 1
-  end
-end

Added: MacRuby/branches/experimental/spec/macruby/objc_method_spec.rb
===================================================================
--- MacRuby/branches/experimental/spec/macruby/objc_method_spec.rb	                        (rev 0)
+++ MacRuby/branches/experimental/spec/macruby/objc_method_spec.rb	2009-04-28 02:23:44 UTC (rev 1495)
@@ -0,0 +1,372 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+framework 'Foundation'
+
+fixture_source = File.dirname(__FILE__) + '/fixtures/method.m'
+fixture_ext = '/tmp/method.bundle'
+if !File.exist?(fixture_ext) or File.mtime(fixture_source) > File.mtime(fixture_ext)
+=begin
+  # #system is currently broken
+  unless system("/usr/bin/gcc #{fixture_source} -o #{fixture_ext} -g -framework Foundation -dynamiclib -fobjc-gc -arch i386 -arch x86_64 -arch ppc")
+    $stderr.puts "cannot compile fixture source file `#{fixture_source}' - aborting"
+    exit 1
+  end
+=end
+  `/usr/bin/gcc #{fixture_source} -o #{fixture_ext} -g -framework Foundation -dynamiclib -fobjc-gc -arch i386 -arch x86_64 -arch ppc`
+end
+require '/tmp/method'
+load_bridge_support_file File.dirname(__FILE__) + '/fixtures/method.bridgesupport'
+
+describe "A pure Objective-C method" do
+  before :each do
+    @o = TestMethod.new
+  end
+
+  it "can be called with #foo= if it matches the #setFoo pattern" do
+    o = []
+
+    # TODO Stopped here: This should be sufficient, but doesn't work.
+    # o.should have_method(:'setArray', true)
+    # o.should have_method(:'array=', true)
+
+    o.respond_to?(:'setArray').should == true
+    o.respond_to?(:'array=').should == true
+    o.array = [1, 2, 3]
+    o.should == [1, 2, 3]
+  end
+
+  it "can be called with #foo? if it matches the #isFoo pattern" do
+    o = NSBundle.mainBundle
+    o.respond_to?(:'isLoaded').should == true
+    o.respond_to?(:'loaded?').should == true
+    o.loaded?.should == true
+  end
+
+  it "is only exposed in #methods if the second argument is true" do
+    o = Object.new
+    o.methods.include?(:'performSelector').should == false
+    o.methods(true).include?(:'performSelector').should == false
+    o.methods(false).include?(:'performSelector').should == false
+    o.methods(true, true).include?(:'performSelector').should == true
+    o.methods(false, true).include?(:'performSelector').should == true
+  end
+
+  it "can be called on an immediate object" do
+    123.self.should == 123
+    true.self.should == true
+    false.self.should == false
+    nil.self.should == nil
+  end
+
+  it "returning void returns nil in Ruby" do
+    @o.methodReturningVoid.should == nil
+  end
+
+  it "returning nil returns nil in Ruby" do
+    @o.methodReturningNil.should == nil
+  end
+
+  it "returning self returns the same receiver object" do
+    @o.methodReturningSelf.should == @o
+    @o.methodReturningSelf.object_id == @o.object_id
+  end
+
+  it "returning kCFBooleanTrue returns true in Ruby" do
+    @o.methodReturningCFTrue.should == true
+    @o.methodReturningCFTrue.class.should == TrueClass
+  end
+
+  it "returning kCFBooleanFalse returns false in Ruby" do
+    @o.methodReturningCFFalse.should == false
+    @o.methodReturningCFFalse.class.should == FalseClass
+  end
+
+  it "returning kCFNull returns nil in Ruby" do
+    @o.methodReturningCFNull.should == nil
+    @o.methodReturningCFNull.class.should == NilClass
+  end
+
+  it "returning YES returns true in Ruby" do
+    @o.methodReturningYES.should == true
+  end
+
+  it "returning NO returns true in Ruby" do
+    @o.methodReturningNO.should == false
+  end
+
+  it "returning 'char' or 'unsigned char' returns a Fixnum in Ruby" do
+    @o.methodReturningChar.should == 42
+    @o.methodReturningChar2.should == -42
+    @o.methodReturningUnsignedChar.should == 42
+  end
+ 
+  it "returning 'short' or 'unsigned short' returns a Fixnum in Ruby" do
+    @o.methodReturningShort.should == 42
+    @o.methodReturningShort2.should == -42
+    @o.methodReturningUnsignedShort.should == 42
+  end
+
+  it "returning 'int' or 'unsigned int' returns a Fixnum in Ruby" do
+    @o.methodReturningInt.should == 42
+    @o.methodReturningInt2.should == -42
+    @o.methodReturningUnsignedInt.should == 42
+  end
+
+  it "returning 'long' or 'unsigned long' returns a Fixnum if possible in Ruby" do
+    @o.methodReturningLong.should == 42
+    @o.methodReturningLong2.should == -42
+    @o.methodReturningUnsignedLong.should == 42
+  end
+
+  it "returning 'long' or 'unsigned long' returns a Bignum if it cannot fix in a Fixnum in Ruby" do
+    @o.methodReturningLong3.should ==
+      (RUBY_ARCH == 'x86_64' ? 4611686018427387904 : 1073741824)
+    @o.methodReturningLong3.class.should == Bignum
+    @o.methodReturningLong4.should ==
+      (RUBY_ARCH == 'x86_64' ? -4611686018427387905 : -1073741825)
+    @o.methodReturningLong4.class.should == Bignum
+    @o.methodReturningUnsignedLong2.should ==
+      (RUBY_ARCH == 'x86_64' ? 4611686018427387904 : 1073741824)
+    @o.methodReturningUnsignedLong2.class.should == Bignum
+  end
+
+  it "returning 'float' returns a Float in Ruby" do
+    @o.methodReturningFloat.should be_close(3.1415, 0.0001)
+    @o.methodReturningFloat.class.should == Float
+  end
+
+  it "returning 'double' returns a Float in Ruby" do
+    @o.methodReturningDouble.should be_close(3.1415, 0.0001)
+    @o.methodReturningDouble.class.should == Float
+  end
+
+  it "returning 'SEL' returns a Symbol or nil in Ruby" do
+    @o.methodReturningSEL.class.should == Symbol
+    @o.methodReturningSEL.should == :'foo:with:with:'
+    @o.methodReturningSEL2.class.should == NilClass
+    @o.methodReturningSEL2.should == nil
+  end
+
+  it "returning 'char *' returns a String or nil in Ruby" do
+    @o.methodReturningCharPtr.class.should == String
+    @o.methodReturningCharPtr.should == 'foo'
+    @o.methodReturningCharPtr2.class.should == NilClass
+    @o.methodReturningCharPtr2.should == nil
+  end
+
+  it "returning 'NSPoint' returns an NSPoint boxed object in Ruby" do
+    b = @o.methodReturningNSPoint
+    b.class.should == NSPoint
+    b.x.class.should == Float
+    b.x.should == 1.0
+    b.y.class.should == Float
+    b.y.should == 2.0
+  end
+
+  it "returning 'NSSize' returns an NSSize boxed object in Ruby" do
+    b = @o.methodReturningNSSize
+    b.class.should == NSSize
+    b.width.class.should == Float
+    b.width.should == 3.0
+    b.height.class.should == Float
+    b.height.should == 4.0
+  end
+
+  it "returning 'NSRect' returns an NSRect boxed object in Ruby" do
+    b = @o.methodReturningNSRect
+    b.class.should == NSRect
+    b.origin.class.should == NSPoint
+    b.origin.x.should == 1.0
+    b.origin.y.should == 2.0
+    b.size.class.should == NSSize
+    b.size.width.should == 3.0
+    b.size.height.should == 4.0
+  end
+
+  it "returning 'NSRange' returns an NSRange boxed object in Ruby" do
+    b = @o.methodReturningNSRange
+    b.class.should == NSRange
+    b.location.class.should == Fixnum
+    b.location.should == 0
+    b.length.class.should == Fixnum
+    b.length.should == 42
+  end
+
+  it "accepting the receiver as 'id' should receive the exact same object" do
+    @o.methodAcceptingSelf(@o).should == 1
+  end
+
+  it "accepting the receiver's class as 'id' should receive the exact same object" do
+    @o.methodAcceptingSelfClass(@o.class).should == 1
+  end
+
+  it "accepting 'nil' as 'id' should receive Objective-C's nil" do
+    @o.methodAcceptingNil(nil).should == 1
+  end
+
+  it "accepting 'true' as 'id; should receive CF's kCFBooleanTrue" do
+    @o.methodAcceptingTrue(true).should == 1
+  end
+
+  it "accepting 'false' as 'id' should receive CF's kCFBooleanFalse" do
+    @o.methodAcceptingFalse(false).should == 1
+  end
+
+  it "accepting a Fixnum as 'id' should receive a Fixnum boxed object" do
+    @o.methodAcceptingFixnum(42).should == 1
+  end
+
+  it "accepting nil or false as 'BOOL' should receive NO, any other object should receive YES" do
+    @o.methodAcceptingFalseBOOL(nil).should == 1
+    @o.methodAcceptingFalseBOOL(false).should == 1
+
+    @o.methodAcceptingTrueBOOL(true).should == 1
+    @o.methodAcceptingTrueBOOL(0).should == 1
+    @o.methodAcceptingTrueBOOL(123).should == 1
+    @o.methodAcceptingTrueBOOL('foo').should == 1
+    @o.methodAcceptingTrueBOOL(Object.new).should == 1
+  end
+
+  it "accepting a Fixnum-compatible object as 'char', 'unsigned char', 'short', 'unsigned short', 'int', 'unsigned int', 'long', 'unsigned long' should receive the converted data, or raise an exception" do
+    @o.methodAcceptingChar(42).should == 1
+    @o.methodAcceptingUnsignedChar(42).should == 1
+    @o.methodAcceptingShort(42).should == 1
+    @o.methodAcceptingUnsignedShort(42).should == 1
+    @o.methodAcceptingInt(42).should == 1
+    @o.methodAcceptingUnsignedInt(42).should == 1
+    @o.methodAcceptingLong(42).should == 1
+    @o.methodAcceptingUnsignedLong(42).should == 1
+
+    @o.methodAcceptingChar(42.0).should == 1
+    @o.methodAcceptingUnsignedChar(42.0).should == 1
+    @o.methodAcceptingShort(42.0).should == 1
+    @o.methodAcceptingUnsignedShort(42.0).should == 1
+    @o.methodAcceptingInt(42.0).should == 1
+    @o.methodAcceptingUnsignedInt(42.0).should == 1
+    @o.methodAcceptingLong(42.0).should == 1
+    @o.methodAcceptingUnsignedLong(42.0).should == 1
+
+    o2 = Object.new
+    def o2.to_i; 42; end
+
+    @o.methodAcceptingChar(o2).should == 1
+    @o.methodAcceptingUnsignedChar(o2).should == 1
+    @o.methodAcceptingShort(o2).should == 1
+    @o.methodAcceptingUnsignedShort(o2).should == 1
+    @o.methodAcceptingInt(o2).should == 1
+    @o.methodAcceptingUnsignedInt(o2).should == 1
+    @o.methodAcceptingLong(o2).should == 1
+    @o.methodAcceptingUnsignedLong(o2).should == 1
+
+    lambda { @o.methodAcceptingChar(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingUnsignedChar(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingShort(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingUnsignedShort(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingInt(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingUnsignedInt(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingLong(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingUnsignedLong(nil) }.should raise_error(TypeError)
+
+    lambda { @o.methodAcceptingChar(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingUnsignedChar(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingShort(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingUnsignedShort(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingInt(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingUnsignedInt(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingLong(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingUnsignedLong(Object.new) }.should raise_error(TypeError)
+  end
+
+  it "accepting a one-character string as 'char' or 'unsigned char' should receive the first character" do
+    @o.methodAcceptingChar('*').should == 1
+    @o.methodAcceptingUnsignedChar('*').should == 1
+  end
+
+  it "accepting a String, Symbol or nil as 'SEL' should receive the appropriate selector" do
+    @o.methodAcceptingSEL(:'foo:with:with:').should == 1
+    @o.methodAcceptingSEL('foo:with:with:').should == 1
+    @o.methodAcceptingSEL2(nil).should == 1
+
+    lambda { @o.methodAcceptingSEL(123) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingSEL(Object.new) }.should raise_error(TypeError)
+  end
+
+  it "accepting a Float-compatible object as 'float' or 'double' should receive the appropriate data" do
+    @o.methodAcceptingFloat(3.1415).should == 1 
+    @o.methodAcceptingDouble(3.1415).should == 1
+
+    o2 = Object.new
+    def o2.to_f; 3.1415; end
+
+    @o.methodAcceptingFloat(o2).should == 1 
+    @o.methodAcceptingDouble(o2).should == 1
+
+    lambda { @o.methodAcceptingFloat(nil) }.should raise_error(TypeError) 
+    lambda { @o.methodAcceptingDouble(nil) }.should raise_error(TypeError) 
+    lambda { @o.methodAcceptingFloat(Object.new) }.should raise_error(TypeError) 
+    lambda { @o.methodAcceptingDouble(Object.new) }.should raise_error(TypeError) 
+  end
+
+  it "accepting a String-compatible object as 'char *' should receive the appropriate data" do
+    @o.methodAcceptingCharPtr('foo').should == 1
+
+    o2 = Object.new
+    def o2.to_str; 'foo' end
+
+    @o.methodAcceptingCharPtr(o2).should == 1
+
+    lambda { @o.methodAcceptingCharPtr(123) }.should raise_error(TypeError) 
+    lambda { @o.methodAcceptingCharPtr([]) }.should raise_error(TypeError) 
+    lambda { @o.methodAcceptingCharPtr(Object.new) }.should raise_error(TypeError) 
+
+    @o.methodAcceptingCharPtr2(nil).should == 1
+  end
+
+  it "accepting an NSPoint, NSSize, NSRange or NSRect object as 'NSPoint', 'NSSize', 'NSRange' or 'NSRect' should receive the C structure" do
+    p = @o.methodReturningNSPoint
+    @o.methodAcceptingNSPoint(p).should == 1
+    p = @o.methodReturningNSSize
+    @o.methodAcceptingNSSize(p).should == 1
+    p = @o.methodReturningNSRect
+    @o.methodAcceptingNSRect(p).should == 1
+    p = @o.methodReturningNSRange
+    @o.methodAcceptingNSRange(p).should == 1
+
+    lambda { @o.methodAcceptingNSPoint(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSPoint(123) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSPoint(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSPoint(@o.methodReturningNSSize) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSSize(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSSize(123) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSSize(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSSize(@o.methodReturningNSPoint) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSRect(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSRect(123) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSRect(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSRect(@o.methodReturningNSPoint) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSRange(nil) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSRange(123) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSRange(Object.new) }.should raise_error(TypeError)
+    lambda { @o.methodAcceptingNSRange(@o.methodReturningNSPoint) }.should raise_error(TypeError)
+  end
+
+  it "accepting an Array of valid objects as a structure type should receive the C structure" do
+    @o.methodAcceptingNSPoint([1, 2]).should == 1
+    @o.methodAcceptingNSSize([3, 4]).should == 1
+    @o.methodAcceptingNSRect([[1, 2], [3, 4]]).should == 1
+    @o.methodAcceptingNSRect([1, 2, 3, 4]).should == 1
+    @o.methodAcceptingNSRange([0, 42]).should == 1
+
+    lambda { @o.methodAcceptingNSPoint([1]) }.should raise_error(ArgumentError)
+    lambda { @o.methodAcceptingNSPoint([1, 2, 3]) }.should raise_error(ArgumentError)
+    lambda { @o.methodAcceptingNSRect([1, 2, 3]) }.should raise_error(ArgumentError)
+    lambda { @o.methodAcceptingNSRect([1, 2, 3, 4, 5]) }.should raise_error(ArgumentError)
+    lambda { @o.methodAcceptingNSRect([[1, 2], [3]]) }.should raise_error(ArgumentError)
+    lambda { @o.methodAcceptingNSRect([[1, 2], [3, 4, 5]]) }.should raise_error(ArgumentError)
+  end
+
+  it "accepting various C types should receive these types as expected" do
+    @o.methodAcceptingInt(42, float:42, double:42, short:42, NSPoint:[42, 42],
+                          NSRect:[42, 42, 42, 42], char:42).should == 1
+  end
+end

Added: MacRuby/branches/experimental/spec/macruby/pointer_spec.rb
===================================================================
--- MacRuby/branches/experimental/spec/macruby/pointer_spec.rb	                        (rev 0)
+++ MacRuby/branches/experimental/spec/macruby/pointer_spec.rb	2009-04-28 02:23:44 UTC (rev 1495)
@@ -0,0 +1,52 @@
+require File.dirname(__FILE__) + '/../spec_helper'
+
+framework 'Foundation'
+
+describe "A Pointer object" do
+=begin # TODO
+  it "can be created using the #new class method and with a valid Objective-C type or a valid Symbol object" do
+    types = {
+      :object     => '@',
+      :char       => 'c',
+      :uchar      => 'C',
+      :short      => 's',
+      :ushort     => 'S',
+      :int        => 'i',
+      :uint       => 'I',
+      :long       => 'l',
+      :ulong      => 'L',
+      :long_long  => 'q',
+      :ulong_long => 'Q',
+      :float      => 'f',
+      :double     => 'd'
+    }
+
+    types.each do |sym, typestr|
+      p = nil
+      lambda { p = Pointer.new(sym) }.should_not raise_error
+      p.type.should == typestr
+
+      lambda { p = Pointer.new(typestr) }.should_not raise_error
+      p.type.should == typestr
+    end
+
+    lambda { Pointer.new }.should raise_error(ArgumentError)
+    lambda { Pointer.new('invalid') }.should raise_error(TypeError)
+  end
+=end
+
+=begin # TODO
+  it "can be assigned an object of the given type and retrieve it later, using #[] and #[]=" 
+    p = Pointer.new('@')
+    o = Object.new
+    p[0] = o
+    p[0].should == o
+
+    p = Pointer.new('i')
+    p[0] = 42
+    p[0].should == 42
+
+    lambda { p[0] = Object.new }.should raise_error(TypeError)
+  end
+=end 
+end
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090427/ca3c01b9/attachment-0001.html>


More information about the macruby-changes mailing list