KAGUYA_TEST_FUNCTION_DEF(compare_null_ptr)(kaguya::State& state) { { kaguya::LuaRef nullref = state.newRef(nullptr); TEST_CHECK(nullref.typeTest<std::nullptr_t>()); TEST_CHECK(nullref.weakTypeTest<std::nullptr_t>()); TEST_CHECK(nullref == nullptr); void* ptr = nullref.get<std::nullptr_t>(); TEST_CHECK(!ptr); } { kaguya::LuaRef ref = state.newRef(1); TEST_CHECK(!(ref.typeTest<std::nullptr_t>())); TEST_CHECK(!(ref.weakTypeTest<std::nullptr_t>())); TEST_CHECK(ref != nullptr); bool catch_except = false; try { ref.get<std::nullptr_t>(); } catch (const kaguya::LuaTypeMismatch&) { catch_except = true; } TEST_CHECK(catch_except); } }
KAGUYA_TEST_FUNCTION_DEF(load_string)(kaguya::State& state) { kaguya::LuaRef luafun = state.loadstring("assert(11 == 11);return true"); TEST_CHECK(luafun() != false); state.setErrorHandler(ignore_error_fun); kaguya::LuaRef errorref = state.loadstring("function() e");//syntax error TEST_CHECK(!errorref); }
KAGUYA_TEST_FUNCTION_DEF(luaL_requiref_test)(kaguya::State& s) { using namespace kaguya; luaL_requiref(s.state(),"mylib", lua_mylibf,false); kaguya::LuaStackRef ref(s.state(), -1,true); TEST_EQUAL(ref["value"],111); TEST_CHECK(s("assert(mylib == nil)")); }
KAGUYA_TEST_FUNCTION_DEF(object_take_copy)(kaguya::State& state) { state["Base"].setClass(kaguya::ClassMetatable<Base>() .addConstructor() .addProperty("a", &Base::a) ); TEST_CHECK(state("fn = function(object,value) object.a = value end")); { Base base; base.a = 232; state["obj"] = base; TEST_CHECK(state("assert(obj.a==232)")); TEST_CHECK(state("obj.a = 2")); TEST_CHECK(state("assert(obj.a==2)")); TEST_EQUAL(base.a, 232); state.garbageCollect(); TEST_CHECK(state("assert(obj.a==2)")); state["fn"](base, 54); TEST_EQUAL(base.a, 232); } {// Base basesrc; Base& base = basesrc; base.a = 232; state["obj"] = base; TEST_CHECK(state("assert(obj.a==232)")); TEST_CHECK(state("obj.a = 2")); TEST_CHECK(state("assert(obj.a==2)")); TEST_EQUAL(base.a, 232); state.garbageCollect(); TEST_CHECK(state("assert(obj.a==2)")); state["fn"](base, 54); TEST_EQUAL(base.a, 232); } {// Base basesrc; const Base& base = basesrc; basesrc.a = 232; state["obj"] = base; TEST_CHECK(state("assert(obj.a==232)")); TEST_CHECK(state("obj.a = 2")); TEST_CHECK(state("assert(obj.a==2)")); TEST_EQUAL(base.a, 232); state.garbageCollect(); TEST_CHECK(state("assert(obj.a==2)")); state["fn"](base, 54); TEST_EQUAL(base.a, 232); } }
KAGUYA_TEST_FUNCTION_DEF(defaultarguments)(kaguya::State& state) { KAGUYA_FUNCTION_OVERLOADS(defargfn_wrapper, defargfn,0,3) state["defargfn"] = kaguya::function(defargfn_wrapper); state.dostring("assert(defargfn() == 6)"); state.dostring("assert(defargfn(6) == 12)"); state.dostring("assert(defargfn(6,5) == 30)"); state.dostring("assert(defargfn(2,2,2) == 8)"); }
KAGUYA_TEST_FUNCTION_DEF(void_defaultarguments)(kaguya::State& state) { KAGUYA_VOID_FUNCTION_OVERLOADS(defargfn_wrapper, void_defargfn,0,3) state["defargfn"] = kaguya::function(defargfn_wrapper); state.dostring("defargfn()"); state.dostring("defargfn(3)"); state.dostring("defargfn(3,2)"); state.dostring("defargfn(3,2,1)"); }
KAGUYA_TEST_FUNCTION_DEF(load_with_other_env)(kaguya::State& state) { state.dostring("foo = 'bar'"); state["otherEnv"] = kaguya::NewTable(); state.dostring("foo = 'dar'", state["otherEnv"]); TEST_CHECK(state("assert(foo == 'bar')")); TEST_CHECK(state("assert(otherEnv.foo == 'dar')")); }
KAGUYA_TEST_FUNCTION_DEF(defaultarguments)(kaguya::State& state) { state.setErrorHandler(error_fun); state["defargfn"] = kaguya::function(defargfn_wrapper()); state["defargfn2"] = kaguya::function(defargfn_wrapper2()); state.dostring("defargfn('abc')"); last_error_message.find("[OPT]int,[OPT]int,[OPT]int"); state.dostring("defargfn2('abc')"); last_error_message.find("int,int,[OPT]int"); }
KAGUYA_TEST_FUNCTION_DEF(lua_resume_test)(kaguya::State& s) { using namespace kaguya; LuaThread t = s.newThread(s.loadstring("v={...}")); lua_State* co = t.get<lua_State*>(); lua_pushnumber(co, 2); lua_pushnumber(co, 3); lua_resume(co,s.state(),2); TEST_EQUAL(s["v"][1], 2); TEST_EQUAL(s["v"][2], 3); }
KAGUYA_TEST_FUNCTION_DEF(member_function_defaultarguments)(kaguya::State& state) { KAGUYA_MEMBER_FUNCTION_OVERLOADS(defargfn_wrapper, TestClass, default_arg, 0, 3) state["TestClass"].setClass(kaguya::UserdataMetatable<TestClass>() .setConstructors<TestClass()>() .addFunction("defargfn", defargfn_wrapper) ); state.dostring("test = TestClass.new()"); state.dostring("assert(test:defargfn() == 6)"); state.dostring("assert(test:defargfn(6) == 12)"); state.dostring("assert(test:defargfn(6,5) == 30)"); state.dostring("assert(test:defargfn(2,2,2) == 8)"); }
KAGUYA_TEST_FUNCTION_DEF(object_take_const_pointer)(kaguya::State& state) { state["Base"].setClass(kaguya::ClassMetatable<Base>() .addConstructor() .addProperty("a", &Base::a) ); TEST_CHECK(state("fn = function(object,value) object.a = value end")); Base basesrc; basesrc.a = 232; const Base& base = basesrc; state["obj"] = kaguya::standard::ref(base); TEST_CHECK(state("assert(obj.a==232)")); // TEST_CHECK(!state("obj.a = 2"));//cannot assign TEST_CHECK(state("assert(obj.a==232)")); TEST_EQUAL(base.a, 232); basesrc.a = 22; TEST_CHECK(state("assert(obj.a==22)")); state.garbageCollect(); TEST_CHECK(state("assert(obj.a==22)")); // state["fn"](base, 54);//cannot assign TEST_EQUAL(base.a, 22); }
KAGUYA_TEST_FUNCTION_DEF(function_call_error)(kaguya::State& state) { error_count = 0; state.setErrorHandler(error_fun); state["errofun"] = kaguya::function(error_fun); state["errofun"](33); TEST_CHECK(error_count == 1); kaguya::LuaRef f; f.resume<void>(); f.call<void>(); TEST_COMPARE_EQ(f.threadStatus(), LUA_ERRRUN); TEST_COMPARE_EQ(state.newRef(1).threadStatus(), LUA_ERRRUN); }
KAGUYA_TEST_FUNCTION_DEF(defaultarguments)(kaguya::State& state) { state.setErrorHandler(error_fun); state["defargfn"] = kaguya::function(defargfn_wrapper()); state["defargfn2"] = kaguya::function(defargfn_wrapper2()); std::string intname = kaguya::util::pretty_name(typeid(int)); if (intname == "int") { state.dostring("defargfn('abc')"); TEST_CHECK_M(last_error_message.find("[OPT]int,[OPT]int,[OPT]int") != std::string::npos, last_error_message); state.dostring("defargfn2('abc',3)"); TEST_CHECK_M(last_error_message.find("int,int,[OPT]int") != std::string::npos, last_error_message); } }
KAGUYA_TEST_FUNCTION_DEF(luacfunction)(kaguya::State& state) { state["cfunction"] = &cfunction; state.dostring("cfunction(3)"); }
KAGUYA_TEST_FUNCTION_DEF(set_error_function)(kaguya::State& state) { error_count = 0; state.setErrorHandler(error_fun); TEST_CHECK(!state("awdorgkwl;gw")); TEST_CHECK(error_count == 1); state["yy"]["yy"]["yy"](); TEST_CHECK(error_count > 0); }
KAGUYA_TEST_FUNCTION_DEF(nil_to_nullpointer)(kaguya::State& state) { state["pointerfun"] = kaguya::function(pointerfun); TEST_CHECK(state("pointerfun(nil)")); state["const_pointerfun"] = kaguya::function(const_pointerfun); TEST_CHECK(state("const_pointerfun(nil)")); state.setErrorHandler(ignore_error_fun); TEST_CHECK(!state("pointerfun(32)"));// is error TEST_CHECK(!state("pointerfun('232')"));// is error }
void LuaInterfaceBase::Register(kaguya::State& state) { state["RTTRBase"].setClass(kaguya::ClassMetatable<LuaInterfaceBase>() .addMemberFunction("Log", &LuaInterfaceBase::Log) .addMemberFunction("IsHost", &LuaInterfaceBase::IsHost) .addMemberFunction("GetLocalPlayerIdx", &LuaInterfaceBase::GetLocalPlayerIdx) .addMemberFunction("MsgBox", &LuaInterfaceBase::MsgBox) .addMemberFunction("MsgBox", &LuaInterfaceBase::MsgBox2) .addMemberFunction("MsgBoxEx", &LuaInterfaceBase::MsgBoxEx) .addMemberFunction("MsgBoxEx", &LuaInterfaceBase::MsgBoxEx2) ); state.setErrorHandler(ErrorHandler); }
KAGUYA_TEST_FUNCTION_DEF(copy_constructor)(kaguya::State& state) { state["ABC"].setClass(kaguya::ClassMetatable<ABC>() .addConstructor<const char*>() .addConstructor<int>() .addConstructor<std::string>() .addConstructor<int, const std::string&>() .addConstructor<const std::string&, int>() .addMember("getString", &ABC::getString) .addMember("setString", &ABC::setString) .addMember("getInt", &ABC::getInt) .addMember("references", static_cast<ABC& (ABC::*)()>(&ABC::references)) .addMember("references", static_cast<const ABC& (ABC::*)()const>(&ABC::references)) .addMember("const_pointer", &ABC::const_pointer) .addMember("pointer", &ABC::pointer) .addMember("copy", &ABC::copy) .addMember("shared_copy", &ABC::shared_copy) ); TEST_CHECK(state("value = assert(ABC.new(64,'string_value3'))")); TEST_CHECK(state("value2 = assert(value:copy())")); TEST_CHECK(state("assert(value2:getString() == 'string_value3')")); TEST_CHECK(state("assert(value2:getInt() == 64)")); TEST_CHECK(state("value3 = assert(value:references())")); TEST_CHECK(state("cvalue = assert(value:const_pointer())")); TEST_CHECK(state("assert(cvalue:getString() == 'string_value3')")); TEST_CHECK(state("assert(cvalue:getInt() == 64)")); TEST_CHECK(state("assert(value3:getString() == 'string_value3')")); TEST_CHECK(state("assert(value3:getInt() == 64)")); TEST_CHECK(state("value4 = assert(value:pointer())")); TEST_CHECK(state("assert(value4:getString() == 'string_value3')")); TEST_CHECK(state("assert(value4:getInt() == 64)")); TEST_CHECK(state("value5 = assert(value:shared_copy())")); TEST_CHECK(state("value =1")); state.garbageCollect();//warning!! value3 and value4 to dangling pointer TEST_CHECK(state("assert(value5:getString() == 'string_value3')")); TEST_CHECK(state("assert(value5:getInt() == 64)")); { kaguya::standard::shared_ptr<ABC> shared_ptr(new ABC("shared_object", 53)); state["shared_object"] = shared_ptr; } TEST_CHECK(state("assert(shared_object:getInt() == 53)")); TEST_CHECK(state("assert(shared_object:getString() =='shared_object')")); };
KAGUYA_TEST_FUNCTION_DEF(int_constructor)(kaguya::State& state) { state.openlib("test_bind", &luaopen_test_bind); TEST_CHECK(state("value = assert(test_bind.TestClass.new(32))")); TEST_CHECK(state("assert(value:getInt() == 32)")); TEST_CHECK(state("assert(test_bind.squared(3) == 9)")); TEST_CHECK(state("assert(test_bind.submodule.squared(6) == 36)")); TEST_CHECK(state("assert(test_bind.submodule.submodule.squared3(6) == 36)")); TEST_CHECK(state("assert(test_bind.x == 1)")) TEST_CHECK(state("assert(test_bind.ENUM_TEST_TYPE.ENUM_TEST_A == 2)")); TEST_CHECK(state("assert(test_bind.ENUM_TEST_TYPE.ENUM_TEST_B == 4)")); }
KAGUYA_TEST_FUNCTION_DEF(movable_class_test)(kaguya::State& state) { state["MoveOnlyClass"].setClass(kaguya::UserdataMetatable<MoveOnlyClass>() .setConstructors<MoveOnlyClass(int)>() .addProperty("member", &MoveOnlyClass::member) ); state["moveonly"] = MoveOnlyClass(2); const MoveOnlyClass* ref = state["moveonly"]; TEST_CHECK(ref); TEST_CHECK(ref->member == 2); state("func =function(arg) return assert(arg.member == 5) end"); state["func"](MoveOnlyClass(5)); state.newRef(MoveOnlyClass(5)); }
KAGUYA_TEST_FUNCTION_DEF(errorThrowing)(kaguya::State& state) { state["foobar"] = kaguya::overload(foobar1, foobar2, foobar3); state["Foo"].setClass(kaguya::ClassMetatable<Foo>().addConstructor()); state.setErrorHandler(registerError); TEST_CHECK(!state("foobar()")); TEST_EQUAL(errorOccurred, true); TEST_CHECK(lastMsg.find("candidate is:") != std::string::npos); lastMsg = lastMsg.substr(lastMsg.find("candidate is:\n")); lastMsg = lastMsg.substr(0, lastMsg.find("stack ")); std::vector<std::string> parts = remove_empty(split(lastMsg, '\n')); TEST_EQUAL(parts.size(), 4); std::string intName = typeid(int).name(); TEST_CHECK(parts[1].find(intName) != std::string::npos); TEST_CHECK(parts[2].find(intName + "," + intName) != std::string::npos); TEST_CHECK(parts[3].find(intName + "," + typeid(Foo).name() + "," + intName) != std::string::npos); errorOccurred = false; TEST_CHECK(!state("foobar(Foo.new(), 1, 1)")); TEST_EQUAL(errorOccurred, true); TEST_CHECK(lastMsg.find("candidate is:") != std::string::npos); errorOccurred = false; TEST_CHECK(!state("foobar(1)")); TEST_EQUAL(errorOccurred, true); TEST_CHECK(lastMsg.find("MyRuntimeError") != std::string::npos); #ifndef KAGUYA_NO_STD_MAP_TO_TABLE errorOccurred = false; state["noTable"] = 5; std::map<int, int> map = state["noTable"]; TEST_EQUAL(errorOccurred, true); TEST_CHECK(lastMsg.find("type mismatch") != std::string::npos); errorOccurred = false; state["noTable"] = 5; std::vector<int> vec = state["noTable"]; TEST_EQUAL(errorOccurred, true); TEST_CHECK(lastMsg.find("type mismatch") != std::string::npos); #endif }
KAGUYA_TEST_FUNCTION_DEF(object_take_reference)(kaguya::State& state) { state["Base"].setClass(kaguya::ClassMetatable<Base>() .addConstructor() .addProperty("a", &Base::a) ); TEST_CHECK(state("fn = function(object,value) object.a = value end")); Base base; base.a = 232; state["obj"] = kaguya::standard::ref(base); TEST_CHECK(state("assert(obj.a==232)")); TEST_CHECK(state("obj.a = 2")); TEST_CHECK(state("assert(obj.a==2)")); TEST_EQUAL(base.a, 2); state.garbageCollect(); TEST_CHECK(state("assert(obj.a==2)")); state["fn"](kaguya::standard::ref(base), 54); TEST_EQUAL(base.a, 54); }
KAGUYA_TEST_FUNCTION_DEF(native_function_call_test)(kaguya::State& state) { using namespace kaguya::nativefunction; Foo foo; state.newRef(6).push(); state.newRef(9).push(); state.newRef(2).push(); call(state.state(), &free_standing_function); lua_settop(state.state(), 0); state.newRef(&foo).push(); state.newRef("Bar").push(); call(state.state(), &Foo::setBar); #if KAGUYA_USE_CPP11 state.newRef(&foo).push(); state.newRef(9).push(); call(state.state(), [](Foo* foo, int b) { foo->setBar("fromlambda"); }); TEST_EQUAL(foo.bar, "fromlambda"); std::string capture("capture"); call(state.state(), [=](Foo* foo, int b) { foo->setBar(capture + "lambda"); }); TEST_EQUAL(foo.bar, "capturelambda"); #endif lua_settop(state.state(), 0); }
KAGUYA_TEST_FUNCTION_DEF(lua_compare_test)(kaguya::State& s) { using namespace kaguya; s.pushToStack(2); s.pushToStack(2); TEST_CHECK(lua_compare(s.state(), -2, -1, LUA_OPEQ)); TEST_CHECK(lua_compare(s.state(), -2, -1, LUA_OPLE)); TEST_CHECK(!lua_compare(s.state(), -2, -1, LUA_OPLT)); TEST_CHECK(!lua_compare(s.state(), -2, -1, LUA_OPLE + 2));//invalid option s.popFromStack(); s.popFromStack(); s.pushToStack(4); s.pushToStack(2); TEST_CHECK(!lua_compare(s.state(), -2, -1, LUA_OPEQ)); TEST_CHECK(!lua_compare(s.state(), -2, -1, LUA_OPLE)); TEST_CHECK(!lua_compare(s.state(), -2, -1, LUA_OPLT)); TEST_CHECK(!lua_compare(s.state(), -2, -1, LUA_OPLE + 2));//invalid option s.popFromStack(); s.popFromStack(); s.pushToStack(2); s.pushToStack(4); TEST_CHECK(!lua_compare(s.state(), -2, -1, LUA_OPEQ)); TEST_CHECK(lua_compare(s.state(), -2, -1, LUA_OPLE)); TEST_CHECK(lua_compare(s.state(), -2, -1, LUA_OPLT)); TEST_CHECK(!lua_compare(s.state(), -2, -1, LUA_OPLE + 2));//invalid option s.popFromStack(); s.popFromStack(); }
KAGUYA_TEST_FUNCTION_DEF(stackValueDump)(kaguya::State& s) { using namespace kaguya; util::stackValueDump(std::cout, s.state(), 4, 2); }