Mercurial > code
view C++/Tests/Luae/main.cpp @ 250:b686a09fb9c6
Merge
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 01 Oct 2014 14:39:24 +0200 |
parents | C++/Tests/Luae/TestLuae.cpp@927c4f3b8a88 C++/Tests/Luae/TestLuae.cpp@3b4ae8feca1c |
children |
line wrap: on
line source
/* * main.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 <gtest/gtest.h> #include <Luae.h> #include <LuaeState.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 * -------------------------------------------------------- */ TEST(Push, point) { 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) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Push, object) { 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) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Push, shared) { 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) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Push, sharedTwice) { 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) { FAIL() << "unexpected exception: " << error.what(); } } /* -------------------------------------------------------- * Other functions * -------------------------------------------------------- */ TEST(Basic, 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) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Basic, 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) { FAIL() << "unexpected exception: " << error.what(); } } /* -------------------------------------------------------- * Standard types push / get / check * -------------------------------------------------------- */ TEST(Standard, 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); ASSERT_FALSE(Luae::check<bool>(L, 1)); } catch (const std::runtime_error &error) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Standard, 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); ASSERT_EQ(-10.0, Luae::check<double>(L, 1)); } catch (const std::runtime_error &error) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Standard, 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); ASSERT_EQ(-123, Luae::check<int>(L, 1)); } catch (const std::runtime_error &error) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Standard, 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); ASSERT_EQ(-9999L, Luae::check<long>(L, 1)); } catch (const std::runtime_error &error) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Standard, 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); ASSERT_EQ(LUA_TNIL, Luae::type(L, -1)); } catch (const std::runtime_error &error) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Standard, 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); ASSERT_EQ("olleH", Luae::check<std::string>(L, 1)); } catch (const std::runtime_error &error) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Standard, 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); ASSERT_EQ(expected, Luae::check<std::u32string>(L, 1)); } catch (const std::runtime_error &error) { FAIL() << "unexpected exception: " << error.what(); } } TEST(Standard, optionalbool) { LuaeState L; Luae::openlibs(L); Luae::push(L, nullptr); ASSERT_FALSE(Luae::optional<bool>(L, -1, false)); Luae::push(L, true); ASSERT_TRUE(Luae::optional<bool>(L, -1, false)); } TEST(Standard, optionalint) { LuaeState L; Luae::openlibs(L); Luae::push(L, nullptr); ASSERT_EQ(123, Luae::optional<int>(L, -1, 123)); Luae::push(L, 456); ASSERT_EQ(456, Luae::optional<int>(L, -1, 999)); } TEST(Standard, optionallong) { LuaeState L; Luae::openlibs(L); Luae::push(L, nullptr); ASSERT_EQ(123456789, Luae::optional<long>(L, -1, 123456789)); Luae::push(L, 789); ASSERT_EQ(789, Luae::optional<long>(L, -1, 888)); } TEST(Standard, optionaldouble) { LuaeState L; Luae::openlibs(L); Luae::push(L, nullptr); ASSERT_EQ(123.321, Luae::optional<double>(L, -1, 123.321)); Luae::push(L, 99.44); ASSERT_EQ(99.44, Luae::optional<double>(L, -1, 321.321)); } TEST(Standard, optionalstring) { LuaeState L; Luae::openlibs(L); Luae::push(L, nullptr); ASSERT_EQ("abc", Luae::optional<std::string>(L, -1, "abc")); Luae::push(L, "xyz"); ASSERT_EQ("xyz", Luae::optional<std::string>(L, -1, "qwerty")); } TEST(Standard, optionalustring) { LuaeState L; Luae::openlibs(L); std::u32string expected { 'a', 'b', 'c' }; Luae::push(L, nullptr); ASSERT_EQ(expected, Luae::optional<std::u32string>(L, -1, expected)); std::u32string notthatone { 'x', 'y' }; Luae::push(L, expected); ASSERT_EQ(expected, Luae::optional<std::u32string>(L, -1, notthatone)); } int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }