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
@@ -0,0 +1,697 @@
1
+ #include <complex>
2
+ #include <memory>
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(UnorderedMap);
12
+
13
+ SETUP(UnorderedMap)
14
+ {
15
+ embed_ruby();
16
+ }
17
+
18
+ namespace
19
+ {
20
+
21
+ class MyClass
22
+ {
23
+ public:
24
+ std::unordered_map<std::string, std::string> stringUnorderedMap()
25
+ {
26
+ std::unordered_map<std::string, std::string> result{ {"One", "1"}, {"Two", "2"}, {"Three", "3"} };
27
+ return result;
28
+ }
29
+ };
30
+ }
31
+
32
+ Class makeUnorderedUnorderedMapClass()
33
+ {
34
+ Class c = define_class<MyClass>("MyClass").
35
+ define_constructor(Constructor<MyClass>()).
36
+ define_method("stringUnorderedMap", &MyClass::stringUnorderedMap);
37
+
38
+ return c;
39
+ }
40
+
41
+ TESTCASE(StringUnorderedMap)
42
+ {
43
+ Module m = define_module("Testing");
44
+
45
+ Class c = define_unordered_map<std::unordered_map<std::string, std::string>>("StringUnorderedMap");
46
+
47
+ Object unordered_map = m.module_eval("$unordered_map = StringUnorderedMap.new");
48
+ Object result = unordered_map.call("size");
49
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
50
+
51
+ m.module_eval("$unordered_map['a_key'] = 'a_value'");
52
+ result = unordered_map.call("size");
53
+ ASSERT_EQUAL(1, detail::From_Ruby<int32_t>().convert(result));
54
+
55
+ m.module_eval("$unordered_map.clear");
56
+ result = unordered_map.call("size");
57
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
58
+ }
59
+
60
+ TESTCASE(WrongType)
61
+ {
62
+ Module m = define_module("Testing");
63
+
64
+ Class c = define_unordered_map<std::unordered_map<std::string, std::string>>("StringUnorderedMap");
65
+ Object unordered_map = m.module_eval("$unordered_map = StringUnorderedMap.new");
66
+
67
+ ASSERT_EXCEPTION_CHECK(
68
+ Exception,
69
+ m.module_eval("$unordered_map[1] = 'abc'"),
70
+ ASSERT_EQUAL("wrong argument type Integer (expected String)", ex.what()));
71
+
72
+ ASSERT_EXCEPTION_CHECK(
73
+ Exception,
74
+ m.module_eval("$unordered_map['abc'] = true"),
75
+ ASSERT_EQUAL("wrong argument type true (expected String)", ex.what()));
76
+ }
77
+
78
+ TESTCASE(Empty)
79
+ {
80
+ Module m = define_module("Testing");
81
+
82
+ Class c = define_unordered_map<std::unordered_map<std::string, std::int32_t>>("IntUnorderedMap");
83
+ Object unordered_map = c.call("new");
84
+
85
+ Object result = unordered_map.call("size");
86
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
87
+
88
+ result = unordered_map.call("empty?");
89
+ ASSERT_EQUAL(Qtrue, result.value());
90
+ }
91
+
92
+ TESTCASE(Include)
93
+ {
94
+ Module m = define_module("Testing");
95
+
96
+ Class c = define_unordered_map<std::unordered_map<std::string, std::int32_t>>("IntUnorderedMap");
97
+ Object unordered_map = c.call("new");
98
+ unordered_map.call("[]=", "one", 1);
99
+ unordered_map.call("[]=", "two", 2);
100
+
101
+ Object result = unordered_map.call("include?", "two");
102
+ ASSERT_EQUAL(Qtrue, result.value());
103
+
104
+ result = unordered_map.call("include?", "three");
105
+ ASSERT_EQUAL(Qfalse, result.value());
106
+
107
+ result = unordered_map.call("[]", "three");
108
+ ASSERT_EQUAL(Qnil, result.value());
109
+ }
110
+
111
+ TESTCASE(Value)
112
+ {
113
+ Module m = define_module("Testing");
114
+
115
+ Class c = define_unordered_map<std::unordered_map<std::string, std::int32_t>>("IntUnorderedMap");
116
+ Object unordered_map = c.call("new");
117
+ unordered_map.call("[]=", "one", 1);
118
+ unordered_map.call("[]=", "two", 2);
119
+
120
+ Object result = unordered_map.call("value?", 2);
121
+ ASSERT_EQUAL(Qtrue, result.value());
122
+
123
+ result = unordered_map.call("value?", 4);
124
+ ASSERT_EQUAL(Qfalse, result.value());
125
+ }
126
+
127
+ TESTCASE(ToString)
128
+ {
129
+ Module m = define_module("Testing");
130
+
131
+ Class c = define_unordered_map<std::unordered_map<std::string, std::int32_t>>("IntUnorderedMap");
132
+ Object unordered_map = c.call("new");
133
+ unordered_map.call("[]=", "one", 1);
134
+ unordered_map.call("[]=", "two", 2);
135
+
136
+ Object result = unordered_map.call("to_s");
137
+ ASSERT_EQUAL("{two => 2, one => 1}", detail::From_Ruby<std::string>().convert(result));
138
+
139
+ unordered_map.call("clear");
140
+
141
+ result = unordered_map.call("to_s");
142
+ ASSERT_EQUAL("{}", detail::From_Ruby<std::string>().convert(result));
143
+ }
144
+
145
+ TESTCASE(Update)
146
+ {
147
+ Module m = define_module("Testing");
148
+
149
+ Class c = define_unordered_map<std::unordered_map<std::string, std::string>>("StringUnorderedMap");
150
+ Object unordered_map = c.call("new");
151
+ unordered_map.call("[]=", "one", "original 1");
152
+ unordered_map.call("[]=", "two", "original 2");
153
+
154
+ Object result = unordered_map.call("size");
155
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
156
+
157
+ result = unordered_map.call("[]=", "two", "new 2");
158
+ ASSERT_EQUAL("new 2", detail::From_Ruby<std::string>().convert(result));
159
+
160
+ result = unordered_map.call("size");
161
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
162
+
163
+ result = unordered_map.call("[]", "two");
164
+ ASSERT_EQUAL("new 2", detail::From_Ruby<std::string>().convert(result));
165
+ }
166
+
167
+ TESTCASE(Modify)
168
+ {
169
+ Module m = define_module("Testing");
170
+
171
+ Class c = define_unordered_map<std::unordered_map<std::string, int64_t>>("Int64UnorderedMap");
172
+ Object unordered_map = c.call("new");
173
+
174
+ Object result = unordered_map.call("[]=", "one", 3232323232);
175
+
176
+ result = unordered_map.call("size");
177
+ ASSERT_EQUAL(1, detail::From_Ruby<int32_t>().convert(result));
178
+
179
+ result = unordered_map.call("delete", "one");
180
+ ASSERT_EQUAL(3232323232, detail::From_Ruby<int64_t>().convert(result));
181
+
182
+ result = unordered_map.call("size");
183
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
184
+ }
185
+
186
+ TESTCASE(keysAndValues)
187
+ {
188
+ Module m = define_module("Testing");
189
+
190
+ Class c = define_unordered_map<std::unordered_map<std::string, int32_t>>("Int32UnorderedMap");
191
+ Object unordered_map = c.call("new");
192
+
193
+ unordered_map.call("[]=", "one", 1);
194
+ unordered_map.call("[]=", "two", 2);
195
+ unordered_map.call("[]=", "three", 3);
196
+
197
+ // Keys returns a std::vector
198
+ Data_Object<std::vector<std::string>> keys = unordered_map.call("keys");
199
+ //std::vector<std::string> expected_keys{ {"one", "three", "two"} };
200
+ ASSERT_EQUAL(3u, keys->size());
201
+ //ASSERT_EQUAL(expected_keys[0], keys->operator[](0));
202
+ //ASSERT_EQUAL(expected_keys[1], keys->operator[](1));
203
+ //ASSERT_EQUAL(expected_keys[2], keys->operator[](2));
204
+
205
+ // Keys returns a std::vector
206
+ Data_Object<std::vector<std::int32_t>> values = unordered_map.call("values");
207
+ //std::vector<std::int32_t> expected_values{ {1, 3, 2} };
208
+ ASSERT_EQUAL(3u, values->size());
209
+ //ASSERT_EQUAL(expected_values[0], values->operator[](0));
210
+ //ASSERT_EQUAL(expected_values[1], values->operator[](1));
211
+ //ASSERT_EQUAL(expected_values[2], values->operator[](2));
212
+ }
213
+
214
+ TESTCASE(Copy)
215
+ {
216
+ Module m = define_module("Testing");
217
+
218
+ Class c = define_unordered_map<std::unordered_map<std::string, double>>("DoubleUnorderedMap");
219
+ Object object = c.call("new");
220
+
221
+ object.call("[]=", "one", 11.1);
222
+ object.call("[]=", "two", 22.2);
223
+ std::unordered_map<std::string, double>& unordered_map = detail::From_Ruby<std::unordered_map<std::string, double>&>().convert(object);
224
+
225
+ Object result = object.call("copy");
226
+ std::unordered_map<std::string, double>& unordered_mapCopy = detail::From_Ruby<std::unordered_map<std::string, double>&>().convert(result);
227
+
228
+ ASSERT_EQUAL(unordered_map.size(), unordered_mapCopy.size());
229
+ ASSERT_EQUAL(unordered_map["one"], unordered_mapCopy["one"]);
230
+ ASSERT_EQUAL(unordered_map["two"], unordered_mapCopy["two"]);
231
+
232
+ unordered_mapCopy["three"] = 33.3;
233
+ ASSERT_NOT_EQUAL(unordered_map.size(), unordered_mapCopy.size());
234
+ }
235
+
236
+ TESTCASE(Iterate)
237
+ {
238
+ Module m = define_module("Testing");
239
+ Class c = define_unordered_map<std::unordered_map<std::string, int>>("IntUnorderedMap");
240
+
241
+ std::string code = R"(unordered_map = IntUnorderedMap.new
242
+ unordered_map["five"] = 5
243
+ unordered_map["six"] = 6
244
+ unordered_map["seven"] = 7
245
+
246
+ result = Hash.new
247
+ unordered_map.each do |pair|
248
+ result[pair.first] = 2 * pair.second
249
+ end
250
+ result)";
251
+
252
+ Hash result = m.module_eval(code);
253
+ ASSERT_EQUAL(3u, result.size());
254
+
255
+ std::string result_string = result.to_s().str();
256
+ ASSERT_EQUAL(R"({"seven"=>14, "six"=>12, "five"=>10})", result_string);
257
+ }
258
+
259
+ TESTCASE(ToEnum)
260
+ {
261
+ Module m = define_module("Testing");
262
+ Class c = define_unordered_map<std::unordered_map<std::string, int>>("IntUnorderedMap");
263
+
264
+ std::string code = R"(unordered_map = IntUnorderedMap.new
265
+ unordered_map["five"] = 5
266
+ unordered_map["six"] = 6
267
+ unordered_map["seven"] = 7
268
+
269
+ result = Hash.new
270
+ unordered_map.each.each do |pair|
271
+ result[pair.first] = 2 * pair.second
272
+ end
273
+ result)";
274
+
275
+ Hash result = m.module_eval(code);
276
+ ASSERT_EQUAL(3u, result.size());
277
+
278
+ std::string result_string = result.to_s().str();
279
+ ASSERT_EQUAL(R"({"seven"=>14, "six"=>12, "five"=>10})", result_string);
280
+ }
281
+
282
+ TESTCASE(ToEnumSize)
283
+ {
284
+ Module m = define_module("TestingModule");
285
+ Class c = define_unordered_map<std::unordered_map<std::string, int>>("IntUnorderedMap");
286
+
287
+ std::string code = R"(map = IntUnorderedMap.new
288
+ map["five"] = 5
289
+ map["six"] = 6
290
+ map["seven"] = 7
291
+ map["eight"] = 7
292
+ map)";
293
+
294
+ Object map = m.module_eval(code);
295
+ Object enumerable = map.call("each");
296
+ Object result = enumerable.call("size");
297
+
298
+ ASSERT_EQUAL(4, detail::From_Ruby<int>().convert(result));
299
+ }
300
+
301
+
302
+ namespace
303
+ {
304
+ class NotComparable
305
+ {
306
+ public:
307
+ NotComparable(uint32_t value) : value_(value)
308
+ {
309
+ };
310
+
311
+ NotComparable() = default;
312
+
313
+ uint32_t value_;
314
+ };
315
+ }
316
+
317
+ TESTCASE(NotComparable)
318
+ {
319
+ define_class<NotComparable>("NotComparable").
320
+ define_constructor(Constructor<NotComparable, uint32_t>());
321
+
322
+ Class c = define_unordered_map<std::unordered_map<std::string, NotComparable>>("NotComparableUnorderedMap");
323
+
324
+ Object unordered_map = c.call("new");
325
+ unordered_map.call("[]=", "one", NotComparable(1));
326
+ unordered_map.call("[]=", "two", NotComparable(2));
327
+ unordered_map.call("[]=", "three", NotComparable(3));
328
+
329
+ Object result = unordered_map.call("include?", "two");
330
+ ASSERT_EQUAL(Qtrue, result.value());
331
+
332
+ result = unordered_map.call("value?", NotComparable(3));
333
+ ASSERT_EQUAL(Qfalse, result.value());
334
+ }
335
+
336
+ TESTCASE(NotPrintable)
337
+ {
338
+ define_class<NotComparable>("NotComparable").
339
+ define_constructor(Constructor<NotComparable, uint32_t>());
340
+
341
+ Class c = define_unordered_map<std::unordered_map<std::string, NotComparable>>("NotComparableUnorderedMap");
342
+
343
+ Object unordered_map = c.call("new");
344
+ unordered_map.call("[]=", "one", NotComparable(1));
345
+ unordered_map.call("[]=", "two", NotComparable(2));
346
+ unordered_map.call("[]=", "three", NotComparable(3));
347
+
348
+ Object result = unordered_map.call("to_s");
349
+ ASSERT_EQUAL("[Not printable]", detail::From_Ruby<std::string>().convert(result));
350
+ }
351
+
352
+ namespace
353
+ {
354
+ class Comparable
355
+ {
356
+ public:
357
+ Comparable() = default;
358
+ Comparable(uint32_t value) : value_(value)
359
+ {
360
+ };
361
+
362
+ bool operator==(const Comparable& other)
363
+ {
364
+ return this->value_ == other.value_;
365
+ }
366
+
367
+ uint32_t value_;
368
+ };
369
+
370
+ inline std::ostream& operator<<(std::ostream& stream, Comparable const& comparable)
371
+ {
372
+ stream << "Comparable(" << std::to_string(comparable.value_) << ")";
373
+ return stream;
374
+ }
375
+ }
376
+
377
+ TESTCASE(Comparable)
378
+ {
379
+ define_class<Comparable>("IsComparable").
380
+ define_constructor(Constructor<Comparable, uint32_t>());
381
+
382
+ Class c = define_unordered_map<std::unordered_map<std::string, Comparable>>("ComparableUnorderedMap");
383
+
384
+ Object unordered_map = c.call("new");
385
+
386
+ unordered_map.call("[]=", "one", Comparable(1));
387
+ unordered_map.call("[]=", "two", Comparable(2));
388
+ unordered_map.call("[]=", "three", Comparable(3));
389
+
390
+ Object result = unordered_map.call("value?", Comparable(2));
391
+ ASSERT_EQUAL(Qtrue, result.value());
392
+ }
393
+
394
+ TESTCASE(Printable)
395
+ {
396
+ define_class<Comparable>("IsComparable").
397
+ define_constructor(Constructor<Comparable, uint32_t>());
398
+
399
+ Class c = define_unordered_map<std::unordered_map<std::string, Comparable>>("ComparableUnorderedMap");
400
+
401
+ Object unordered_map = c.call("new");
402
+ unordered_map.call("[]=", "one", Comparable(1));
403
+ unordered_map.call("[]=", "two", Comparable(2));
404
+ unordered_map.call("[]=", "three", Comparable(3));
405
+
406
+ Object result = unordered_map.call("to_s");
407
+ ASSERT_EQUAL("{three => Comparable(3), two => Comparable(2), one => Comparable(1)}", detail::From_Ruby<std::string>().convert(result));
408
+ }
409
+
410
+ namespace
411
+ {
412
+ std::unordered_map<std::string, std::complex<double>> returnComplexUnorderedMap()
413
+ {
414
+ std::complex<double> complex1(1, 1);
415
+ std::complex<double> complex2(2, 2);
416
+ std::complex<double> complex3(3, 3);
417
+
418
+ std::unordered_map<std::string, std::complex<double>> result;
419
+ result["one"] = complex1;
420
+ result["two"] = complex2;
421
+ result["three"] = complex3;
422
+ return result;
423
+ }
424
+
425
+ std::unordered_map<std::string, std::complex<double>> passComplexUnorderedMap(std::unordered_map<std::string, std::complex<double>>& complexes)
426
+ {
427
+ return complexes;
428
+ }
429
+ }
430
+
431
+ TESTCASE(AutoRegisterReturn)
432
+ {
433
+ define_global_function("return_complex_unordered_map", &returnComplexUnorderedMap);
434
+
435
+ Module m = define_module("Testing");
436
+ Object unordered_map = m.module_eval("return_complex_unordered_map");
437
+ ASSERT_EQUAL("Rice::Std::Unordered_map__basic_string__char_char_traits__char___allocator__char_____complex__double___hash__basic_string__char_char_traits__char___allocator__char_______equal_to__basic_string__char_char_traits__char___allocator__char_______allocator__pair__basic_string__char_char_traits__char___allocator__char____Const_complex__double________",
438
+ unordered_map.class_name().str());
439
+
440
+ std::string code = R"(unordered_map = return_complex_unordered_map
441
+ complex = unordered_map['three']
442
+ complex == Complex(3, 3))";
443
+
444
+ Object result = m.module_eval(code);
445
+ ASSERT_EQUAL(Qtrue, result.value());
446
+
447
+ // Now register the unordered_map again
448
+ define_unordered_map<std::unordered_map<std::string, std::complex<double>>>("ComplexUnorderedMap");
449
+ code = R"(unordered_map = ComplexUnorderedMap.new)";
450
+ result = m.module_eval(code);
451
+ ASSERT(result.is_instance_of(unordered_map.class_of()));
452
+
453
+ // And again in the module
454
+ define_unordered_map_under<std::unordered_map<std::string, std::complex<double>>>(m, "ComplexUnorderedMap2");
455
+ code = R"(unordered_map = Testing::ComplexUnorderedMap2.new)";
456
+ result = m.module_eval(code);
457
+ ASSERT(result.is_instance_of(unordered_map.class_of()));
458
+ }
459
+
460
+ TESTCASE(AutoRegisterParameter)
461
+ {
462
+ define_global_function("pass_complex_unordered_map", &passComplexUnorderedMap);
463
+
464
+ std::string code = R"(unordered_map = Rice::Std::Unordered_map__basic_string__char_char_traits__char___allocator__char_____complex__double___hash__basic_string__char_char_traits__char___allocator__char_______equal_to__basic_string__char_char_traits__char___allocator__char_______allocator__pair__basic_string__char_char_traits__char___allocator__char____Const_complex__double________.new
465
+ unordered_map["four"] = Complex(4.0, 4.0)
466
+ unordered_map["five"] = Complex(5.0, 5.0)
467
+ pass_complex_unordered_map(unordered_map))";
468
+
469
+ Module m = define_module("Testing");
470
+ Object unordered_map = m.module_eval(code);
471
+
472
+ Object result = unordered_map.call("size");
473
+ ASSERT_EQUAL("Rice::Std::Unordered_map__basic_string__char_char_traits__char___allocator__char_____complex__double___hash__basic_string__char_char_traits__char___allocator__char_______equal_to__basic_string__char_char_traits__char___allocator__char_______allocator__pair__basic_string__char_char_traits__char___allocator__char____Const_complex__double________",
474
+ unordered_map.class_name().str());
475
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
476
+
477
+ std::unordered_map<std::string, std::complex<double>> complexes = detail::From_Ruby<std::unordered_map<std::string, std::complex<double>>>().convert(unordered_map);
478
+ ASSERT_EQUAL(complexes["four"], std::complex<double>(4, 4));
479
+ ASSERT_EQUAL(complexes["five"], std::complex<double>(5, 5));
480
+ }
481
+
482
+ namespace
483
+ {
484
+ std::unordered_map<std::string, std::string> defaultUnorderedMap(std::unordered_map<std::string, std::string> strings = {{"one", "value 1"}, {"two", "value 2"}, {"three", "value 3"}})
485
+ {
486
+ return strings;
487
+ }
488
+ }
489
+
490
+ TESTCASE(DefaultValue)
491
+ {
492
+ define_unordered_map<std::unordered_map<std::string, std::string>>("StringUnorderedMap");
493
+ define_global_function("default_unordered_map", &defaultUnorderedMap, Arg("strings") = std::unordered_map<std::string, std::string>{ {"one", "value 1"}, {"two", "value 2"}, {"three", "value 3"} });
494
+
495
+ Module m = define_module("Testing");
496
+ Object result = m.module_eval("default_unordered_map");
497
+ std::unordered_map<std::string, std::string> actual = detail::From_Ruby<std::unordered_map<std::string, std::string>>().convert(result);
498
+
499
+ std::unordered_map<std::string, std::string> expected{ {"one", "value 1"}, {"two", "value 2"}, {"three", "value 3"} };
500
+
501
+ ASSERT_EQUAL(expected.size(), actual.size());
502
+ ASSERT_EQUAL(expected["one"], actual["one"]);
503
+ ASSERT_EQUAL(expected["two"], actual["two"]);
504
+ ASSERT_EQUAL(expected["three"], actual["three"]);
505
+ }
506
+
507
+ namespace
508
+ {
509
+ std::unordered_map<std::string, int> ints;
510
+ std::unordered_map<std::string, float> floats;
511
+ std::unordered_map<std::string, std::string> strings;
512
+
513
+ void hashToUnorderedMap(std::unordered_map<std::string, int> aInts, std::unordered_map<std::string, float> aFloats, std::unordered_map<std::string, std::string> aStrings)
514
+ {
515
+ ints = aInts;
516
+ floats = aFloats;
517
+ strings = aStrings;
518
+ }
519
+
520
+ void hashToUnorderedMapRefs(std::unordered_map<std::string, int>& aInts, std::unordered_map<std::string, float>& aFloats, std::unordered_map<std::string, std::string>& aStrings)
521
+ {
522
+ ints = aInts;
523
+ floats = aFloats;
524
+ strings = aStrings;
525
+ }
526
+
527
+ void hashToUnorderedMapPointers(std::unordered_map<std::string, int>* aInts, std::unordered_map<std::string, float>* aFloats, std::unordered_map<std::string, std::string>* aStrings)
528
+ {
529
+ ints = *aInts;
530
+ floats = *aFloats;
531
+ strings = *aStrings;
532
+ }
533
+ }
534
+
535
+ TESTCASE(HashToUnorderedMap)
536
+ {
537
+ define_global_function("hash_to_unordered_map", &hashToUnorderedMap);
538
+
539
+ Module m = define_module("Testing");
540
+
541
+ std::string code = R"(hash_to_unordered_map({"seven" => 7,
542
+ "nine" => 9,
543
+ "million" => 1_000_000},
544
+ {"forty nine" => 49.0,
545
+ "seventy eight" => 78.0,
546
+ "nine hundred ninety nine" => 999.0},
547
+ {"one" => "one",
548
+ "two" => "two",
549
+ "three" => "three"}))";
550
+
551
+ m.module_eval(code);
552
+
553
+ ASSERT_EQUAL(3u, ints.size());
554
+ ASSERT_EQUAL(7, ints["seven"]);
555
+ ASSERT_EQUAL(9, ints["nine"]);
556
+ ASSERT_EQUAL(1'000'000, ints["million"]);
557
+
558
+ ASSERT_EQUAL(3u, floats.size());
559
+ ASSERT_EQUAL(49.0, floats["forty nine"]);
560
+ ASSERT_EQUAL(78.0, floats["seventy eight"]);
561
+ ASSERT_EQUAL(999.0, floats["nine hundred ninety nine"]);
562
+
563
+ ASSERT_EQUAL(3u, strings.size());
564
+ ASSERT_EQUAL("one", strings["one"]);
565
+ ASSERT_EQUAL("two", strings["two"]);
566
+ ASSERT_EQUAL("three", strings["three"]);
567
+ }
568
+
569
+ TESTCASE(HashToUnorderedMapRefs)
570
+ {
571
+ define_global_function("hash_to_unordered_map_refs", &hashToUnorderedMapRefs);
572
+
573
+ Module m = define_module("Testing");
574
+
575
+ std::string code = R"(hash_to_unordered_map_refs({"eight" => 8,
576
+ "ten" => 10,
577
+ "million one" => 1_000_001},
578
+ {"fifty" => 50.0,
579
+ "seventy nine" => 79.0,
580
+ "one thousand" => 1_000.0},
581
+ {"eleven" => "eleven",
582
+ "twelve" => "twelve",
583
+ "thirteen" => "thirteen"}))";
584
+ m.module_eval(code);
585
+
586
+ ASSERT_EQUAL(3u, ints.size());
587
+ ASSERT_EQUAL(8, ints["eight"]);
588
+ ASSERT_EQUAL(10, ints["ten"]);
589
+ ASSERT_EQUAL(1'000'001, ints["million one"]);
590
+
591
+ ASSERT_EQUAL(3u, floats.size());
592
+ ASSERT_EQUAL(50.0, floats["fifty"]);
593
+ ASSERT_EQUAL(79.0, floats["seventy nine"]);
594
+ ASSERT_EQUAL(1'000.0, floats["one thousand"]);
595
+
596
+ ASSERT_EQUAL(3u, strings.size());
597
+ ASSERT_EQUAL("eleven", strings["eleven"]);
598
+ ASSERT_EQUAL("twelve", strings["twelve"]);
599
+ ASSERT_EQUAL("thirteen", strings["thirteen"]);
600
+ }
601
+
602
+ TESTCASE(HashToUnorderedMapPointers)
603
+ {
604
+ define_global_function("hash_to_unordered_map_pointers", &hashToUnorderedMapPointers);
605
+
606
+ Module m = define_module("Testing");
607
+
608
+ std::string code = R"(hash_to_unordered_map_pointers({"nine" => 9,
609
+ "eleven" => 11,
610
+ "million two" => 1_000_002},
611
+ {"fifty one" => 51.0,
612
+ "eighty" => 80.0,
613
+ "one thousand one" => 1_001.0},
614
+ {"fourteen" => "fourteen",
615
+ "fifteen" => "fifteen",
616
+ "sixteen" => "sixteen"}))";
617
+
618
+ m.module_eval(code);
619
+
620
+ ASSERT_EQUAL(3u, ints.size());
621
+ ASSERT_EQUAL(9, ints["nine"]);
622
+ ASSERT_EQUAL(11, ints["eleven"]);
623
+ ASSERT_EQUAL(1'000'002, ints["million two"]);
624
+
625
+ ASSERT_EQUAL(3u, floats.size());
626
+ ASSERT_EQUAL(51.0, floats["fifty one"]);
627
+ ASSERT_EQUAL(80.0, floats["eighty"]);
628
+ ASSERT_EQUAL(1'001.0, floats["one thousand one"]);
629
+
630
+ ASSERT_EQUAL(3u, strings.size());
631
+ ASSERT_EQUAL("fourteen", strings["fourteen"]);
632
+ ASSERT_EQUAL("fifteen", strings["fifteen"]);
633
+ ASSERT_EQUAL("sixteen", strings["sixteen"]);
634
+ }
635
+
636
+ TESTCASE(HashToUnorderedMapWrongTypes)
637
+ {
638
+ define_global_function("hash_to_unordered_map", &hashToUnorderedMap);
639
+
640
+ Module m = define_module("Testing");
641
+
642
+ std::string code = R"(hash_to_unordered_map({"seven" => 7,
643
+ "nine" => 9,
644
+ "million" => 1_000_000},
645
+ {"forty nine" => 49.0,
646
+ "seventy eight" => 78.0,
647
+ "nine hundred ninety nine" => 999.0},
648
+ {"one" => 50.0,
649
+ "two" => 79.0,
650
+ "three" => 1000.0}))";
651
+
652
+ ASSERT_EXCEPTION_CHECK(
653
+ Exception,
654
+ m.module_eval(code),
655
+ ASSERT_EQUAL("wrong argument type Float (expected String)", ex.what())
656
+ );
657
+ }
658
+
659
+ TESTCASE(HashToUnorderedMapMixedTypes)
660
+ {
661
+ define_global_function("hash_to_unordered_map", &hashToUnorderedMap);
662
+
663
+ Module m = define_module("Testing");
664
+
665
+ std::string code = R"(hash_to_unordered_map({"seven" => 7,
666
+ "nine" => "nine",
667
+ "million" => true},
668
+ {"forty nine" => 49.0,
669
+ "seventy eight" => 78.0,
670
+ "nine hundred ninety nine" => 999.0},
671
+ {"one" => "one",
672
+ "two" => "two",
673
+ "three" => "three"}))";
674
+
675
+ ASSERT_EXCEPTION_CHECK(
676
+ Exception,
677
+ m.module_eval(code),
678
+ ASSERT_EQUAL("no implicit conversion of String into Integer", ex.what())
679
+ );
680
+ }
681
+
682
+ TESTCASE(UnorderedMapToHash)
683
+ {
684
+ Module m = define_module("Testing");
685
+ Class c = makeUnorderedUnorderedMapClass();
686
+
687
+ std::string code = R"(my_class = MyClass.new
688
+ unordered_map = my_class.stringUnorderedMap
689
+ hash = unordered_map.to_h)";
690
+
691
+ Hash hash = m.module_eval(code);
692
+ ASSERT_EQUAL(3u, hash.size());
693
+
694
+ ASSERT_EQUAL("1", detail::From_Ruby<std::string>().convert(hash["One"].value()));
695
+ ASSERT_EQUAL("2", detail::From_Ruby<std::string>().convert(hash["Two"].value()));
696
+ ASSERT_EQUAL("3", detail::From_Ruby<std::string>().convert(hash["Three"].value()));
697
+ }