rice 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Doxyfile +1 -1
- data/Makefile.in +3 -2
- data/README +247 -16
- data/aclocal.m4 +62 -51
- data/configure +1585 -1456
- data/extconf.rb +9 -1
- data/rice/Arg.hpp +8 -0
- data/rice/Arg_impl.hpp +124 -0
- data/rice/Arg_operators.cpp +21 -0
- data/rice/Arg_operators.hpp +19 -0
- data/rice/Constructor.hpp +150 -0
- data/rice/Data_Type.ipp +51 -6
- data/rice/Director.cpp +19 -0
- data/rice/Director.hpp +47 -0
- data/rice/Enum.hpp +2 -3
- data/rice/Enum.ipp +1 -1
- data/rice/Hash.hpp +1 -1
- data/rice/Makefile.am +7 -0
- data/rice/Makefile.in +18 -7
- data/rice/Module_impl.hpp +36 -3
- data/rice/Module_impl.ipp +56 -7
- data/rice/VM.cpp +2 -2
- data/rice/config.hpp +1 -1
- data/rice/detail/Arguments.hpp +118 -0
- data/rice/detail/Auto_Function_Wrapper.hpp +206 -96
- data/rice/detail/Auto_Function_Wrapper.ipp +1687 -144
- data/rice/detail/Auto_Member_Function_Wrapper.hpp +234 -123
- data/rice/detail/Auto_Member_Function_Wrapper.ipp +1133 -306
- data/rice/detail/Caster.hpp +3 -1
- data/rice/detail/creation_funcs.hpp +0 -8
- data/rice/detail/creation_funcs.ipp +1 -27
- data/rice/detail/define_method_and_auto_wrap.hpp +3 -1
- data/rice/detail/define_method_and_auto_wrap.ipp +4 -3
- data/rice/detail/object_call.ipp +1 -1
- data/rice/detail/ruby.hpp +1 -33
- data/rice/detail/wrap_function.hpp +103 -48
- data/rice/detail/wrap_function.ipp +154 -96
- data/rice/generate_code.rb +520 -55
- data/rice/global_function.hpp +12 -1
- data/rice/global_function.ipp +14 -2
- data/ruby/Makefile.in +5 -4
- data/ruby/lib/Makefile.in +4 -3
- data/ruby/lib/version.rb +1 -1
- data/sample/Makefile.in +4 -3
- data/test/Makefile.am +2 -0
- data/test/Makefile.in +32 -13
- data/test/test_Class.cpp +36 -14
- data/test/test_Constructor.cpp +176 -1
- data/test/test_Data_Type.cpp +121 -0
- data/test/test_Director.cpp +225 -0
- data/test/test_Enum.cpp +33 -0
- data/test/test_Module.cpp +175 -0
- data/test/test_global_functions.cpp +70 -1
- metadata +27 -7
@@ -0,0 +1,121 @@
|
|
1
|
+
#include "unittest.hpp"
|
2
|
+
#include "rice/Data_Type.hpp"
|
3
|
+
#include "rice/Exception.hpp"
|
4
|
+
#include "rice/Constructor.hpp"
|
5
|
+
|
6
|
+
using namespace Rice;
|
7
|
+
|
8
|
+
TESTSUITE(Data_Type);
|
9
|
+
|
10
|
+
/**
|
11
|
+
* The tests here are for the feature of taking an instance
|
12
|
+
* of a Ruby-subclass of a Rice wrapped class and passing
|
13
|
+
* that instance back into the Rice wrapper. While that
|
14
|
+
* might be confusing, the test code is pretty straight foward
|
15
|
+
* to see what we're talking about.
|
16
|
+
*/
|
17
|
+
|
18
|
+
namespace {
|
19
|
+
|
20
|
+
/**
|
21
|
+
* The class we will subclass in Ruby
|
22
|
+
*/
|
23
|
+
class Listener {
|
24
|
+
public:
|
25
|
+
Listener() { }
|
26
|
+
|
27
|
+
virtual ~Listener() { }
|
28
|
+
|
29
|
+
virtual int getValue() { return 4; }
|
30
|
+
};
|
31
|
+
|
32
|
+
/**
|
33
|
+
* This class will recieve a new Listener instance
|
34
|
+
* from Ruby
|
35
|
+
*/
|
36
|
+
class ListenerHandler {
|
37
|
+
|
38
|
+
public:
|
39
|
+
|
40
|
+
ListenerHandler() { }
|
41
|
+
|
42
|
+
void addListener(Listener* newList) {
|
43
|
+
mListeners.push_back(newList);
|
44
|
+
}
|
45
|
+
|
46
|
+
int process() {
|
47
|
+
vector<Listener*>::iterator i = mListeners.begin();
|
48
|
+
int accum = 0;
|
49
|
+
for(; i != mListeners.end(); i++) {
|
50
|
+
accum += (*i)->getValue();
|
51
|
+
}
|
52
|
+
|
53
|
+
return accum;
|
54
|
+
}
|
55
|
+
|
56
|
+
int listenerCount() { return mListeners.size(); }
|
57
|
+
|
58
|
+
private:
|
59
|
+
vector<Listener*> mListeners;
|
60
|
+
};
|
61
|
+
}
|
62
|
+
|
63
|
+
SETUP(Data_Type)
|
64
|
+
{
|
65
|
+
ruby_init();
|
66
|
+
|
67
|
+
define_class<Listener>("Listener")
|
68
|
+
.define_constructor(Constructor<Listener>())
|
69
|
+
.define_method("get_value", &Listener::getValue);
|
70
|
+
|
71
|
+
define_class<ListenerHandler>("ListenerHandler")
|
72
|
+
.define_constructor(Constructor<ListenerHandler>())
|
73
|
+
.define_method("add_listener", &ListenerHandler::addListener)
|
74
|
+
.define_method("process", &ListenerHandler::process)
|
75
|
+
.define_method("listener_count", &ListenerHandler::listenerCount);
|
76
|
+
|
77
|
+
}
|
78
|
+
|
79
|
+
TESTCASE(can_send_ruby_instance_back_into_rice)
|
80
|
+
{
|
81
|
+
Module m = define_module("TestingModule");
|
82
|
+
Object handler = m.instance_eval("@handler = ListenerHandler.new");
|
83
|
+
|
84
|
+
ASSERT_EQUAL(INT2NUM(0), handler.call("listener_count").value());
|
85
|
+
|
86
|
+
m.instance_eval("class MyListener < Listener; end;");
|
87
|
+
m.instance_eval("@handler.add_listener(MyListener.new)");
|
88
|
+
|
89
|
+
ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
|
90
|
+
ASSERT_EQUAL(INT2NUM(4), handler.call("process").value());
|
91
|
+
|
92
|
+
m.instance_eval("@handler.add_listener(Listener.new)");
|
93
|
+
|
94
|
+
ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
|
95
|
+
ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
|
96
|
+
}
|
97
|
+
|
98
|
+
/**
|
99
|
+
* The following test SEGFAULTs right now
|
100
|
+
*/
|
101
|
+
/*
|
102
|
+
TESTCASE(no_super_in_constructor_still_works)
|
103
|
+
{
|
104
|
+
Module m = define_module("TestingModule");
|
105
|
+
Object handler = m.instance_eval("@handler = ListenerHandler.new");
|
106
|
+
|
107
|
+
ASSERT_EQUAL(INT2NUM(0), handler.call("listener_count").value());
|
108
|
+
|
109
|
+
// Because of this, there's a constructor but no super call
|
110
|
+
m.instance_eval("class MyListener < Listener; def initialize; @val = 10; end; end;");
|
111
|
+
m.instance_eval("@handler.add_listener(MyListener.new)");
|
112
|
+
|
113
|
+
ASSERT_EQUAL(INT2NUM(1), handler.call("listener_count").value());
|
114
|
+
ASSERT_EQUAL(INT2NUM(4), handler.call("process").value());
|
115
|
+
|
116
|
+
m.instance_eval("@handler.add_listener(MyListener.new)");
|
117
|
+
|
118
|
+
ASSERT_EQUAL(INT2NUM(2), handler.call("listener_count").value());
|
119
|
+
ASSERT_EQUAL(INT2NUM(8), handler.call("process").value());
|
120
|
+
}
|
121
|
+
*/
|
@@ -0,0 +1,225 @@
|
|
1
|
+
#include "unittest.hpp"
|
2
|
+
#include "rice/Director.hpp"
|
3
|
+
#include "rice/Constructor.hpp"
|
4
|
+
#include "rice/Data_Type.hpp"
|
5
|
+
|
6
|
+
#include <vector>
|
7
|
+
#include <iostream>
|
8
|
+
|
9
|
+
using namespace std;
|
10
|
+
using namespace Rice;
|
11
|
+
|
12
|
+
TESTSUITE(Director);
|
13
|
+
|
14
|
+
namespace {
|
15
|
+
/**
|
16
|
+
* Abstract base class
|
17
|
+
*/
|
18
|
+
class Worker {
|
19
|
+
public:
|
20
|
+
virtual ~Worker() { }
|
21
|
+
|
22
|
+
int getNumber() { return 12; }
|
23
|
+
|
24
|
+
virtual int doSomething(int num) { return num * 4; }
|
25
|
+
|
26
|
+
virtual int process(int num) = 0;
|
27
|
+
};
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Subclass that implements pure virtual
|
31
|
+
*/
|
32
|
+
class MultiplyWorker : public Worker {
|
33
|
+
public:
|
34
|
+
virtual ~MultiplyWorker() { }
|
35
|
+
|
36
|
+
virtual int process(int num) { return num * 2; }
|
37
|
+
};
|
38
|
+
|
39
|
+
/**
|
40
|
+
* Class to handle workers
|
41
|
+
*/
|
42
|
+
class Handler {
|
43
|
+
std::vector<Worker*> mWorkers;
|
44
|
+
|
45
|
+
public:
|
46
|
+
|
47
|
+
void addWorker(Worker* worker) { mWorkers.push_back(worker); }
|
48
|
+
|
49
|
+
int processWorkers(int start) {
|
50
|
+
std::vector<Worker*>::iterator i = mWorkers.begin();
|
51
|
+
int results = start;
|
52
|
+
|
53
|
+
for(; i != mWorkers.end(); i++) {
|
54
|
+
results = (*i)->process(results);
|
55
|
+
}
|
56
|
+
|
57
|
+
return results;
|
58
|
+
}
|
59
|
+
};
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Our Director wrapper of Worker
|
63
|
+
*/
|
64
|
+
class WorkerDirector : public Worker, public Rice::Director {
|
65
|
+
public:
|
66
|
+
WorkerDirector(Object self) : Director(self) { }
|
67
|
+
|
68
|
+
int process(int num) {
|
69
|
+
if(callIsFromRuby("process")) {
|
70
|
+
raisePureVirtual();
|
71
|
+
} else {
|
72
|
+
return from_ruby<int>( getSelf().call("process", num) );
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
int doSomething(int num) {
|
77
|
+
if(callIsFromRuby("do_something")) {
|
78
|
+
return this->Worker::doSomething(num);
|
79
|
+
} else {
|
80
|
+
return from_ruby<int>( getSelf().call("do_something", num) );
|
81
|
+
}
|
82
|
+
}
|
83
|
+
};
|
84
|
+
};
|
85
|
+
|
86
|
+
SETUP(Director)
|
87
|
+
{
|
88
|
+
ruby_init();
|
89
|
+
|
90
|
+
// Always need to tell Rice about the base class so that
|
91
|
+
// casting works correctly
|
92
|
+
define_class<Worker>("__Worker__");
|
93
|
+
}
|
94
|
+
|
95
|
+
TESTCASE(exposes_worker_as_instantiatable_class)
|
96
|
+
{
|
97
|
+
define_class<WorkerDirector, Worker>("Worker")
|
98
|
+
.define_constructor(Constructor<WorkerDirector, Object>())
|
99
|
+
.define_method("get_number", &Worker::getNumber);
|
100
|
+
|
101
|
+
Module m = define_module("Testing");
|
102
|
+
Object result = m.instance_eval("worker = Worker.new; worker.get_number");
|
103
|
+
|
104
|
+
ASSERT_EQUAL(12, from_ruby<int>(result.value()));
|
105
|
+
}
|
106
|
+
|
107
|
+
TESTCASE(can_call_virtual_methods_on_base_class)
|
108
|
+
{
|
109
|
+
define_class<WorkerDirector, Worker>("Worker")
|
110
|
+
.define_constructor(Constructor<WorkerDirector, Object>())
|
111
|
+
.define_method("get_number", &Worker::getNumber)
|
112
|
+
.define_method("do_something", &WorkerDirector::doSomething);
|
113
|
+
|
114
|
+
Module m = define_module("Testing");
|
115
|
+
|
116
|
+
Object result = m.instance_eval("worker = Worker.new; worker.do_something(4)");
|
117
|
+
|
118
|
+
ASSERT_EQUAL(16, from_ruby<int>(result.value()));
|
119
|
+
}
|
120
|
+
|
121
|
+
TESTCASE(super_calls_pass_execution_up_the_inheritance_chain)
|
122
|
+
{
|
123
|
+
define_class<WorkerDirector, Worker>("Worker")
|
124
|
+
.define_constructor(Constructor<WorkerDirector, Object>())
|
125
|
+
.define_method("do_something", &WorkerDirector::doSomething);
|
126
|
+
|
127
|
+
Module m = define_module("Testing");
|
128
|
+
m.instance_eval("class RubyWorker < Worker; def do_something(num); super * num; end; end");
|
129
|
+
|
130
|
+
Object result = m.instance_eval("worker = RubyWorker.new; worker.do_something(10)");
|
131
|
+
|
132
|
+
ASSERT_EQUAL(400, from_ruby<int>(result.value()));
|
133
|
+
}
|
134
|
+
|
135
|
+
TESTCASE(super_calls_on_pure_virtual_raise_error)
|
136
|
+
{
|
137
|
+
define_class<WorkerDirector, Worker>("Worker")
|
138
|
+
.define_constructor(Constructor<WorkerDirector, Object>())
|
139
|
+
.define_method("process", &WorkerDirector::process);
|
140
|
+
|
141
|
+
Module m = define_module("Testing");
|
142
|
+
m.instance_eval("class RubyWorker < Worker; def process(num); super; end; end");
|
143
|
+
|
144
|
+
ASSERT_EXCEPTION_CHECK(
|
145
|
+
Exception,
|
146
|
+
m.instance_eval("worker = RubyWorker.new; worker.process(10)"),
|
147
|
+
ASSERT_EQUAL(
|
148
|
+
Object(rb_eNotImpError),
|
149
|
+
Object(CLASS_OF(ex.value()))
|
150
|
+
)
|
151
|
+
);
|
152
|
+
}
|
153
|
+
|
154
|
+
TESTCASE(polymorphic_calls_head_down_the_call_chain)
|
155
|
+
{
|
156
|
+
define_class<Handler>("Handler")
|
157
|
+
.define_constructor(Constructor<Handler>())
|
158
|
+
.define_method("add_worker", &Handler::addWorker)
|
159
|
+
.define_method("process_workers", &Handler::processWorkers);
|
160
|
+
|
161
|
+
define_class<WorkerDirector, Worker>("Worker")
|
162
|
+
.define_constructor(Constructor<WorkerDirector, Object>())
|
163
|
+
.define_method("process", &WorkerDirector::process);
|
164
|
+
|
165
|
+
Module m = define_module("Testing");
|
166
|
+
|
167
|
+
m.instance_eval(
|
168
|
+
"class EchoWorker < Worker; def process(num); num + 2; end; end;"
|
169
|
+
"class DoubleWorker < Worker; def process(num); num * 2; end; end;"
|
170
|
+
"handler = Handler.new;"
|
171
|
+
"handler.add_worker(EchoWorker.new);"
|
172
|
+
"handler.add_worker(DoubleWorker.new);"
|
173
|
+
);
|
174
|
+
|
175
|
+
Object result = m.instance_eval("handler.process_workers(5)");
|
176
|
+
|
177
|
+
// Hit's EchoWorker, so 5 + 2, then passes that to DoubleWorker, so 7 * 2 = 14
|
178
|
+
ASSERT_EQUAL(14, from_ruby<int>(result.value()));
|
179
|
+
}
|
180
|
+
|
181
|
+
namespace {
|
182
|
+
|
183
|
+
class CallsSelf {
|
184
|
+
public:
|
185
|
+
int doIt(int in) {
|
186
|
+
return doItImpl(in);
|
187
|
+
}
|
188
|
+
|
189
|
+
virtual int doItImpl(int in) = 0;
|
190
|
+
};
|
191
|
+
|
192
|
+
class CallsSelfDirector : public CallsSelf, public Director {
|
193
|
+
|
194
|
+
public:
|
195
|
+
CallsSelfDirector(Object self) : Director(self) { }
|
196
|
+
|
197
|
+
virtual int doItImpl(int in) {
|
198
|
+
if(!callIsFromRuby("do_it_impl")) {
|
199
|
+
return 0;
|
200
|
+
} else {
|
201
|
+
return from_ruby<int>( getSelf().call("do_it_impl", in) );
|
202
|
+
}
|
203
|
+
}
|
204
|
+
};
|
205
|
+
|
206
|
+
}
|
207
|
+
|
208
|
+
TESTCASE(mix_of_polymorphic_calls_and_inheritance_dont_cause_infinite_loops)
|
209
|
+
{
|
210
|
+
define_class<CallsSelf>("__CallsSelf__");
|
211
|
+
|
212
|
+
define_class<CallsSelfDirector, CallsSelf>("CallsSelf")
|
213
|
+
.define_constructor(Constructor<CallsSelfDirector, Rice::Object>())
|
214
|
+
.define_method("do_it_impl", &CallsSelfDirector::doItImpl)
|
215
|
+
.define_method("do_it", &CallsSelf::doIt);
|
216
|
+
|
217
|
+
Module m = define_module("Testing");
|
218
|
+
|
219
|
+
Object result = m.instance_eval(
|
220
|
+
"class MySelf < CallsSelf; def do_it_impl(num); num * 10; end; end;"
|
221
|
+
"c = MySelf.new; c.do_it(10)"
|
222
|
+
);
|
223
|
+
|
224
|
+
ASSERT_EQUAL(100, from_ruby<int>(result.value()));
|
225
|
+
}
|
data/test/test_Enum.cpp
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
#include "rice/Enum.hpp"
|
3
3
|
#include "rice/Array.hpp"
|
4
4
|
#include "rice/String.hpp"
|
5
|
+
#include "rice/Constructor.hpp"
|
5
6
|
#include <iostream>
|
6
7
|
|
7
8
|
using namespace Rice;
|
@@ -146,12 +147,14 @@ TESTCASE(different_objects_eql)
|
|
146
147
|
ASSERT_EQUAL(true, red1 == red2);
|
147
148
|
}
|
148
149
|
|
150
|
+
/*
|
149
151
|
TESTCASE(hash)
|
150
152
|
{
|
151
153
|
Enum<Color> rb_cColor = define_color_enum();
|
152
154
|
Data_Object<Color> red(new Color(RED));
|
153
155
|
ASSERT_EQUAL(to_ruby(int(RED)), red.call("hash"));
|
154
156
|
}
|
157
|
+
*/
|
155
158
|
|
156
159
|
TESTCASE(from_int)
|
157
160
|
{
|
@@ -160,3 +163,33 @@ TESTCASE(from_int)
|
|
160
163
|
ASSERT_EQUAL(RED, *color);
|
161
164
|
}
|
162
165
|
|
166
|
+
namespace
|
167
|
+
{
|
168
|
+
class Inner
|
169
|
+
{
|
170
|
+
public:
|
171
|
+
enum Props
|
172
|
+
{
|
173
|
+
VALUE1,
|
174
|
+
VALUE2,
|
175
|
+
VALUE3
|
176
|
+
};
|
177
|
+
};
|
178
|
+
}
|
179
|
+
|
180
|
+
TESTCASE(nested_enums)
|
181
|
+
{
|
182
|
+
{
|
183
|
+
Data_Type<Inner> inner = define_class<Inner>("Inner");
|
184
|
+
define_enum<Inner::Props>("Props", inner)
|
185
|
+
.define_value("VALUE1", Inner::VALUE1)
|
186
|
+
.define_value("VALUE2", Inner::VALUE2)
|
187
|
+
.define_value("VALUE3", Inner::VALUE3);
|
188
|
+
inner.define_constructor(Constructor<Inner>());
|
189
|
+
}
|
190
|
+
|
191
|
+
ASSERT_EQUAL(to_ruby(int(0)), Object(protect(rb_eval_string, "Inner::Props::VALUE1.to_i")));
|
192
|
+
ASSERT_EQUAL(to_ruby(int(1)), Object(protect(rb_eval_string, "Inner::Props::VALUE2.to_i")));
|
193
|
+
ASSERT_EQUAL(to_ruby(int(2)), Object(protect(rb_eval_string, "Inner::Props::VALUE3.to_i")));
|
194
|
+
}
|
195
|
+
|
data/test/test_Module.cpp
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
#include "rice/Module.hpp"
|
3
3
|
#include "rice/Exception.hpp"
|
4
4
|
#include "rice/Array.hpp"
|
5
|
+
#include "rice/Arg.hpp"
|
6
|
+
#include "rice/global_function.hpp"
|
5
7
|
|
6
8
|
using namespace Rice;
|
7
9
|
|
@@ -251,3 +253,176 @@ TESTCASE(mod_name_anonymous)
|
|
251
253
|
ASSERT_EQUAL(String(""), m.name());
|
252
254
|
}
|
253
255
|
|
256
|
+
/**
|
257
|
+
* Tests for default arguments
|
258
|
+
*/
|
259
|
+
namespace
|
260
|
+
{
|
261
|
+
int defaults_method_one_arg1;
|
262
|
+
int defaults_method_one_arg2;
|
263
|
+
bool defaults_method_one_arg3 = false;
|
264
|
+
|
265
|
+
void defaults_method_one(int arg1, int arg2 = 3, bool arg3 = true)
|
266
|
+
{
|
267
|
+
defaults_method_one_arg1 = arg1;
|
268
|
+
defaults_method_one_arg2 = arg2;
|
269
|
+
defaults_method_one_arg3 = arg3;
|
270
|
+
}
|
271
|
+
}
|
272
|
+
|
273
|
+
TESTCASE(define_method_default_arguments)
|
274
|
+
{
|
275
|
+
Module m(anonymous_module());
|
276
|
+
m.define_method("foo", &defaults_method_one, (Arg("arg1"), Arg("arg2") = 3, Arg("arg3") = true));
|
277
|
+
|
278
|
+
Object o = m.instance_eval("o = Object.new; o.extend(self); o");
|
279
|
+
o.call("foo", 2);
|
280
|
+
|
281
|
+
ASSERT_EQUAL(2, defaults_method_one_arg1);
|
282
|
+
ASSERT_EQUAL(3, defaults_method_one_arg2);
|
283
|
+
ASSERT(defaults_method_one_arg3);
|
284
|
+
|
285
|
+
o.call("foo", 11, 10);
|
286
|
+
|
287
|
+
ASSERT_EQUAL(11, defaults_method_one_arg1);
|
288
|
+
ASSERT_EQUAL(10, defaults_method_one_arg2);
|
289
|
+
ASSERT(defaults_method_one_arg3);
|
290
|
+
|
291
|
+
o.call("foo", 22, 33, false);
|
292
|
+
|
293
|
+
ASSERT_EQUAL(22, defaults_method_one_arg1);
|
294
|
+
ASSERT_EQUAL(33, defaults_method_one_arg2);
|
295
|
+
ASSERT(!defaults_method_one_arg3);
|
296
|
+
}
|
297
|
+
|
298
|
+
TESTCASE(default_arguments_still_throws_argument_error)
|
299
|
+
{
|
300
|
+
Module m(anonymous_module());
|
301
|
+
m.define_method("foo", &defaults_method_one, (Arg("arg1"), Arg("arg2") = 3, Arg("arg3") = true));
|
302
|
+
|
303
|
+
ASSERT_EXCEPTION_CHECK(
|
304
|
+
Exception,
|
305
|
+
m.instance_eval("o = Object.new; o.extend(self); o.foo()"),
|
306
|
+
ASSERT_EQUAL(
|
307
|
+
Object(rb_eArgError),
|
308
|
+
Object(CLASS_OF(ex.value()))
|
309
|
+
)
|
310
|
+
);
|
311
|
+
|
312
|
+
ASSERT_EXCEPTION_CHECK(
|
313
|
+
Exception,
|
314
|
+
m.instance_eval("o = Object.new; o.extend(self); o.foo(3, 4, false, 17)"),
|
315
|
+
ASSERT_EQUAL(
|
316
|
+
Object(rb_eArgError),
|
317
|
+
Object(CLASS_OF(ex.value()))
|
318
|
+
)
|
319
|
+
);
|
320
|
+
}
|
321
|
+
|
322
|
+
namespace {
|
323
|
+
int the_one_default_arg = 0;
|
324
|
+
void method_with_one_default_arg(int num = 4) {
|
325
|
+
the_one_default_arg = num;
|
326
|
+
}
|
327
|
+
}
|
328
|
+
|
329
|
+
TESTCASE(defining_methods_with_single_default_argument)
|
330
|
+
{
|
331
|
+
// define_method
|
332
|
+
Module m(anonymous_module());
|
333
|
+
m.define_method("foo", &method_with_one_default_arg, (Arg("num") = 4));
|
334
|
+
m.instance_eval("o = Object.new; o.extend(self); o.foo()");
|
335
|
+
ASSERT_EQUAL(4, the_one_default_arg);
|
336
|
+
|
337
|
+
the_one_default_arg = 0;
|
338
|
+
|
339
|
+
// define_singleton_method
|
340
|
+
Class c(anonymous_class());
|
341
|
+
c.define_singleton_method("foo", &method_with_one_default_arg, (Arg("num") = 4));
|
342
|
+
c.call("foo");
|
343
|
+
ASSERT_EQUAL(4, the_one_default_arg);
|
344
|
+
|
345
|
+
the_one_default_arg = 0;
|
346
|
+
|
347
|
+
// define_module_function
|
348
|
+
m.define_module_function("foo2", &method_with_one_default_arg, (Arg("num") = 4));
|
349
|
+
|
350
|
+
m.call("foo2");
|
351
|
+
ASSERT_EQUAL(4, the_one_default_arg);
|
352
|
+
}
|
353
|
+
|
354
|
+
TESTCASE(default_arguments_for_define_singleton_method)
|
355
|
+
{
|
356
|
+
Class c(anonymous_class());
|
357
|
+
c.define_singleton_method("foo", &defaults_method_one, (Arg("arg1"), Arg("arg2") = 3, Arg("arg3") = true));
|
358
|
+
|
359
|
+
c.call("foo", 2);
|
360
|
+
|
361
|
+
ASSERT_EQUAL(2, defaults_method_one_arg1);
|
362
|
+
ASSERT_EQUAL(3, defaults_method_one_arg2);
|
363
|
+
ASSERT(defaults_method_one_arg3);
|
364
|
+
|
365
|
+
c.call("foo", 11, 10);
|
366
|
+
|
367
|
+
ASSERT_EQUAL(11, defaults_method_one_arg1);
|
368
|
+
ASSERT_EQUAL(10, defaults_method_one_arg2);
|
369
|
+
ASSERT(defaults_method_one_arg3);
|
370
|
+
|
371
|
+
c.call("foo", 22, 33, false);
|
372
|
+
|
373
|
+
ASSERT_EQUAL(22, defaults_method_one_arg1);
|
374
|
+
ASSERT_EQUAL(33, defaults_method_one_arg2);
|
375
|
+
ASSERT(!defaults_method_one_arg3);
|
376
|
+
}
|
377
|
+
|
378
|
+
TESTCASE(default_arguments_for_define_module_function)
|
379
|
+
{
|
380
|
+
Module m(anonymous_module());
|
381
|
+
m.define_module_function("foo", &defaults_method_one, (Arg("arg1"), Arg("arg2") = 3, Arg("arg3") = true));
|
382
|
+
|
383
|
+
m.call("foo", 2);
|
384
|
+
|
385
|
+
ASSERT_EQUAL(2, defaults_method_one_arg1);
|
386
|
+
ASSERT_EQUAL(3, defaults_method_one_arg2);
|
387
|
+
ASSERT(defaults_method_one_arg3);
|
388
|
+
|
389
|
+
m.call("foo", 11, 10);
|
390
|
+
|
391
|
+
ASSERT_EQUAL(11, defaults_method_one_arg1);
|
392
|
+
ASSERT_EQUAL(10, defaults_method_one_arg2);
|
393
|
+
ASSERT(defaults_method_one_arg3);
|
394
|
+
|
395
|
+
m.call("foo", 22, 33, false);
|
396
|
+
|
397
|
+
ASSERT_EQUAL(22, defaults_method_one_arg1);
|
398
|
+
ASSERT_EQUAL(33, defaults_method_one_arg2);
|
399
|
+
ASSERT(!defaults_method_one_arg3);
|
400
|
+
}
|
401
|
+
|
402
|
+
namespace {
|
403
|
+
std::string with_defaults_and_references_x;
|
404
|
+
bool with_defaults_and_references_doIt;
|
405
|
+
|
406
|
+
void with_defaults_and_references(std::string const& x, bool doIt = false)
|
407
|
+
{
|
408
|
+
with_defaults_and_references_x = x;
|
409
|
+
with_defaults_and_references_doIt = doIt;
|
410
|
+
}
|
411
|
+
}
|
412
|
+
|
413
|
+
template<>
|
414
|
+
std::string* from_ruby<std::string*>(Rice::Object x) {
|
415
|
+
return new std::string(from_ruby<char const*>(x));
|
416
|
+
}
|
417
|
+
|
418
|
+
TESTCASE(define_method_works_with_reference_arguments)
|
419
|
+
{
|
420
|
+
Module m(anonymous_module());
|
421
|
+
m.define_module_function("foo", &with_defaults_and_references,
|
422
|
+
(Arg("x"), Arg("doIt") = false));
|
423
|
+
|
424
|
+
m.call("foo", "test");
|
425
|
+
|
426
|
+
ASSERT_EQUAL("test", with_defaults_and_references_x);
|
427
|
+
ASSERT(!with_defaults_and_references_doIt);
|
428
|
+
}
|