fixed #59. Wrong return value in two-argument object::operator().
[luabind.git] / test / test_lua_classes.cpp
blobc8fe0bc04cae62a7359d8d8d1d3dc960bf87a53e
1 // Copyright (c) 2005 Daniel Wallin, Arvid Norberg
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
14 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
15 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
17 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
18 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
21 // OR OTHER DEALINGS IN THE SOFTWARE.
23 #include "test.hpp"
25 #include <luabind/luabind.hpp>
26 #include <luabind/wrapper_base.hpp>
27 #include <luabind/adopt_policy.hpp>
28 #include <boost/shared_ptr.hpp>
30 namespace luabind {
32 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
33 template<class T>
34 T* get_pointer(boost::shared_ptr<T> const& p) { return p.get(); }
35 #endif
37 template<class A>
38 boost::shared_ptr<const A>* get_const_holder(boost::shared_ptr<A>*)
40 return 0;
44 using namespace luabind;
46 struct A : counted_type<A>
48 virtual ~A() {}
50 virtual std::string f()
51 { return "A:f()"; }
53 virtual std::string g() const
54 { return "A:g()"; }
57 struct A_wrap : A, wrap_base
59 std::string f()
61 return call_member<std::string>(this, "f");
64 static std::string default_f(A* p)
65 { return p->A::f(); }
67 std::string g() const
69 return call_member<std::string>(this, "g");
72 static std::string default_g(A const* p)
73 { return p->A::g(); }
76 struct B : A
78 virtual std::string f()
79 { return "B:f()"; }
82 struct B_wrap : B, wrap_base
84 virtual std::string f()
85 { return call_member<std::string>(this, "f"); }
87 static std::string default_f(B* p)
88 { return p->B::f(); }
90 virtual std::string g() const
91 { return call_member<std::string>(this, "g"); }
93 static std::string default_g(B const* p)
94 { return p->B::g(); }
98 struct base : counted_type<base>
100 virtual ~base() {}
102 virtual std::string f()
104 return "base:f()";
107 virtual std::string g() const { return ""; }
110 base* filter(base* p) { return p; }
112 struct base_wrap : base, wrap_base
114 virtual std::string f()
116 return call_member<std::string>(this, "f");
119 static std::string default_f(base* p)
121 return p->base::f();
124 virtual std::string g() const
126 return call_member<std::string>(this, "g");
130 struct T_ // vc6.5, don't name your types T!
132 int f(int) { return 1; }
135 struct U : T_
137 int g() { return 3; }
138 int f(int, int) { return 2; }
141 void test_main(lua_State* L)
143 module(L)
145 class_<A, A_wrap, boost::shared_ptr<A> >("A")
146 .def(constructor<>())
147 .def("f", &A::f, &A_wrap::default_f)
148 .def("g", &A::g, &A_wrap::default_g),
150 class_<B, A, B_wrap, boost::shared_ptr<A> >("B")
151 .def(constructor<>())
152 .def("f", &B::f, &B_wrap::default_f)
153 .def("g", &B::g, &B_wrap::default_g),
155 def("filter", &filter),
157 class_<base, base_wrap>("base")
158 .def(constructor<>())
159 .def("f", &base::f, &base_wrap::default_f)
160 .def("g", &base::g),
162 class_<T_>("T")
163 .def("f", &T_::f),
165 class_<U, T_>("U")
166 .def(constructor<>())
167 .def("f", &U::f)
168 .def("g", &U::g)
171 DOSTRING(L,
172 "u = U()\n"
173 "assert(u:f(0) == 1)\n"
174 "assert(u:f(0,0) == 2)\n"
175 "assert(u:g() == 3)\n");
177 DOSTRING(L,
178 "u = U()\n"
179 "assert(u:f(0) == 1)\n"
180 "assert(u:f(0,0) == 2)\n"
181 "assert(u:g() == 3)\n");
183 DOSTRING(L,
184 "function base:fun()\n"
185 " return 4\n"
186 "end\n"
187 "ba = base()\n"
188 "assert(ba:fun() == 4)");
190 DOSTRING(L,
191 "class 'derived' (base)\n"
192 " function derived:__init() super() end\n"
193 " function derived:f()\n"
194 " return 'derived:f() : ' .. base.f(self)\n"
195 " end\n"
197 "class 'empty_derived' (base)\n"
198 " function empty_derived:__init() super() end\n"
200 "class 'C' (B)\n"
201 " function C:__init() super() end\n"
202 " function C:f() return 'C:f()' end\n"
204 "function make_derived()\n"
205 " return derived()\n"
206 "end\n"
208 "function make_empty_derived()\n"
209 " return empty_derived()\n"
210 "end\n"
212 "function adopt_ptr(x)\n"
213 " a = x\n"
214 "end\n");
216 DOSTRING(L,
217 "function gen_error()\n"
218 " assert(0 == 1)\n"
219 "end\n");
221 DOSTRING(L,
222 "a = A()\n"
223 "b = B()\n"
224 "c = C()\n"
226 "assert(c:f() == 'C:f()')\n"
227 "assert(b:f() == 'B:f()')\n"
228 "assert(a:f() == 'A:f()')\n"
229 "assert(b:g() == 'A:g()')\n"
230 "assert(c:g() == 'A:g()')\n"
232 "assert(C.f(c) == 'C:f()')\n"
233 "assert(B.f(c) == 'B:f()')\n"
234 "assert(A.f(c) == 'A:f()')\n"
235 "assert(A.g(c) == 'A:g()')\n");
237 #ifndef LUABIND_NO_EXCEPTONS
239 LUABIND_CHECK_STACK(L);
241 try { call_function<int>(L, "gen_error"); }
242 catch (luabind::error&)
244 bool result(
245 lua_tostring(L, -1) == std::string("[string \"function "
246 "gen_error()...\"]:2: assertion failed!"));
247 TEST_CHECK(result);
248 lua_pop(L, 1);
253 A a;
255 DOSTRING(L, "function test_ref(x) end");
256 call_function<void>(L, "test_ref", boost::ref(a));
260 LUABIND_CHECK_STACK(L);
262 try { call_function<void>(L, "gen_error"); }
263 catch (luabind::error&)
265 bool result(
266 lua_tostring(L, -1) == std::string("[string \"function "
267 "gen_error()...\"]:2: assertion failed!"));
268 TEST_CHECK(result);
269 lua_pop(L, 1);
274 LUABIND_CHECK_STACK(L);
276 try { call_function<void*>(L, "gen_error") [ adopt(result) ]; }
277 catch (luabind::error&)
279 bool result(
280 lua_tostring(L, -1) == std::string("[string \"function "
281 "gen_error()...\"]:2: assertion failed!"));
282 TEST_CHECK(result);
283 lua_pop(L, 1);
287 #endif
289 base* ptr;
291 LUABIND_CHECK_STACK(L);
293 TEST_NOTHROW(
294 object a = globals(L)["ba"];
295 TEST_CHECK(call_member<int>(a, "fun") == 4);
300 LUABIND_CHECK_STACK(L);
302 object make_derived = globals(L)["make_derived"];
303 TEST_NOTHROW(
304 call_function<void>(make_derived)
308 std::auto_ptr<base> own_ptr;
310 LUABIND_CHECK_STACK(L);
312 TEST_NOTHROW(
313 own_ptr = std::auto_ptr<base>(
314 call_function<base*>(L, "make_derived") [ adopt(result) ])
318 // make sure the derived lua-part is still referenced by
319 // the adopted c++ pointer
320 DOSTRING(L,
321 "collectgarbage()\n"
322 "collectgarbage()\n"
323 "collectgarbage()\n"
324 "collectgarbage()\n"
325 "collectgarbage()\n");
327 TEST_NOTHROW(
328 TEST_CHECK(own_ptr->f() == "derived:f() : base:f()")
330 own_ptr = std::auto_ptr<base>();
332 // test virtual functions that are not overridden by lua
333 TEST_NOTHROW(
334 own_ptr = std::auto_ptr<base>(
335 call_function<base*>(L, "make_empty_derived") [ adopt(result) ])
337 TEST_NOTHROW(
338 TEST_CHECK(own_ptr->f() == "base:f()")
340 TEST_NOTHROW(
341 call_function<void>(L, "adopt_ptr", own_ptr.get()) [ adopt(_1) ]
343 own_ptr.release();
345 // test virtual functions that are overridden by lua
346 TEST_NOTHROW(
347 ptr = call_function<base*>(L, "derived")
350 TEST_NOTHROW(
351 TEST_CHECK(ptr->f() == "derived:f() : base:f()")
354 // test virtual function dispatch from within lua
355 DOSTRING(L,
356 "a = derived()\n"
357 "b = filter(a)\n"
358 "assert(b:f() == 'derived:f() : base:f()')\n");
360 // test back references
361 DOSTRING(L,
362 "a = derived()\n"
363 "assert(a == filter(a))\n");