Fixed for VC6.5.
[luabind.git] / test / test_lua_classes.cpp
blob3933077399745485367536c670ac4649a69fb3b0
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 template<class T>
33 T* get_pointer(boost::shared_ptr<T>& p) { return p.get(); }
35 template<class A>
36 boost::shared_ptr<const A>* get_const_holder(boost::shared_ptr<A>*)
38 return 0;
42 using namespace luabind;
44 struct A : counted_type<A>
46 virtual ~A() {}
48 virtual std::string f()
49 { return "A:f()"; }
51 virtual std::string g() const
52 { return "A:g()"; }
55 struct A_wrap : A, wrap_base
57 std::string f()
59 return call_member<std::string>(this, "f");
62 static std::string default_f(A* p)
63 { return p->A::f(); }
65 std::string g() const
67 return call_member<std::string>(this, "g");
70 static std::string default_g(A const* p)
71 { return p->A::g(); }
74 struct B : A
76 virtual std::string f()
77 { return "B:f()"; }
80 struct B_wrap : B, wrap_base
82 virtual std::string f()
83 { return call_member<std::string>(this, "f"); }
85 static std::string default_f(B* p)
86 { return p->B::f(); }
88 virtual std::string g() const
89 { return call_member<std::string>(this, "g"); }
91 static std::string default_g(B const* p)
92 { return p->B::g(); }
96 struct base : counted_type<base>
98 virtual ~base() {}
100 virtual std::string f()
102 return "base:f()";
105 virtual std::string g() const { return ""; }
108 base* filter(base* p) { return p; }
110 struct base_wrap : base, wrap_base
112 virtual std::string f()
114 return call_member<std::string>(this, "f");
117 static std::string default_f(base* p)
119 return p->base::f();
122 virtual std::string g() const
124 return call_member<std::string>(this, "g");
128 struct T_ // vc6.5, don't name your types T!
130 int f(int) { return 1; }
133 struct U : T_
135 int g() { return 3; }
136 int f(int, int) { return 2; }
139 void test_main(lua_State* L)
141 module(L)
143 class_<A, A_wrap, boost::shared_ptr<A> >("A")
144 .def(constructor<>())
145 .def("f", &A::f, &A_wrap::default_f)
146 .def("g", &A::g, &A_wrap::default_g),
148 class_<B, A, B_wrap, boost::shared_ptr<A> >("B")
149 .def(constructor<>())
150 .def("f", &B::f, &B_wrap::default_f)
151 .def("g", &B::g, &B_wrap::default_g),
153 def("filter", &filter),
155 class_<base, base_wrap>("base")
156 .def(constructor<>())
157 .def("f", &base::f, &base_wrap::default_f)
158 .def("g", &base::g),
160 class_<T_>("T")
161 .def("f", &T_::f),
163 class_<U, T_>("U")
164 .def(constructor<>())
165 .def("f", &U::f)
166 .def("g", &U::g)
169 DOSTRING(L,
170 "u = U()\n"
171 "assert(u:f(0) == 1)\n"
172 "assert(u:f(0,0) == 2)\n"
173 "assert(u:g() == 3)\n");
175 DOSTRING(L,
176 "u = U()\n"
177 "assert(u:f(0) == 1)\n"
178 "assert(u:f(0,0) == 2)\n"
179 "assert(u:g() == 3)\n");
181 DOSTRING(L,
182 "function base:fun()\n"
183 " return 4\n"
184 "end\n"
185 "ba = base()\n"
186 "assert(ba:fun() == 4)");
188 DOSTRING(L,
189 "class 'derived' (base)\n"
190 " function derived:__init() super() end\n"
191 " function derived:f()\n"
192 " return 'derived:f() : ' .. base.f(self)\n"
193 " end\n"
195 "class 'empty_derived' (base)\n"
196 " function empty_derived:__init() super() end\n"
198 "class 'C' (B)\n"
199 " function C:__init() super() end\n"
200 " function C:f() return 'C:f()' end\n"
202 "function make_derived()\n"
203 " return derived()\n"
204 "end\n"
206 "function make_empty_derived()\n"
207 " return empty_derived()\n"
208 "end\n"
210 "function adopt_ptr(x)\n"
211 " a = x\n"
212 "end\n");
214 DOSTRING(L,
215 "function gen_error()\n"
216 " assert(0 == 1)\n"
217 "end\n");
219 DOSTRING(L,
220 "a = A()\n"
221 "b = B()\n"
222 "c = C()\n"
224 "assert(c:f() == 'C:f()')\n"
225 "assert(b:f() == 'B:f()')\n"
226 "assert(a:f() == 'A:f()')\n"
227 "assert(b:g() == 'A:g()')\n"
228 "assert(c:g() == 'A:g()')\n"
230 "assert(C.f(c) == 'C:f()')\n"
231 "assert(B.f(c) == 'B:f()')\n"
232 "assert(A.f(c) == 'A:f()')\n"
233 "assert(A.g(c) == 'A:g()')\n");
235 #ifndef LUABIND_NO_EXCEPTONS
237 LUABIND_CHECK_STACK(L);
239 try { call_function<int>(L, "gen_error"); }
240 catch (luabind::error&)
242 bool result(
243 lua_tostring(L, -1) == std::string("[string \"function "
244 "gen_error()...\"]:2: assertion failed!"));
245 TEST_CHECK(result);
246 lua_pop(L, 1);
251 A a;
253 DOSTRING(L, "function test_ref(x) end");
254 call_function<void>(L, "test_ref", boost::ref(a));
258 LUABIND_CHECK_STACK(L);
260 try { call_function<void>(L, "gen_error"); }
261 catch (luabind::error&)
263 bool result(
264 lua_tostring(L, -1) == std::string("[string \"function "
265 "gen_error()...\"]:2: assertion failed!"));
266 TEST_CHECK(result);
267 lua_pop(L, 1);
272 LUABIND_CHECK_STACK(L);
274 try { call_function<void*>(L, "gen_error") [ adopt(result) ]; }
275 catch (luabind::error&)
277 bool result(
278 lua_tostring(L, -1) == std::string("[string \"function "
279 "gen_error()...\"]:2: assertion failed!"));
280 TEST_CHECK(result);
281 lua_pop(L, 1);
285 #endif
287 base* ptr;
289 LUABIND_CHECK_STACK(L);
291 TEST_NOTHROW(
292 object a = globals(L)["ba"];
293 TEST_CHECK(call_member<int>(a, "fun") == 4);
298 LUABIND_CHECK_STACK(L);
300 object make_derived = globals(L)["make_derived"];
301 TEST_NOTHROW(
302 call_function<void>(make_derived)
306 std::auto_ptr<base> own_ptr;
308 LUABIND_CHECK_STACK(L);
310 TEST_NOTHROW(
311 own_ptr = std::auto_ptr<base>(
312 call_function<base*>(L, "make_derived") [ adopt(result) ])
316 // make sure the derived lua-part is still referenced by
317 // the adopted c++ pointer
318 DOSTRING(L,
319 "collectgarbage()\n"
320 "collectgarbage()\n"
321 "collectgarbage()\n"
322 "collectgarbage()\n"
323 "collectgarbage()\n");
325 TEST_NOTHROW(
326 TEST_CHECK(own_ptr->f() == "derived:f() : base:f()")
328 own_ptr = std::auto_ptr<base>();
330 // test virtual functions that are not overridden by lua
331 TEST_NOTHROW(
332 own_ptr = std::auto_ptr<base>(
333 call_function<base*>(L, "make_empty_derived") [ adopt(result) ])
335 TEST_NOTHROW(
336 TEST_CHECK(own_ptr->f() == "base:f()")
338 TEST_NOTHROW(
339 call_function<void>(L, "adopt_ptr", own_ptr.get()) [ adopt(_1) ]
341 own_ptr.release();
343 // test virtual functions that are overridden by lua
344 TEST_NOTHROW(
345 ptr = call_function<base*>(L, "derived")
348 TEST_NOTHROW(
349 TEST_CHECK(ptr->f() == "derived:f() : base:f()")
352 // test virtual function dispatch from within lua
353 DOSTRING(L,
354 "a = derived()\n"
355 "b = filter(a)\n"
356 "assert(b:f() == 'derived:f() : base:f()')\n");
358 // test back references
359 DOSTRING(L,
360 "a = derived()\n"
361 "assert(a == filter(a))\n");