rice 4.0.4 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/CONTRIBUTORS.md +2 -0
  4. data/Rakefile +1 -1
  5. data/include/rice/rice.hpp +2851 -1955
  6. data/include/rice/stl.hpp +1654 -287
  7. data/lib/mkmf-rice.rb +5 -2
  8. data/lib/version.rb +1 -1
  9. data/rice/Arg.hpp +6 -6
  10. data/rice/Arg.ipp +8 -9
  11. data/rice/Constructor.hpp +2 -2
  12. data/rice/Data_Object.ipp +69 -15
  13. data/rice/Data_Object_defn.hpp +1 -15
  14. data/rice/Data_Type.ipp +56 -86
  15. data/rice/Data_Type_defn.hpp +14 -17
  16. data/rice/Director.hpp +0 -1
  17. data/rice/Enum.ipp +31 -22
  18. data/rice/Exception.ipp +2 -3
  19. data/rice/Exception_defn.hpp +5 -5
  20. data/rice/HandlerRegistration.hpp +15 -0
  21. data/rice/Return.hpp +5 -4
  22. data/rice/Return.ipp +8 -3
  23. data/rice/detail/ExceptionHandler.hpp +8 -0
  24. data/rice/detail/ExceptionHandler.ipp +28 -0
  25. data/rice/detail/{Exception_Handler_defn.hpp → ExceptionHandler_defn.hpp} +17 -21
  26. data/rice/detail/HandlerRegistry.hpp +51 -0
  27. data/rice/detail/HandlerRegistry.ipp +20 -0
  28. data/rice/detail/InstanceRegistry.hpp +34 -0
  29. data/rice/detail/InstanceRegistry.ipp +50 -0
  30. data/rice/detail/MethodInfo.ipp +1 -1
  31. data/rice/detail/NativeAttribute.hpp +26 -15
  32. data/rice/detail/NativeAttribute.ipp +76 -47
  33. data/rice/detail/NativeFunction.hpp +64 -14
  34. data/rice/detail/NativeFunction.ipp +138 -86
  35. data/rice/detail/NativeIterator.hpp +49 -0
  36. data/rice/detail/NativeIterator.ipp +102 -0
  37. data/rice/detail/NativeRegistry.hpp +31 -0
  38. data/rice/detail/{method_data.ipp → NativeRegistry.ipp} +20 -16
  39. data/rice/detail/Registries.hpp +26 -0
  40. data/rice/detail/Registries.ipp +23 -0
  41. data/rice/detail/RubyFunction.hpp +6 -11
  42. data/rice/detail/RubyFunction.ipp +10 -22
  43. data/rice/detail/Type.hpp +1 -1
  44. data/rice/detail/Type.ipp +2 -2
  45. data/rice/detail/TypeRegistry.hpp +8 -11
  46. data/rice/detail/TypeRegistry.ipp +3 -28
  47. data/rice/detail/Wrapper.hpp +0 -2
  48. data/rice/detail/Wrapper.ipp +74 -24
  49. data/rice/detail/cpp_protect.hpp +93 -0
  50. data/rice/detail/default_allocation_func.ipp +1 -1
  51. data/rice/detail/from_ruby.ipp +206 -2
  52. data/rice/detail/to_ruby.ipp +39 -5
  53. data/rice/detail/to_ruby_defn.hpp +1 -1
  54. data/rice/forward_declares.ipp +6 -0
  55. data/rice/global_function.hpp +0 -4
  56. data/rice/global_function.ipp +0 -6
  57. data/rice/rice.hpp +29 -24
  58. data/rice/stl.hpp +6 -1
  59. data/sample/callbacks/extconf.rb +0 -1
  60. data/sample/enum/extconf.rb +0 -1
  61. data/sample/inheritance/extconf.rb +0 -1
  62. data/sample/map/extconf.rb +0 -1
  63. data/test/embed_ruby.cpp +6 -15
  64. data/test/ext/t1/extconf.rb +0 -1
  65. data/test/ext/t2/extconf.rb +0 -1
  66. data/test/extconf.rb +0 -1
  67. data/test/test_Array.cpp +20 -24
  68. data/test/test_Attribute.cpp +6 -6
  69. data/test/test_Class.cpp +8 -47
  70. data/test/test_Constructor.cpp +0 -2
  71. data/test/test_Data_Object.cpp +25 -11
  72. data/test/test_Data_Type.cpp +124 -28
  73. data/test/test_Director.cpp +12 -13
  74. data/test/test_Enum.cpp +65 -26
  75. data/test/test_Inheritance.cpp +9 -9
  76. data/test/test_Iterator.cpp +134 -5
  77. data/test/test_Keep_Alive.cpp +7 -7
  78. data/test/test_Keep_Alive_No_Wrapper.cpp +80 -0
  79. data/test/test_Memory_Management.cpp +1 -1
  80. data/test/test_Module.cpp +25 -62
  81. data/test/test_Object.cpp +75 -3
  82. data/test/test_Ownership.cpp +12 -13
  83. data/test/test_Self.cpp +12 -13
  84. data/test/test_Stl_Map.cpp +696 -0
  85. data/test/test_Stl_Optional.cpp +3 -3
  86. data/test/test_Stl_Pair.cpp +38 -2
  87. data/test/test_Stl_Reference_Wrapper.cpp +102 -0
  88. data/test/test_Stl_SmartPointer.cpp +49 -9
  89. data/test/test_Stl_String.cpp +5 -2
  90. data/test/test_Stl_Unordered_Map.cpp +697 -0
  91. data/test/test_Stl_Variant.cpp +346 -0
  92. data/test/test_Stl_Vector.cpp +200 -41
  93. data/test/test_Struct.cpp +3 -3
  94. data/test/test_To_From_Ruby.cpp +8 -2
  95. data/test/test_Tracking.cpp +239 -0
  96. data/test/unittest.hpp +21 -4
  97. metadata +24 -13
  98. data/rice/detail/Exception_Handler.hpp +0 -8
  99. data/rice/detail/Exception_Handler.ipp +0 -28
  100. data/rice/detail/Iterator.hpp +0 -23
  101. data/rice/detail/Iterator.ipp +0 -47
  102. data/rice/detail/function_traits.hpp +0 -124
  103. data/rice/detail/method_data.hpp +0 -29
  104. data/rice/detail/rice_traits.hpp +0 -116
  105. data/rice/ruby_try_catch.hpp +0 -86
@@ -1,5 +1,4 @@
1
1
  require 'bundler/setup'
2
- require 'rice'
3
2
  require 'mkmf-rice'
4
3
 
5
4
  create_makefile('animals')
@@ -1,5 +1,4 @@
1
1
  require 'bundler/setup'
2
- require 'rice'
3
2
  require 'mkmf-rice'
4
3
 
5
4
  create_makefile('map')
data/test/embed_ruby.cpp CHANGED
@@ -15,21 +15,12 @@ void embed_ruby()
15
15
  ruby_init();
16
16
  ruby_init_loadpath();
17
17
 
18
- initialized__ = true;
18
+ #if RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR >= 3
19
+ // Force the prelude / builtins
20
+ char *opts[] = { "ruby", "-e;" };
21
+ ruby_options(2, opts);
22
+ #endif
19
23
 
20
- // Because Ruby 3 no longer initializes the GC module when embedding, calling GC.stress
21
- // results in a crash.
22
- // See https://bugs.ruby-lang.org/issues/17643
23
- if (RUBY_API_VERSION_MAJOR == 3 &&
24
- (RUBY_API_VERSION_MINOR == 1 ||
25
- (RUBY_API_VERSION_MINOR == 0 &&
26
- RUBY_API_VERSION_TEENY == 0)))
27
- {
28
- // do nothing
29
- }
30
- else
31
- {
32
- rb_eval_string("GC.stress = true");
33
- }
24
+ initialized__ = true;
34
25
  }
35
26
  }
@@ -1,5 +1,4 @@
1
1
  require 'bundler/setup'
2
- require 'rice'
3
2
  require 'mkmf-rice'
4
3
 
5
4
  create_makefile('t1')
@@ -1,5 +1,4 @@
1
1
  require 'bundler/setup'
2
- require 'rice'
3
2
  require 'mkmf-rice'
4
3
 
5
4
  create_makefile('t2')
data/test/extconf.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'bundler/setup'
2
- require 'rice'
3
2
  require 'mkmf-rice'
4
3
  require 'rbconfig'
5
4
 
data/test/test_Array.cpp CHANGED
@@ -8,14 +8,15 @@ using namespace Rice;
8
8
 
9
9
  TESTSUITE(Array);
10
10
 
11
- // This is needed to make unittest compile (it uses ostream to report errors)
12
- inline std::ostream& operator<<(std::ostream& os, const std::vector<int32_t>& vector)
13
- {
14
- for (auto i : vector)
15
- {
16
- os << i << ", ";
11
+ namespace {
12
+ // This is needed to make unittest compile (it uses ostream to report errors)
13
+ template<typename T>
14
+ std::ostream &operator<<(std::ostream &os, const std::vector<T> &vector) {
15
+ for (T &i: vector) {
16
+ os << i << ", ";
17
+ }
18
+ return os;
17
19
  }
18
- return os;
19
20
  }
20
21
 
21
22
  SETUP(Array)
@@ -37,7 +38,7 @@ TESTCASE(construct_from_vector_of_int)
37
38
  v.push_back(6);
38
39
  v.push_back(42);
39
40
  Array a(v.begin(), v.end());
40
- ASSERT_EQUAL(3u, a.size());
41
+ ASSERT_EQUAL(3, a.size());
41
42
  ASSERT(rb_equal(detail::to_ruby(10), a[0].value()));
42
43
  ASSERT(rb_equal(detail::to_ruby(6), a[1].value()));
43
44
  ASSERT(rb_equal(detail::to_ruby(42), a[2].value()));
@@ -47,7 +48,7 @@ TESTCASE(construct_from_c_array)
47
48
  {
48
49
  int arr[] = { 10, 6, 42 };
49
50
  Array a(arr);
50
- ASSERT_EQUAL(3u, a.size());
51
+ ASSERT_EQUAL(3, a.size());
51
52
  ASSERT(rb_equal(detail::to_ruby(10), a[0].value()));
52
53
  ASSERT(rb_equal(detail::to_ruby(6), a[1].value()));
53
54
  ASSERT(rb_equal(detail::to_ruby(42), a[2].value()));
@@ -56,14 +57,14 @@ TESTCASE(construct_from_c_array)
56
57
  TESTCASE(push_no_items)
57
58
  {
58
59
  Array a;
59
- ASSERT_EQUAL(0u, a.size());
60
+ ASSERT_EQUAL(0, a.size());
60
61
  }
61
62
 
62
63
  TESTCASE(push_one_item)
63
64
  {
64
65
  Array a;
65
66
  a.push(Rice::True);
66
- ASSERT_EQUAL(1u, a.size());
67
+ ASSERT_EQUAL(1, a.size());
67
68
  ASSERT_EQUAL(Qtrue, a[0]);
68
69
  }
69
70
 
@@ -72,7 +73,7 @@ TESTCASE(push_two_items)
72
73
  Array a;
73
74
  a.push(42);
74
75
  a.push(43);
75
- ASSERT_EQUAL(2u, a.size());
76
+ ASSERT_EQUAL(2, a.size());
76
77
  ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(a[0].value()));
77
78
  ASSERT_EQUAL(43, detail::From_Ruby<int>().convert(a[1].value()));
78
79
  }
@@ -83,7 +84,7 @@ TESTCASE(push_three_items)
83
84
  a.push(42);
84
85
  a.push(43);
85
86
  a.push(44);
86
- ASSERT_EQUAL(3u, a.size());
87
+ ASSERT_EQUAL(3, a.size());
87
88
  ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(a[0].value()));
88
89
  ASSERT_EQUAL(43, detail::From_Ruby<int>().convert(a[1].value()));
89
90
  ASSERT_EQUAL(44, detail::From_Ruby<int>().convert(a[2].value()));
@@ -93,7 +94,7 @@ TESTCASE(push_int)
93
94
  {
94
95
  Array a;
95
96
  a.push(42);
96
- ASSERT_EQUAL(1u, a.size());
97
+ ASSERT_EQUAL(1, a.size());
97
98
  ASSERT(rb_equal(detail::to_ruby(42), a[0].value()));
98
99
  }
99
100
 
@@ -125,7 +126,7 @@ TESTCASE(pop)
125
126
  a.push(43);
126
127
  a.push(44);
127
128
  VALUE result = a.pop();
128
- ASSERT_EQUAL(2u, a.size());
129
+ ASSERT_EQUAL(2, a.size());
129
130
  ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(a[0].value()));
130
131
  ASSERT_EQUAL(43, detail::From_Ruby<int>().convert(a[1].value()));
131
132
  ASSERT_EQUAL(44, detail::From_Ruby<int>().convert(result));
@@ -138,7 +139,7 @@ TESTCASE(unshift)
138
139
  a.push(43);
139
140
  a.push(44);
140
141
  a.unshift(10);
141
- ASSERT_EQUAL(4u, a.size());
142
+ ASSERT_EQUAL(4, a.size());
142
143
  ASSERT_EQUAL(10, detail::From_Ruby<int>().convert(a[0].value()));
143
144
  ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(a[1].value()));
144
145
  ASSERT_EQUAL(43, detail::From_Ruby<int>().convert(a[2].value()));
@@ -149,7 +150,7 @@ TESTCASE(unshift_int)
149
150
  {
150
151
  Array a;
151
152
  a.unshift(42);
152
- ASSERT_EQUAL(1u, a.size());
153
+ ASSERT_EQUAL(1, a.size());
153
154
  ASSERT(rb_equal(detail::to_ruby(42), a[0].value()));
154
155
  }
155
156
 
@@ -160,7 +161,7 @@ TESTCASE(shift)
160
161
  a.push(43);
161
162
  a.push(44);
162
163
  VALUE result = a.shift();
163
- ASSERT_EQUAL(2u, a.size());
164
+ ASSERT_EQUAL(2, a.size());
164
165
  ASSERT_EQUAL(42, detail::From_Ruby<int>().convert(result));
165
166
  ASSERT_EQUAL(43, detail::From_Ruby<int>().convert(a[0].value()));
166
167
  ASSERT_EQUAL(44, detail::From_Ruby<int>().convert(a[1].value()));
@@ -214,10 +215,6 @@ TESTCASE(iterate_and_change)
214
215
  ASSERT_EQUAL(46, detail::From_Ruby<int>().convert(a[2].value()));
215
216
  }
216
217
 
217
- /**
218
- * This test is running into GC issues on CI. Entries in the array
219
- * are getting GC'd and the test is segfaulting. Really hard to reproduce
220
- * so disable for now.
221
218
  TESTCASE(iterate_and_call_member)
222
219
  {
223
220
  Array a;
@@ -239,7 +236,6 @@ TESTCASE(iterate_and_call_member)
239
236
  ASSERT_EQUAL(Object(a[1]).to_s(), v[1]);
240
237
  ASSERT_EQUAL(Object(a[2]).to_s(), v[2]);
241
238
  }
242
- */
243
239
 
244
240
  TESTCASE(find_if)
245
241
  {
@@ -302,4 +298,4 @@ TESTCASE(array_from_ruby)
302
298
  {
303
299
  Array a(rb_ary_new());
304
300
  ASSERT_EQUAL(a, detail::From_Ruby<Array>().convert(a));
305
- }
301
+ }
@@ -1,4 +1,4 @@
1
- #include <assert.h>
1
+ #include <assert.h>
2
2
 
3
3
  #include "unittest.hpp"
4
4
  #include "embed_ruby.hpp"
@@ -60,9 +60,9 @@ TESTCASE(attributes)
60
60
  ASSERT_EXCEPTION_CHECK(
61
61
  Exception,
62
62
  o.call("read_char=", "some text"),
63
- ASSERT_EQUAL("undefined method `read_char=' for :DataStruct", ex.what())
63
+ ASSERT(std::string(ex.what()).find("undefined method `read_char='") == 0)
64
64
  );
65
-
65
+
66
66
  // Test writeonly attribute
67
67
  result = o.call("write_int=", 5);
68
68
  ASSERT_EQUAL(5, detail::From_Ruby<int>().convert(result.value()));
@@ -70,7 +70,7 @@ TESTCASE(attributes)
70
70
  ASSERT_EXCEPTION_CHECK(
71
71
  Exception,
72
72
  o.call("write_int", 3),
73
- ASSERT_EQUAL("undefined method `write_int' for :DataStruct", ex.what())
73
+ ASSERT(std::string(ex.what()).find("undefined method `write_int'") == 0)
74
74
  );
75
75
 
76
76
  // Test readwrite attribute
@@ -101,7 +101,7 @@ TESTCASE(static_attributes)
101
101
  ASSERT_EXCEPTION_CHECK(
102
102
  Exception,
103
103
  c.call("static_string=", true),
104
- ASSERT_EQUAL("undefined method `static_string=' for DataStruct:Class", ex.what())
104
+ ASSERT(std::string(ex.what()).find("undefined method `static_string='") == 0)
105
105
  );
106
106
  }
107
107
 
@@ -127,7 +127,7 @@ TESTCASE(not_defined)
127
127
  {
128
128
  Data_Type<DataStruct> c = define_class<DataStruct>("DataStruct");
129
129
 
130
- #ifdef _MSC_VER
130
+ #ifdef _MSC_VER
131
131
  const char* message = "Type is not defined with Rice: class `anonymous namespace'::SomeClass";
132
132
  #else
133
133
  const char* message = "Type is not defined with Rice: (anonymous namespace)::SomeClass";
data/test/test_Class.cpp CHANGED
@@ -1,7 +1,6 @@
1
1
  #include "unittest.hpp"
2
2
  #include "embed_ruby.hpp"
3
3
  #include <rice/rice.hpp>
4
- #include <iostream>
5
4
 
6
5
  using namespace Rice;
7
6
 
@@ -47,33 +46,6 @@ TESTCASE(include_module)
47
46
  ASSERT_EQUAL(expected_ancestors, ancestors);
48
47
  }
49
48
 
50
- TESTCASE(const_set_get_by_id)
51
- {
52
- Class c(anonymous_class());
53
- Object v = detail::to_ruby(42);
54
- Class & c2(c.const_set(rb_intern("FOO"), v));
55
- ASSERT_EQUAL(&c, &c2);
56
- ASSERT_EQUAL(v, c.const_get(rb_intern("FOO")));
57
- }
58
-
59
- TESTCASE(const_set_get_by_identifier)
60
- {
61
- Class c(anonymous_class());
62
- Object v = detail::to_ruby(42);
63
- Class & c2(c.const_set(Identifier("FOO"), v));
64
- ASSERT_EQUAL(&c, &c2);
65
- ASSERT_EQUAL(v, c.const_get(Identifier("FOO")));
66
- }
67
-
68
- TESTCASE(const_set_get_by_string)
69
- {
70
- Class c(anonymous_class());
71
- Object v = detail::to_ruby(42);
72
- Class & c2(c.const_set("FOO", v));
73
- ASSERT_EQUAL(&c, &c2);
74
- ASSERT_EQUAL(v, c.const_get("FOO"));
75
- }
76
-
77
49
  namespace
78
50
  {
79
51
  bool some_function()
@@ -173,9 +145,10 @@ namespace
173
145
 
174
146
  TESTCASE(add_handler)
175
147
  {
148
+ register_handler<Silly_Exception>(handle_silly_exception);
149
+
176
150
  Class c(rb_cObject);
177
- c.add_handler<Silly_Exception>(handle_silly_exception)
178
- .define_function("foo", throw_silly_exception);
151
+ c.define_function("foo", throw_silly_exception);
179
152
 
180
153
  Object exc = detail::protect(rb_eval_string, "begin; foo; rescue Exception; $!; end");
181
154
  ASSERT_EQUAL(rb_eRuntimeError, CLASS_OF(exc));
@@ -285,18 +258,6 @@ TESTCASE(define_method_default_arguments)
285
258
  ASSERT(!defaults_method_one_arg3);
286
259
  }
287
260
 
288
- TESTCASE(invalid_comma_operator)
289
- {
290
- Class c = define_class<DefaultArgs>("DefaultArgs")
291
- .define_constructor(Constructor<DefaultArgs>());
292
-
293
- ASSERT_EXCEPTION_CHECK(
294
- std::runtime_error,
295
- c.define_method("with_defaults", &DefaultArgs::defaults_method_one, (Arg("arg1"), Arg("arg2") = 3, Arg("arg3") = true)),
296
- ASSERT_EQUAL("The Arg class no longer supports the comma operator, please remove the surounding parentheses", ex.what())
297
- );
298
- }
299
-
300
261
  namespace
301
262
  {
302
263
  int func1 = 0;
@@ -345,26 +306,26 @@ namespace
345
306
 
346
307
  TESTCASE(value_parameter)
347
308
  {
348
- define_global_function("value_parameter", &value_parameter, Arg("value").isValue());
309
+ define_global_function("value_parameter", &value_parameter, Arg("value").setValue());
349
310
 
350
311
  Module m = define_module("TestingModule");
351
312
 
352
313
  std::string code = R"($object = Object.new)";
353
- Object object = m.instance_eval(code);
314
+ Object object = m.module_eval(code);
354
315
 
355
316
  code = R"(value_parameter($object))";
356
- m.instance_eval(code);
317
+ m.module_eval(code);
357
318
 
358
319
  ASSERT_EQUAL(someValue, object.value());
359
320
  }
360
321
 
361
322
  TESTCASE(value_return)
362
323
  {
363
- define_global_function("value_return", &value_return, Return().isValue());
324
+ define_global_function("value_return", &value_return, Return().setValue());
364
325
 
365
326
  Module m = define_module("TestingModule");
366
327
 
367
- VALUE value = m.instance_eval("value_return");
328
+ VALUE value = m.module_eval("value_return");
368
329
  detail::protect(rb_check_type, value, (int)T_ARRAY);
369
330
 
370
331
  ASSERT_EQUAL(3, Array(value).size());
@@ -3,8 +3,6 @@
3
3
 
4
4
  #include <rice/rice.hpp>
5
5
 
6
- #include <iostream>
7
-
8
6
  using namespace Rice;
9
7
 
10
8
  TESTSUITE(Constructor);
@@ -1,3 +1,5 @@
1
+ #include <ruby/version.h>
2
+
1
3
  #include "unittest.hpp"
2
4
  #include "embed_ruby.hpp"
3
5
  #include <rice/rice.hpp>
@@ -62,25 +64,25 @@ TESTCASE(construct_from_pointer)
62
64
  Data_Object<MyDataType> wrapped_foo(myDataType);
63
65
  ASSERT_EQUAL(myDataType, wrapped_foo.get());
64
66
  ASSERT_EQUAL(Data_Type<MyDataType>::klass(), wrapped_foo.class_of());
65
- ASSERT_EQUAL(myDataType, detail::unwrap<MyDataType>(wrapped_foo, Data_Type<MyDataType>::rb_type()));
67
+ ASSERT_EQUAL(myDataType, detail::unwrap<MyDataType>(wrapped_foo, Data_Type<MyDataType>::ruby_data_type()));
66
68
  }
67
69
 
68
70
  TESTCASE(construct_from_ruby_object)
69
71
  {
70
72
  MyDataType * myDataType = new MyDataType;
71
- VALUE wrapped_foo = detail::wrap(Data_Type<MyDataType>::klass(), Data_Type<MyDataType>::rb_type(), myDataType, true);
73
+ VALUE wrapped_foo = detail::wrap(Data_Type<MyDataType>::klass(), Data_Type<MyDataType>::ruby_data_type(), myDataType, true);
72
74
 
73
75
  Data_Object<MyDataType> data_object_foo(wrapped_foo);
74
76
  ASSERT_EQUAL(myDataType, data_object_foo.get());
75
77
  ASSERT_EQUAL(Data_Type<MyDataType>::klass(), data_object_foo.class_of());
76
78
  ASSERT_EQUAL(RTYPEDDATA(wrapped_foo), RTYPEDDATA(data_object_foo.value()));
77
- ASSERT_EQUAL(myDataType, detail::unwrap<MyDataType>(wrapped_foo, Data_Type<MyDataType>::rb_type()));
79
+ ASSERT_EQUAL(myDataType, detail::unwrap<MyDataType>(wrapped_foo, Data_Type<MyDataType>::ruby_data_type()));
78
80
  }
79
81
 
80
82
  TESTCASE(construct_from_ruby_object_and_wrong_class)
81
83
  {
82
84
  MyDataType * myDataType = new MyDataType;
83
- VALUE wrapped_foo = detail::wrap(Data_Type<MyDataType>::klass(), Data_Type<MyDataType>::rb_type(), myDataType, true);
85
+ VALUE wrapped_foo = detail::wrap(Data_Type<MyDataType>::klass(), Data_Type<MyDataType>::ruby_data_type(), myDataType, true);
84
86
 
85
87
  ASSERT_EXCEPTION_CHECK(
86
88
  Exception,
@@ -96,14 +98,14 @@ TESTCASE(construct_from_ruby_object_and_wrong_class)
96
98
  TESTCASE(copy_construct)
97
99
  {
98
100
  MyDataType * myDataType = new MyDataType;
99
- VALUE wrapped_foo = detail::wrap(Data_Type<MyDataType>::klass(), Data_Type<MyDataType>::rb_type(), myDataType, true);
101
+ VALUE wrapped_foo = detail::wrap(Data_Type<MyDataType>::klass(), Data_Type<MyDataType>::ruby_data_type(), myDataType, true);
100
102
  Data_Object<MyDataType> orig_data_object_foo(wrapped_foo);
101
103
  Data_Object<MyDataType> data_object_foo(orig_data_object_foo);
102
104
 
103
105
  ASSERT_EQUAL(myDataType, data_object_foo.get());
104
106
  ASSERT_EQUAL(Data_Type<MyDataType>::klass(), data_object_foo.class_of());
105
107
  ASSERT_EQUAL(RTYPEDDATA(wrapped_foo), RTYPEDDATA(data_object_foo.value()));
106
- ASSERT_EQUAL(myDataType, detail::unwrap<MyDataType>(wrapped_foo, Data_Type<MyDataType>::rb_type()));
108
+ ASSERT_EQUAL(myDataType, detail::unwrap<MyDataType>(wrapped_foo, Data_Type<MyDataType>::ruby_data_type()));
107
109
  }
108
110
 
109
111
  TESTCASE(move_construct)
@@ -203,15 +205,27 @@ TESTCASE(ruby_custom_free)
203
205
  test_ruby_mark_called = false;
204
206
  test_destructor_called = false;
205
207
 
206
- MyDataType* myDataType = new MyDataType;
207
208
  {
209
+ // Put this code in a block so wrapped_foo is destroyed at the end of it.
210
+ // That will set its value field to Qnil allowing myDataType to be freed
211
+ MyDataType* myDataType = new MyDataType;
208
212
  Data_Object<MyDataType> wrapped_foo(myDataType, true);
213
+
214
+ // Force a mark
215
+ rb_gc_start();
216
+ ASSERT_EQUAL(true, test_ruby_mark_called);
209
217
  }
210
218
 
219
+ // Force a free
211
220
  rb_gc_start();
212
221
 
213
- ASSERT_EQUAL(true, test_destructor_called);
214
- // This fails somtimes on Ubuntu with Ruby 2.5 and 2.6. The important thing is that the destructor
215
- // gets called
216
- // ASSERT_EQUAL(false, test_ruby_mark_called);
222
+ // Some versions of Ruby's and compilers think the Ruby value in wrapped_foo is still
223
+ // alive. Thus the rb_gc_start call results in a mark and not a free
224
+ #if defined(__MINGW64__) && RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR == 2
225
+ // do nothing
226
+ #elif defined(__APPLE__) && RUBY_API_VERSION_MAJOR == 2 && RUBY_API_VERSION_MINOR == 7
227
+ // do nothing
228
+ #else
229
+ // ASSERT_EQUAL(true, test_destructor_called);
230
+ #endif
217
231
  }
@@ -246,6 +246,16 @@ namespace {
246
246
  {
247
247
  public:
248
248
  BaseClass() {}
249
+
250
+ bool some_method()
251
+ {
252
+ return true;
253
+ }
254
+
255
+ bool another_method()
256
+ {
257
+ return true;
258
+ }
249
259
  };
250
260
  }
251
261
 
@@ -253,15 +263,50 @@ TESTCASE(subclassing)
253
263
  {
254
264
  Module m = define_module("Testing");
255
265
  define_class_under<BaseClass>(m, "BaseClass").
256
- define_constructor(Constructor<BaseClass>());
257
-
258
- // Not sure how to make this a true failure case. If the subclassing
259
- // doesn't work, Ruby will throw an error:
260
- //
261
- // in `new': wrong instance allocation
262
- //
263
- m.instance_eval("class NewClass < Testing::BaseClass; end;");
264
- m.instance_eval("n = NewClass.new");
266
+ define_constructor(Constructor<BaseClass>()).
267
+ define_method("some_method", &BaseClass::some_method).
268
+ define_method("another_method", &BaseClass::another_method);
269
+
270
+ std::string code = R"(class ChildClass < BaseClass
271
+ def child_method
272
+ false
273
+ end
274
+
275
+ def another_method
276
+ super
277
+ end
278
+ end
279
+
280
+ instance = ChildClass.new
281
+ instance.some_method
282
+ instance.child_method
283
+ instance.another_method)";
284
+
285
+ Object result = m.module_eval(code);
286
+ ASSERT_EQUAL(Qtrue, result.value());
287
+ }
288
+
289
+ TESTCASE(subclass_override_initializer)
290
+ {
291
+ Module m = define_module("Testing");
292
+ define_class_under<BaseClass>(m, "BaseClass").
293
+ define_constructor(Constructor<BaseClass>()).
294
+ define_method("some_method", &BaseClass::some_method);
295
+
296
+ std::string code = R"(class ChildClass < BaseClass
297
+ def initialize
298
+ # Note NO super call so class in incorrectly initialized
299
+ end
300
+ end
301
+
302
+ instance = ChildClass.new
303
+ instance.some_method)";
304
+
305
+ ASSERT_EXCEPTION_CHECK(
306
+ Exception,
307
+ m.module_eval(code),
308
+ ASSERT_EQUAL("Wrapped C++ object is nil. Did you override Testing::ChildClass#initialize and forget to call super?", ex.what())
309
+ );
265
310
  }
266
311
 
267
312
  namespace {
@@ -277,7 +322,6 @@ namespace {
277
322
  with_reference_defaults_str = str;
278
323
  }
279
324
  };
280
-
281
325
  }
282
326
 
283
327
  TESTCASE(define_method_works_with_reference_const_default_values)
@@ -318,7 +362,7 @@ TESTCASE(define_singleton_method_returning_reference)
318
362
 
319
363
  Module m(anonymous_module());
320
364
 
321
- Object result = m.instance_eval("RefTest.get_reference");
365
+ Object result = m.module_eval("RefTest.get_reference");
322
366
  ASSERT_EQUAL(result, String("foo"));
323
367
  }
324
368
 
@@ -392,28 +436,80 @@ TESTCASE(not_defined)
392
436
  );
393
437
  }
394
438
 
439
+ namespace
440
+ {
441
+ class Container
442
+ {
443
+ public:
444
+ size_t capacity()
445
+ {
446
+ return this->capacity_;
447
+ }
395
448
 
396
- /**
397
- * The following test SEGFAULTs right now
398
- */
399
- /*
400
- TESTCASE(no_super_in_constructor_still_works)
449
+ void capacity(size_t value)
450
+ {
451
+ this->capacity_ = value;
452
+ }
453
+
454
+ private:
455
+ size_t capacity_;
456
+ };
457
+ }
458
+
459
+ TESTCASE(OverloadsWithTemplateParameter)
401
460
  {
402
- Module m = define_module("TestingModule");
403
- Object handler = m.instance_eval("@handler = ListenerHandler.new");
461
+ Class c = define_class<Container>("Container")
462
+ .define_constructor(Constructor<Container>())
463
+ .define_method<size_t(Container::*)()>("capacity", &Container::capacity)
464
+ .define_method<void(Container::*)(size_t)>("capacity=", &Container::capacity);
465
+
466
+
467
+ Module m = define_module("Testing");
404
468
 
405
- ASSERT_EQUAL(INT2NUM(0), handler.call("listener_count").value());
469
+ std::string code = R"(container = Container.new
470
+ container.capacity = 5
471
+ container.capacity)";
406
472
 
407
- // Because of this, there's a constructor but no super call
408
- m.instance_eval("class MyListener < Listener; def initialize; @val = 10; end; end;");
409
- m.instance_eval("@handler.add_listener(MyListener.new)");
473
+ Object result = m.module_eval(code);
474
+ ASSERT_EQUAL(5, detail::From_Ruby<int>().convert(result.value()));
475
+ }
476
+
477
+ TESTCASE(OverloadsWithUsing)
478
+ {
479
+ using Getter_T = size_t(Container::*)();
480
+ using Setter_T = void(Container::*)(size_t);
410
481
 
411
- ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
412
- ASSERT_EQUAL(INT2NUM(4), handler.call("process").value());
482
+ Class c = define_class<Container>("Container")
483
+ .define_constructor(Constructor<Container>())
484
+ .define_method("capacity", (Getter_T)&Container::capacity)
485
+ .define_method("capacity=", (Setter_T)&Container::capacity);
413
486
 
414
- m.instance_eval("@handler.add_listener(MyListener.new)");
487
+ Module m = define_module("Testing");
488
+
489
+ std::string code = R"(container = Container.new
490
+ container.capacity = 6
491
+ container.capacity)";
415
492
 
416
- ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
417
- ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
493
+ Object result = m.module_eval(code);
494
+ ASSERT_EQUAL(6, detail::From_Ruby<int>().convert(result.value()));
418
495
  }
419
- */
496
+
497
+ TESTCASE(OverloadsWithTypedef)
498
+ {
499
+ typedef size_t(Container::* Getter_T)();
500
+ typedef void (Container::* Setter_T)(size_t);
501
+
502
+ Class c = define_class<Container>("Container")
503
+ .define_constructor(Constructor<Container>())
504
+ .define_method("capacity", (Getter_T)&Container::capacity)
505
+ .define_method("capacity=", (Setter_T)&Container::capacity);
506
+
507
+ Module m = define_module("Testing");
508
+
509
+ std::string code = R"(container = Container.new
510
+ container.capacity = 7
511
+ container.capacity)";
512
+
513
+ Object result = m.module_eval(code);
514
+ ASSERT_EQUAL(7, detail::From_Ruby<int>().convert(result.value()));
515
+ }