rice 4.0.4 → 4.1.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 (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/Rakefile +1 -1
  4. data/include/rice/rice.hpp +2596 -1771
  5. data/include/rice/stl.hpp +1580 -271
  6. data/lib/mkmf-rice.rb +5 -2
  7. data/lib/version.rb +1 -1
  8. data/rice/Arg.hpp +6 -6
  9. data/rice/Arg.ipp +8 -9
  10. data/rice/Constructor.hpp +2 -2
  11. data/rice/Data_Object.ipp +69 -15
  12. data/rice/Data_Object_defn.hpp +1 -15
  13. data/rice/Data_Type.ipp +56 -86
  14. data/rice/Data_Type_defn.hpp +14 -17
  15. data/rice/Director.hpp +0 -1
  16. data/rice/Enum.ipp +31 -22
  17. data/rice/Exception.ipp +2 -3
  18. data/rice/Exception_defn.hpp +5 -5
  19. data/rice/HandlerRegistration.hpp +15 -0
  20. data/rice/Return.hpp +5 -4
  21. data/rice/Return.ipp +8 -3
  22. data/rice/detail/ExceptionHandler.hpp +8 -0
  23. data/rice/detail/ExceptionHandler.ipp +28 -0
  24. data/rice/detail/{Exception_Handler_defn.hpp → ExceptionHandler_defn.hpp} +17 -21
  25. data/rice/detail/HandlerRegistry.hpp +51 -0
  26. data/rice/detail/HandlerRegistry.ipp +20 -0
  27. data/rice/detail/InstanceRegistry.hpp +34 -0
  28. data/rice/detail/InstanceRegistry.ipp +50 -0
  29. data/rice/detail/MethodInfo.ipp +1 -1
  30. data/rice/detail/NativeAttribute.hpp +26 -15
  31. data/rice/detail/NativeAttribute.ipp +76 -47
  32. data/rice/detail/NativeFunction.hpp +60 -13
  33. data/rice/detail/NativeFunction.ipp +103 -85
  34. data/rice/detail/NativeIterator.hpp +49 -0
  35. data/rice/detail/NativeIterator.ipp +102 -0
  36. data/rice/detail/NativeRegistry.hpp +31 -0
  37. data/rice/detail/{method_data.ipp → NativeRegistry.ipp} +20 -16
  38. data/rice/detail/Registries.hpp +26 -0
  39. data/rice/detail/Registries.ipp +23 -0
  40. data/rice/detail/RubyFunction.hpp +6 -11
  41. data/rice/detail/RubyFunction.ipp +10 -22
  42. data/rice/detail/Type.hpp +1 -1
  43. data/rice/detail/Type.ipp +2 -2
  44. data/rice/detail/TypeRegistry.hpp +8 -11
  45. data/rice/detail/TypeRegistry.ipp +3 -28
  46. data/rice/detail/Wrapper.hpp +0 -2
  47. data/rice/detail/Wrapper.ipp +73 -23
  48. data/rice/detail/cpp_protect.hpp +93 -0
  49. data/rice/detail/default_allocation_func.ipp +1 -1
  50. data/rice/detail/from_ruby.ipp +206 -2
  51. data/rice/detail/to_ruby.ipp +39 -5
  52. data/rice/detail/to_ruby_defn.hpp +1 -1
  53. data/rice/forward_declares.ipp +6 -0
  54. data/rice/global_function.hpp +0 -4
  55. data/rice/global_function.ipp +0 -6
  56. data/rice/rice.hpp +29 -24
  57. data/rice/stl.hpp +6 -1
  58. data/test/embed_ruby.cpp +0 -15
  59. data/test/test_Array.cpp +20 -24
  60. data/test/test_Class.cpp +8 -47
  61. data/test/test_Constructor.cpp +0 -2
  62. data/test/test_Data_Object.cpp +25 -11
  63. data/test/test_Data_Type.cpp +124 -28
  64. data/test/test_Director.cpp +12 -13
  65. data/test/test_Enum.cpp +65 -26
  66. data/test/test_Inheritance.cpp +9 -9
  67. data/test/test_Iterator.cpp +134 -5
  68. data/test/test_Keep_Alive.cpp +7 -7
  69. data/test/test_Memory_Management.cpp +1 -1
  70. data/test/test_Module.cpp +25 -62
  71. data/test/test_Object.cpp +66 -3
  72. data/test/test_Ownership.cpp +12 -13
  73. data/test/test_Self.cpp +12 -13
  74. data/test/test_Stl_Map.cpp +696 -0
  75. data/test/test_Stl_Optional.cpp +3 -3
  76. data/test/test_Stl_Pair.cpp +38 -2
  77. data/test/test_Stl_Reference_Wrapper.cpp +102 -0
  78. data/test/test_Stl_SmartPointer.cpp +5 -5
  79. data/test/test_Stl_Unordered_Map.cpp +697 -0
  80. data/test/test_Stl_Variant.cpp +301 -0
  81. data/test/test_Stl_Vector.cpp +200 -41
  82. data/test/test_Struct.cpp +3 -3
  83. data/test/test_To_From_Ruby.cpp +6 -0
  84. data/test/test_Tracking.cpp +239 -0
  85. data/test/unittest.hpp +13 -4
  86. metadata +23 -13
  87. data/rice/detail/Exception_Handler.hpp +0 -8
  88. data/rice/detail/Exception_Handler.ipp +0 -28
  89. data/rice/detail/Iterator.hpp +0 -23
  90. data/rice/detail/Iterator.ipp +0 -47
  91. data/rice/detail/function_traits.hpp +0 -124
  92. data/rice/detail/method_data.hpp +0 -29
  93. data/rice/detail/rice_traits.hpp +0 -116
  94. data/rice/ruby_try_catch.hpp +0 -86
data/test/embed_ruby.cpp CHANGED
@@ -16,20 +16,5 @@ void embed_ruby()
16
16
  ruby_init_loadpath();
17
17
 
18
18
  initialized__ = true;
19
-
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
- }
34
19
  }
35
20
  }
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
+ }
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
+ }
@@ -3,7 +3,6 @@
3
3
  #include <rice/rice.hpp>
4
4
 
5
5
  #include <vector>
6
- #include <iostream>
7
6
 
8
7
  using namespace Rice;
9
8
 
@@ -107,7 +106,7 @@ TESTCASE(exposes_worker_as_instantiatable_class)
107
106
  .define_method("get_number", &Worker::getNumber);
108
107
 
109
108
  Module m = define_module("Testing");
110
- Object result = m.instance_eval("worker = Worker.new; worker.get_number");
109
+ Object result = m.module_eval("worker = Worker.new; worker.get_number");
111
110
 
112
111
  ASSERT_EQUAL(12, detail::From_Ruby<int>().convert(result.value()));
113
112
  }
@@ -122,7 +121,7 @@ TESTCASE(can_call_virtual_methods_on_base_class)
122
121
 
123
122
  Module m = define_module("Testing");
124
123
 
125
- Object result = m.instance_eval("worker = Worker.new; worker.do_something(4)");
124
+ Object result = m.module_eval("worker = Worker.new; worker.do_something(4)");
126
125
 
127
126
  ASSERT_EQUAL(16, detail::From_Ruby<int>().convert(result.value()));
128
127
  }
@@ -135,9 +134,9 @@ TESTCASE(super_calls_pass_execution_up_the_inheritance_chain)
135
134
  .define_method("do_something", &WorkerDirector::default_doSomething);
136
135
 
137
136
  Module m = define_module("Testing");
138
- m.instance_eval("class RubyWorker < Worker; def do_something(num); super * num; end; end");
137
+ m.module_eval("class RubyWorker < Worker; def do_something(num); super * num; end; end");
139
138
 
140
- Object result = m.instance_eval("worker = RubyWorker.new; worker.do_something(10)");
139
+ Object result = m.module_eval("worker = RubyWorker.new; worker.do_something(10)");
141
140
 
142
141
  ASSERT_EQUAL(400, detail::From_Ruby<int>().convert(result.value()));
143
142
  }
@@ -150,11 +149,11 @@ TESTCASE(super_calls_on_pure_virtual_raise_error)
150
149
  .define_method("process", &WorkerDirector::default_process);
151
150
 
152
151
  Module m = define_module("Testing");
153
- m.instance_eval("class RubyWorker < Worker; def process(num); super; end; end");
152
+ m.module_eval("class RubyWorker < Worker; def process(num); super; end; end");
154
153
 
155
154
  ASSERT_EXCEPTION_CHECK(
156
155
  Exception,
157
- m.instance_eval("worker = RubyWorker.new; worker.process(10)"),
156
+ m.module_eval("worker = RubyWorker.new; worker.process(10)"),
158
157
  ASSERT_EQUAL(
159
158
  Object(rb_eNotImpError),
160
159
  Object(CLASS_OF(ex.value()))
@@ -176,7 +175,7 @@ TESTCASE(polymorphic_calls_head_down_the_call_chain)
176
175
 
177
176
  Module m = define_module("Testing");
178
177
 
179
- m.instance_eval(
178
+ m.module_eval(
180
179
  "class EchoWorker < Worker; def process(num); num + 2; end; end;"
181
180
  "class DoubleWorker < Worker; def process(num); num * 2; end; end;"
182
181
  "$handler = Handler.new;"
@@ -184,7 +183,7 @@ TESTCASE(polymorphic_calls_head_down_the_call_chain)
184
183
  "$handler.add_worker(DoubleWorker.new);"
185
184
  );
186
185
 
187
- Object result = m.instance_eval("$handler.process_workers(5)");
186
+ Object result = m.module_eval("$handler.process_workers(5)");
188
187
 
189
188
  // Hit's EchoWorker, so 5 + 2, then passes that to DoubleWorker, so 7 * 2 = 14
190
189
  ASSERT_EQUAL(14, detail::From_Ruby<int>().convert(result.value()));
@@ -257,7 +256,7 @@ TESTCASE(mix_of_polymorphic_calls_and_inheritance_dont_cause_infinite_loops)
257
256
 
258
257
  Module m = define_module("Testing");
259
258
 
260
- Object result = m.instance_eval(
259
+ Object result = m.module_eval(
261
260
  "class MySelf < CallsSelf; def do_it_impl(num); num * 10; end; end;"
262
261
  "c = MySelf.new; c.do_it(10)"
263
262
  );
@@ -276,7 +275,7 @@ TESTCASE(director_class_super_classes_get_type_bound)
276
275
  .define_method("do_it_impl", &CallsSelfDirector::default_doItImpl)
277
276
  .define_method("do_it", &CallsSelf::doIt);
278
277
 
279
- Object result = m.instance_eval(R"(cs = Testing::get_calls_self
278
+ Object result = m.module_eval(R"(cs = Testing::get_calls_self
280
279
  cs.do_it(3))");
281
280
  ASSERT_EQUAL(36, detail::From_Ruby<int>().convert(result.value()));
282
281
  }
@@ -292,7 +291,7 @@ TESTCASE(director_allows_abstract_types_used_as_parameters_pointers)
292
291
  .define_method("do_it_impl", &CallsSelfDirector::default_doItImpl)
293
292
  .define_method("do_it", &CallsSelf::doIt);
294
293
 
295
- Object result = m.instance_eval(
294
+ Object result = m.module_eval(
296
295
  "class MySelf < CallsSelf; def do_it_impl(num); num * 10; end; end;"
297
296
  "c = MySelf.new;"
298
297
  "Testing::do_it_on_pointer(c, 5)"
@@ -312,7 +311,7 @@ TESTCASE(director_allows_abstract_types_used_as_parameters_reference)
312
311
  .define_method("do_it_impl", &CallsSelfDirector::default_doItImpl)
313
312
  .define_method("do_it", &CallsSelf::doIt);
314
313
 
315
- Object result = m.instance_eval(
314
+ Object result = m.module_eval(
316
315
  "class MySelf < CallsSelf; def do_it_impl(num); num * 10; end; end;"
317
316
  "c = MySelf.new;"
318
317
  "Testing::do_it_on_ref(c, 3)"