rice 4.3.3 → 4.6.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 (237) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -26
  3. data/CMakeLists.txt +31 -0
  4. data/CMakePresets.json +75 -0
  5. data/COPYING +3 -2
  6. data/FindRuby.cmake +437 -0
  7. data/README.md +7 -2
  8. data/Rakefile +12 -5
  9. data/include/rice/rice.hpp +9522 -4426
  10. data/include/rice/stl.hpp +2831 -1198
  11. data/lib/make_rice_headers.rb +79 -0
  12. data/lib/mkmf-rice.rb +40 -94
  13. data/lib/rice/version.rb +3 -0
  14. data/lib/rice.rb +1 -0
  15. data/lib/rubygems/builder.rb +11 -0
  16. data/lib/rubygems/cmake_builder.rb +113 -0
  17. data/lib/rubygems_plugin.rb +9 -0
  18. data/rice/Address_Registration_Guard.hpp +72 -3
  19. data/rice/Arg.hpp +26 -6
  20. data/rice/Arg.ipp +35 -2
  21. data/rice/Buffer.hpp +123 -0
  22. data/rice/Buffer.ipp +599 -0
  23. data/rice/Callback.hpp +21 -0
  24. data/rice/Callback.ipp +13 -0
  25. data/rice/Constructor.hpp +4 -27
  26. data/rice/Constructor.ipp +79 -0
  27. data/rice/Data_Object.hpp +73 -3
  28. data/rice/Data_Object.ipp +388 -96
  29. data/rice/Data_Type.hpp +214 -3
  30. data/rice/Data_Type.ipp +144 -67
  31. data/rice/Director.hpp +0 -2
  32. data/rice/Enum.hpp +4 -7
  33. data/rice/Enum.ipp +102 -55
  34. data/rice/Exception.hpp +62 -2
  35. data/rice/Exception.ipp +7 -12
  36. data/rice/Init.hpp +8 -0
  37. data/rice/Init.ipp +8 -0
  38. data/rice/JumpException.hpp +44 -0
  39. data/rice/JumpException.ipp +48 -0
  40. data/rice/MemoryView.hpp +11 -0
  41. data/rice/MemoryView.ipp +3 -0
  42. data/rice/Return.hpp +7 -27
  43. data/rice/Return.ipp +13 -13
  44. data/rice/cpp_api/Array.hpp +209 -0
  45. data/rice/cpp_api/Array.ipp +304 -0
  46. data/rice/cpp_api/Builtin_Object.hpp +31 -0
  47. data/rice/cpp_api/Builtin_Object.ipp +37 -0
  48. data/rice/cpp_api/Class.hpp +70 -0
  49. data/rice/cpp_api/Class.ipp +97 -0
  50. data/rice/cpp_api/Encoding.hpp +32 -0
  51. data/rice/cpp_api/Encoding.ipp +59 -0
  52. data/rice/cpp_api/Hash.hpp +194 -0
  53. data/rice/cpp_api/Hash.ipp +257 -0
  54. data/rice/{Identifier.hpp → cpp_api/Identifier.hpp} +2 -6
  55. data/rice/{Identifier.ipp → cpp_api/Identifier.ipp} +4 -2
  56. data/rice/cpp_api/Module.hpp +72 -0
  57. data/rice/cpp_api/Module.ipp +101 -0
  58. data/rice/cpp_api/Object.hpp +272 -0
  59. data/rice/cpp_api/Object.ipp +235 -0
  60. data/rice/cpp_api/String.hpp +74 -0
  61. data/rice/cpp_api/String.ipp +120 -0
  62. data/rice/cpp_api/Struct.hpp +113 -0
  63. data/rice/cpp_api/Struct.ipp +92 -0
  64. data/rice/cpp_api/Symbol.hpp +46 -0
  65. data/rice/cpp_api/Symbol.ipp +93 -0
  66. data/rice/cpp_api/shared_methods.hpp +134 -0
  67. data/rice/detail/DefaultHandler.hpp +12 -0
  68. data/rice/detail/DefaultHandler.ipp +8 -0
  69. data/rice/detail/HandlerRegistry.hpp +5 -35
  70. data/rice/detail/HandlerRegistry.ipp +7 -11
  71. data/rice/detail/InstanceRegistry.hpp +1 -4
  72. data/rice/detail/MethodInfo.hpp +12 -10
  73. data/rice/detail/MethodInfo.ipp +26 -21
  74. data/rice/detail/Native.hpp +33 -0
  75. data/rice/detail/Native.ipp +157 -0
  76. data/rice/detail/NativeAttributeGet.hpp +52 -0
  77. data/rice/detail/NativeAttributeGet.ipp +57 -0
  78. data/rice/detail/NativeAttributeSet.hpp +44 -0
  79. data/rice/detail/NativeAttributeSet.ipp +88 -0
  80. data/rice/detail/NativeCallbackFFI.hpp +55 -0
  81. data/rice/detail/NativeCallbackFFI.ipp +151 -0
  82. data/rice/detail/NativeCallbackSimple.hpp +30 -0
  83. data/rice/detail/NativeCallbackSimple.ipp +29 -0
  84. data/rice/detail/NativeFunction.hpp +33 -23
  85. data/rice/detail/NativeFunction.ipp +309 -70
  86. data/rice/detail/NativeIterator.hpp +9 -11
  87. data/rice/detail/NativeIterator.ipp +33 -31
  88. data/rice/detail/NativeRegistry.hpp +24 -15
  89. data/rice/detail/NativeRegistry.ipp +23 -48
  90. data/rice/detail/Proc.hpp +4 -0
  91. data/rice/detail/Proc.ipp +85 -0
  92. data/rice/detail/Registries.hpp +0 -7
  93. data/rice/detail/Registries.ipp +0 -18
  94. data/rice/detail/RubyFunction.hpp +0 -3
  95. data/rice/detail/RubyFunction.ipp +4 -8
  96. data/rice/detail/RubyType.hpp +16 -0
  97. data/rice/detail/RubyType.ipp +232 -0
  98. data/rice/detail/Type.hpp +7 -6
  99. data/rice/detail/Type.ipp +192 -45
  100. data/rice/detail/TypeRegistry.hpp +15 -7
  101. data/rice/detail/TypeRegistry.ipp +105 -12
  102. data/rice/detail/Wrapper.hpp +68 -32
  103. data/rice/detail/Wrapper.ipp +121 -109
  104. data/rice/detail/cpp_protect.hpp +5 -6
  105. data/rice/detail/default_allocation_func.ipp +0 -2
  106. data/rice/detail/from_ruby.hpp +38 -3
  107. data/rice/detail/from_ruby.ipp +1321 -492
  108. data/rice/detail/ruby.hpp +18 -0
  109. data/rice/detail/to_ruby.hpp +41 -3
  110. data/rice/detail/to_ruby.ipp +1424 -194
  111. data/rice/global_function.hpp +0 -4
  112. data/rice/global_function.ipp +0 -1
  113. data/rice/libc/file.hpp +11 -0
  114. data/rice/libc/file.ipp +32 -0
  115. data/rice/rice.hpp +116 -26
  116. data/rice/ruby_mark.hpp +4 -3
  117. data/rice/stl/complex.hpp +6 -0
  118. data/rice/stl/complex.ipp +93 -0
  119. data/rice/stl/exception.hpp +11 -0
  120. data/rice/stl/exception.ipp +29 -0
  121. data/rice/stl/exception_ptr.hpp +6 -0
  122. data/rice/stl/exception_ptr.ipp +27 -0
  123. data/rice/stl/map.hpp +12 -0
  124. data/rice/stl/map.ipp +469 -0
  125. data/rice/stl/monostate.hpp +6 -0
  126. data/rice/stl/monostate.ipp +80 -0
  127. data/rice/stl/multimap.hpp +14 -0
  128. data/rice/stl/multimap.ipp +448 -0
  129. data/rice/stl/optional.hpp +6 -0
  130. data/rice/stl/optional.ipp +118 -0
  131. data/rice/stl/pair.hpp +13 -0
  132. data/rice/stl/pair.ipp +155 -0
  133. data/rice/stl/reference_wrapper.hpp +6 -0
  134. data/rice/stl/reference_wrapper.ipp +41 -0
  135. data/rice/stl/set.hpp +12 -0
  136. data/rice/stl/set.ipp +495 -0
  137. data/rice/stl/shared_ptr.hpp +28 -0
  138. data/rice/stl/shared_ptr.ipp +224 -0
  139. data/rice/stl/string.hpp +6 -0
  140. data/rice/stl/string.ipp +158 -0
  141. data/rice/stl/string_view.hpp +6 -0
  142. data/rice/stl/string_view.ipp +65 -0
  143. data/rice/stl/tuple.hpp +6 -0
  144. data/rice/stl/tuple.ipp +128 -0
  145. data/rice/stl/type_index.hpp +6 -0
  146. data/rice/stl/type_index.ipp +30 -0
  147. data/rice/stl/type_info.hpp +6 -0
  148. data/rice/stl/type_info.ipp +29 -0
  149. data/rice/stl/unique_ptr.hpp +22 -0
  150. data/rice/stl/unique_ptr.ipp +139 -0
  151. data/rice/stl/unordered_map.hpp +12 -0
  152. data/rice/stl/unordered_map.ipp +469 -0
  153. data/rice/stl/variant.hpp +6 -0
  154. data/rice/stl/variant.ipp +242 -0
  155. data/rice/stl/vector.hpp +12 -0
  156. data/rice/stl/vector.ipp +590 -0
  157. data/rice/stl.hpp +11 -3
  158. data/rice/traits/attribute_traits.hpp +26 -0
  159. data/rice/traits/function_traits.hpp +95 -0
  160. data/rice/traits/method_traits.hpp +47 -0
  161. data/rice/traits/rice_traits.hpp +160 -0
  162. data/rice.gemspec +85 -0
  163. data/test/embed_ruby.cpp +7 -1
  164. data/test/extconf.rb +2 -0
  165. data/test/test_Address_Registration_Guard.cpp +5 -0
  166. data/test/test_Array.cpp +18 -4
  167. data/test/test_Attribute.cpp +136 -21
  168. data/test/test_Buffer.cpp +285 -0
  169. data/test/test_Builtin_Object.cpp +5 -0
  170. data/test/test_Callback.cpp +230 -0
  171. data/test/test_Class.cpp +5 -31
  172. data/test/test_Constructor.cpp +69 -6
  173. data/test/test_Data_Object.cpp +97 -38
  174. data/test/test_Data_Type.cpp +470 -65
  175. data/test/test_Director.cpp +17 -8
  176. data/test/test_Enum.cpp +155 -40
  177. data/test/test_Exception.cpp +235 -0
  178. data/test/test_File.cpp +70 -0
  179. data/test/test_From_Ruby.cpp +609 -0
  180. data/test/test_Hash.cpp +5 -0
  181. data/test/test_Identifier.cpp +5 -0
  182. data/test/test_Inheritance.cpp +6 -1
  183. data/test/test_Iterator.cpp +6 -1
  184. data/test/test_Jump_Exception.cpp +23 -0
  185. data/test/test_Keep_Alive.cpp +13 -19
  186. data/test/test_Keep_Alive_No_Wrapper.cpp +5 -1
  187. data/test/test_Memory_Management.cpp +5 -0
  188. data/test/test_Module.cpp +128 -67
  189. data/test/test_Native_Registry.cpp +2 -34
  190. data/test/test_Object.cpp +5 -0
  191. data/test/test_Overloads.cpp +806 -0
  192. data/test/test_Ownership.cpp +160 -54
  193. data/test/test_Proc.cpp +44 -0
  194. data/test/test_Self.cpp +9 -4
  195. data/test/test_Stl_Exception.cpp +109 -0
  196. data/test/test_Stl_Map.cpp +54 -42
  197. data/test/test_Stl_Multimap.cpp +693 -0
  198. data/test/test_Stl_Optional.cpp +5 -0
  199. data/test/test_Stl_Pair.cpp +14 -9
  200. data/test/test_Stl_Reference_Wrapper.cpp +9 -2
  201. data/test/test_Stl_Set.cpp +790 -0
  202. data/test/test_Stl_SharedPtr.cpp +458 -0
  203. data/test/test_Stl_String.cpp +5 -0
  204. data/test/test_Stl_String_View.cpp +5 -0
  205. data/test/test_Stl_Tuple.cpp +116 -0
  206. data/test/test_Stl_Type.cpp +147 -0
  207. data/test/test_Stl_UniquePtr.cpp +202 -0
  208. data/test/test_Stl_Unordered_Map.cpp +43 -38
  209. data/test/test_Stl_Variant.cpp +217 -84
  210. data/test/test_Stl_Vector.cpp +306 -58
  211. data/test/test_String.cpp +5 -0
  212. data/test/test_Struct.cpp +5 -0
  213. data/test/test_Symbol.cpp +5 -0
  214. data/test/test_Template.cpp +192 -0
  215. data/test/test_To_Ruby.cpp +524 -0
  216. data/test/test_Tracking.cpp +1 -0
  217. data/test/test_Type.cpp +171 -0
  218. data/test/test_global_functions.cpp +67 -7
  219. data/test/unittest.cpp +8 -0
  220. metadata +127 -26
  221. data/lib/version.rb +0 -3
  222. data/rice/Address_Registration_Guard_defn.hpp +0 -79
  223. data/rice/Data_Object_defn.hpp +0 -84
  224. data/rice/Data_Type_defn.hpp +0 -190
  225. data/rice/Exception_defn.hpp +0 -68
  226. data/rice/HandlerRegistration.hpp +0 -15
  227. data/rice/detail/ExceptionHandler.hpp +0 -8
  228. data/rice/detail/ExceptionHandler.ipp +0 -28
  229. data/rice/detail/ExceptionHandler_defn.hpp +0 -77
  230. data/rice/detail/Jump_Tag.hpp +0 -21
  231. data/rice/detail/NativeAttribute.hpp +0 -64
  232. data/rice/detail/NativeAttribute.ipp +0 -112
  233. data/rice/detail/from_ruby_defn.hpp +0 -38
  234. data/rice/detail/to_ruby_defn.hpp +0 -48
  235. data/test/test_Jump_Tag.cpp +0 -17
  236. data/test/test_Stl_SmartPointer.cpp +0 -283
  237. data/test/test_To_From_Ruby.cpp +0 -399
data/test/test_Enum.cpp CHANGED
@@ -9,19 +9,21 @@ using namespace Rice;
9
9
 
10
10
  TESTSUITE(Enum);
11
11
 
12
+ SETUP(Enum)
13
+ {
14
+ embed_ruby();
15
+ }
16
+
17
+ TEARDOWN(Enum)
18
+ {
19
+ Rice::detail::Registries::instance.types.clearUnverifiedTypes();
20
+ rb_gc_start();
21
+ }
22
+
12
23
  namespace
13
24
  {
14
25
  enum Color { RED, BLACK, GREEN };
15
26
 
16
- Enum<Color> define_color_enum()
17
- {
18
- static Enum<Color> colors = define_enum<Color>("Color")
19
- .define_value("RED", RED)
20
- .define_value("BLACK", BLACK)
21
- .define_value("GREEN", GREEN);
22
- return colors;
23
- }
24
-
25
27
  enum class Season { Spring, Summer, Fall, Winter };
26
28
 
27
29
  // This is needed to make unittest compile (it uses ostream to report errors)
@@ -30,22 +32,26 @@ namespace
30
32
  os << static_cast<std::underlying_type_t<Season>>(season);
31
33
  return os;
32
34
  }
35
+ }
33
36
 
34
- Enum<Season> define_season_enum()
35
- {
36
- static Enum<Season> seasons = define_enum<Season>("Season")
37
- .define_value("Spring", Season::Spring)
38
- .define_value("Summer", Season::Summer)
39
- .define_value("Fall", Season::Fall)
40
- .define_value("Winter", Season::Winter);
41
-
42
- return seasons;
43
- }
37
+ Enum<Color> define_color_enum()
38
+ {
39
+ static Enum<Color> colors = define_enum<Color>("Color")
40
+ .define_value("RED", RED)
41
+ .define_value("BLACK", BLACK)
42
+ .define_value("GREEN", GREEN);
43
+ return colors;
44
44
  }
45
45
 
46
- SETUP(Enum)
46
+ Enum<Season> define_season_enum()
47
47
  {
48
- embed_ruby();
48
+ static Enum<Season> seasons = define_enum<Season>("Season")
49
+ .define_value("Spring", Season::Spring)
50
+ .define_value("Summer", Season::Summer)
51
+ .define_value("Fall", Season::Fall)
52
+ .define_value("Winter", Season::Winter);
53
+
54
+ return seasons;
49
55
  }
50
56
 
51
57
  TESTCASE(copy_construct)
@@ -147,6 +153,48 @@ TESTCASE(each_seasons)
147
153
  ASSERT_EQUAL(Season::Winter, *enum_3);
148
154
  }
149
155
 
156
+ TESTCASE(bitset_operators)
157
+ {
158
+ Module m = define_module("TestingBitsetOperators");
159
+
160
+ Enum<Season> rb_cSeason = define_season_enum();
161
+
162
+ std::string code = R"(Season::Summer & Season::Winter)";
163
+ Object value = m.module_eval(code);
164
+ ASSERT_EQUAL(1, detail::From_Ruby<int>().convert(value));
165
+
166
+ code = R"(Season::Spring | Season::Summer)";
167
+ value = m.module_eval(code);
168
+ ASSERT_EQUAL(1, detail::From_Ruby<int>().convert(value));
169
+
170
+ code = R"(Season::Spring | Season::Summer | Season::Fall)";
171
+ value = m.module_eval(code);
172
+ ASSERT_EQUAL(3, detail::From_Ruby<int>().convert(value));
173
+
174
+ code = R"(Season::Summer ^ Season::Winter)";
175
+ value = m.module_eval(code);
176
+ ASSERT_EQUAL(2, detail::From_Ruby<int>().convert(value));
177
+
178
+ code = R"(~Season::Winter)";
179
+ value = m.module_eval(code);
180
+ ASSERT_EQUAL(-4, detail::From_Ruby<int>().convert(value));
181
+ }
182
+
183
+ TESTCASE(shift_operators)
184
+ {
185
+ Module m = define_module("TestingShiftOperators");
186
+
187
+ Enum<Season> rb_cSeason = define_season_enum();
188
+
189
+ std::string code = R"(Season::Winter << 1)";
190
+ Object value = m.module_eval(code);
191
+ ASSERT_EQUAL(6, detail::From_Ruby<int>().convert(value));
192
+
193
+ code = R"(Season::Winter >> 1)";
194
+ value = m.module_eval(code);
195
+ ASSERT_EQUAL(1, detail::From_Ruby<int>().convert(value));
196
+ }
197
+
150
198
  TESTCASE(to_s)
151
199
  {
152
200
  Module m = define_module("Testing");
@@ -157,14 +205,14 @@ TESTCASE(to_s)
157
205
  ASSERT_EQUAL(String("GREEN"), String(m.module_eval("Color::GREEN.to_s")));
158
206
  }
159
207
 
160
- TESTCASE(to_i)
208
+ TESTCASE(to_int)
161
209
  {
162
210
  Module m = define_module("Testing");
163
211
 
164
212
  Enum<Color> colorEnum = define_color_enum();
165
- ASSERT_EQUAL(detail::to_ruby(int(RED)), m.module_eval("Color::RED.to_i").value());
166
- ASSERT_EQUAL(detail::to_ruby(int(BLACK)), m.module_eval("Color::BLACK.to_i").value());
167
- ASSERT_EQUAL(detail::to_ruby(int(GREEN)), m.module_eval("Color::GREEN.to_i").value());
213
+ ASSERT_EQUAL(detail::to_ruby(int(RED)), m.module_eval("Color::RED.to_int").value());
214
+ ASSERT_EQUAL(detail::to_ruby(int(BLACK)), m.module_eval("Color::BLACK.to_int").value());
215
+ ASSERT_EQUAL(detail::to_ruby(int(GREEN)), m.module_eval("Color::GREEN.to_int").value());
168
216
  }
169
217
 
170
218
  TESTCASE(inspect)
@@ -275,7 +323,7 @@ namespace
275
323
  TESTCASE(nested_enums)
276
324
  {
277
325
  Data_Type<Inner> inner = define_class<Inner>("Inner");
278
- define_enum<Inner::Props>("Props", inner)
326
+ define_enum_under<Inner::Props>("Props", inner)
279
327
  .define_value("VALUE1", Inner::VALUE1)
280
328
  .define_value("VALUE2", Inner::VALUE2)
281
329
  .define_value("VALUE3", Inner::VALUE3);
@@ -283,9 +331,9 @@ TESTCASE(nested_enums)
283
331
 
284
332
  Module m = define_module("Testing");
285
333
 
286
- ASSERT_EQUAL(detail::to_ruby(int(0)), m.module_eval("Inner::Props::VALUE1.to_i").value());
287
- ASSERT_EQUAL(detail::to_ruby(int(1)), m.module_eval("Inner::Props::VALUE2.to_i").value());
288
- ASSERT_EQUAL(detail::to_ruby(int(2)), m.module_eval("Inner::Props::VALUE3.to_i").value());
334
+ ASSERT_EQUAL(detail::to_ruby(int(0)), m.module_eval("Inner::Props::VALUE1.to_int").value());
335
+ ASSERT_EQUAL(detail::to_ruby(int(1)), m.module_eval("Inner::Props::VALUE2.to_int").value());
336
+ ASSERT_EQUAL(detail::to_ruby(int(2)), m.module_eval("Inner::Props::VALUE3.to_int").value());
289
337
  }
290
338
 
291
339
  namespace
@@ -295,9 +343,14 @@ namespace
295
343
  return RED;
296
344
  }
297
345
 
298
- bool isMyFavoriteColor(Color aColor)
346
+ bool isMyFavoriteColor(Color color)
299
347
  {
300
- return aColor == RED;
348
+ return color == RED;
349
+ }
350
+
351
+ bool myFavoriteColorAsInt(int color)
352
+ {
353
+ return color == RED;
301
354
  }
302
355
  }
303
356
 
@@ -305,9 +358,8 @@ TESTCASE(using_enums)
305
358
  {
306
359
  Enum<Color> colorEnum = define_color_enum();
307
360
  colorEnum.define_singleton_function("my_favorite_color", &myFavoriteColor)
308
- .define_singleton_function("is_my_favorite_color", &isMyFavoriteColor)
309
- .define_singleton_function("is_my_favorite_color", &isMyFavoriteColor)
310
- .define_method("is_my_favorite_color", &isMyFavoriteColor);
361
+ .define_singleton_function("is_my_favorite_color", &isMyFavoriteColor)
362
+ .define_method("is_my_favorite_color", &isMyFavoriteColor);
311
363
 
312
364
  Module m = define_module("Testing");
313
365
 
@@ -327,6 +379,46 @@ TESTCASE(using_enums)
327
379
  ASSERT_EQUAL(Qfalse, result.value());
328
380
  }
329
381
 
382
+ TESTCASE(enum_to_int)
383
+ {
384
+ Enum<Color> colorEnum = define_color_enum();
385
+
386
+ Module m = define_module("Testing");
387
+ m.define_module_function("my_favorite_color_as_int", &myFavoriteColorAsInt);
388
+
389
+ std::string code = R"(my_favorite_color_as_int(Color::RED))";
390
+ Object result = m.module_eval(code);
391
+ ASSERT_EQUAL(Qtrue, result.value());
392
+
393
+ code = R"(my_favorite_color_as_int(Color::GREEN))";
394
+ result = m.module_eval(code);
395
+ ASSERT_EQUAL(Qfalse, result.value());
396
+ }
397
+
398
+ namespace
399
+ {
400
+ bool isMyFavoriteSeasonAsInt(int season)
401
+ {
402
+ return ((Season)season == Season::Summer);
403
+ }
404
+ }
405
+
406
+ TESTCASE(enum_class_to_int)
407
+ {
408
+ define_season_enum();
409
+
410
+ Module m = define_module("Testing");
411
+ m.define_module_function("is_my_favorite_season_as_int", &isMyFavoriteSeasonAsInt);
412
+
413
+ std::string code = R"(is_my_favorite_season_as_int(Season::Spring))";
414
+ Object result = m.module_eval(code);
415
+ ASSERT_EQUAL(Qfalse, result.value());
416
+
417
+ code = R"(is_my_favorite_season_as_int(Season::Summer))";
418
+ result = m.module_eval(code);
419
+ ASSERT_EQUAL(Qtrue, result.value());
420
+ }
421
+
330
422
  namespace
331
423
  {
332
424
  Color defaultColor(Color aColor = BLACK)
@@ -360,21 +452,44 @@ namespace
360
452
 
361
453
  TESTCASE(not_defined)
362
454
  {
455
+ Module m = define_module("TestingEnumNotDefined");
456
+
363
457
  #ifdef _MSC_VER
364
- const char* message = "Type is not defined with Rice: enum `anonymous namespace'::Undefined";
458
+ const char* message = "The following types are not registered with Rice:\n enum `anonymous namespace'::Undefined\n";
365
459
  #else
366
- const char* message = "Type is not defined with Rice: (anonymous namespace)::Undefined";
460
+ const char* message = "The following types are not registered with Rice:\n (anonymous namespace)::Undefined\n";
367
461
  #endif
368
462
 
463
+ m.define_module_function("undefined_arg", &undefinedArg);
464
+
369
465
  ASSERT_EXCEPTION_CHECK(
370
466
  std::invalid_argument,
371
- define_global_function("undefined_arg", &undefinedArg),
467
+ Rice::detail::Registries::instance.types.validateTypes(),
468
+ ASSERT_EQUAL(message, ex.what())
469
+ );
470
+
471
+ #ifdef _MSC_VER
472
+ message = "Type is not registered with Rice: enum `anonymous namespace'::Undefined";
473
+ #else
474
+ message = "Type is not registered with Rice: (anonymous namespace)::Undefined";
475
+ #endif
476
+
477
+ m.define_module_function("undefined_return", &undefinedReturn);
478
+ ASSERT_EXCEPTION_CHECK(
479
+ Rice::Exception,
480
+ m.call("undefined_return"),
372
481
  ASSERT_EQUAL(message, ex.what())
373
482
  );
374
483
 
484
+ #ifdef _MSC_VER
485
+ message = "Type is not defined with Rice: enum `anonymous namespace'::Undefined";
486
+ #else
487
+ message = "Type is not defined with Rice: (anonymous namespace)::Undefined";
488
+ #endif
489
+
375
490
  ASSERT_EXCEPTION_CHECK(
376
- std::invalid_argument,
377
- define_global_function("undefined_return", &undefinedReturn),
491
+ Rice::Exception,
492
+ m.call("undefined_arg", 1),
378
493
  ASSERT_EQUAL(message, ex.what())
379
494
  );
380
- }
495
+ }
@@ -11,6 +11,11 @@ SETUP(Exception)
11
11
  embed_ruby();
12
12
  }
13
13
 
14
+ TEARDOWN(Exception)
15
+ {
16
+ rb_gc_start();
17
+ }
18
+
14
19
  TESTCASE(construct_from_exception_object)
15
20
  {
16
21
  VALUE v = detail::protect(rb_exc_new2, rb_eRuntimeError, "foo");
@@ -45,3 +50,233 @@ TESTCASE(what)
45
50
  ASSERT_EQUAL(foo, ex.what());
46
51
  }
47
52
 
53
+ namespace
54
+ {
55
+ enum class ErrorCode
56
+ {
57
+ MEMORY,
58
+ DISK,
59
+ CPU
60
+ };
61
+
62
+ class CustomException
63
+ {
64
+ public:
65
+ CustomException(ErrorCode code) : code(code)
66
+ {
67
+ }
68
+
69
+ const char* what() const noexcept
70
+ {
71
+ return "My custom exception occurred!";
72
+ }
73
+
74
+ ErrorCode code;
75
+ };
76
+
77
+ void raiseCustomException(ErrorCode code)
78
+ {
79
+ throw CustomException(code);
80
+ }
81
+
82
+ class MyExceptionHandler
83
+ {
84
+ public:
85
+ void operator()()
86
+ {
87
+ try
88
+ {
89
+ throw;
90
+ }
91
+ catch (const CustomException& exception)
92
+ {
93
+ Data_Object<CustomException> wrapper(exception, true);
94
+ rb_exc_raise(wrapper);
95
+ }
96
+ }
97
+ };
98
+ }
99
+
100
+ Enum<ErrorCode> define_error_code_enum()
101
+ {
102
+ static Enum<ErrorCode> errorCodes = define_enum<ErrorCode>("ErrorCode")
103
+ .define_value("MEMORY", ErrorCode::MEMORY)
104
+ .define_value("DISK", ErrorCode::DISK)
105
+ .define_value("CPU", ErrorCode::CPU);
106
+
107
+ return errorCodes;
108
+ }
109
+
110
+ TESTCASE(default_handler)
111
+ {
112
+ define_error_code_enum();
113
+ Module m = define_module("Testing");
114
+ m.define_singleton_function("raise_custom_exception", &raiseCustomException);
115
+ Class MyExceptionClass = define_class_under<CustomException>(rb_cObject, "CustomException", rb_eStandardError).
116
+ define_method("message", &CustomException::what);
117
+
118
+ ASSERT_EXCEPTION_CHECK(
119
+ Exception,
120
+ m.call("raise_custom_exception", ErrorCode::MEMORY),
121
+ ASSERT_EQUAL("Unknown C++ exception thrown", ex.what())
122
+ );
123
+ }
124
+
125
+ TESTCASE(custom_handler_functor)
126
+ {
127
+ define_error_code_enum();
128
+ Class MyExceptionClass = define_class_under<CustomException>(rb_cObject, "CustomException", rb_eStandardError).
129
+ define_method("message", &CustomException::what);
130
+
131
+ detail::Registries::instance.handlers.set(MyExceptionHandler());
132
+
133
+ Module m = define_module("Testing");
134
+ m.define_singleton_function("raise_custom_exception", &raiseCustomException);
135
+
136
+ ASSERT_EXCEPTION_CHECK(
137
+ Exception,
138
+ m.call("raise_custom_exception", ErrorCode::DISK),
139
+ ASSERT_EQUAL("My custom exception occurred!", ex.what())
140
+ );
141
+
142
+ std::string code = R"(begin
143
+ raise_custom_exception(ErrorCode::DISK)
144
+ rescue CustomException => exception
145
+ "Caught in Ruby"
146
+ end)";
147
+
148
+ String string = m.instance_eval(code);
149
+ ASSERT_EQUAL("Caught in Ruby", string.c_str());
150
+ }
151
+
152
+ TESTCASE(custom_handler_lambda)
153
+ {
154
+ define_error_code_enum();
155
+ Class rb_eCustomException = define_class("CustomException", rb_eStandardError).
156
+ define_method("message", &CustomException::what);
157
+
158
+ auto handler = []()
159
+ {
160
+ try
161
+ {
162
+ throw;
163
+ }
164
+ catch (const CustomException& exception)
165
+ {
166
+ Data_Object<CustomException> wrapper(exception);
167
+ rb_exc_raise(wrapper);
168
+ }
169
+ };
170
+
171
+ detail::Registries::instance.handlers.set(handler);
172
+
173
+ Module m = define_module("Testing");
174
+ m.define_singleton_function("raise_custom_exception", &raiseCustomException);
175
+
176
+ ASSERT_EXCEPTION_CHECK(
177
+ Exception,
178
+ m.call("raise_custom_exception", ErrorCode::CPU),
179
+ ASSERT_EQUAL("My custom exception occurred!", ex.what())
180
+ );
181
+
182
+ std::string code = R"(begin
183
+ raise_custom_exception(ErrorCode::CPU)
184
+ rescue CustomException => exception
185
+ $!
186
+ end)";
187
+
188
+ Object object = m.instance_eval(code);
189
+ ASSERT_EQUAL(rb_eCustomException.value(), object.class_of().value());
190
+ }
191
+
192
+ TESTCASE(subclasses)
193
+ {
194
+ define_error_code_enum();
195
+ Class rb_eCustomException = define_class("CustomException", rb_eStandardError).
196
+ define_method("message", &CustomException::what);
197
+ Class rb_eMemoryException = define_class_under(rb_cObject, "MemoryException", rb_eCustomException);
198
+ Class rb_eDiskException = define_class_under(rb_cObject, "DiskException", rb_eCustomException);
199
+ Class rb_eCpuException = define_class_under(rb_cObject, "CpuException", rb_eCustomException);
200
+
201
+ auto handler = [&]()
202
+ {
203
+ try
204
+ {
205
+ throw;
206
+ }
207
+ catch (const CustomException& exception)
208
+ {
209
+ Class exceptionKlass = rb_eCustomException;
210
+
211
+ switch (exception.code)
212
+ {
213
+ case ErrorCode::MEMORY:
214
+ exceptionKlass = rb_eMemoryException;
215
+ break;
216
+ case ErrorCode::DISK:
217
+ exceptionKlass = rb_eDiskException;
218
+ break;
219
+ case ErrorCode::CPU:
220
+ exceptionKlass = rb_eCpuException;
221
+ break;
222
+ }
223
+
224
+ // Take ownership of the exception object and map it to the right subclass
225
+ Data_Object<CustomException> wrapper(exception, true, exceptionKlass);
226
+ rb_exc_raise(wrapper);
227
+ }
228
+ };
229
+
230
+ detail::Registries::instance.handlers.set(handler);
231
+
232
+ Module m = define_module("Testing");
233
+ m.define_singleton_function("raise_custom_exception", &raiseCustomException);
234
+
235
+ std::string code = R"(begin
236
+ raise_custom_exception(ErrorCode::MEMORY)
237
+ rescue => e
238
+ e.class.name
239
+ end)";
240
+
241
+ String result = m.instance_eval(code);
242
+ ASSERT_EQUAL("MemoryException", result.c_str());
243
+
244
+ code = R"(begin
245
+ raise_custom_exception(ErrorCode::MEMORY)
246
+ rescue MemoryException => e
247
+ e.class.name
248
+ end)";
249
+
250
+ result = m.instance_eval(code);
251
+ ASSERT_EQUAL("MemoryException", result.c_str());
252
+
253
+ code = R"(begin
254
+ raise_custom_exception(ErrorCode::DISK)
255
+ rescue DiskException => e
256
+ e.class.name
257
+ end)";
258
+
259
+ result = m.instance_eval(code);
260
+ ASSERT_EQUAL("DiskException", result.c_str());
261
+
262
+ code = R"(begin
263
+ raise_custom_exception(ErrorCode::CPU)
264
+ rescue CpuException => e
265
+ e.class.name
266
+ end)";
267
+
268
+ result = m.instance_eval(code);
269
+ ASSERT_EQUAL("CpuException", result.c_str());
270
+
271
+ code = R"(begin
272
+ raise_custom_exception(ErrorCode::CPU)
273
+ rescue RuntimeError => e
274
+ e.class.name
275
+ end)";
276
+
277
+ ASSERT_EXCEPTION_CHECK(
278
+ Exception,
279
+ m.instance_eval(code),
280
+ ASSERT_EQUAL("My custom exception occurred!", ex.what())
281
+ );
282
+ }
@@ -0,0 +1,70 @@
1
+ #include <cstdio>
2
+ #include <filesystem>
3
+
4
+ #include "unittest.hpp"
5
+ #include "embed_ruby.hpp"
6
+ #include <rice/rice.hpp>
7
+ #include <rice/stl.hpp>
8
+
9
+ using namespace Rice;
10
+
11
+ TESTSUITE(FILE);
12
+
13
+ SETUP(FILE)
14
+ {
15
+ embed_ruby();
16
+ }
17
+
18
+ TEARDOWN(FILE)
19
+ {
20
+ rb_gc_start();
21
+ }
22
+
23
+ namespace
24
+ {
25
+ FILE* openFile()
26
+ {
27
+ std::filesystem::path path = __FILE__;
28
+ FILE* fptr = fopen(path.string().c_str(), "rb");
29
+ return fptr;
30
+ }
31
+
32
+ std::string readFile(FILE* fptr)
33
+ {
34
+ std::ostringstream result;
35
+
36
+ char buffer[255];
37
+ while (fgets(buffer, sizeof(buffer), fptr) != NULL)
38
+ {
39
+ result << buffer;
40
+ }
41
+ return result.str();
42
+ }
43
+
44
+ bool closeFile(FILE* fptr)
45
+ {
46
+ // Ruby override fclose and replaces it with rb_w32_fclose which causes a segementation fault. Oy!
47
+ #ifndef _MSC_VER
48
+ fclose(fptr);
49
+ #endif
50
+ return true;
51
+ }
52
+ }
53
+
54
+ TESTCASE(File)
55
+ {
56
+ Module m = define_module("TestingModule");
57
+ m.define_module_function("open_file", openFile).
58
+ define_module_function("read_file", readFile).
59
+ define_module_function("close_file", closeFile);
60
+
61
+ Data_Object<FILE> file = m.call("open_file");
62
+ ASSERT((file.value() != Qnil));
63
+ ASSERT((file.get() != nullptr));
64
+
65
+ String string = m.call("read_file", file);
66
+ ASSERT((string.length() > 1300));
67
+
68
+ Object result = m.call("close_file", file);
69
+ ASSERT_EQUAL(Qtrue, result.value());
70
+ }