comparison C++/Tests/Luae/TestLuae.cpp @ 225:e01ee0c72c43

Luae: begin refactoring of Luae
author David Demelier <markand@malikania.fr>
date Fri, 09 May 2014 17:12:25 +0200
parents
children 927c4f3b8a88
comparison
equal deleted inserted replaced
224:ca69910b1407 225:e01ee0c72c43
1 /*
2 * TestLuae.cpp -- test the Luae class
3 *
4 * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <cppunit/TextTestRunner.h>
20
21 #include <Luae.h>
22 #include <LuaeState.h>
23
24 #include "TestLuae.h"
25
26 /* --------------------------------------------------------
27 * Custom type Point
28 * -------------------------------------------------------- */
29
30 struct Point {
31 int x;
32 int y;
33 };
34
35 template <>
36 struct Luae::TypeInfo<Point> : Luae::TypeCustom {
37 static void push(lua_State *L, const Point &point)
38 {
39 lua_createtable(L, 0, 0);
40 lua_pushinteger(L, point.x);
41 lua_setfield(L, -2, "x");
42 lua_pushinteger(L, point.y);
43 lua_setfield(L, -2, "y");
44 }
45
46 static Point get(lua_State *L, int index)
47 {
48 Point p{0, 0};
49
50 if (lua_type(L, index) == LUA_TTABLE) {
51 lua_getfield(L, index, "x");
52 p.x = luaL_optint(L, -1, 0);
53 lua_pop(L, 1);
54 lua_getfield(L, index, "y");
55 p.y = luaL_optint(L, -1, 0);
56 lua_pop(L, 1);
57 }
58
59 return p;
60 }
61
62 static Point check(lua_State *L, int index)
63 {
64 luaL_checktype(L, index, LUA_TTABLE);
65
66 return get(L, index);
67 }
68 };
69
70 /* --------------------------------------------------------
71 * Userdata type Object
72 * -------------------------------------------------------- */
73
74 struct Object {
75 std::string hello()
76 {
77 return "hello";
78 }
79 };
80
81 template <>
82 struct Luae::TypeInfo<Object> : Luae::TypeUserdata {
83 static constexpr const char *name = "Object";
84 };
85
86 int l_hello(lua_State *L)
87 {
88 return Luae::push(L, Luae::check<Object>(L, 1)->hello());
89 }
90
91 const Luae::Reg methods {
92 { "hello", l_hello }
93 };
94
95 /* --------------------------------------------------------
96 * Userdata as shared_ptr Widget
97 * -------------------------------------------------------- */
98
99 class Widget {
100 private:
101 int m_width;
102 int m_height;
103 std::string m_name;
104
105 public:
106 Widget(int width, int height, const std::string &name)
107 : m_width(width)
108 , m_height(height)
109 , m_name(name)
110 {
111 }
112
113 int width() const
114 {
115 return m_width;
116 }
117
118 int height() const
119 {
120 return m_height;
121 }
122
123 const std::string &name() const
124 {
125 return m_name;
126 }
127 };
128
129 using WidgetPtr = std::shared_ptr<Widget>;
130
131 template <>
132 struct Luae::TypeInfo<Widget> : Luae::TypeUserdata {
133 static constexpr const char *name = "Widget";
134 };
135
136 int l_width(lua_State *L)
137 {
138 return Luae::push(L, Luae::check<WidgetPtr>(L, 1)->width());
139 }
140
141 int l_height(lua_State *L)
142 {
143 return Luae::push(L, Luae::check<WidgetPtr>(L, 1)->height());
144 }
145
146 int l_name(lua_State *L)
147 {
148 return Luae::push(L, Luae::check<WidgetPtr>(L, 1)->name());
149 }
150
151 const Luae::Reg widgetMethods {
152 { "width", l_width },
153 { "height", l_height },
154 { "name", l_name }
155 };
156
157 /* --------------------------------------------------------
158 * Push function tests
159 * -------------------------------------------------------- */
160
161 void TestLuae::pushPoint()
162 {
163 LuaeState L;
164 Luae::openlibs(L);
165
166 try {
167 Luae::dofile(L, "push.lua");
168 Luae::getglobal(L, "pushPoint");
169 Luae::push(L, Point{10, 20});
170 Luae::pcall(L, 1, 0);
171 } catch (const std::runtime_error &error) {
172 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
173 }
174 }
175
176 void TestLuae::pushObject()
177 {
178 LuaeState L;
179 Luae::openlibs(L);
180
181 // Object metatable
182 Luae::newmetatable(L, "Object");
183 Luae::newlib(L, methods);
184 Luae::setfield(L, -2, "__index");
185 Luae::pop(L);
186
187 try {
188 Luae::dofile(L, "push.lua");
189 Luae::getglobal(L, "pushObject");
190 Luae::push(L, Object());
191 Luae::pcall(L, 1, 0);
192 } catch (const std::runtime_error &error) {
193 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
194 }
195 }
196
197 void TestLuae::pushShared()
198 {
199 LuaeState L;
200 Luae::openlibs(L);
201
202 // Widget metatable
203 Luae::newmetatable(L, "Widget");
204 Luae::newlib(L, widgetMethods);
205 Luae::setfield(L, -2, "__index");
206 Luae::pop(L);
207
208 try {
209 Luae::dofile(L, "push.lua");
210 Luae::getglobal(L, "pushShared");
211 Luae::push(L, std::make_shared<Widget>(100, 200, "Button"));
212 Luae::pcall(L, 1, 0);
213 } catch (const std::runtime_error &error) {
214 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
215 }
216 }
217
218 void TestLuae::pushSharedTwice()
219 {
220 LuaeState L;
221 Luae::openlibs(L);
222
223 // Widget metatable
224 Luae::newmetatable(L, "Widget");
225 Luae::newlib(L, widgetMethods);
226 Luae::setfield(L, -2, "__index");
227 Luae::pop(L);
228
229 try {
230 auto widget = std::make_shared<Widget>(640, 480, "Screen");
231
232 Luae::dofile(L, "push.lua");
233 Luae::getglobal(L, "pushSharedTwice");
234 Luae::push(L, widget);
235 Luae::push(L, widget);
236 Luae::pcall(L, 2, 0);
237 } catch (const std::runtime_error &error) {
238 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
239 }
240 }
241
242 /* --------------------------------------------------------
243 * Other functions
244 * -------------------------------------------------------- */
245
246 void TestLuae::preload()
247 {
248 LuaeState L;
249 Luae::openlibs(L);
250
251 Luae::preload(L, "luae", [] (lua_State *L) -> int {
252 lua_createtable(L, 0, 0);
253 lua_pushstring(L, "1.0");
254 lua_setfield(L, -2, "version");
255 lua_pushstring(L, "Luae");
256 lua_setfield(L, -2, "name");
257
258 return 1;
259 });
260
261 try {
262 Luae::dofile(L, "loading.lua");
263 Luae::getglobal(L, "test");
264 } catch (const std::runtime_error &error) {
265 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
266 }
267 }
268
269 void TestLuae::require()
270 {
271 LuaeState L;
272 Luae::openlibs(L);
273
274 Luae::require(L, "luae", [] (lua_State *L) -> int {
275 lua_createtable(L, 0, 0);
276 lua_pushstring(L, "1.0");
277 lua_setfield(L, -2, "version");
278 lua_pushstring(L, "Luae");
279 lua_setfield(L, -2, "name");
280
281 return 1;
282 });
283
284 try {
285 Luae::dofile(L, "loading.lua");
286 Luae::getglobal(L, "test");
287 } catch (const std::runtime_error &error) {
288 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
289 }
290 }
291
292 /* --------------------------------------------------------
293 * Standard types push / get / check
294 * -------------------------------------------------------- */
295
296 void TestLuae::testbool()
297 {
298 LuaeState L;
299 Luae::openlibs(L);
300
301 try {
302 Luae::dofile(L, "standard.lua");
303 Luae::getglobal(L, "testbool");
304 Luae::push(L, true);
305 Luae::pcall(L, 1, 1);
306 CPPUNIT_ASSERT_EQUAL(Luae::check<bool>(L, 1), false);
307 } catch (const std::runtime_error &error) {
308 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
309 }
310 }
311
312 void TestLuae::testdouble()
313 {
314 LuaeState L;
315 Luae::openlibs(L);
316
317 try {
318 Luae::dofile(L, "standard.lua");
319 Luae::getglobal(L, "testdouble");
320 Luae::push(L, 10.0);
321 Luae::pcall(L, 1, 1);
322 CPPUNIT_ASSERT_EQUAL(Luae::check<double>(L, 1), -10.0);
323 } catch (const std::runtime_error &error) {
324 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
325 }
326 }
327
328 void TestLuae::testint()
329 {
330 LuaeState L;
331 Luae::openlibs(L);
332
333 try {
334 Luae::dofile(L, "standard.lua");
335 Luae::getglobal(L, "testint");
336 Luae::push(L, 123);
337 Luae::pcall(L, 1, 1);
338 CPPUNIT_ASSERT_EQUAL(Luae::check<int>(L, 1), -123);
339 } catch (const std::runtime_error &error) {
340 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
341 }
342 }
343
344 void TestLuae::testlong()
345 {
346 LuaeState L;
347 Luae::openlibs(L);
348
349 try {
350 Luae::dofile(L, "standard.lua");
351 Luae::getglobal(L, "testlong");
352 Luae::push(L, 9999L);
353 Luae::pcall(L, 1, 1);
354 CPPUNIT_ASSERT_EQUAL(Luae::check<long>(L, 1), -9999L);
355 } catch (const std::runtime_error &error) {
356 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
357 }
358 }
359
360 void TestLuae::testnil()
361 {
362 LuaeState L;
363 Luae::openlibs(L);
364
365 try {
366 Luae::dofile(L, "standard.lua");
367 Luae::getglobal(L, "testnil");
368 Luae::push(L, nullptr);
369 Luae::pcall(L, 1, 1);
370 CPPUNIT_ASSERT_EQUAL(Luae::type(L, -1), LUA_TNIL);
371 } catch (const std::runtime_error &error) {
372 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
373 }
374 }
375
376 void TestLuae::teststring()
377 {
378 LuaeState L;
379 Luae::openlibs(L);
380
381 try {
382 Luae::dofile(L, "standard.lua");
383 Luae::getglobal(L, "teststring");
384 Luae::push(L, "Hello");
385 Luae::pcall(L, 1, 1);
386 CPPUNIT_ASSERT_EQUAL(Luae::check<std::string>(L, 1), std::string("olleH"));
387 } catch (const std::runtime_error &error) {
388 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
389 }
390 }
391
392 void TestLuae::testustring()
393 {
394 LuaeState L;
395 Luae::openlibs(L);
396
397 try {
398 std::u32string arg{'H', 'e', 'l', 'l', 'o'};
399 std::u32string expected{'o', 'l', 'l', 'e', 'H'};
400
401 Luae::dofile(L, "standard.lua");
402 Luae::getglobal(L, "testustring");
403 Luae::push(L, arg);
404 Luae::pcall(L, 1, 1);
405 CPPUNIT_ASSERT_MESSAGE("u32string failure", Luae::check<std::u32string>(L, 1) == expected);
406 } catch (const std::runtime_error &error) {
407 CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false);
408 }
409 }
410
411 int main()
412 {
413 CppUnit::TextTestRunner runnerText;
414
415 runnerText.addTest(TestLuae::suite());
416
417 return runnerText.run("", false) == 1 ? 0 : 1;
418 }