Mercurial > code
view 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 |
line wrap: on
line source
/* * TestLuae.cpp -- test the Luae class * * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <cppunit/TextTestRunner.h> #include <Luae.h> #include <LuaeState.h> #include "TestLuae.h" /* -------------------------------------------------------- * Custom type Point * -------------------------------------------------------- */ struct Point { int x; int y; }; template <> struct Luae::TypeInfo<Point> : Luae::TypeCustom { static void push(lua_State *L, const Point &point) { lua_createtable(L, 0, 0); lua_pushinteger(L, point.x); lua_setfield(L, -2, "x"); lua_pushinteger(L, point.y); lua_setfield(L, -2, "y"); } static Point get(lua_State *L, int index) { Point p{0, 0}; if (lua_type(L, index) == LUA_TTABLE) { lua_getfield(L, index, "x"); p.x = luaL_optint(L, -1, 0); lua_pop(L, 1); lua_getfield(L, index, "y"); p.y = luaL_optint(L, -1, 0); lua_pop(L, 1); } return p; } static Point check(lua_State *L, int index) { luaL_checktype(L, index, LUA_TTABLE); return get(L, index); } }; /* -------------------------------------------------------- * Userdata type Object * -------------------------------------------------------- */ struct Object { std::string hello() { return "hello"; } }; template <> struct Luae::TypeInfo<Object> : Luae::TypeUserdata { static constexpr const char *name = "Object"; }; int l_hello(lua_State *L) { return Luae::push(L, Luae::check<Object>(L, 1)->hello()); } const Luae::Reg methods { { "hello", l_hello } }; /* -------------------------------------------------------- * Userdata as shared_ptr Widget * -------------------------------------------------------- */ class Widget { private: int m_width; int m_height; std::string m_name; public: Widget(int width, int height, const std::string &name) : m_width(width) , m_height(height) , m_name(name) { } int width() const { return m_width; } int height() const { return m_height; } const std::string &name() const { return m_name; } }; using WidgetPtr = std::shared_ptr<Widget>; template <> struct Luae::TypeInfo<Widget> : Luae::TypeUserdata { static constexpr const char *name = "Widget"; }; int l_width(lua_State *L) { return Luae::push(L, Luae::check<WidgetPtr>(L, 1)->width()); } int l_height(lua_State *L) { return Luae::push(L, Luae::check<WidgetPtr>(L, 1)->height()); } int l_name(lua_State *L) { return Luae::push(L, Luae::check<WidgetPtr>(L, 1)->name()); } const Luae::Reg widgetMethods { { "width", l_width }, { "height", l_height }, { "name", l_name } }; /* -------------------------------------------------------- * Push function tests * -------------------------------------------------------- */ void TestLuae::pushPoint() { LuaeState L; Luae::openlibs(L); try { Luae::dofile(L, "push.lua"); Luae::getglobal(L, "pushPoint"); Luae::push(L, Point{10, 20}); Luae::pcall(L, 1, 0); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } void TestLuae::pushObject() { LuaeState L; Luae::openlibs(L); // Object metatable Luae::newmetatable(L, "Object"); Luae::newlib(L, methods); Luae::setfield(L, -2, "__index"); Luae::pop(L); try { Luae::dofile(L, "push.lua"); Luae::getglobal(L, "pushObject"); Luae::push(L, Object()); Luae::pcall(L, 1, 0); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } void TestLuae::pushShared() { LuaeState L; Luae::openlibs(L); // Widget metatable Luae::newmetatable(L, "Widget"); Luae::newlib(L, widgetMethods); Luae::setfield(L, -2, "__index"); Luae::pop(L); try { Luae::dofile(L, "push.lua"); Luae::getglobal(L, "pushShared"); Luae::push(L, std::make_shared<Widget>(100, 200, "Button")); Luae::pcall(L, 1, 0); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } void TestLuae::pushSharedTwice() { LuaeState L; Luae::openlibs(L); // Widget metatable Luae::newmetatable(L, "Widget"); Luae::newlib(L, widgetMethods); Luae::setfield(L, -2, "__index"); Luae::pop(L); try { auto widget = std::make_shared<Widget>(640, 480, "Screen"); Luae::dofile(L, "push.lua"); Luae::getglobal(L, "pushSharedTwice"); Luae::push(L, widget); Luae::push(L, widget); Luae::pcall(L, 2, 0); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } /* -------------------------------------------------------- * Other functions * -------------------------------------------------------- */ void TestLuae::preload() { LuaeState L; Luae::openlibs(L); Luae::preload(L, "luae", [] (lua_State *L) -> int { lua_createtable(L, 0, 0); lua_pushstring(L, "1.0"); lua_setfield(L, -2, "version"); lua_pushstring(L, "Luae"); lua_setfield(L, -2, "name"); return 1; }); try { Luae::dofile(L, "loading.lua"); Luae::getglobal(L, "test"); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } void TestLuae::require() { LuaeState L; Luae::openlibs(L); Luae::require(L, "luae", [] (lua_State *L) -> int { lua_createtable(L, 0, 0); lua_pushstring(L, "1.0"); lua_setfield(L, -2, "version"); lua_pushstring(L, "Luae"); lua_setfield(L, -2, "name"); return 1; }); try { Luae::dofile(L, "loading.lua"); Luae::getglobal(L, "test"); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } /* -------------------------------------------------------- * Standard types push / get / check * -------------------------------------------------------- */ void TestLuae::testbool() { LuaeState L; Luae::openlibs(L); try { Luae::dofile(L, "standard.lua"); Luae::getglobal(L, "testbool"); Luae::push(L, true); Luae::pcall(L, 1, 1); CPPUNIT_ASSERT_EQUAL(Luae::check<bool>(L, 1), false); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } void TestLuae::testdouble() { LuaeState L; Luae::openlibs(L); try { Luae::dofile(L, "standard.lua"); Luae::getglobal(L, "testdouble"); Luae::push(L, 10.0); Luae::pcall(L, 1, 1); CPPUNIT_ASSERT_EQUAL(Luae::check<double>(L, 1), -10.0); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } void TestLuae::testint() { LuaeState L; Luae::openlibs(L); try { Luae::dofile(L, "standard.lua"); Luae::getglobal(L, "testint"); Luae::push(L, 123); Luae::pcall(L, 1, 1); CPPUNIT_ASSERT_EQUAL(Luae::check<int>(L, 1), -123); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } void TestLuae::testlong() { LuaeState L; Luae::openlibs(L); try { Luae::dofile(L, "standard.lua"); Luae::getglobal(L, "testlong"); Luae::push(L, 9999L); Luae::pcall(L, 1, 1); CPPUNIT_ASSERT_EQUAL(Luae::check<long>(L, 1), -9999L); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } void TestLuae::testnil() { LuaeState L; Luae::openlibs(L); try { Luae::dofile(L, "standard.lua"); Luae::getglobal(L, "testnil"); Luae::push(L, nullptr); Luae::pcall(L, 1, 1); CPPUNIT_ASSERT_EQUAL(Luae::type(L, -1), LUA_TNIL); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } void TestLuae::teststring() { LuaeState L; Luae::openlibs(L); try { Luae::dofile(L, "standard.lua"); Luae::getglobal(L, "teststring"); Luae::push(L, "Hello"); Luae::pcall(L, 1, 1); CPPUNIT_ASSERT_EQUAL(Luae::check<std::string>(L, 1), std::string("olleH")); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } void TestLuae::testustring() { LuaeState L; Luae::openlibs(L); try { std::u32string arg{'H', 'e', 'l', 'l', 'o'}; std::u32string expected{'o', 'l', 'l', 'e', 'H'}; Luae::dofile(L, "standard.lua"); Luae::getglobal(L, "testustring"); Luae::push(L, arg); Luae::pcall(L, 1, 1); CPPUNIT_ASSERT_MESSAGE("u32string failure", Luae::check<std::u32string>(L, 1) == expected); } catch (const std::runtime_error &error) { CPPUNIT_ASSERT_MESSAGE("unexpected exception: " + std::string(error.what()), false); } } int main() { CppUnit::TextTestRunner runnerText; runnerText.addTest(TestLuae::suite()); return runnerText.run("", false) == 1 ? 0 : 1; }