Added `get_const_holder()` overload for `boost::shared_ptr`.
[luabind.git] / test / test_lua_classes.cpp
blob9bdd500cfda18f592eed5434f6ca4eac6748339c
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
39 using namespace luabind;
41 struct A : counted_type<A>
43 virtual ~A() {}
45 virtual std::string f()
46 { return "A:f()"; }
48 virtual std::string g() const
49 { return "A:g()"; }
52 struct A_wrap : A, wrap_base
54 std::string f()
56 return call_member<std::string>(this, "f");
59 static std::string default_f(A* p)
60 { return p->A::f(); }
62 std::string g() const
64 return call_member<std::string>(this, "g");
67 static std::string default_g(A const* p)
68 { return p->A::g(); }
71 struct B : A
73 virtual std::string f()
74 { return "B:f()"; }
77 struct B_wrap : B, wrap_base
79 virtual std::string f()
80 { return call_member<std::string>(this, "f"); }
82 static std::string default_f(B* p)
83 { return p->B::f(); }
85 virtual std::string g() const
86 { return call_member<std::string>(this, "g"); }
88 static std::string default_g(B const* p)
89 { return p->B::g(); }
93 struct base : counted_type<base>
95 virtual ~base() {}
97 virtual std::string f()
99 return "base:f()";
102 virtual std::string g() const { return ""; }
105 base* filter(base* p) { return p; }
107 struct base_wrap : base, wrap_base
109 virtual std::string f()
111 return call_member<std::string>(this, "f");
114 static std::string default_f(base* p)
116 return p->base::f();
119 virtual std::string g() const
121 return call_member<std::string>(this, "g");
125 struct T_ // vc6.5, don't name your types T!
127 int f(int) { return 1; }
130 struct U : T_
132 int g() { return 3; }
133 int f(int, int) { return 2; }
136 void test_main(lua_State* L)
138 module(L)
140 class_<A, A_wrap, boost::shared_ptr<A> >("A")
141 .def(constructor<>())
142 .def("f", &A::f, &A_wrap::default_f)
143 .def("g", &A::g, &A_wrap::default_g),
145 class_<B, A, B_wrap, boost::shared_ptr<A> >("B")
146 .def(constructor<>())
147 .def("f", &B::f, &B_wrap::default_f)
148 .def("g", &B::g, &B_wrap::default_g),
150 def("filter", &filter),
152 class_<base, base_wrap>("base")
153 .def(constructor<>())
154 .def("f", &base::f, &base_wrap::default_f)
155 .def("g", &base::g),
157 class_<T_>("T")
158 .def("f", &T_::f),
160 class_<U, T_>("U")
161 .def(constructor<>())
162 .def("f", &U::f)
163 .def("g", &U::g)
166 DOSTRING(L,
167 "u = U()\n"
168 "assert(u:f(0) == 1)\n"
169 "assert(u:f(0,0) == 2)\n"
170 "assert(u:g() == 3)\n");
172 DOSTRING(L,
173 "u = U()\n"
174 "assert(u:f(0) == 1)\n"
175 "assert(u:f(0,0) == 2)\n"
176 "assert(u:g() == 3)\n");
178 DOSTRING(L,
179 "function base:fun()\n"
180 " return 4\n"
181 "end\n"
182 "ba = base()\n"
183 "assert(ba:fun() == 4)");
185 DOSTRING(L,
186 "class 'derived' (base)\n"
187 " function derived:__init() super() end\n"
188 " function derived:f()\n"
189 " return 'derived:f() : ' .. base.f(self)\n"
190 " end\n"
192 "class 'empty_derived' (base)\n"
193 " function empty_derived:__init() super() end\n"
195 "class 'C' (B)\n"
196 " function C:__init() super() end\n"
197 " function C:f() return 'C:f()' end\n"
199 "function make_derived()\n"
200 " return derived()\n"
201 "end\n"
203 "function make_empty_derived()\n"
204 " return empty_derived()\n"
205 "end\n"
207 "function adopt_ptr(x)\n"
208 " a = x\n"
209 "end\n");
211 DOSTRING(L,
212 "function gen_error()\n"
213 " assert(0 == 1)\n"
214 "end\n");
216 DOSTRING(L,
217 "a = A()\n"
218 "b = B()\n"
219 "c = C()\n"
221 "assert(c:f() == 'C:f()')\n"
222 "assert(b:f() == 'B:f()')\n"
223 "assert(a:f() == 'A:f()')\n"
224 "assert(b:g() == 'A:g()')\n"
225 "assert(c:g() == 'A:g()')\n"
227 "assert(C.f(c) == 'C:f()')\n"
228 "assert(B.f(c) == 'B:f()')\n"
229 "assert(A.f(c) == 'A:f()')\n"
230 "assert(A.g(c) == 'A:g()')\n");
232 #ifndef LUABIND_NO_EXCEPTONS
234 LUABIND_CHECK_STACK(L);
236 try { call_function<int>(L, "gen_error"); }
237 catch (luabind::error&)
239 bool result(
240 lua_tostring(L, -1) == std::string("[string \"function "
241 "gen_error()...\"]:2: assertion failed!"));
242 TEST_CHECK(result);
243 lua_pop(L, 1);
248 A a;
250 DOSTRING(L, "function test_ref(x) end");
251 call_function<void>(L, "test_ref", boost::ref(a));
255 LUABIND_CHECK_STACK(L);
257 try { call_function<void>(L, "gen_error"); }
258 catch (luabind::error&)
260 bool result(
261 lua_tostring(L, -1) == std::string("[string \"function "
262 "gen_error()...\"]:2: assertion failed!"));
263 TEST_CHECK(result);
264 lua_pop(L, 1);
269 LUABIND_CHECK_STACK(L);
271 try { call_function<void*>(L, "gen_error") [ adopt(result) ]; }
272 catch (luabind::error&)
274 bool result(
275 lua_tostring(L, -1) == std::string("[string \"function "
276 "gen_error()...\"]:2: assertion failed!"));
277 TEST_CHECK(result);
278 lua_pop(L, 1);
282 #endif
284 base* ptr;
286 LUABIND_CHECK_STACK(L);
288 TEST_NOTHROW(
289 object a = globals(L)["ba"];
290 TEST_CHECK(call_member<int>(a, "fun") == 4);
295 LUABIND_CHECK_STACK(L);
297 object make_derived = globals(L)["make_derived"];
298 TEST_NOTHROW(
299 call_function<void>(make_derived)
303 std::auto_ptr<base> own_ptr;
305 LUABIND_CHECK_STACK(L);
307 TEST_NOTHROW(
308 own_ptr = std::auto_ptr<base>(
309 call_function<base*>(L, "make_derived") [ adopt(result) ])
313 // make sure the derived lua-part is still referenced by
314 // the adopted c++ pointer
315 DOSTRING(L,
316 "collectgarbage()\n"
317 "collectgarbage()\n"
318 "collectgarbage()\n"
319 "collectgarbage()\n"
320 "collectgarbage()\n");
322 TEST_NOTHROW(
323 TEST_CHECK(own_ptr->f() == "derived:f() : base:f()")
325 own_ptr = std::auto_ptr<base>();
327 // test virtual functions that are not overridden by lua
328 TEST_NOTHROW(
329 own_ptr = std::auto_ptr<base>(
330 call_function<base*>(L, "make_empty_derived") [ adopt(result) ])
332 TEST_NOTHROW(
333 TEST_CHECK(own_ptr->f() == "base:f()")
335 TEST_NOTHROW(
336 call_function<void>(L, "adopt_ptr", own_ptr.get()) [ adopt(_1) ]
338 own_ptr.release();
340 // test virtual functions that are overridden by lua
341 TEST_NOTHROW(
342 ptr = call_function<base*>(L, "derived")
345 TEST_NOTHROW(
346 TEST_CHECK(ptr->f() == "derived:f() : base:f()")
349 // test virtual function dispatch from within lua
350 DOSTRING(L,
351 "a = derived()\n"
352 "b = filter(a)\n"
353 "assert(b:f() == 'derived:f() : base:f()')\n");
355 // test back references
356 DOSTRING(L,
357 "a = derived()\n"
358 "assert(a == filter(a))\n");