test/test_Data_Object.cpp in rice-3.0.0 vs test/test_Data_Object.cpp in rice-4.0.0

- old
+ new

@@ -1,276 +1,217 @@ #include "unittest.hpp" #include "embed_ruby.hpp" -#include "rice/Data_Object.hpp" -#include "rice/Data_Type.hpp" -#include "rice/Exception.hpp" +#include <rice/rice.hpp> using namespace Rice; TESTSUITE(Data_Object); namespace { - struct Foo { Foo() : x_(42) { } int x_; }; + bool test_destructor_called = false; + bool test_ruby_mark_called = false; - bool test_ruby_mark__marked = false; + struct MyDataType + { + MyDataType() : x(42) + { + } + + ~MyDataType() + { + test_destructor_called = true; + } + + int x; + }; + + struct Bar + { + }; } -template<> -void ruby_mark(Foo * foo) +namespace Rice { - test_ruby_mark__marked = true; + template<> + void ruby_mark(MyDataType* myDataType) + { + test_ruby_mark_called = true; + } } SETUP(Data_Object) { embed_ruby(); - if(!Data_Type<Foo>::is_bound()) + if (!Data_Type<MyDataType>::is_bound()) { Class object(rb_cObject); - if(object.const_defined("Foo")) + if(object.const_defined("MyDataType")) { - object.remove_const("Foo"); + object.remove_const("MyDataType"); } - define_class<Foo>("Foo"); + define_class<MyDataType>("MyDataType"); + define_class<Bar>("Bar"); } } -TESTCASE(construct_from_pointer_with_defaults) +TESTCASE(construct_from_pointer) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo); - ASSERT_EQUAL(foo, wrapped_foo.get()); - ASSERT_EQUAL(Data_Type<Foo>::klass(), wrapped_foo.class_of()); - typedef void (*Mark_Func)(void *); - typedef void (*Mark_Func_Foo)(Foo *); - Mark_Func expected_mark_func = - Mark_Func(Mark_Func_Foo(ruby_mark<Foo>)); - ASSERT_EQUAL( - expected_mark_func, - RDATA(wrapped_foo.value())->dmark); - ASSERT_EQUAL( - RUBY_DATA_FUNC(Default_Free_Function<Foo>::free), - RUBY_DATA_FUNC(RDATA(wrapped_foo.value())->dfree)); - ASSERT_EQUAL(foo, DATA_PTR(wrapped_foo.value())); + MyDataType* myDataType = new MyDataType; + Data_Object<MyDataType> wrapped_foo(myDataType); + ASSERT_EQUAL(myDataType, wrapped_foo.get()); + ASSERT_EQUAL(Data_Type<MyDataType>::klass(), wrapped_foo.class_of()); + ASSERT_EQUAL(myDataType, detail::unwrap<MyDataType>(wrapped_foo, Data_Type<MyDataType>::rb_type())); } -TESTCASE(construct_from_pointer_and_klass) +TESTCASE(construct_from_ruby_object) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo, Data_Type<Foo>::klass()); - ASSERT_EQUAL(foo, wrapped_foo.get()); - ASSERT_EQUAL(Data_Type<Foo>::klass(), wrapped_foo.class_of()); - typedef void (*Mark_Func)(void *); - typedef void (*Mark_Func_Foo)(Foo *); - Mark_Func expected_mark_func = - Mark_Func(Mark_Func_Foo(ruby_mark<Foo>)); - ASSERT_EQUAL( - expected_mark_func, - RDATA(wrapped_foo.value())->dmark); - ASSERT_EQUAL( - RUBY_DATA_FUNC(Default_Free_Function<Foo>::free), - RUBY_DATA_FUNC(RDATA(wrapped_foo.value())->dfree)); - ASSERT_EQUAL(foo, DATA_PTR(wrapped_foo.value())); -} + MyDataType * myDataType = new MyDataType; + VALUE wrapped_foo = detail::wrap(Data_Type<MyDataType>::klass(), Data_Type<MyDataType>::rb_type(), myDataType, true); -TESTCASE(construct_from_pointer_and_alternate_klass) -{ - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo, rb_cObject); - ASSERT_EQUAL(foo, wrapped_foo.get()); - ASSERT_EQUAL(rb_cObject, CLASS_OF(wrapped_foo.value())); - typedef void (*Mark_Func)(void *); - typedef void (*Mark_Func_Foo)(Foo *); - Mark_Func expected_mark_func = - Mark_Func(Mark_Func_Foo(ruby_mark<Foo>)); - ASSERT_EQUAL( - expected_mark_func, - RDATA(wrapped_foo.value())->dmark); - ASSERT_EQUAL( - RUBY_DATA_FUNC(Default_Free_Function<Foo>::free), - RUBY_DATA_FUNC(RDATA(wrapped_foo.value())->dfree)); - ASSERT_EQUAL(foo, DATA_PTR(wrapped_foo.value())); + Data_Object<MyDataType> data_object_foo(wrapped_foo); + ASSERT_EQUAL(myDataType, data_object_foo.get()); + ASSERT_EQUAL(Data_Type<MyDataType>::klass(), data_object_foo.class_of()); + ASSERT_EQUAL(RTYPEDDATA(wrapped_foo), RTYPEDDATA(data_object_foo.value())); + ASSERT_EQUAL(myDataType, detail::unwrap<MyDataType>(wrapped_foo, Data_Type<MyDataType>::rb_type())); } -namespace +TESTCASE(construct_from_ruby_object_and_wrong_class) { - void dummy_mark(Foo *) - { - } -} + MyDataType * myDataType = new MyDataType; + VALUE wrapped_foo = detail::wrap(Data_Type<MyDataType>::klass(), Data_Type<MyDataType>::rb_type(), myDataType, true); -TESTCASE(construct_from_pointer_and_klass_and_mark_function) -{ - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo, rb_cFoo, dummy_mark); - ASSERT_EQUAL(foo, wrapped_foo.get()); - ASSERT_EQUAL(Data_Type<Foo>::klass(), wrapped_foo.class_of()); - ASSERT_EQUAL((void *)dummy_mark, RDATA(wrapped_foo.value())->dmark); - ASSERT_EQUAL( - RUBY_DATA_FUNC(Default_Free_Function<Foo>::free), - RUBY_DATA_FUNC(RDATA(wrapped_foo.value())->dfree)); - ASSERT_EQUAL(foo, DATA_PTR(wrapped_foo.value())); -} + ASSERT_EXCEPTION_CHECK( + Exception, + Data_Object<Bar> bar(wrapped_foo), + ASSERT_EQUAL(rb_eTypeError, CLASS_OF(ex.value()))); -namespace -{ - void my_free(Foo * f) - { - delete f; - } + ASSERT_EXCEPTION_CHECK( + Exception, + Data_Object<Bar> bar(wrapped_foo), + ASSERT_EQUAL("Wrong argument type. Expected: Bar. Received: MyDataType.", ex.what())); } -TESTCASE(construct_from_pointer_and_klass_and_mark_and_free) +TESTCASE(copy_construct) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo, rb_cFoo, dummy_mark, my_free); - ASSERT_EQUAL(foo, wrapped_foo.get()); - ASSERT_EQUAL(Data_Type<Foo>::klass(), wrapped_foo.class_of()); - ASSERT_EQUAL((void *)dummy_mark, RDATA(wrapped_foo.value())->dmark); - ASSERT_EQUAL( - RUBY_DATA_FUNC(my_free), - RUBY_DATA_FUNC(RDATA(wrapped_foo.value())->dfree)); - ASSERT_EQUAL(foo, DATA_PTR(wrapped_foo.value())); -} + MyDataType * myDataType = new MyDataType; + VALUE wrapped_foo = detail::wrap(Data_Type<MyDataType>::klass(), Data_Type<MyDataType>::rb_type(), myDataType, true); + Data_Object<MyDataType> orig_data_object_foo(wrapped_foo); + Data_Object<MyDataType> data_object_foo(orig_data_object_foo); -TESTCASE(construct_from_ruby_object) -{ - Foo * foo = new Foo; - VALUE wrapped_foo = Data_Wrap_Struct(Data_Type<Foo>::klass(), 0, Default_Free_Function<Foo>::free, foo); - Data_Object<Foo> data_object_foo(wrapped_foo); - ASSERT_EQUAL(foo, data_object_foo.get()); - ASSERT_EQUAL(Data_Type<Foo>::klass(), data_object_foo.class_of()); - ASSERT_EQUAL(RDATA(wrapped_foo), RDATA(data_object_foo.value())); - ASSERT_EQUAL(RUBY_DATA_FUNC(0), RDATA(data_object_foo.value())->dmark); - ASSERT_EQUAL( - RUBY_DATA_FUNC(Default_Free_Function<Foo>::free), - RUBY_DATA_FUNC(RDATA(data_object_foo.value())->dfree)); - ASSERT_EQUAL(foo, DATA_PTR(data_object_foo.value())); + ASSERT_EQUAL(myDataType, data_object_foo.get()); + ASSERT_EQUAL(Data_Type<MyDataType>::klass(), data_object_foo.class_of()); + ASSERT_EQUAL(RTYPEDDATA(wrapped_foo), RTYPEDDATA(data_object_foo.value())); + ASSERT_EQUAL(myDataType, detail::unwrap<MyDataType>(wrapped_foo, Data_Type<MyDataType>::rb_type())); } -TESTCASE(construct_from_ruby_object_and_class) +TESTCASE(move_construct) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - VALUE wrapped_foo = Data_Wrap_Struct(Data_Type<Foo>::klass(), 0, Default_Free_Function<Foo>::free, foo); - Data_Object<Foo> data_object_foo(wrapped_foo, rb_cFoo); - ASSERT_EQUAL(foo, data_object_foo.get()); - ASSERT_EQUAL(Data_Type<Foo>::klass(), data_object_foo.class_of()); - ASSERT_EQUAL(RDATA(wrapped_foo), RDATA(data_object_foo.value())); - ASSERT_EQUAL(RUBY_DATA_FUNC(0), RDATA(data_object_foo.value())->dmark); - ASSERT_EQUAL( - RUBY_DATA_FUNC(Default_Free_Function<Foo>::free), - RUBY_DATA_FUNC(RDATA(data_object_foo.value())->dfree)); - ASSERT_EQUAL(foo, DATA_PTR(data_object_foo.value())); -} + MyDataType* myDataType = new MyDataType; -TESTCASE(construct_from_ruby_object_and_wrong_class) -{ - Foo * foo = new Foo; - Data_Type<Foo> rb_cFoo; - VALUE wrapped_foo = Data_Wrap_Struct(rb_cObject, 0, Default_Free_Function<Foo>::free, foo); - ASSERT_EXCEPTION_CHECK( - Exception, - Data_Object<Foo> data_object_foo(wrapped_foo, rb_cFoo), - ASSERT_EQUAL( - Object(rb_eTypeError), - Object(CLASS_OF(ex.value())) - ) - ); + Data_Object<MyDataType> wrapper1(myDataType); + Data_Object<MyDataType> wrapper2(std::move(wrapper1)); + + ASSERT_EQUAL(myDataType, wrapper2.get()); + ASSERT((wrapper1.get() == nullptr)); } -TESTCASE(copy_construct) +TESTCASE(move_assign) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - VALUE wrapped_foo = Data_Wrap_Struct(Data_Type<Foo>::klass(), 0, Default_Free_Function<Foo>::free, foo); - Data_Object<Foo> orig_data_object_foo(wrapped_foo, rb_cFoo); - Data_Object<Foo> data_object_foo(orig_data_object_foo); - ASSERT_EQUAL(foo, data_object_foo.get()); - ASSERT_EQUAL(Data_Type<Foo>::klass(), data_object_foo.class_of()); - ASSERT_EQUAL(RDATA(wrapped_foo), RDATA(data_object_foo.value())); - ASSERT_EQUAL(RUBY_DATA_FUNC(0), RDATA(data_object_foo.value())->dmark); - ASSERT_EQUAL( - RUBY_DATA_FUNC(Default_Free_Function<Foo>::free), - RUBY_DATA_FUNC(RDATA(data_object_foo.value())->dfree)); - ASSERT_EQUAL(foo, DATA_PTR(data_object_foo.value())); + MyDataType* foo1 = new MyDataType; + Data_Object<MyDataType> wrapper1(foo1); + + MyDataType* foo2 = new MyDataType; + Data_Object<MyDataType> wrapper2(foo2); + + wrapper2 = std::move(wrapper1); + + ASSERT_EQUAL(foo1, wrapper2.get()); + ASSERT((wrapper1.get() == nullptr)); } TESTCASE(dereference) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo); - ASSERT_EQUAL(foo, &*wrapped_foo); + Data_Type<MyDataType> rb_cFoo; + MyDataType * myDataType = new MyDataType; + Data_Object<MyDataType> wrapped_foo(myDataType); + ASSERT_EQUAL(myDataType, &*wrapped_foo); } TESTCASE(arrow) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo); - ASSERT_EQUAL(42, foo->x_); + Data_Type<MyDataType> rb_cFoo; + MyDataType * myDataType = new MyDataType; + Data_Object<MyDataType> wrapped_foo(myDataType); + ASSERT_EQUAL(42, myDataType->x); } TESTCASE(get) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo); - ASSERT_EQUAL(foo, wrapped_foo.get()); + Data_Type<MyDataType> rb_cFoo; + MyDataType * myDataType = new MyDataType; + Data_Object<MyDataType> wrapped_foo(myDataType); + ASSERT_EQUAL(myDataType, wrapped_foo.get()); } -// TODO: swap - TESTCASE(to_ruby) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo); - ASSERT_EQUAL(wrapped_foo.value(), to_ruby(wrapped_foo).value()); + Data_Type<MyDataType> rb_cFoo; + MyDataType * myDataType = new MyDataType; + Data_Object<MyDataType> wrapped_foo(myDataType); + ASSERT_EQUAL(String("MyDataType"), wrapped_foo.class_name()); } TESTCASE(from_ruby) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo); - ASSERT_EQUAL(foo, from_ruby<Foo *>(wrapped_foo)); + Data_Type<MyDataType> rb_cFoo; + MyDataType* myDataType = new MyDataType(); + Data_Object<MyDataType> wrapped_foo(myDataType); + ASSERT_EQUAL(myDataType, wrapped_foo.get()); } TESTCASE(from_ruby_const_ref) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo); - ASSERT_EQUAL(foo->x_, from_ruby<Foo const &>(wrapped_foo).x_); + Data_Type<MyDataType> rb_cFoo; + MyDataType * myDataType = new MyDataType; + Data_Object<MyDataType> wrapped_foo(myDataType); + ASSERT_EQUAL(myDataType->x, detail::From_Ruby<MyDataType const &>().convert(wrapped_foo).x); } TESTCASE(from_ruby_copy) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo); - ASSERT_EQUAL(foo->x_, from_ruby<Foo>(wrapped_foo).x_); + Data_Type<MyDataType> rb_cFoo; + MyDataType * myDataType = new MyDataType; + Data_Object<MyDataType> wrapped_foo(myDataType); + ASSERT_EQUAL(myDataType->x, detail::From_Ruby<MyDataType>().convert(wrapped_foo).x); } -TESTCASE(ruby_mark) +TESTCASE(ruby_custom_mark) { - Data_Type<Foo> rb_cFoo; - Foo * foo = new Foo; - Data_Object<Foo> wrapped_foo(foo); + test_ruby_mark_called = false; - test_ruby_mark__marked = false; - + MyDataType* myDataType = new MyDataType; + Data_Object<MyDataType> wrapped_foo(myDataType); rb_gc_start(); - ASSERT_EQUAL(true, test_ruby_mark__marked); + ASSERT_EQUAL(true, test_ruby_mark_called); } +TESTCASE(ruby_custom_free) +{ + test_ruby_mark_called = false; + test_destructor_called = false; + + MyDataType* myDataType = new MyDataType; + { + Data_Object<MyDataType> wrapped_foo(myDataType, true); + } + + rb_gc_start(); + + ASSERT_EQUAL(true, test_destructor_called); + // This fails somtimes on Ubuntu with Ruby 2.5 and 2.6. The important thing is that the destructor + // gets called + // ASSERT_EQUAL(false, test_ruby_mark_called); +}