rice 4.3.2 → 4.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -25
- data/README.md +7 -2
- data/Rakefile +7 -1
- data/include/rice/rice.hpp +7321 -4470
- data/include/rice/stl.hpp +769 -222
- data/lib/mkmf-rice.rb +37 -95
- data/rice/Address_Registration_Guard.hpp +72 -3
- data/rice/Arg.hpp +19 -5
- data/rice/Arg.ipp +24 -0
- data/rice/Callback.hpp +21 -0
- data/rice/Callback.ipp +13 -0
- data/rice/Constructor.hpp +4 -27
- data/rice/Constructor.ipp +79 -0
- data/rice/Data_Object.hpp +74 -3
- data/rice/Data_Object.ipp +324 -32
- data/rice/Data_Type.hpp +215 -3
- data/rice/Data_Type.ipp +125 -64
- data/rice/Director.hpp +0 -2
- data/rice/Enum.hpp +4 -6
- data/rice/Enum.ipp +101 -57
- data/rice/Exception.hpp +62 -2
- data/rice/Exception.ipp +7 -12
- data/rice/JumpException.hpp +44 -0
- data/rice/JumpException.ipp +48 -0
- data/rice/MemoryView.hpp +11 -0
- data/rice/MemoryView.ipp +43 -0
- data/rice/Return.hpp +6 -26
- data/rice/Return.ipp +10 -16
- data/rice/detail/DefaultHandler.hpp +12 -0
- data/rice/detail/DefaultHandler.ipp +8 -0
- data/rice/detail/HandlerRegistry.hpp +5 -35
- data/rice/detail/HandlerRegistry.ipp +7 -11
- data/rice/detail/InstanceRegistry.hpp +1 -4
- data/rice/detail/MethodInfo.hpp +15 -5
- data/rice/detail/MethodInfo.ipp +78 -6
- data/rice/detail/Native.hpp +32 -0
- data/rice/detail/Native.ipp +129 -0
- data/rice/detail/NativeAttributeGet.hpp +51 -0
- data/rice/detail/NativeAttributeGet.ipp +51 -0
- data/rice/detail/NativeAttributeSet.hpp +43 -0
- data/rice/detail/NativeAttributeSet.ipp +82 -0
- data/rice/detail/NativeCallbackFFI.hpp +55 -0
- data/rice/detail/NativeCallbackFFI.ipp +151 -0
- data/rice/detail/NativeCallbackSimple.hpp +30 -0
- data/rice/detail/NativeCallbackSimple.ipp +29 -0
- data/rice/detail/NativeFunction.hpp +20 -21
- data/rice/detail/NativeFunction.ipp +199 -64
- data/rice/detail/NativeIterator.hpp +8 -11
- data/rice/detail/NativeIterator.ipp +27 -31
- data/rice/detail/NativeRegistry.hpp +24 -17
- data/rice/detail/NativeRegistry.ipp +23 -56
- data/rice/detail/Proc.hpp +4 -0
- data/rice/detail/Proc.ipp +85 -0
- data/rice/detail/Registries.hpp +0 -7
- data/rice/detail/Registries.ipp +0 -18
- data/rice/detail/RubyFunction.hpp +0 -3
- data/rice/detail/RubyFunction.ipp +4 -8
- data/rice/detail/RubyType.hpp +19 -0
- data/rice/detail/RubyType.ipp +187 -0
- data/rice/detail/TupleIterator.hpp +14 -0
- data/rice/detail/Type.hpp +5 -6
- data/rice/detail/Type.ipp +150 -33
- data/rice/detail/TypeRegistry.hpp +15 -7
- data/rice/detail/TypeRegistry.ipp +105 -12
- data/rice/detail/Wrapper.hpp +6 -5
- data/rice/detail/Wrapper.ipp +45 -23
- data/rice/detail/cpp_protect.hpp +5 -6
- data/rice/detail/default_allocation_func.ipp +0 -2
- data/rice/detail/from_ruby.hpp +37 -3
- data/rice/detail/from_ruby.ipp +911 -454
- data/rice/detail/ruby.hpp +18 -0
- data/rice/detail/to_ruby.hpp +41 -3
- data/rice/detail/to_ruby.ipp +437 -113
- data/rice/global_function.hpp +0 -4
- data/rice/global_function.ipp +1 -2
- data/rice/rice.hpp +105 -22
- data/rice/ruby_mark.hpp +4 -3
- data/rice/stl.hpp +4 -0
- data/test/embed_ruby.cpp +4 -1
- data/test/extconf.rb +2 -0
- data/test/ruby/test_multiple_extensions_same_class.rb +14 -14
- data/test/test_Address_Registration_Guard.cpp +5 -0
- data/test/test_Array.cpp +12 -1
- data/test/test_Attribute.cpp +103 -21
- data/test/test_Builtin_Object.cpp +5 -0
- data/test/test_Callback.cpp +231 -0
- data/test/test_Class.cpp +5 -31
- data/test/test_Constructor.cpp +69 -6
- data/test/test_Data_Object.cpp +9 -4
- data/test/test_Data_Type.cpp +428 -64
- data/test/test_Director.cpp +10 -5
- data/test/test_Enum.cpp +152 -40
- data/test/test_Exception.cpp +235 -0
- data/test/test_File.cpp +70 -0
- data/test/test_From_Ruby.cpp +542 -0
- data/test/test_Hash.cpp +5 -0
- data/test/test_Identifier.cpp +5 -0
- data/test/test_Inheritance.cpp +6 -1
- data/test/test_Iterator.cpp +5 -0
- data/test/test_JumpException.cpp +22 -0
- data/test/test_Keep_Alive.cpp +6 -1
- data/test/test_Keep_Alive_No_Wrapper.cpp +5 -0
- data/test/test_Memory_Management.cpp +5 -0
- data/test/test_Module.cpp +118 -64
- data/test/test_Native_Registry.cpp +2 -33
- data/test/test_Object.cpp +5 -0
- data/test/test_Overloads.cpp +631 -0
- data/test/test_Ownership.cpp +67 -4
- data/test/test_Proc.cpp +45 -0
- data/test/test_Self.cpp +5 -0
- data/test/test_Stl_Exception.cpp +109 -0
- data/test/test_Stl_Map.cpp +22 -8
- data/test/test_Stl_Optional.cpp +5 -0
- data/test/test_Stl_Pair.cpp +7 -2
- data/test/test_Stl_Reference_Wrapper.cpp +5 -0
- data/test/test_Stl_SmartPointer.cpp +210 -5
- data/test/test_Stl_String.cpp +5 -0
- data/test/test_Stl_String_View.cpp +5 -0
- data/test/test_Stl_Type.cpp +147 -0
- data/test/test_Stl_Unordered_Map.cpp +18 -7
- data/test/test_Stl_Variant.cpp +5 -0
- data/test/test_Stl_Vector.cpp +130 -8
- data/test/test_String.cpp +5 -0
- data/test/test_Struct.cpp +5 -0
- data/test/test_Symbol.cpp +5 -0
- data/test/test_Template.cpp +192 -0
- data/test/test_To_Ruby.cpp +152 -0
- data/test/test_Tracking.cpp +1 -0
- data/test/test_Type.cpp +100 -0
- data/test/test_global_functions.cpp +53 -6
- data/test/unittest.cpp +8 -0
- metadata +37 -20
- data/lib/version.rb +0 -3
- data/rice/Address_Registration_Guard_defn.hpp +0 -79
- data/rice/Data_Object_defn.hpp +0 -84
- data/rice/Data_Type_defn.hpp +0 -190
- data/rice/Exception_defn.hpp +0 -68
- data/rice/HandlerRegistration.hpp +0 -15
- data/rice/Identifier.hpp +0 -50
- data/rice/Identifier.ipp +0 -29
- data/rice/detail/ExceptionHandler.hpp +0 -8
- data/rice/detail/ExceptionHandler.ipp +0 -28
- data/rice/detail/ExceptionHandler_defn.hpp +0 -77
- data/rice/detail/Jump_Tag.hpp +0 -21
- data/rice/detail/NativeAttribute.hpp +0 -64
- data/rice/detail/NativeAttribute.ipp +0 -112
- data/rice/detail/from_ruby_defn.hpp +0 -38
- data/rice/detail/to_ruby_defn.hpp +0 -48
- data/test/test_Jump_Tag.cpp +0 -17
- data/test/test_To_From_Ruby.cpp +0 -399
data/test/test_Enum.cpp
CHANGED
@@ -9,19 +9,22 @@ 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
|
+
|
23
|
+
|
12
24
|
namespace
|
13
25
|
{
|
14
26
|
enum Color { RED, BLACK, GREEN };
|
15
27
|
|
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
28
|
enum class Season { Spring, Summer, Fall, Winter };
|
26
29
|
|
27
30
|
// This is needed to make unittest compile (it uses ostream to report errors)
|
@@ -30,22 +33,26 @@ namespace
|
|
30
33
|
os << static_cast<std::underlying_type_t<Season>>(season);
|
31
34
|
return os;
|
32
35
|
}
|
36
|
+
}
|
33
37
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
return seasons;
|
43
|
-
}
|
38
|
+
Enum<Color> define_color_enum()
|
39
|
+
{
|
40
|
+
static Enum<Color> colors = define_enum<Color>("Color")
|
41
|
+
.define_value("RED", RED)
|
42
|
+
.define_value("BLACK", BLACK)
|
43
|
+
.define_value("GREEN", GREEN);
|
44
|
+
return colors;
|
44
45
|
}
|
45
46
|
|
46
|
-
|
47
|
+
Enum<Season> define_season_enum()
|
47
48
|
{
|
48
|
-
|
49
|
+
static Enum<Season> seasons = define_enum<Season>("Season")
|
50
|
+
.define_value("Spring", Season::Spring)
|
51
|
+
.define_value("Summer", Season::Summer)
|
52
|
+
.define_value("Fall", Season::Fall)
|
53
|
+
.define_value("Winter", Season::Winter);
|
54
|
+
|
55
|
+
return seasons;
|
49
56
|
}
|
50
57
|
|
51
58
|
TESTCASE(copy_construct)
|
@@ -147,6 +154,44 @@ TESTCASE(each_seasons)
|
|
147
154
|
ASSERT_EQUAL(Season::Winter, *enum_3);
|
148
155
|
}
|
149
156
|
|
157
|
+
TESTCASE(bitset_operators)
|
158
|
+
{
|
159
|
+
Module m = define_module("TestingBitsetOperators");
|
160
|
+
|
161
|
+
Enum<Season> rb_cSeason = define_season_enum();
|
162
|
+
|
163
|
+
std::string code = R"(Season::Summer & Season::Winter)";
|
164
|
+
Object value = m.module_eval(code);
|
165
|
+
ASSERT_EQUAL(1, detail::From_Ruby<int>().convert(value));
|
166
|
+
|
167
|
+
code = R"(Season::Summer | Season::Fall)";
|
168
|
+
value = m.module_eval(code);
|
169
|
+
ASSERT_EQUAL(3, detail::From_Ruby<int>().convert(value));
|
170
|
+
|
171
|
+
code = R"(Season::Summer ^ Season::Winter)";
|
172
|
+
value = m.module_eval(code);
|
173
|
+
ASSERT_EQUAL(2, detail::From_Ruby<int>().convert(value));
|
174
|
+
|
175
|
+
code = R"(~Season::Winter)";
|
176
|
+
value = m.module_eval(code);
|
177
|
+
ASSERT_EQUAL(-4, detail::From_Ruby<int>().convert(value));
|
178
|
+
}
|
179
|
+
|
180
|
+
TESTCASE(shift_operators)
|
181
|
+
{
|
182
|
+
Module m = define_module("TestingShiftOperators");
|
183
|
+
|
184
|
+
Enum<Season> rb_cSeason = define_season_enum();
|
185
|
+
|
186
|
+
std::string code = R"(Season::Winter << 1)";
|
187
|
+
Object value = m.module_eval(code);
|
188
|
+
ASSERT_EQUAL(6, detail::From_Ruby<int>().convert(value));
|
189
|
+
|
190
|
+
code = R"(Season::Winter >> 1)";
|
191
|
+
value = m.module_eval(code);
|
192
|
+
ASSERT_EQUAL(1, detail::From_Ruby<int>().convert(value));
|
193
|
+
}
|
194
|
+
|
150
195
|
TESTCASE(to_s)
|
151
196
|
{
|
152
197
|
Module m = define_module("Testing");
|
@@ -157,14 +202,14 @@ TESTCASE(to_s)
|
|
157
202
|
ASSERT_EQUAL(String("GREEN"), String(m.module_eval("Color::GREEN.to_s")));
|
158
203
|
}
|
159
204
|
|
160
|
-
TESTCASE(
|
205
|
+
TESTCASE(to_int)
|
161
206
|
{
|
162
207
|
Module m = define_module("Testing");
|
163
208
|
|
164
209
|
Enum<Color> colorEnum = define_color_enum();
|
165
|
-
ASSERT_EQUAL(detail::to_ruby(int(RED)), m.module_eval("Color::RED.
|
166
|
-
ASSERT_EQUAL(detail::to_ruby(int(BLACK)), m.module_eval("Color::BLACK.
|
167
|
-
ASSERT_EQUAL(detail::to_ruby(int(GREEN)), m.module_eval("Color::GREEN.
|
210
|
+
ASSERT_EQUAL(detail::to_ruby(int(RED)), m.module_eval("Color::RED.to_int").value());
|
211
|
+
ASSERT_EQUAL(detail::to_ruby(int(BLACK)), m.module_eval("Color::BLACK.to_int").value());
|
212
|
+
ASSERT_EQUAL(detail::to_ruby(int(GREEN)), m.module_eval("Color::GREEN.to_int").value());
|
168
213
|
}
|
169
214
|
|
170
215
|
TESTCASE(inspect)
|
@@ -275,7 +320,7 @@ namespace
|
|
275
320
|
TESTCASE(nested_enums)
|
276
321
|
{
|
277
322
|
Data_Type<Inner> inner = define_class<Inner>("Inner");
|
278
|
-
|
323
|
+
define_enum_under<Inner::Props>("Props", inner)
|
279
324
|
.define_value("VALUE1", Inner::VALUE1)
|
280
325
|
.define_value("VALUE2", Inner::VALUE2)
|
281
326
|
.define_value("VALUE3", Inner::VALUE3);
|
@@ -283,9 +328,9 @@ TESTCASE(nested_enums)
|
|
283
328
|
|
284
329
|
Module m = define_module("Testing");
|
285
330
|
|
286
|
-
ASSERT_EQUAL(detail::to_ruby(int(0)), m.module_eval("Inner::Props::VALUE1.
|
287
|
-
ASSERT_EQUAL(detail::to_ruby(int(1)), m.module_eval("Inner::Props::VALUE2.
|
288
|
-
ASSERT_EQUAL(detail::to_ruby(int(2)), m.module_eval("Inner::Props::VALUE3.
|
331
|
+
ASSERT_EQUAL(detail::to_ruby(int(0)), m.module_eval("Inner::Props::VALUE1.to_int").value());
|
332
|
+
ASSERT_EQUAL(detail::to_ruby(int(1)), m.module_eval("Inner::Props::VALUE2.to_int").value());
|
333
|
+
ASSERT_EQUAL(detail::to_ruby(int(2)), m.module_eval("Inner::Props::VALUE3.to_int").value());
|
289
334
|
}
|
290
335
|
|
291
336
|
namespace
|
@@ -295,9 +340,14 @@ namespace
|
|
295
340
|
return RED;
|
296
341
|
}
|
297
342
|
|
298
|
-
bool isMyFavoriteColor(Color
|
343
|
+
bool isMyFavoriteColor(Color color)
|
299
344
|
{
|
300
|
-
return
|
345
|
+
return color == RED;
|
346
|
+
}
|
347
|
+
|
348
|
+
bool myFavoriteColorAsInt(int color)
|
349
|
+
{
|
350
|
+
return color == RED;
|
301
351
|
}
|
302
352
|
}
|
303
353
|
|
@@ -305,9 +355,8 @@ TESTCASE(using_enums)
|
|
305
355
|
{
|
306
356
|
Enum<Color> colorEnum = define_color_enum();
|
307
357
|
colorEnum.define_singleton_function("my_favorite_color", &myFavoriteColor)
|
308
|
-
|
309
|
-
|
310
|
-
.define_method("is_my_favorite_color", &isMyFavoriteColor);
|
358
|
+
.define_singleton_function("is_my_favorite_color", &isMyFavoriteColor)
|
359
|
+
.define_method("is_my_favorite_color", &isMyFavoriteColor);
|
311
360
|
|
312
361
|
Module m = define_module("Testing");
|
313
362
|
|
@@ -327,6 +376,46 @@ TESTCASE(using_enums)
|
|
327
376
|
ASSERT_EQUAL(Qfalse, result.value());
|
328
377
|
}
|
329
378
|
|
379
|
+
TESTCASE(enum_to_int)
|
380
|
+
{
|
381
|
+
Enum<Color> colorEnum = define_color_enum();
|
382
|
+
|
383
|
+
Module m = define_module("Testing");
|
384
|
+
m.define_module_function("my_favorite_color_as_int", &myFavoriteColorAsInt);
|
385
|
+
|
386
|
+
std::string code = R"(my_favorite_color_as_int(Color::RED))";
|
387
|
+
Object result = m.module_eval(code);
|
388
|
+
ASSERT_EQUAL(Qtrue, result.value());
|
389
|
+
|
390
|
+
code = R"(my_favorite_color_as_int(Color::GREEN))";
|
391
|
+
result = m.module_eval(code);
|
392
|
+
ASSERT_EQUAL(Qfalse, result.value());
|
393
|
+
}
|
394
|
+
|
395
|
+
namespace
|
396
|
+
{
|
397
|
+
bool isMyFavoriteSeasonAsInt(int season)
|
398
|
+
{
|
399
|
+
return ((Season)season == Season::Summer);
|
400
|
+
}
|
401
|
+
}
|
402
|
+
|
403
|
+
TESTCASE(enum_class_to_int)
|
404
|
+
{
|
405
|
+
define_season_enum();
|
406
|
+
|
407
|
+
Module m = define_module("Testing");
|
408
|
+
m.define_module_function("is_my_favorite_season_as_int", &isMyFavoriteSeasonAsInt);
|
409
|
+
|
410
|
+
std::string code = R"(is_my_favorite_season_as_int(Season::Spring))";
|
411
|
+
Object result = m.module_eval(code);
|
412
|
+
ASSERT_EQUAL(Qfalse, result.value());
|
413
|
+
|
414
|
+
code = R"(is_my_favorite_season_as_int(Season::Summer))";
|
415
|
+
result = m.module_eval(code);
|
416
|
+
ASSERT_EQUAL(Qtrue, result.value());
|
417
|
+
}
|
418
|
+
|
330
419
|
namespace
|
331
420
|
{
|
332
421
|
Color defaultColor(Color aColor = BLACK)
|
@@ -360,21 +449,44 @@ namespace
|
|
360
449
|
|
361
450
|
TESTCASE(not_defined)
|
362
451
|
{
|
452
|
+
Module m = define_module("TestingEnumNotDefined");
|
453
|
+
|
363
454
|
#ifdef _MSC_VER
|
364
|
-
const char* message = "
|
455
|
+
const char* message = "The following types are not registered with Rice:\n enum `anonymous namespace'::Undefined\n";
|
365
456
|
#else
|
366
|
-
const char* message = "
|
457
|
+
const char* message = "The following types are not registered with Rice:\n (anonymous namespace)::Undefined\n";
|
367
458
|
#endif
|
368
459
|
|
460
|
+
m.define_module_function("undefined_arg", &undefinedArg);
|
461
|
+
|
369
462
|
ASSERT_EXCEPTION_CHECK(
|
370
463
|
std::invalid_argument,
|
371
|
-
|
464
|
+
Rice::detail::Registries::instance.types.validateTypes(),
|
465
|
+
ASSERT_EQUAL(message, ex.what())
|
466
|
+
);
|
467
|
+
|
468
|
+
#ifdef _MSC_VER
|
469
|
+
message = "Type is not registered with Rice: enum `anonymous namespace'::Undefined";
|
470
|
+
#else
|
471
|
+
message = "Type is not registered with Rice: (anonymous namespace)::Undefined";
|
472
|
+
#endif
|
473
|
+
|
474
|
+
m.define_module_function("undefined_return", &undefinedReturn);
|
475
|
+
ASSERT_EXCEPTION_CHECK(
|
476
|
+
Rice::Exception,
|
477
|
+
m.call("undefined_return"),
|
372
478
|
ASSERT_EQUAL(message, ex.what())
|
373
479
|
);
|
374
480
|
|
481
|
+
#ifdef _MSC_VER
|
482
|
+
message = "Type is not defined with Rice: enum `anonymous namespace'::Undefined";
|
483
|
+
#else
|
484
|
+
message = "Type is not defined with Rice: (anonymous namespace)::Undefined";
|
485
|
+
#endif
|
486
|
+
|
375
487
|
ASSERT_EXCEPTION_CHECK(
|
376
|
-
|
377
|
-
|
488
|
+
Rice::Exception,
|
489
|
+
m.call("undefined_arg", 1),
|
378
490
|
ASSERT_EQUAL(message, ex.what())
|
379
491
|
);
|
380
|
-
}
|
492
|
+
}
|
data/test/test_Exception.cpp
CHANGED
@@ -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
|
+
}
|
data/test/test_File.cpp
ADDED
@@ -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.u8string().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
|
+
}
|