rice 4.0.4 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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)"