rice 4.3.0 → 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,871 +1,871 @@
1
- #include <complex>
2
-
3
- #include "unittest.hpp"
4
- #include "embed_ruby.hpp"
5
- #include <rice/rice.hpp>
6
- #include <rice/stl.hpp>
7
-
8
- using namespace Rice;
9
-
10
- TESTSUITE(Vector);
11
-
12
- SETUP(Vector)
13
- {
14
- embed_ruby();
15
- }
16
-
17
- namespace
18
- {
19
-
20
- class MyClass
21
- {
22
- public:
23
- std::vector<std::string> stringVector()
24
- {
25
- std::vector<std::string> result{ "One", "Two", "Three" };
26
- return result;
27
- }
28
- };
29
- }
30
-
31
- Class makeVectorClass()
32
- {
33
- Class c = define_class<MyClass>("MyClass").
34
- define_constructor(Constructor<MyClass>()).
35
- define_method("stringVector", &MyClass::stringVector);
36
-
37
- return c;
38
- }
39
-
40
- TESTCASE(StringVector)
41
- {
42
- Module m = define_module("Testing");
43
-
44
- Class c = define_vector<std::vector<std::string>>("StringVector");
45
-
46
- Object vec = m.module_eval("$vector = StringVector.new");
47
- Object result = vec.call("size");
48
- ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
49
-
50
- m.module_eval("$vector << 'one' << 'two' << 'two' << 'three'");
51
- result = vec.call("size");
52
- ASSERT_EQUAL(4, detail::From_Ruby<int32_t>().convert(result));
53
-
54
- m.module_eval("$vector.append('four')");
55
- result = vec.call("size");
56
- ASSERT_EQUAL(5, detail::From_Ruby<int32_t>().convert(result));
57
-
58
- result = vec.call("first");
59
- ASSERT_EQUAL("one", detail::From_Ruby<std::string>().convert(result));
60
-
61
- result = vec.call("last");
62
- ASSERT_EQUAL("four", detail::From_Ruby<std::string>().convert(result));
63
- }
64
-
65
- TESTCASE(WrongType)
66
- {
67
- Module m = define_module("Testing");
68
-
69
- Class c = define_vector<std::vector<std::string>>("StringVector");
70
-
71
- Object vec = m.module_eval("$vector = StringVector.new");
72
- ASSERT_EXCEPTION_CHECK(
73
- Exception,
74
- m.module_eval("$vector << 1"),
75
- ASSERT_EQUAL("wrong argument type Integer (expected String)", ex.what()));
76
- }
77
-
78
- TESTCASE(Empty)
79
- {
80
- Module m = define_module("Testing");
81
-
82
- Class c = define_vector<std::vector<std::int32_t>>("IntVector");
83
- Object vec = c.call("new");
84
-
85
- Object result = vec.call("size");
86
- ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
87
-
88
- result = vec.call("empty?");
89
- ASSERT_EQUAL(Qtrue, result.value());
90
-
91
- result = vec.call("first");
92
- ASSERT_EQUAL(Qnil, result.value());
93
-
94
- result = vec.call("last");
95
- ASSERT_EQUAL(Qnil, result.value());
96
- }
97
-
98
- TESTCASE(Indexing)
99
- {
100
- Module m = define_module("Testing");
101
-
102
- Class c = define_vector<std::vector<std::int32_t>>("IntVector");
103
- Object vec = c.call("new");
104
- vec.call("push", 0);
105
- vec.call("push", 1);
106
- vec.call("push", 2);
107
-
108
- Object result = vec.call("size");
109
- ASSERT_EQUAL(3, detail::From_Ruby<int32_t>().convert(result));
110
-
111
- result = vec.call("[]", 0);
112
- ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
113
-
114
- result = vec.call("[]", 1);
115
- ASSERT_EQUAL(1, detail::From_Ruby<int32_t>().convert(result));
116
-
117
- result = vec.call("[]", 2);
118
- ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
119
-
120
- result = vec.call("[]", 3);
121
- ASSERT_EQUAL(Qnil, result.value());
122
-
123
- result = vec.call("[]", -1);
124
- ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
125
-
126
- result = vec.call("[]", -2);
127
- ASSERT_EQUAL(1, detail::From_Ruby<int32_t>().convert(result));
128
-
129
- result = vec.call("[]", -3);
130
- ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
131
-
132
- result = vec.call("[]", -4);
133
- ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
134
-
135
- result = vec.call("[]", -7);
136
- ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
137
- }
138
-
139
- TESTCASE(Sizing)
140
- {
141
- Module m = define_module("Testing");
142
-
143
- Class c = define_vector<std::vector<std::int32_t>>("IntVector");
144
- Object vec = c.call("new");
145
- vec.call("resize", 10);
146
-
147
- Object result = vec.call("size");
148
- ASSERT_EQUAL(10, detail::From_Ruby<int32_t>().convert(result));
149
-
150
- vec.call("clear");
151
-
152
- result = vec.call("size");
153
- ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
154
- }
155
-
156
- TESTCASE(ToString)
157
- {
158
- Module m = define_module("Testing");
159
-
160
- Class c = define_vector<std::vector<std::int32_t>>("IntVector");
161
- Object vec = c.call("new");
162
- vec.call("resize", 3);
163
-
164
- Object result = vec.call("to_s");
165
- ASSERT_EQUAL("[0, 0, 0]", detail::From_Ruby<std::string>().convert(result));
166
-
167
- vec.call("clear");
168
-
169
- result = vec.call("to_s");
170
- ASSERT_EQUAL("[]", detail::From_Ruby<std::string>().convert(result));
171
- }
172
-
173
- TESTCASE(Update)
174
- {
175
- Module m = define_module("Testing");
176
-
177
- Class c = define_vector<std::vector<std::string>>("StringVector");
178
- Object vec = c.call("new");
179
- vec.call("push", "original 1");
180
- vec.call("push", "original 2");
181
-
182
- Object result = vec.call("size");
183
- ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
184
-
185
- result = vec.call("[]=", 1, "new 2");
186
- ASSERT_EQUAL("new 2", detail::From_Ruby<std::string>().convert(result));
187
-
188
- result = vec.call("[]", 1);
189
- ASSERT_EQUAL("new 2", detail::From_Ruby<std::string>().convert(result));
190
-
191
- ASSERT_EXCEPTION_CHECK(
192
- Exception,
193
- result = vec.call("[]=", 99999, "new 2"),
194
- ASSERT_EQUAL("Invalid index: 99999", ex.what()));
195
- }
196
-
197
- TESTCASE(Modify)
198
- {
199
- Module m = define_module("Testing");
200
-
201
- Class c = define_vector<std::vector<int64_t>>("Int64Vector");
202
- Object vec = c.call("new");
203
-
204
- Object result = vec.call("push", 11);
205
- ASSERT(result.is_equal(vec));
206
-
207
- result = vec.call("push", 22);
208
- ASSERT(result.is_equal(vec));
209
-
210
- result = vec.call("size");
211
- ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
212
-
213
- result = vec.call("insert", 1, 33);
214
- ASSERT(result.is_equal(vec));
215
-
216
- result = vec.call("to_s");
217
- ASSERT_EQUAL("[11, 33, 22]", detail::From_Ruby<std::string>().convert(result));
218
-
219
- result = vec.call("delete", 11);
220
- ASSERT_EQUAL(11, detail::From_Ruby<int64_t>().convert(result));
221
-
222
- result = vec.call("size");
223
- ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
224
-
225
- result = vec.call("delete_at", 0);
226
- ASSERT_EQUAL(33, detail::From_Ruby<int64_t>().convert(result));
227
-
228
- result = vec.call("size");
229
- ASSERT_EQUAL(1, detail::From_Ruby<int32_t>().convert(result));
230
-
231
- result = vec.call("pop");
232
- ASSERT_EQUAL(22, detail::From_Ruby<int64_t>().convert(result));
233
-
234
- result = vec.call("size");
235
- ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
236
-
237
- result = vec.call("pop");
238
- ASSERT_EQUAL(Qnil, result.value());
239
- }
240
-
241
- TESTCASE(Copy)
242
- {
243
- Module m = define_module("Testing");
244
-
245
- Class c = define_vector<std::vector<double>>("DoubleVector");
246
- Object object = c.call("new");
247
-
248
- object.call("push", 11.1);
249
- object.call("push", 22.2);
250
- std::vector<double>& vec = detail::From_Ruby<std::vector<double>&>().convert(object);
251
-
252
- Object result = object.call("copy");
253
- std::vector<double>& vecCopy = detail::From_Ruby<std::vector<double>&>().convert(result);
254
-
255
- ASSERT_EQUAL(vec.size(), vecCopy.size());
256
- ASSERT_EQUAL(vec[0], vecCopy[0]);
257
- ASSERT_EQUAL(vec[1], vecCopy[1]);
258
-
259
- vecCopy.push_back(33.3);
260
- ASSERT_NOT_EQUAL(vec.size(), vecCopy.size());
261
- }
262
-
263
- namespace
264
- {
265
- class NotComparable
266
- {
267
- public:
268
- NotComparable(uint32_t value) : value_(value)
269
- {
270
- };
271
-
272
- uint32_t value_;
273
- };
274
- }
275
-
276
- TESTCASE(NotComparable)
277
- {
278
- define_class<NotComparable>("NotComparable").
279
- define_constructor(Constructor<NotComparable, uint32_t>());
280
-
281
- Class c = define_vector<std::vector<NotComparable>>("NotComparableVector");
282
-
283
- Object vec = c.call("new");
284
- vec.call("push", NotComparable(1));
285
- vec.call("push", NotComparable(2));
286
- vec.call("push", NotComparable(3));
287
-
288
- Object result = vec.call("delete", NotComparable(1));
289
- ASSERT_EQUAL(Qnil, result.value());
290
-
291
- result = vec.call("length");
292
- ASSERT_EQUAL(3u, detail::From_Ruby<size_t>().convert(result));
293
-
294
- result = vec.call("include?", NotComparable(2));
295
- ASSERT_EQUAL(Qfalse, result.value());
296
-
297
- result = vec.call("index", NotComparable(3));
298
- ASSERT_EQUAL(Qnil, result.value());
299
- }
300
-
301
- TESTCASE(NotDefaultConstructable)
302
- {
303
- define_class<NotComparable>("NotComparable").
304
- define_constructor(Constructor<NotComparable, uint32_t>());
305
-
306
- Class c = define_vector<std::vector<NotComparable>>("NotComparableVector");
307
- Object vec = c.call("new");
308
-
309
- Object result = vec.call("resize", 10);
310
- ASSERT_EQUAL(Qnil, result.value());
311
-
312
- result = vec.call("length");
313
- ASSERT_EQUAL(0, detail::From_Ruby<size_t>().convert(result));
314
- }
315
-
316
- TESTCASE(NotPrintable)
317
- {
318
- define_class<NotComparable>("NotComparable").
319
- define_constructor(Constructor<NotComparable, uint32_t>());
320
-
321
- Class c = define_vector<std::vector<NotComparable>>("NotComparableVector");
322
-
323
- Object vec = c.call("new");
324
- vec.call("push", NotComparable(1));
325
- vec.call("push", NotComparable(2));
326
- vec.call("push", NotComparable(3));
327
-
328
- Object result = vec.call("to_s");
329
- ASSERT_EQUAL("[Not printable]", detail::From_Ruby<std::string>().convert(result));
330
- }
331
-
332
- namespace
333
- {
334
- class Comparable
335
- {
336
- public:
337
- Comparable(uint32_t value) : value_(value)
338
- {
339
- };
340
-
341
- bool operator==(const Comparable& other)
342
- {
343
- return this->value_ == other.value_;
344
- }
345
-
346
- uint32_t value_;
347
- };
348
-
349
- inline std::ostream& operator<<(std::ostream& stream, Comparable const& comparable)
350
- {
351
- stream << "Comparable(" << std::to_string(comparable.value_) << ")";
352
- return stream;
353
- }
354
- }
355
-
356
- TESTCASE(Comparable)
357
- {
358
- define_class<Comparable>("IsComparable").
359
- define_constructor(Constructor<Comparable, uint32_t>());
360
-
361
- Class c = define_vector<std::vector<Comparable>>("ComparableVector");
362
-
363
- Object vec = c.call("new");
364
-
365
- Comparable comparable1(1);
366
- vec.call("push", comparable1);
367
-
368
- Comparable comparable2(2);
369
- vec.call("push", comparable2);
370
-
371
- Comparable comparable3(3);
372
- vec.call("push", comparable3);
373
-
374
- Object result = vec.call("delete", Comparable(1));
375
- Comparable comparable = detail::From_Ruby<Comparable>().convert(result);
376
- ASSERT_EQUAL(1, comparable.value_);
377
-
378
- result = vec.call("length");
379
- ASSERT_EQUAL(2, detail::From_Ruby<size_t>().convert(result));
380
-
381
- result = vec.call("include?", Comparable(2));
382
- ASSERT_EQUAL(Qtrue, result.value());
383
-
384
- result = vec.call("index", Comparable(3));
385
- ASSERT_EQUAL(1, detail::From_Ruby<size_t>().convert(result.value()));
386
- }
387
-
388
- TESTCASE(DefaultConstructable)
389
- {
390
- define_class<Comparable>("IsComparable").
391
- define_constructor(Constructor<Comparable, uint32_t>());
392
-
393
- Class c = define_vector<std::vector<Comparable>>("ComparableVector");
394
- Object vec = c.call("new");
395
-
396
- Object result = vec.call("resize", 10);
397
- ASSERT_EQUAL(Qnil, result.value());
398
-
399
- result = vec.call("length");
400
- ASSERT_EQUAL(0, detail::From_Ruby<size_t>().convert(result));
401
- }
402
-
403
- TESTCASE(Printable)
404
- {
405
- define_class<Comparable>("IsComparable").
406
- define_constructor(Constructor<Comparable, uint32_t>());
407
-
408
- Class c = define_vector<std::vector<Comparable>>("ComparableVector");
409
-
410
- Object vec = c.call("new");
411
- vec.call("push", Comparable(1));
412
- vec.call("push", Comparable(2));
413
- vec.call("push", Comparable(3));
414
-
415
- Object result = vec.call("to_s");
416
- ASSERT_EQUAL("[Comparable(1), Comparable(2), Comparable(3)]", detail::From_Ruby<std::string>().convert(result));
417
- }
418
-
419
- namespace
420
- {
421
- std::vector<std::complex<double>> returnComplexVector()
422
- {
423
- std::complex<double> complex1(1, 1);
424
- std::complex<double> complex2(2, 2);
425
- std::complex<double> complex3(3, 3);
426
-
427
- std::vector<std::complex<double>> result;
428
- result.push_back(complex1);
429
- result.push_back(complex2);
430
- result.push_back(complex3);
431
- return result;
432
- }
433
-
434
- std::vector<std::complex<double>> passComplexVector(std::vector<std::complex<double>>& complexes)
435
- {
436
- return complexes;
437
- }
438
- }
439
-
440
- TESTCASE(AutoRegisterReturn)
441
- {
442
- define_global_function("return_complex_vector", &returnComplexVector);
443
-
444
- Module m = define_module("Testing");
445
- Object vec = m.module_eval("return_complex_vector");
446
- ASSERT_EQUAL("Rice::Std::Vector__complex__double___allocator__complex__double______", vec.class_name().str());
447
-
448
- std::string code = R"(vector = return_complex_vector
449
- complex = vector.last
450
- complex == Complex(3, 3))";
451
-
452
- Object result = m.module_eval(code);
453
- ASSERT_EQUAL(Qtrue, result.value());
454
-
455
- // Now register this same vector
456
- define_vector<std::vector<std::complex<double>>>("ComplexVector");
457
- code = R"(vector = ComplexVector.new)";
458
- result = m.module_eval(code);
459
- ASSERT(result.is_instance_of(vec.class_of()));
460
-
461
- // Now register it again in the module
462
- define_vector_under<std::vector<std::complex<double>>>(m, "ComplexVector2");
463
- code = R"(vector = Testing::ComplexVector2.new)";
464
- result = m.module_eval(code);
465
- ASSERT(result.is_instance_of(vec.class_of()));
466
- }
467
-
468
- TESTCASE(AutoRegisterParameter)
469
- {
470
- define_global_function("pass_complex_vector", &passComplexVector);
471
-
472
- std::string code = R"(vector = Rice::Std::Vector__complex__double___allocator__complex__double______.new
473
- vector << Complex(4.0, 4.0)
474
- vector << Complex(5.0, 5.0)
475
- pass_complex_vector(vector))";
476
-
477
- Module m = define_module("Testing");
478
- Object vec = m.module_eval(code);
479
-
480
- Object result = vec.call("size");
481
- ASSERT_EQUAL("Rice::Std::Vector__complex__double___allocator__complex__double______", vec.class_name().str());
482
- ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
483
-
484
- std::vector<std::complex<double>> complexes = detail::From_Ruby<std::vector<std::complex<double>>>().convert(vec);
485
- ASSERT_EQUAL(complexes[0], std::complex<double>(4, 4));
486
- ASSERT_EQUAL(complexes[1], std::complex<double>(5, 5));
487
- }
488
-
489
- namespace
490
- {
491
- std::vector<std::string> defaultVector(std::vector<std::string> strings = {"one", "two", "three"})
492
- {
493
- return strings;
494
- }
495
- }
496
-
497
- TESTCASE(DefaultValue)
498
- {
499
- define_vector<std::vector<std::string>>("StringVector");
500
- define_global_function("default_vector", &defaultVector, Arg("strings") = std::vector<std::string> { "one", "two", "three" });
501
-
502
- Module m = define_module("Testing");
503
- Object result = m.module_eval("default_vector");
504
- std::vector<std::string> actual = detail::From_Ruby<std::vector<std::string>>().convert(result);
505
-
506
- std::vector<std::string> expected{ "one", "two", "three" };
507
-
508
- ASSERT_EQUAL(expected.size(), actual.size());
509
- ASSERT_EQUAL(expected[0], actual[0]);
510
- ASSERT_EQUAL(expected[1], actual[1]);
511
- ASSERT_EQUAL(expected[2], actual[2]);
512
- }
513
-
514
- TESTCASE(ToArray)
515
- {
516
- Module m = define_module("Testing");
517
-
518
- Class c = define_vector<std::vector<std::string>>("StringVector").
519
- define_constructor(Constructor<std::vector<std::string>>());
520
-
521
- std::string code = R"(vector = StringVector.new
522
- vector << "abc"
523
- vector << "def"
524
- vector << "ghi"
525
- vector.to_a)";
526
-
527
- Array array = m.module_eval(code);
528
- ASSERT_EQUAL(3u, array.size());
529
-
530
- ASSERT_EQUAL("abc", detail::From_Ruby<std::string>().convert(array[0].value()));
531
- ASSERT_EQUAL("def", detail::From_Ruby<std::string>().convert(array[1].value()));
532
- ASSERT_EQUAL("ghi", detail::From_Ruby<std::string>().convert(array[2].value()));
533
- }
534
-
535
- namespace
536
- {
537
- std::vector<int> ints;
538
- std::vector<float> floats;
539
- std::vector<std::string> strings;
540
-
541
- void arrayToVector(std::vector<int> aInts, std::vector<float> aFloats, std::vector<std::string> aStrings)
542
- {
543
- ints = aInts;
544
- floats = aFloats;
545
- strings = aStrings;
546
- }
547
-
548
- void arrayToVectorRefs(std::vector<int>& aInts, std::vector<float>& aFloats, std::vector<std::string>& aStrings)
549
- {
550
- ints = aInts;
551
- floats = aFloats;
552
- strings = aStrings;
553
- }
554
-
555
- void arrayToVectorPointers(std::vector<int>* aInts, std::vector<float>* aFloats, std::vector<std::string>* aStrings)
556
- {
557
- ints = *aInts;
558
- floats = *aFloats;
559
- strings = *aStrings;
560
- }
561
- }
562
-
563
- TESTCASE(ArrayToVector)
564
- {
565
- define_global_function("array_to_vector", &arrayToVector);
566
-
567
- Module m = define_module("Testing");
568
-
569
- std::string code = "array_to_vector([7, 9, 1_000_000], [49.0, 78.0, 999.0], %w[one two three])";
570
- m.module_eval(code);
571
-
572
- ASSERT_EQUAL(3, ints.size());
573
- ASSERT_EQUAL(7, ints[0]);
574
- ASSERT_EQUAL(9, ints[1]);
575
- ASSERT_EQUAL(1'000'000, ints[2]);
576
-
577
- ASSERT_EQUAL(3, floats.size());
578
- ASSERT_EQUAL(49.0, floats[0]);
579
- ASSERT_EQUAL(78.0, floats[1]);
580
- ASSERT_EQUAL(999.0, floats[2]);
581
-
582
- ASSERT_EQUAL(3, strings.size());
583
- ASSERT_EQUAL("one", strings[0]);
584
- ASSERT_EQUAL("two", strings[1]);
585
- ASSERT_EQUAL("three", strings[2]);
586
- }
587
-
588
- TESTCASE(ArrayToVectorRefs)
589
- {
590
- define_global_function("array_to_vector_refs", &arrayToVectorRefs);
591
-
592
- Module m = define_module("Testing");
593
-
594
- std::string code = "array_to_vector_refs([8, 10, 1_000_001], [50.0, 79.0, 1_000.0], %w[eleven twelve thirteen])";
595
- m.module_eval(code);
596
-
597
- ASSERT_EQUAL(3, ints.size());
598
- ASSERT_EQUAL(8, ints[0]);
599
- ASSERT_EQUAL(10, ints[1]);
600
- ASSERT_EQUAL(1'000'001, ints[2]);
601
-
602
- ASSERT_EQUAL(3, floats.size());
603
- ASSERT_EQUAL(50.0, floats[0]);
604
- ASSERT_EQUAL(79.0, floats[1]);
605
- ASSERT_EQUAL(1'000.0, floats[2]);
606
-
607
- ASSERT_EQUAL(3, strings.size());
608
- ASSERT_EQUAL("eleven", strings[0]);
609
- ASSERT_EQUAL("twelve", strings[1]);
610
- ASSERT_EQUAL("thirteen", strings[2]);
611
- }
612
-
613
- TESTCASE(ArrayToVectorPointers)
614
- {
615
- define_global_function("array_to_vector_pointers", &arrayToVectorPointers);
616
-
617
- Module m = define_module("Testing");
618
-
619
- std::string code = "array_to_vector_pointers([9, 11, 1_000_002], [51.0, 80.0, 1_001.0], %w[fourteen fifteen sixteen])";
620
- m.module_eval(code);
621
-
622
- ASSERT_EQUAL(3, ints.size());
623
- ASSERT_EQUAL(9, ints[0]);
624
- ASSERT_EQUAL(11, ints[1]);
625
- ASSERT_EQUAL(1'000'002, ints[2]);
626
-
627
- ASSERT_EQUAL(3, floats.size());
628
- ASSERT_EQUAL(51.0, floats[0]);
629
- ASSERT_EQUAL(80.0, floats[1]);
630
- ASSERT_EQUAL(1'001.0, floats[2]);
631
-
632
- ASSERT_EQUAL(3, strings.size());
633
- ASSERT_EQUAL("fourteen", strings[0]);
634
- ASSERT_EQUAL("fifteen", strings[1]);
635
- ASSERT_EQUAL("sixteen", strings[2]);
636
- }
637
-
638
- TESTCASE(ArrayToVectorWrongTypes)
639
- {
640
- define_global_function("array_to_vector", &arrayToVector);
641
-
642
- Module m = define_module("Testing");
643
-
644
- std::string code = "array_to_vector([7, 9, 1_000_000], [49.0, 78.0, 999.0], [50.0, 79.0, 1000.0])";
645
-
646
- ASSERT_EXCEPTION_CHECK(
647
- Exception,
648
- m.module_eval(code),
649
- ASSERT_EQUAL("wrong argument type Float (expected String)", ex.what())
650
- );
651
- }
652
-
653
- TESTCASE(ArrayToVectorMixedTypes)
654
- {
655
- define_global_function("array_to_vector", &arrayToVector);
656
-
657
- Module m = define_module("Testing");
658
-
659
- std::string code = "array_to_vector([7, 'nine', true], [49.0, 78.0, 999.0], %w[one two three])";
660
-
661
- ASSERT_EXCEPTION_CHECK(
662
- Exception,
663
- m.module_eval(code),
664
- ASSERT_EQUAL("no implicit conversion of String into Integer", ex.what())
665
- );
666
- }
667
-
668
- namespace
669
- {
670
- class Factory
671
- {
672
- public:
673
- std::vector<std::string>* returnPointer()
674
- {
675
- return &this->instance_;
676
- }
677
-
678
- std::vector<std::string>& returnReference()
679
- {
680
- return this->instance_;
681
- }
682
-
683
- std::vector<std::string> returnValue()
684
- {
685
- return this->instance_;
686
- }
687
-
688
- public:
689
- static inline std::vector<std::string> instance_{ "one", "two", "three" };
690
- };
691
-
692
- std::ostream& operator<<(std::ostream& stream, const std::vector<std::string>& vector)
693
- {
694
- stream << "Vector";
695
- return stream;
696
- }
697
- }
698
-
699
- void createFactoryClass()
700
- {
701
- define_class<Factory>("Factory").
702
- define_constructor(Constructor<Factory>()).
703
- define_method("pointer", &Factory::returnPointer).
704
- define_method("reference", &Factory::returnReference).
705
- define_method("value", &Factory::returnValue);
706
- }
707
-
708
- TESTCASE(Returns)
709
- {
710
- createFactoryClass();
711
- Module m = define_module("TestingModule");
712
- Object factory = m.module_eval("Factory.new");
713
-
714
- std::vector<std::string> expected{ "one", "two", "three" };
715
-
716
- Data_Object<std::vector<std::string>> vec1 = factory.call("pointer");
717
- ASSERT_EQUAL(expected, *vec1);
718
-
719
- Data_Object<std::vector<std::string>> vec2 = factory.call("reference");
720
- ASSERT_EQUAL(expected, *vec2);
721
-
722
- Data_Object<std::vector<std::string>> vec3 = factory.call("value");
723
- ASSERT_EQUAL(expected, *vec3);
724
- }
725
-
726
- TESTCASE(Iterate)
727
- {
728
- Module m = define_module("Testing");
729
- Class c = define_vector<std::vector<double>>("DoubleVector");
730
-
731
- std::string code = R"(vector = DoubleVector.new
732
- vector << 5.0 << 6.0 << 7.0
733
- updated = vector.map do |value|
734
- value * 2.0
735
- end)";
736
-
737
- Array result = m.module_eval(code);
738
- ASSERT_EQUAL(3, result.size());
739
- ASSERT_EQUAL(10.0, detail::From_Ruby<double>().convert(result[0].value()));
740
- ASSERT_EQUAL(12.0, detail::From_Ruby<double>().convert(result[1].value()));
741
- ASSERT_EQUAL(14.0, detail::From_Ruby<double>().convert(result[2].value()));
742
- }
743
-
744
- TESTCASE(ToEnumPointer)
745
- {
746
- createFactoryClass();
747
- Module m = define_module("TestingModule");
748
-
749
- std::string code = R"(factory = Factory.new
750
- vector = factory.pointer
751
- updated = vector.each.map do |value|
752
- value + "_updated"
753
- end)";
754
-
755
- Array result = m.module_eval(code);
756
-
757
- ASSERT_EQUAL(3, result.size());
758
- ASSERT_EQUAL("one_updated", detail::From_Ruby<std::string>().convert(result[0].value()));
759
- ASSERT_EQUAL("two_updated", detail::From_Ruby<std::string>().convert(result[1].value()));
760
- ASSERT_EQUAL("three_updated", detail::From_Ruby<std::string>().convert(result[2].value()));
761
- }
762
-
763
- TESTCASE(ToEnumReference)
764
- {
765
- createFactoryClass();
766
- Module m = define_module("TestingModule");
767
-
768
- std::string code = R"(factory = Factory.new
769
- vector = factory.reference
770
- updated = vector.each.map do |value|
771
- value + "_updated"
772
- end)";
773
-
774
- Array result = m.module_eval(code);
775
-
776
- ASSERT_EQUAL(3, result.size());
777
- ASSERT_EQUAL("one_updated", detail::From_Ruby<std::string>().convert(result[0].value()));
778
- ASSERT_EQUAL("two_updated", detail::From_Ruby<std::string>().convert(result[1].value()));
779
- ASSERT_EQUAL("three_updated", detail::From_Ruby<std::string>().convert(result[2].value()));
780
- }
781
-
782
- TESTCASE(ToEnumValue)
783
- {
784
- createFactoryClass();
785
- Module m = define_module("TestingModule");
786
-
787
- std::string code = R"(factory = Factory.new
788
- vector = factory.value
789
- updated = vector.each.map do |value|
790
- value + "_updated"
791
- end)";
792
-
793
- Array result = m.module_eval(code);
794
-
795
- ASSERT_EQUAL(3, result.size());
796
- ASSERT_EQUAL("one_updated", detail::From_Ruby<std::string>().convert(result[0].value()));
797
- ASSERT_EQUAL("two_updated", detail::From_Ruby<std::string>().convert(result[1].value()));
798
- ASSERT_EQUAL("three_updated", detail::From_Ruby<std::string>().convert(result[2].value()));
799
- }
800
-
801
- TESTCASE(ToEnumSize)
802
- {
803
- createFactoryClass();
804
- Module m = define_module("TestingModule");
805
- Object factory = m.module_eval("Factory.new");
806
- Object vector = factory.call("pointer");
807
- Object enumerable = vector.call("each");
808
- Object result = enumerable.call("size");
809
-
810
- ASSERT_EQUAL(3, detail::From_Ruby<int>().convert(result));
811
- }
812
-
813
- namespace
814
- {
815
- std::vector<std::string*> vectorOfStringPointers()
816
- {
817
- std::vector<std::string*> result;
818
- std::string* pString = new std::string("Hello");
819
- result.push_back(pString);
820
- return result;
821
- }
822
- }
823
-
824
- TESTCASE(StringPointerVector)
825
- {
826
- define_global_function("vector_of_string_pointers", &vectorOfStringPointers);
827
-
828
- Module m(rb_mKernel);
829
- Data_Object<std::vector<std::string*>> vec = m.call("vector_of_string_pointers");
830
- ASSERT_EQUAL(1, vec->size());
831
-
832
- std::string expected("Hello");
833
- std::string* actual = (*vec)[0];
834
- ASSERT_EQUAL(expected, *actual);
835
- }
836
-
837
- namespace
838
- {
839
- class MyClass2
840
- {
841
- public:
842
- MyClass2(std::string name): name(name)
843
- {
844
- }
845
- std::string name;
846
- };
847
-
848
- std::vector<MyClass2*> vectorOfMyClass2Pointers()
849
- {
850
- std::vector<MyClass2*> result;
851
- MyClass2* pMyClass = new MyClass2("Hello MyClass2");
852
- result.push_back(pMyClass);
853
- return result;
854
- }
855
- }
856
-
857
- TESTCASE(MyClass2PointerVector)
858
- {
859
- Class c = define_class<MyClass2>("MyClass2").
860
- define_constructor(Constructor<MyClass2, std::string>()).
861
- define_attr("name", &MyClass2::name, AttrAccess::Read);
862
-
863
- define_global_function("vector_of_myclass2_pointers", &vectorOfMyClass2Pointers);
864
-
865
- Module m(rb_mKernel);
866
- Data_Object<std::vector<MyClass2*>> result = m.call("vector_of_myclass2_pointers");
867
- ASSERT_EQUAL(1, result->size());
868
-
869
- MyClass2* pMyClass = (*result)[0];
870
- ASSERT_EQUAL("Hello MyClass2", pMyClass->name);
871
- }
1
+ #include <complex>
2
+
3
+ #include "unittest.hpp"
4
+ #include "embed_ruby.hpp"
5
+ #include <rice/rice.hpp>
6
+ #include <rice/stl.hpp>
7
+
8
+ using namespace Rice;
9
+
10
+ TESTSUITE(Vector);
11
+
12
+ SETUP(Vector)
13
+ {
14
+ embed_ruby();
15
+ }
16
+
17
+ namespace
18
+ {
19
+
20
+ class MyClass
21
+ {
22
+ public:
23
+ std::vector<std::string> stringVector()
24
+ {
25
+ std::vector<std::string> result{ "One", "Two", "Three" };
26
+ return result;
27
+ }
28
+ };
29
+ }
30
+
31
+ Class makeVectorClass()
32
+ {
33
+ Class c = define_class<MyClass>("MyClass").
34
+ define_constructor(Constructor<MyClass>()).
35
+ define_method("stringVector", &MyClass::stringVector);
36
+
37
+ return c;
38
+ }
39
+
40
+ TESTCASE(StringVector)
41
+ {
42
+ Module m = define_module("Testing");
43
+
44
+ Class c = define_vector<std::vector<std::string>>("StringVector");
45
+
46
+ Object vec = m.module_eval("$vector = StringVector.new");
47
+ Object result = vec.call("size");
48
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
49
+
50
+ m.module_eval("$vector << 'one' << 'two' << 'two' << 'three'");
51
+ result = vec.call("size");
52
+ ASSERT_EQUAL(4, detail::From_Ruby<int32_t>().convert(result));
53
+
54
+ m.module_eval("$vector.append('four')");
55
+ result = vec.call("size");
56
+ ASSERT_EQUAL(5, detail::From_Ruby<int32_t>().convert(result));
57
+
58
+ result = vec.call("first");
59
+ ASSERT_EQUAL("one", detail::From_Ruby<std::string>().convert(result));
60
+
61
+ result = vec.call("last");
62
+ ASSERT_EQUAL("four", detail::From_Ruby<std::string>().convert(result));
63
+ }
64
+
65
+ TESTCASE(WrongType)
66
+ {
67
+ Module m = define_module("Testing");
68
+
69
+ Class c = define_vector<std::vector<std::string>>("StringVector");
70
+
71
+ Object vec = m.module_eval("$vector = StringVector.new");
72
+ ASSERT_EXCEPTION_CHECK(
73
+ Exception,
74
+ m.module_eval("$vector << 1"),
75
+ ASSERT_EQUAL("wrong argument type Integer (expected String)", ex.what()));
76
+ }
77
+
78
+ TESTCASE(Empty)
79
+ {
80
+ Module m = define_module("Testing");
81
+
82
+ Class c = define_vector<std::vector<std::int32_t>>("IntVector");
83
+ Object vec = c.call("new");
84
+
85
+ Object result = vec.call("size");
86
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
87
+
88
+ result = vec.call("empty?");
89
+ ASSERT_EQUAL(Qtrue, result.value());
90
+
91
+ result = vec.call("first");
92
+ ASSERT_EQUAL(Qnil, result.value());
93
+
94
+ result = vec.call("last");
95
+ ASSERT_EQUAL(Qnil, result.value());
96
+ }
97
+
98
+ TESTCASE(Indexing)
99
+ {
100
+ Module m = define_module("Testing");
101
+
102
+ Class c = define_vector<std::vector<std::int32_t>>("IntVector");
103
+ Object vec = c.call("new");
104
+ vec.call("push", 0);
105
+ vec.call("push", 1);
106
+ vec.call("push", 2);
107
+
108
+ Object result = vec.call("size");
109
+ ASSERT_EQUAL(3, detail::From_Ruby<int32_t>().convert(result));
110
+
111
+ result = vec.call("[]", 0);
112
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
113
+
114
+ result = vec.call("[]", 1);
115
+ ASSERT_EQUAL(1, detail::From_Ruby<int32_t>().convert(result));
116
+
117
+ result = vec.call("[]", 2);
118
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
119
+
120
+ result = vec.call("[]", 3);
121
+ ASSERT_EQUAL(Qnil, result.value());
122
+
123
+ result = vec.call("[]", -1);
124
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
125
+
126
+ result = vec.call("[]", -2);
127
+ ASSERT_EQUAL(1, detail::From_Ruby<int32_t>().convert(result));
128
+
129
+ result = vec.call("[]", -3);
130
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
131
+
132
+ result = vec.call("[]", -4);
133
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
134
+
135
+ result = vec.call("[]", -7);
136
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
137
+ }
138
+
139
+ TESTCASE(Sizing)
140
+ {
141
+ Module m = define_module("Testing");
142
+
143
+ Class c = define_vector<std::vector<std::int32_t>>("IntVector");
144
+ Object vec = c.call("new");
145
+ vec.call("resize", 10);
146
+
147
+ Object result = vec.call("size");
148
+ ASSERT_EQUAL(10, detail::From_Ruby<int32_t>().convert(result));
149
+
150
+ vec.call("clear");
151
+
152
+ result = vec.call("size");
153
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
154
+ }
155
+
156
+ TESTCASE(ToString)
157
+ {
158
+ Module m = define_module("Testing");
159
+
160
+ Class c = define_vector<std::vector<std::int32_t>>("IntVector");
161
+ Object vec = c.call("new");
162
+ vec.call("resize", 3);
163
+
164
+ Object result = vec.call("to_s");
165
+ ASSERT_EQUAL("[0, 0, 0]", detail::From_Ruby<std::string>().convert(result));
166
+
167
+ vec.call("clear");
168
+
169
+ result = vec.call("to_s");
170
+ ASSERT_EQUAL("[]", detail::From_Ruby<std::string>().convert(result));
171
+ }
172
+
173
+ TESTCASE(Update)
174
+ {
175
+ Module m = define_module("Testing");
176
+
177
+ Class c = define_vector<std::vector<std::string>>("StringVector");
178
+ Object vec = c.call("new");
179
+ vec.call("push", "original 1");
180
+ vec.call("push", "original 2");
181
+
182
+ Object result = vec.call("size");
183
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
184
+
185
+ result = vec.call("[]=", 1, "new 2");
186
+ ASSERT_EQUAL("new 2", detail::From_Ruby<std::string>().convert(result));
187
+
188
+ result = vec.call("[]", 1);
189
+ ASSERT_EQUAL("new 2", detail::From_Ruby<std::string>().convert(result));
190
+
191
+ ASSERT_EXCEPTION_CHECK(
192
+ Exception,
193
+ result = vec.call("[]=", 99999, "new 2"),
194
+ ASSERT_EQUAL("Invalid index: 99999", ex.what()));
195
+ }
196
+
197
+ TESTCASE(Modify)
198
+ {
199
+ Module m = define_module("Testing");
200
+
201
+ Class c = define_vector<std::vector<int64_t>>("Int64Vector");
202
+ Object vec = c.call("new");
203
+
204
+ Object result = vec.call("push", 11);
205
+ ASSERT(result.is_equal(vec));
206
+
207
+ result = vec.call("push", 22);
208
+ ASSERT(result.is_equal(vec));
209
+
210
+ result = vec.call("size");
211
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
212
+
213
+ result = vec.call("insert", 1, 33);
214
+ ASSERT(result.is_equal(vec));
215
+
216
+ result = vec.call("to_s");
217
+ ASSERT_EQUAL("[11, 33, 22]", detail::From_Ruby<std::string>().convert(result));
218
+
219
+ result = vec.call("delete", 11);
220
+ ASSERT_EQUAL(11, detail::From_Ruby<int64_t>().convert(result));
221
+
222
+ result = vec.call("size");
223
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
224
+
225
+ result = vec.call("delete_at", 0);
226
+ ASSERT_EQUAL(33, detail::From_Ruby<int64_t>().convert(result));
227
+
228
+ result = vec.call("size");
229
+ ASSERT_EQUAL(1, detail::From_Ruby<int32_t>().convert(result));
230
+
231
+ result = vec.call("pop");
232
+ ASSERT_EQUAL(22, detail::From_Ruby<int64_t>().convert(result));
233
+
234
+ result = vec.call("size");
235
+ ASSERT_EQUAL(0, detail::From_Ruby<int32_t>().convert(result));
236
+
237
+ result = vec.call("pop");
238
+ ASSERT_EQUAL(Qnil, result.value());
239
+ }
240
+
241
+ TESTCASE(Copy)
242
+ {
243
+ Module m = define_module("Testing");
244
+
245
+ Class c = define_vector<std::vector<double>>("DoubleVector");
246
+ Object object = c.call("new");
247
+
248
+ object.call("push", 11.1);
249
+ object.call("push", 22.2);
250
+ std::vector<double>& vec = detail::From_Ruby<std::vector<double>&>().convert(object);
251
+
252
+ Object result = object.call("copy");
253
+ std::vector<double>& vecCopy = detail::From_Ruby<std::vector<double>&>().convert(result);
254
+
255
+ ASSERT_EQUAL(vec.size(), vecCopy.size());
256
+ ASSERT_EQUAL(vec[0], vecCopy[0]);
257
+ ASSERT_EQUAL(vec[1], vecCopy[1]);
258
+
259
+ vecCopy.push_back(33.3);
260
+ ASSERT_NOT_EQUAL(vec.size(), vecCopy.size());
261
+ }
262
+
263
+ namespace
264
+ {
265
+ class NotComparable
266
+ {
267
+ public:
268
+ NotComparable(uint32_t value) : value_(value)
269
+ {
270
+ };
271
+
272
+ uint32_t value_;
273
+ };
274
+ }
275
+
276
+ TESTCASE(NotComparable)
277
+ {
278
+ define_class<NotComparable>("NotComparable").
279
+ define_constructor(Constructor<NotComparable, uint32_t>());
280
+
281
+ Class c = define_vector<std::vector<NotComparable>>("NotComparableVector");
282
+
283
+ Object vec = c.call("new");
284
+ vec.call("push", NotComparable(1));
285
+ vec.call("push", NotComparable(2));
286
+ vec.call("push", NotComparable(3));
287
+
288
+ Object result = vec.call("delete", NotComparable(1));
289
+ ASSERT_EQUAL(Qnil, result.value());
290
+
291
+ result = vec.call("length");
292
+ ASSERT_EQUAL(3u, detail::From_Ruby<size_t>().convert(result));
293
+
294
+ result = vec.call("include?", NotComparable(2));
295
+ ASSERT_EQUAL(Qfalse, result.value());
296
+
297
+ result = vec.call("index", NotComparable(3));
298
+ ASSERT_EQUAL(Qnil, result.value());
299
+ }
300
+
301
+ TESTCASE(NotDefaultConstructable)
302
+ {
303
+ define_class<NotComparable>("NotComparable").
304
+ define_constructor(Constructor<NotComparable, uint32_t>());
305
+
306
+ Class c = define_vector<std::vector<NotComparable>>("NotComparableVector");
307
+ Object vec = c.call("new");
308
+
309
+ Object result = vec.call("resize", 10);
310
+ ASSERT_EQUAL(Qnil, result.value());
311
+
312
+ result = vec.call("length");
313
+ ASSERT_EQUAL(0, detail::From_Ruby<size_t>().convert(result));
314
+ }
315
+
316
+ TESTCASE(NotPrintable)
317
+ {
318
+ define_class<NotComparable>("NotComparable").
319
+ define_constructor(Constructor<NotComparable, uint32_t>());
320
+
321
+ Class c = define_vector<std::vector<NotComparable>>("NotComparableVector");
322
+
323
+ Object vec = c.call("new");
324
+ vec.call("push", NotComparable(1));
325
+ vec.call("push", NotComparable(2));
326
+ vec.call("push", NotComparable(3));
327
+
328
+ Object result = vec.call("to_s");
329
+ ASSERT_EQUAL("[Not printable]", detail::From_Ruby<std::string>().convert(result));
330
+ }
331
+
332
+ namespace
333
+ {
334
+ class Comparable
335
+ {
336
+ public:
337
+ Comparable(uint32_t value) : value_(value)
338
+ {
339
+ };
340
+
341
+ bool operator==(const Comparable& other)
342
+ {
343
+ return this->value_ == other.value_;
344
+ }
345
+
346
+ uint32_t value_;
347
+ };
348
+
349
+ inline std::ostream& operator<<(std::ostream& stream, Comparable const& comparable)
350
+ {
351
+ stream << "Comparable(" << std::to_string(comparable.value_) << ")";
352
+ return stream;
353
+ }
354
+ }
355
+
356
+ TESTCASE(Comparable)
357
+ {
358
+ define_class<Comparable>("IsComparable").
359
+ define_constructor(Constructor<Comparable, uint32_t>());
360
+
361
+ Class c = define_vector<std::vector<Comparable>>("ComparableVector");
362
+
363
+ Object vec = c.call("new");
364
+
365
+ Comparable comparable1(1);
366
+ vec.call("push", comparable1);
367
+
368
+ Comparable comparable2(2);
369
+ vec.call("push", comparable2);
370
+
371
+ Comparable comparable3(3);
372
+ vec.call("push", comparable3);
373
+
374
+ Object result = vec.call("delete", Comparable(1));
375
+ Comparable comparable = detail::From_Ruby<Comparable>().convert(result);
376
+ ASSERT_EQUAL(1, comparable.value_);
377
+
378
+ result = vec.call("length");
379
+ ASSERT_EQUAL(2, detail::From_Ruby<size_t>().convert(result));
380
+
381
+ result = vec.call("include?", Comparable(2));
382
+ ASSERT_EQUAL(Qtrue, result.value());
383
+
384
+ result = vec.call("index", Comparable(3));
385
+ ASSERT_EQUAL(1, detail::From_Ruby<size_t>().convert(result.value()));
386
+ }
387
+
388
+ TESTCASE(DefaultConstructable)
389
+ {
390
+ define_class<Comparable>("IsComparable").
391
+ define_constructor(Constructor<Comparable, uint32_t>());
392
+
393
+ Class c = define_vector<std::vector<Comparable>>("ComparableVector");
394
+ Object vec = c.call("new");
395
+
396
+ Object result = vec.call("resize", 10);
397
+ ASSERT_EQUAL(Qnil, result.value());
398
+
399
+ result = vec.call("length");
400
+ ASSERT_EQUAL(0, detail::From_Ruby<size_t>().convert(result));
401
+ }
402
+
403
+ TESTCASE(Printable)
404
+ {
405
+ define_class<Comparable>("IsComparable").
406
+ define_constructor(Constructor<Comparable, uint32_t>());
407
+
408
+ Class c = define_vector<std::vector<Comparable>>("ComparableVector");
409
+
410
+ Object vec = c.call("new");
411
+ vec.call("push", Comparable(1));
412
+ vec.call("push", Comparable(2));
413
+ vec.call("push", Comparable(3));
414
+
415
+ Object result = vec.call("to_s");
416
+ ASSERT_EQUAL("[Comparable(1), Comparable(2), Comparable(3)]", detail::From_Ruby<std::string>().convert(result));
417
+ }
418
+
419
+ namespace
420
+ {
421
+ std::vector<std::complex<double>> returnComplexVector()
422
+ {
423
+ std::complex<double> complex1(1, 1);
424
+ std::complex<double> complex2(2, 2);
425
+ std::complex<double> complex3(3, 3);
426
+
427
+ std::vector<std::complex<double>> result;
428
+ result.push_back(complex1);
429
+ result.push_back(complex2);
430
+ result.push_back(complex3);
431
+ return result;
432
+ }
433
+
434
+ std::vector<std::complex<double>> passComplexVector(std::vector<std::complex<double>>& complexes)
435
+ {
436
+ return complexes;
437
+ }
438
+ }
439
+
440
+ TESTCASE(AutoRegisterReturn)
441
+ {
442
+ define_global_function("return_complex_vector", &returnComplexVector);
443
+
444
+ Module m = define_module("Testing");
445
+ Object vec = m.module_eval("return_complex_vector");
446
+ ASSERT_EQUAL("Rice::Std::Vector__complex__double___allocator__complex__double______", vec.class_name().str());
447
+
448
+ std::string code = R"(vector = return_complex_vector
449
+ complex = vector.last
450
+ complex == Complex(3, 3))";
451
+
452
+ Object result = m.module_eval(code);
453
+ ASSERT_EQUAL(Qtrue, result.value());
454
+
455
+ // Now register this same vector
456
+ define_vector<std::vector<std::complex<double>>>("ComplexVector");
457
+ code = R"(vector = ComplexVector.new)";
458
+ result = m.module_eval(code);
459
+ ASSERT(result.is_instance_of(vec.class_of()));
460
+
461
+ // Now register it again in the module
462
+ define_vector_under<std::vector<std::complex<double>>>(m, "ComplexVector2");
463
+ code = R"(vector = Testing::ComplexVector2.new)";
464
+ result = m.module_eval(code);
465
+ ASSERT(result.is_instance_of(vec.class_of()));
466
+ }
467
+
468
+ TESTCASE(AutoRegisterParameter)
469
+ {
470
+ define_global_function("pass_complex_vector", &passComplexVector);
471
+
472
+ std::string code = R"(vector = Rice::Std::Vector__complex__double___allocator__complex__double______.new
473
+ vector << Complex(4.0, 4.0)
474
+ vector << Complex(5.0, 5.0)
475
+ pass_complex_vector(vector))";
476
+
477
+ Module m = define_module("Testing");
478
+ Object vec = m.module_eval(code);
479
+
480
+ Object result = vec.call("size");
481
+ ASSERT_EQUAL("Rice::Std::Vector__complex__double___allocator__complex__double______", vec.class_name().str());
482
+ ASSERT_EQUAL(2, detail::From_Ruby<int32_t>().convert(result));
483
+
484
+ std::vector<std::complex<double>> complexes = detail::From_Ruby<std::vector<std::complex<double>>>().convert(vec);
485
+ ASSERT_EQUAL(complexes[0], std::complex<double>(4, 4));
486
+ ASSERT_EQUAL(complexes[1], std::complex<double>(5, 5));
487
+ }
488
+
489
+ namespace
490
+ {
491
+ std::vector<std::string> defaultVector(std::vector<std::string> strings = {"one", "two", "three"})
492
+ {
493
+ return strings;
494
+ }
495
+ }
496
+
497
+ TESTCASE(DefaultValue)
498
+ {
499
+ define_vector<std::vector<std::string>>("StringVector");
500
+ define_global_function("default_vector", &defaultVector, Arg("strings") = std::vector<std::string> { "one", "two", "three" });
501
+
502
+ Module m = define_module("Testing");
503
+ Object result = m.module_eval("default_vector");
504
+ std::vector<std::string> actual = detail::From_Ruby<std::vector<std::string>>().convert(result);
505
+
506
+ std::vector<std::string> expected{ "one", "two", "three" };
507
+
508
+ ASSERT_EQUAL(expected.size(), actual.size());
509
+ ASSERT_EQUAL(expected[0], actual[0]);
510
+ ASSERT_EQUAL(expected[1], actual[1]);
511
+ ASSERT_EQUAL(expected[2], actual[2]);
512
+ }
513
+
514
+ TESTCASE(ToArray)
515
+ {
516
+ Module m = define_module("Testing");
517
+
518
+ Class c = define_vector<std::vector<std::string>>("StringVector").
519
+ define_constructor(Constructor<std::vector<std::string>>());
520
+
521
+ std::string code = R"(vector = StringVector.new
522
+ vector << "abc"
523
+ vector << "def"
524
+ vector << "ghi"
525
+ vector.to_a)";
526
+
527
+ Array array = m.module_eval(code);
528
+ ASSERT_EQUAL(3u, array.size());
529
+
530
+ ASSERT_EQUAL("abc", detail::From_Ruby<std::string>().convert(array[0].value()));
531
+ ASSERT_EQUAL("def", detail::From_Ruby<std::string>().convert(array[1].value()));
532
+ ASSERT_EQUAL("ghi", detail::From_Ruby<std::string>().convert(array[2].value()));
533
+ }
534
+
535
+ namespace
536
+ {
537
+ std::vector<int> ints;
538
+ std::vector<float> floats;
539
+ std::vector<std::string> strings;
540
+
541
+ void arrayToVector(std::vector<int> aInts, std::vector<float> aFloats, std::vector<std::string> aStrings)
542
+ {
543
+ ints = aInts;
544
+ floats = aFloats;
545
+ strings = aStrings;
546
+ }
547
+
548
+ void arrayToVectorRefs(std::vector<int>& aInts, std::vector<float>& aFloats, std::vector<std::string>& aStrings)
549
+ {
550
+ ints = aInts;
551
+ floats = aFloats;
552
+ strings = aStrings;
553
+ }
554
+
555
+ void arrayToVectorPointers(std::vector<int>* aInts, std::vector<float>* aFloats, std::vector<std::string>* aStrings)
556
+ {
557
+ ints = *aInts;
558
+ floats = *aFloats;
559
+ strings = *aStrings;
560
+ }
561
+ }
562
+
563
+ TESTCASE(ArrayToVector)
564
+ {
565
+ define_global_function("array_to_vector", &arrayToVector);
566
+
567
+ Module m = define_module("Testing");
568
+
569
+ std::string code = "array_to_vector([7, 9, 1_000_000], [49.0, 78.0, 999.0], %w[one two three])";
570
+ m.module_eval(code);
571
+
572
+ ASSERT_EQUAL(3, ints.size());
573
+ ASSERT_EQUAL(7, ints[0]);
574
+ ASSERT_EQUAL(9, ints[1]);
575
+ ASSERT_EQUAL(1'000'000, ints[2]);
576
+
577
+ ASSERT_EQUAL(3, floats.size());
578
+ ASSERT_EQUAL(49.0, floats[0]);
579
+ ASSERT_EQUAL(78.0, floats[1]);
580
+ ASSERT_EQUAL(999.0, floats[2]);
581
+
582
+ ASSERT_EQUAL(3, strings.size());
583
+ ASSERT_EQUAL("one", strings[0]);
584
+ ASSERT_EQUAL("two", strings[1]);
585
+ ASSERT_EQUAL("three", strings[2]);
586
+ }
587
+
588
+ TESTCASE(ArrayToVectorRefs)
589
+ {
590
+ define_global_function("array_to_vector_refs", &arrayToVectorRefs);
591
+
592
+ Module m = define_module("Testing");
593
+
594
+ std::string code = "array_to_vector_refs([8, 10, 1_000_001], [50.0, 79.0, 1_000.0], %w[eleven twelve thirteen])";
595
+ m.module_eval(code);
596
+
597
+ ASSERT_EQUAL(3, ints.size());
598
+ ASSERT_EQUAL(8, ints[0]);
599
+ ASSERT_EQUAL(10, ints[1]);
600
+ ASSERT_EQUAL(1'000'001, ints[2]);
601
+
602
+ ASSERT_EQUAL(3, floats.size());
603
+ ASSERT_EQUAL(50.0, floats[0]);
604
+ ASSERT_EQUAL(79.0, floats[1]);
605
+ ASSERT_EQUAL(1'000.0, floats[2]);
606
+
607
+ ASSERT_EQUAL(3, strings.size());
608
+ ASSERT_EQUAL("eleven", strings[0]);
609
+ ASSERT_EQUAL("twelve", strings[1]);
610
+ ASSERT_EQUAL("thirteen", strings[2]);
611
+ }
612
+
613
+ TESTCASE(ArrayToVectorPointers)
614
+ {
615
+ define_global_function("array_to_vector_pointers", &arrayToVectorPointers);
616
+
617
+ Module m = define_module("Testing");
618
+
619
+ std::string code = "array_to_vector_pointers([9, 11, 1_000_002], [51.0, 80.0, 1_001.0], %w[fourteen fifteen sixteen])";
620
+ m.module_eval(code);
621
+
622
+ ASSERT_EQUAL(3, ints.size());
623
+ ASSERT_EQUAL(9, ints[0]);
624
+ ASSERT_EQUAL(11, ints[1]);
625
+ ASSERT_EQUAL(1'000'002, ints[2]);
626
+
627
+ ASSERT_EQUAL(3, floats.size());
628
+ ASSERT_EQUAL(51.0, floats[0]);
629
+ ASSERT_EQUAL(80.0, floats[1]);
630
+ ASSERT_EQUAL(1'001.0, floats[2]);
631
+
632
+ ASSERT_EQUAL(3, strings.size());
633
+ ASSERT_EQUAL("fourteen", strings[0]);
634
+ ASSERT_EQUAL("fifteen", strings[1]);
635
+ ASSERT_EQUAL("sixteen", strings[2]);
636
+ }
637
+
638
+ TESTCASE(ArrayToVectorWrongTypes)
639
+ {
640
+ define_global_function("array_to_vector", &arrayToVector);
641
+
642
+ Module m = define_module("Testing");
643
+
644
+ std::string code = "array_to_vector([7, 9, 1_000_000], [49.0, 78.0, 999.0], [50.0, 79.0, 1000.0])";
645
+
646
+ ASSERT_EXCEPTION_CHECK(
647
+ Exception,
648
+ m.module_eval(code),
649
+ ASSERT_EQUAL("wrong argument type Float (expected String)", ex.what())
650
+ );
651
+ }
652
+
653
+ TESTCASE(ArrayToVectorMixedTypes)
654
+ {
655
+ define_global_function("array_to_vector", &arrayToVector);
656
+
657
+ Module m = define_module("Testing");
658
+
659
+ std::string code = "array_to_vector([7, 'nine', true], [49.0, 78.0, 999.0], %w[one two three])";
660
+
661
+ ASSERT_EXCEPTION_CHECK(
662
+ Exception,
663
+ m.module_eval(code),
664
+ ASSERT_EQUAL("no implicit conversion of String into Integer", ex.what())
665
+ );
666
+ }
667
+
668
+ namespace
669
+ {
670
+ class Factory
671
+ {
672
+ public:
673
+ std::vector<std::string>* returnPointer()
674
+ {
675
+ return &this->instance_;
676
+ }
677
+
678
+ std::vector<std::string>& returnReference()
679
+ {
680
+ return this->instance_;
681
+ }
682
+
683
+ std::vector<std::string> returnValue()
684
+ {
685
+ return this->instance_;
686
+ }
687
+
688
+ public:
689
+ static inline std::vector<std::string> instance_{ "one", "two", "three" };
690
+ };
691
+
692
+ std::ostream& operator<<(std::ostream& stream, const std::vector<std::string>& vector)
693
+ {
694
+ stream << "Vector";
695
+ return stream;
696
+ }
697
+ }
698
+
699
+ void createFactoryClass()
700
+ {
701
+ define_class<Factory>("Factory").
702
+ define_constructor(Constructor<Factory>()).
703
+ define_method("pointer", &Factory::returnPointer).
704
+ define_method("reference", &Factory::returnReference).
705
+ define_method("value", &Factory::returnValue);
706
+ }
707
+
708
+ TESTCASE(Returns)
709
+ {
710
+ createFactoryClass();
711
+ Module m = define_module("TestingModule");
712
+ Object factory = m.module_eval("Factory.new");
713
+
714
+ std::vector<std::string> expected{ "one", "two", "three" };
715
+
716
+ Data_Object<std::vector<std::string>> vec1 = factory.call("pointer");
717
+ ASSERT_EQUAL(expected, *vec1);
718
+
719
+ Data_Object<std::vector<std::string>> vec2 = factory.call("reference");
720
+ ASSERT_EQUAL(expected, *vec2);
721
+
722
+ Data_Object<std::vector<std::string>> vec3 = factory.call("value");
723
+ ASSERT_EQUAL(expected, *vec3);
724
+ }
725
+
726
+ TESTCASE(Iterate)
727
+ {
728
+ Module m = define_module("Testing");
729
+ Class c = define_vector<std::vector<double>>("DoubleVector");
730
+
731
+ std::string code = R"(vector = DoubleVector.new
732
+ vector << 5.0 << 6.0 << 7.0
733
+ updated = vector.map do |value|
734
+ value * 2.0
735
+ end)";
736
+
737
+ Array result = m.module_eval(code);
738
+ ASSERT_EQUAL(3, result.size());
739
+ ASSERT_EQUAL(10.0, detail::From_Ruby<double>().convert(result[0].value()));
740
+ ASSERT_EQUAL(12.0, detail::From_Ruby<double>().convert(result[1].value()));
741
+ ASSERT_EQUAL(14.0, detail::From_Ruby<double>().convert(result[2].value()));
742
+ }
743
+
744
+ TESTCASE(ToEnumPointer)
745
+ {
746
+ createFactoryClass();
747
+ Module m = define_module("TestingModule");
748
+
749
+ std::string code = R"(factory = Factory.new
750
+ vector = factory.pointer
751
+ updated = vector.each.map do |value|
752
+ value + "_updated"
753
+ end)";
754
+
755
+ Array result = m.module_eval(code);
756
+
757
+ ASSERT_EQUAL(3, result.size());
758
+ ASSERT_EQUAL("one_updated", detail::From_Ruby<std::string>().convert(result[0].value()));
759
+ ASSERT_EQUAL("two_updated", detail::From_Ruby<std::string>().convert(result[1].value()));
760
+ ASSERT_EQUAL("three_updated", detail::From_Ruby<std::string>().convert(result[2].value()));
761
+ }
762
+
763
+ TESTCASE(ToEnumReference)
764
+ {
765
+ createFactoryClass();
766
+ Module m = define_module("TestingModule");
767
+
768
+ std::string code = R"(factory = Factory.new
769
+ vector = factory.reference
770
+ updated = vector.each.map do |value|
771
+ value + "_updated"
772
+ end)";
773
+
774
+ Array result = m.module_eval(code);
775
+
776
+ ASSERT_EQUAL(3, result.size());
777
+ ASSERT_EQUAL("one_updated", detail::From_Ruby<std::string>().convert(result[0].value()));
778
+ ASSERT_EQUAL("two_updated", detail::From_Ruby<std::string>().convert(result[1].value()));
779
+ ASSERT_EQUAL("three_updated", detail::From_Ruby<std::string>().convert(result[2].value()));
780
+ }
781
+
782
+ TESTCASE(ToEnumValue)
783
+ {
784
+ createFactoryClass();
785
+ Module m = define_module("TestingModule");
786
+
787
+ std::string code = R"(factory = Factory.new
788
+ vector = factory.value
789
+ updated = vector.each.map do |value|
790
+ value + "_updated"
791
+ end)";
792
+
793
+ Array result = m.module_eval(code);
794
+
795
+ ASSERT_EQUAL(3, result.size());
796
+ ASSERT_EQUAL("one_updated", detail::From_Ruby<std::string>().convert(result[0].value()));
797
+ ASSERT_EQUAL("two_updated", detail::From_Ruby<std::string>().convert(result[1].value()));
798
+ ASSERT_EQUAL("three_updated", detail::From_Ruby<std::string>().convert(result[2].value()));
799
+ }
800
+
801
+ TESTCASE(ToEnumSize)
802
+ {
803
+ createFactoryClass();
804
+ Module m = define_module("TestingModule");
805
+ Object factory = m.module_eval("Factory.new");
806
+ Object vector = factory.call("pointer");
807
+ Object enumerable = vector.call("each");
808
+ Object result = enumerable.call("size");
809
+
810
+ ASSERT_EQUAL(3, detail::From_Ruby<int>().convert(result));
811
+ }
812
+
813
+ namespace
814
+ {
815
+ std::vector<std::string*> vectorOfStringPointers()
816
+ {
817
+ std::vector<std::string*> result;
818
+ std::string* pString = new std::string("Hello");
819
+ result.push_back(pString);
820
+ return result;
821
+ }
822
+ }
823
+
824
+ TESTCASE(StringPointerVector)
825
+ {
826
+ define_global_function("vector_of_string_pointers", &vectorOfStringPointers);
827
+
828
+ Module m(rb_mKernel);
829
+ Data_Object<std::vector<std::string*>> vec = m.call("vector_of_string_pointers");
830
+ ASSERT_EQUAL(1, vec->size());
831
+
832
+ std::string expected("Hello");
833
+ std::string* actual = (*vec)[0];
834
+ ASSERT_EQUAL(expected, *actual);
835
+ }
836
+
837
+ namespace
838
+ {
839
+ class MyClass2
840
+ {
841
+ public:
842
+ MyClass2(std::string name): name(name)
843
+ {
844
+ }
845
+ std::string name;
846
+ };
847
+
848
+ std::vector<MyClass2*> vectorOfMyClass2Pointers()
849
+ {
850
+ std::vector<MyClass2*> result;
851
+ MyClass2* pMyClass = new MyClass2("Hello MyClass2");
852
+ result.push_back(pMyClass);
853
+ return result;
854
+ }
855
+ }
856
+
857
+ TESTCASE(MyClass2PointerVector)
858
+ {
859
+ Class c = define_class<MyClass2>("MyClass2").
860
+ define_constructor(Constructor<MyClass2, std::string>()).
861
+ define_attr("name", &MyClass2::name, AttrAccess::Read);
862
+
863
+ define_global_function("vector_of_myclass2_pointers", &vectorOfMyClass2Pointers);
864
+
865
+ Module m(rb_mKernel);
866
+ Data_Object<std::vector<MyClass2*>> result = m.call("vector_of_myclass2_pointers");
867
+ ASSERT_EQUAL(1, result->size());
868
+
869
+ MyClass2* pMyClass = (*result)[0];
870
+ ASSERT_EQUAL("Hello MyClass2", pMyClass->name);
871
+ }