rice 4.2.1 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,290 +1,356 @@
1
- #include "unittest.hpp"
2
- #include "embed_ruby.hpp"
3
- #include <rice/rice.hpp>
4
-
5
- using namespace Rice;
6
-
7
- TESTSUITE(Iterator);
8
-
9
- SETUP(Iterator)
10
- {
11
- embed_ruby();
12
- }
13
-
14
- namespace
15
- {
16
- class Container
17
- {
18
- public:
19
- Container(int* array, size_t length)
20
- : array_(array)
21
- , length_(length)
22
- {
23
- }
24
-
25
- // Custom names to make sure we call the function pointers rather than
26
- // expectable default names.
27
- int* beginFoo() { return array_; }
28
- int* endBar() { return array_ + length_; }
29
-
30
- private:
31
- int* array_;
32
- size_t length_;
33
- };
34
- } // namespace
35
-
36
- TESTCASE(define_array_iterator)
37
- {
38
- define_class<Container>("Container")
39
- .define_constructor(Constructor<Container, int*, size_t>())
40
- .define_iterator(&Container::beginFoo, &Container::endBar);
41
-
42
- int array[] = { 1, 2, 3 };
43
- Container* container = new Container(array, 3);
44
-
45
- Object wrapped_container = Data_Object<Container>(container);
46
-
47
- Array a = wrapped_container.instance_eval("a = []; each() { |x| a << x }; a");
48
- ASSERT_EQUAL(3u, a.size());
49
- ASSERT_EQUAL(Object(detail::to_ruby(1)), a[0]);
50
- ASSERT_EQUAL(Object(detail::to_ruby(2)), a[1]);
51
- ASSERT_EQUAL(Object(detail::to_ruby(3)), a[2]);
52
- }
53
-
54
- namespace
55
- {
56
- struct Data
57
- {
58
- Data(uint32_t value)
59
- {
60
- this->index = value;
61
- }
62
-
63
- uint32_t index;
64
- };
65
-
66
- class ContainerValues
67
- {
68
- public:
69
- ContainerValues()
70
- {
71
- this->data_ = { {1}, {2}, {3}};
72
- }
73
-
74
- std::vector<Data>::iterator begin()
75
- {
76
- return this->data_.begin();
77
- }
78
-
79
- std::vector<Data>::iterator end()
80
- {
81
- return this->data_.end();
82
- }
83
-
84
- std::vector<Data>::const_iterator cbegin() const
85
- {
86
- return this->data_.cbegin();
87
- }
88
-
89
- std::vector<Data>::const_iterator cend() const
90
- {
91
- return this->data_.cend();
92
- }
93
-
94
- std::vector<Data> data_;
95
- };
96
-
97
- class ContainerPointers
98
- {
99
- public:
100
- ContainerPointers()
101
- {
102
- this->data_ = { new Data{1}, new Data{2}, new Data{3} };
103
- }
104
-
105
- ~ContainerPointers()
106
- {
107
- for (Data* data : this->data_)
108
- {
109
- delete data;
110
- }
111
- }
112
-
113
- std::vector<Data*>::iterator begin()
114
- {
115
- return this->data_.begin();
116
- }
117
-
118
- std::vector<Data*>::iterator end()
119
- {
120
- return this->data_.end();
121
- }
122
-
123
- std::vector<Data*>::reverse_iterator rbegin()
124
- {
125
- return this->data_.rbegin();
126
- }
127
-
128
- std::vector<Data*>::reverse_iterator rend()
129
- {
130
- return this->data_.rend();
131
- }
132
-
133
- std::vector<Data*> data_;
134
- };
135
- }
136
-
137
- template <>
138
- struct detail::To_Ruby<Data>
139
- {
140
- static VALUE convert(const Data& data)
141
- {
142
- return detail::to_ruby(data.index);
143
- }
144
- };
145
-
146
- template <>
147
- struct detail::To_Ruby<Data*>
148
- {
149
- static VALUE convert(const Data* data)
150
- {
151
- return detail::to_ruby(data->index);
152
- }
153
- };
154
-
155
- TESTCASE(iterator_value)
156
- {
157
- define_class<ContainerValues>("ContainerValues")
158
- .define_constructor(Constructor<ContainerValues>())
159
- .define_iterator(&ContainerValues::begin, &ContainerValues::end);
160
-
161
- ContainerValues* container = new ContainerValues();
162
- Object wrapper = Data_Object<ContainerValues>(container);
163
-
164
- Array a = wrapper.instance_eval("a = []; each() { |x| a << x }; a");
165
- ASSERT_EQUAL(3u, a.size());
166
-
167
- ASSERT_EQUAL(Object(detail::to_ruby(1)), a[0]);
168
- ASSERT_EQUAL(Object(detail::to_ruby(2)), a[1]);
169
- ASSERT_EQUAL(Object(detail::to_ruby(3)), a[2]);
170
- }
171
-
172
- TESTCASE(const_iterator_value)
173
- {
174
- define_class<ContainerValues>("ContainerValues")
175
- .define_constructor(Constructor<ContainerValues>())
176
- .define_iterator(&ContainerValues::cbegin, &ContainerValues::cend);
177
-
178
- Module m = define_module("TestingModule");
179
-
180
- std::string code = R"(result = []
181
- container = ContainerValues.new
182
- container.each do |x|
183
- result << x
184
- end
185
- result)";
186
-
187
- Array result = m.module_eval(code);
188
-
189
- ASSERT_EQUAL(3u, result.size());
190
- ASSERT_EQUAL(Object(detail::to_ruby(1)), result[0]);
191
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[1]);
192
- ASSERT_EQUAL(Object(detail::to_ruby(3)), result[2]);
193
- }
194
-
195
- TESTCASE(iterator_pointer)
196
- {
197
- define_class<ContainerPointers>("ContainerPointers")
198
- .define_constructor(Constructor<ContainerPointers>())
199
- .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
200
-
201
- ContainerPointers* container = new ContainerPointers();
202
- Object wrapper = Data_Object<ContainerPointers>(container);
203
-
204
- Module m = define_module("TestingModule");
205
-
206
- std::string code = R"(result = []
207
- container = ContainerPointers.new
208
- container.each do |x|
209
- result << x
210
- end
211
- result)";
212
-
213
- Array result = m.module_eval(code);
214
-
215
- ASSERT_EQUAL(3u, result.size());
216
- ASSERT_EQUAL(Object(detail::to_ruby(1)), result[0]);
217
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[1]);
218
- ASSERT_EQUAL(Object(detail::to_ruby(3)), result[2]);
219
- }
220
-
221
- TESTCASE(two_iterator_pointer)
222
- {
223
- define_class<ContainerPointers>("ContainerPointers")
224
- .define_constructor(Constructor<ContainerPointers>())
225
- .define_iterator(&ContainerPointers::begin, &ContainerPointers::end)
226
- .define_iterator(&ContainerPointers::rbegin, &ContainerPointers::rend, "reach");
227
-
228
- ContainerPointers* container = new ContainerPointers();
229
- Object wrapper = Data_Object<ContainerPointers>(container);
230
-
231
- Module m = define_module("TestingModule");
232
-
233
- std::string code = R"(result = []
234
- container = ContainerPointers.new
235
- container.each do |x|
236
- result << x
237
- end
238
- container.reach do |x|
239
- result << x
240
- end
241
- result)";
242
-
243
- Array result = m.module_eval(code);
244
-
245
- ASSERT_EQUAL(6u, result.size());
246
- ASSERT_EQUAL(Object(detail::to_ruby(1)), result[0]);
247
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[1]);
248
- ASSERT_EQUAL(Object(detail::to_ruby(3)), result[2]);
249
- ASSERT_EQUAL(Object(detail::to_ruby(3)), result[3]);
250
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[4]);
251
- ASSERT_EQUAL(Object(detail::to_ruby(1)), result[5]);
252
- }
253
-
254
- TESTCASE(map)
255
- {
256
- define_class<ContainerPointers>("ContainerPointers")
257
- .define_constructor(Constructor<ContainerPointers>())
258
- .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
259
-
260
- Module m = define_module("Testing");
261
-
262
- std::string code = R"(container = ContainerPointers.new
263
- container.map do |x|
264
- x * 2
265
- end)";
266
-
267
- Array result = m.module_eval(code);
268
-
269
- ASSERT_EQUAL(3u, result.size());
270
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[0]);
271
- ASSERT_EQUAL(Object(detail::to_ruby(4)), result[1]);
272
- ASSERT_EQUAL(Object(detail::to_ruby(6)), result[2]);
273
- }
274
-
275
- TESTCASE(to_enum)
276
- {
277
- Module m = define_module("TestingModule");
278
-
279
- std::string code = R"(container = ContainerPointers.new
280
- container.each.map do |x|
281
- x * 2
282
- end)";
283
-
284
- Array result = m.module_eval(code);
285
-
286
- ASSERT_EQUAL(3u, result.size());
287
- ASSERT_EQUAL(Object(detail::to_ruby(2)), result[0]);
288
- ASSERT_EQUAL(Object(detail::to_ruby(4)), result[1]);
289
- ASSERT_EQUAL(Object(detail::to_ruby(6)), result[2]);
290
- }
1
+ #include "unittest.hpp"
2
+ #include "embed_ruby.hpp"
3
+ #include <rice/rice.hpp>
4
+
5
+ using namespace Rice;
6
+
7
+ TESTSUITE(Iterator);
8
+
9
+ SETUP(Iterator)
10
+ {
11
+ embed_ruby();
12
+ }
13
+
14
+ namespace
15
+ {
16
+ class Container
17
+ {
18
+ public:
19
+ Container(int* array, size_t length)
20
+ : array_(array)
21
+ , length_(length)
22
+ {
23
+ }
24
+
25
+ // Custom names to make sure we call the function pointers rather than
26
+ // expectable default names.
27
+ int* beginFoo() { return array_; }
28
+ int* endBar() { return array_ + length_; }
29
+
30
+ private:
31
+ int* array_;
32
+ size_t length_;
33
+ };
34
+ } // namespace
35
+
36
+ TESTCASE(define_array_iterator)
37
+ {
38
+ define_class<Container>("Container")
39
+ .define_constructor(Constructor<Container, int*, size_t>())
40
+ .define_iterator(&Container::beginFoo, &Container::endBar);
41
+
42
+ int array[] = { 1, 2, 3 };
43
+ Container* container = new Container(array, 3);
44
+
45
+ Object wrapped_container = Data_Object<Container>(container);
46
+
47
+ Array a = wrapped_container.instance_eval("a = []; each() { |x| a << x }; a");
48
+ ASSERT_EQUAL(3u, a.size());
49
+ ASSERT_EQUAL(Object(detail::to_ruby(1)), a[0]);
50
+ ASSERT_EQUAL(Object(detail::to_ruby(2)), a[1]);
51
+ ASSERT_EQUAL(Object(detail::to_ruby(3)), a[2]);
52
+ }
53
+
54
+ namespace
55
+ {
56
+ struct Data
57
+ {
58
+ Data(uint32_t value)
59
+ {
60
+ this->index = value;
61
+ }
62
+
63
+ uint32_t index;
64
+ };
65
+
66
+ class ContainerValues
67
+ {
68
+ public:
69
+ ContainerValues()
70
+ {
71
+ this->data_ = { {1}, {2}, {3} };
72
+ }
73
+
74
+ std::vector<Data>::iterator begin()
75
+ {
76
+ return this->data_.begin();
77
+ }
78
+
79
+ std::vector<Data>::iterator end()
80
+ {
81
+ return this->data_.end();
82
+ }
83
+
84
+ std::vector<Data>::const_iterator cbegin() const
85
+ {
86
+ return this->data_.cbegin();
87
+ }
88
+
89
+ std::vector<Data>::const_iterator cend() const
90
+ {
91
+ return this->data_.cend();
92
+ }
93
+
94
+ std::vector<Data> data_;
95
+ };
96
+
97
+ class ContainerPointers
98
+ {
99
+ public:
100
+ ContainerPointers()
101
+ {
102
+ this->data_ = { new Data{1}, new Data{2}, new Data{3} };
103
+ }
104
+
105
+ ~ContainerPointers()
106
+ {
107
+ for (Data* data : this->data_)
108
+ {
109
+ delete data;
110
+ }
111
+ }
112
+
113
+ std::vector<Data*>::iterator begin()
114
+ {
115
+ return this->data_.begin();
116
+ }
117
+
118
+ std::vector<Data*>::iterator end()
119
+ {
120
+ return this->data_.end();
121
+ }
122
+
123
+ std::vector<Data*>::reverse_iterator rbegin()
124
+ {
125
+ return this->data_.rbegin();
126
+ }
127
+
128
+ std::vector<Data*>::reverse_iterator rend()
129
+ {
130
+ return this->data_.rend();
131
+ }
132
+
133
+ std::vector<Data*> data_;
134
+ };
135
+ }
136
+
137
+ TESTCASE(iterator_value)
138
+ {
139
+ define_class<Data>("Data")
140
+ .define_constructor(Constructor<Data, uint32_t>());
141
+
142
+ define_class<ContainerValues>("ContainerValues")
143
+ .define_constructor(Constructor<ContainerValues>())
144
+ .define_iterator(&ContainerValues::begin, &ContainerValues::end);
145
+
146
+ ContainerValues* container = new ContainerValues();
147
+ Data_Object<ContainerValues> wrapper(container);
148
+
149
+ Array a = wrapper.instance_eval("each.to_a");
150
+ ASSERT_EQUAL(3u, a.size());
151
+
152
+ Data_Object<Data> wrappedData(a[0]);
153
+ ASSERT_EQUAL(1, wrappedData->index);
154
+
155
+ wrappedData = (Data_Object<Data>)a[1];
156
+ ASSERT_EQUAL(2, wrappedData->index);
157
+
158
+ wrappedData = (Data_Object<Data>)a[2];
159
+ ASSERT_EQUAL(3, wrappedData->index);
160
+ }
161
+
162
+ TESTCASE(const_iterator_value)
163
+ {
164
+ define_class<Data>("Data")
165
+ .define_constructor(Constructor<Data, uint32_t>());
166
+
167
+ define_class<ContainerValues>("ContainerValues")
168
+ .define_constructor(Constructor<ContainerValues>())
169
+ .define_iterator(&ContainerValues::cbegin, &ContainerValues::cend);
170
+
171
+ Module m = define_module("TestingModule");
172
+
173
+ std::string code = R"(result = []
174
+ container = ContainerValues.new
175
+ container.each do |x|
176
+ result << x
177
+ end
178
+ result)";
179
+
180
+ Array a = m.module_eval(code);
181
+
182
+ Data_Object<Data> wrappedData(a[0]);
183
+ ASSERT_EQUAL(1, wrappedData->index);
184
+
185
+ wrappedData = (Data_Object<Data>)a[1];
186
+ ASSERT_EQUAL(2, wrappedData->index);
187
+
188
+ wrappedData = (Data_Object<Data>)a[2];
189
+ ASSERT_EQUAL(3, wrappedData->index);
190
+ }
191
+
192
+ TESTCASE(iterator_pointer)
193
+ {
194
+ define_class<Data>("Data")
195
+ .define_constructor(Constructor<Data, uint32_t>());
196
+
197
+ define_class<ContainerPointers>("ContainerPointers")
198
+ .define_constructor(Constructor<ContainerPointers>())
199
+ .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
200
+
201
+ ContainerPointers* container = new ContainerPointers();
202
+ Object wrapper = Data_Object<ContainerPointers>(container);
203
+
204
+ Module m = define_module("TestingModule");
205
+
206
+ std::string code = R"(result = []
207
+ container = ContainerPointers.new
208
+ container.each do |x|
209
+ result << x
210
+ end
211
+ result)";
212
+
213
+ Array a = m.module_eval(code);
214
+
215
+ Data_Object<Data> wrappedData(a[0]);
216
+ ASSERT_EQUAL(1, wrappedData->index);
217
+
218
+ wrappedData = (Data_Object<Data>)a[1];
219
+ ASSERT_EQUAL(2, wrappedData->index);
220
+
221
+ wrappedData = (Data_Object<Data>)a[2];
222
+ ASSERT_EQUAL(3, wrappedData->index);
223
+ }
224
+
225
+ TESTCASE(two_iterator_pointer)
226
+ {
227
+ define_class<Data>("Data")
228
+ .define_constructor(Constructor<Data, uint32_t>());
229
+
230
+ define_class<ContainerPointers>("ContainerPointers")
231
+ .define_constructor(Constructor<ContainerPointers>())
232
+ .define_iterator(&ContainerPointers::begin, &ContainerPointers::end)
233
+ .define_iterator(&ContainerPointers::rbegin, &ContainerPointers::rend, "reach");
234
+
235
+ ContainerPointers* container = new ContainerPointers();
236
+ Object wrapper = Data_Object<ContainerPointers>(container);
237
+
238
+ Module m = define_module("TestingModule");
239
+
240
+ std::string code = R"(result = []
241
+ container = ContainerPointers.new
242
+ container.each do |x|
243
+ result << x
244
+ end
245
+ container.reach do |x|
246
+ result << x
247
+ end
248
+ result)";
249
+
250
+ Array a = m.module_eval(code);
251
+
252
+ ASSERT_EQUAL(6u, a.size());
253
+
254
+ Data_Object<Data> wrappedData(a[0]);
255
+ ASSERT_EQUAL(1, wrappedData->index);
256
+
257
+ wrappedData = (Data_Object<Data>)a[1];
258
+ ASSERT_EQUAL(2, wrappedData->index);
259
+
260
+ wrappedData = (Data_Object<Data>)a[2];
261
+ ASSERT_EQUAL(3, wrappedData->index);
262
+
263
+ wrappedData = (Data_Object<Data>)a[3];
264
+ ASSERT_EQUAL(3, wrappedData->index);
265
+
266
+ wrappedData = (Data_Object<Data>)a[4];
267
+ ASSERT_EQUAL(2, wrappedData->index);
268
+
269
+ wrappedData = (Data_Object<Data>)a[5];
270
+ ASSERT_EQUAL(1, wrappedData->index);
271
+ }
272
+
273
+ TESTCASE(map)
274
+ {
275
+ define_class<Data>("Data")
276
+ .define_constructor(Constructor<Data, uint32_t>())
277
+ .define_attr("index", &Data::index, Rice::AttrAccess::Read);
278
+
279
+ define_class<ContainerPointers>("ContainerPointers")
280
+ .define_constructor(Constructor<ContainerPointers>())
281
+ .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
282
+
283
+ Module m = define_module("Testing");
284
+
285
+ std::string code = R"(container = ContainerPointers.new
286
+ container.map do |data|
287
+ data.index * 2
288
+ end)";
289
+
290
+ Array a = m.module_eval(code);
291
+ ASSERT_EQUAL(3u, a.size());
292
+
293
+ Object element = a[0];
294
+ ASSERT_EQUAL(2, detail::From_Ruby<int>().convert(element));
295
+
296
+ element = a[1];
297
+ ASSERT_EQUAL(4, detail::From_Ruby<int>().convert(element));
298
+
299
+ element = a[2];
300
+ ASSERT_EQUAL(6, detail::From_Ruby<int>().convert(element));
301
+ }
302
+
303
+ TESTCASE(to_enum)
304
+ {
305
+ define_class<Data>("Data")
306
+ .define_constructor(Constructor<Data, uint32_t>());
307
+
308
+ define_class<ContainerPointers>("ContainerPointers")
309
+ .define_constructor(Constructor<ContainerPointers>())
310
+ .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
311
+
312
+ Module m = define_module("TestingModule");
313
+
314
+ std::string code = R"(container = ContainerPointers.new
315
+ container.each.map do |data|
316
+ data.index * 2
317
+ end)";
318
+
319
+ Array a = m.module_eval(code);
320
+
321
+ ASSERT_EQUAL(3u, a.size());
322
+
323
+ Object element = a[0];
324
+ ASSERT_EQUAL(2, detail::From_Ruby<int>().convert(element));
325
+
326
+ element = a[1];
327
+ ASSERT_EQUAL(4, detail::From_Ruby<int>().convert(element));
328
+
329
+ element = a[2];
330
+ ASSERT_EQUAL(6, detail::From_Ruby<int>().convert(element));
331
+ }
332
+
333
+ TESTCASE(IterateNoCopy)
334
+ {
335
+ define_class<Data>("Data")
336
+ .define_constructor(Constructor<Data, uint32_t>());
337
+
338
+ define_class<ContainerPointers>("ContainerValues")
339
+ .define_constructor(Constructor<ContainerValues>())
340
+ .define_iterator(&ContainerPointers::begin, &ContainerPointers::end);
341
+
342
+ Module m = define_module("Testing");
343
+
344
+ ContainerValues container;
345
+ Data_Object<ContainerValues> wrapper(container);
346
+ Array a = wrapper.instance_eval("self.to_a");
347
+
348
+ ASSERT_EQUAL(container.data_.size(), a.size());
349
+
350
+ for (int i = 0; i < container.data_.size(); i++)
351
+ {
352
+ Data& expected = container.data_[i];
353
+ Data_Object<Data> actual(a[i]);
354
+ ASSERT_EQUAL(&expected, &(*actual));
355
+ }
356
+ }