#include "StarLua.hpp" #include "gtest/gtest.h" using namespace Star; TEST(LuaJsonTest, Scope) { auto engine = LuaEngine::create(); auto script1 = engine->compile( R"SCRIPT( function increment() self.called = self.called + 1 return self.called end )SCRIPT"); auto script2 = engine->compile( R"SCRIPT( global = 42 function increment() self.called = self.called + 1 return self.called end )SCRIPT"); auto context1 = engine->createContext(); auto context2 = engine->createContext(); context1.load(script1); context2.load(script2); context1.setPath("self", JsonObject{{"called", 0}}); context2.setPath("self", JsonObject{{"called", 0}}); EXPECT_TRUE(context1.contains("self")); EXPECT_TRUE(context1.contains("increment")); EXPECT_EQ(context1.invokePath("increment"), 1); EXPECT_EQ(context1.invokePath("increment"), 2); EXPECT_EQ(context1.invokePath("increment"), 3); EXPECT_EQ(context2.invokePath("increment"), 1); EXPECT_EQ(context1.invokePath("increment"), 4); EXPECT_EQ(context2.invokePath("increment"), 2); auto context3 = engine->createContext(); context3.load(script2); context3.setPath("self", JsonObject{{"called", 0}}); EXPECT_EQ(context2.invokePath("increment"), 3); EXPECT_EQ(context3.invokePath("increment"), 1); EXPECT_EQ(context1.invokePath("increment"), 5); EXPECT_FALSE(context1.contains("global")); EXPECT_TRUE(context3.contains("global")); } TEST(LuaJsonTest, FunkyRecursion) { auto engine = LuaEngine::create(); auto context1 = engine->createContext(); context1.load( R"SCRIPT( mine = 1 function util() mine = 1 return mine end function util3() mine = 1 return callbacks.util2() end )SCRIPT"); auto context2 = engine->createContext(); context2.load( R"SCRIPT( mine = 2 function util2() return 4 end function entry() local other = callbacks.util() return {other, mine} end function entry2() local other = callbacks.util2() return {other, mine} end function entry3() local other = callbacks.util3() return {other, mine} end )SCRIPT"); LuaCallbacks callbacks; callbacks.registerCallback("util", [&context1]() -> Json { return context1.invokePath("util"); }); callbacks.registerCallback("util2", [&context2]() -> Json { return context2.invokePath("util2"); }); callbacks.registerCallback("util3", [&context1]() -> Json { return context1.invokePath("util3"); }); context1.setCallbacks("callbacks", callbacks); context2.setCallbacks("callbacks", callbacks); auto res = context2.invokePath("entry"); EXPECT_EQ(res.get(0), 1); EXPECT_EQ(res.get(1), 2); auto res2 = context2.invokePath("entry2"); EXPECT_EQ(res2.get(0), 4); EXPECT_EQ(res2.get(1), 2); auto res3 = context2.invokePath("entry3"); EXPECT_EQ(res3.get(0), 4); EXPECT_EQ(res3.get(1), 2); } TEST(LuaJsonTest, TypeConversion) { auto engine = LuaEngine::create(); auto context = engine->createContext(); context.load( R"SCRIPT( var1 = "1" var2 = {} )SCRIPT"); EXPECT_EQ(context.getPath("var1"), "1"); EXPECT_EQ(context.getPath("var1"), 1.0); EXPECT_EQ(context.getPath("var2"), JsonArray()); EXPECT_EQ(context.getPath("var2"), JsonObject()); } TEST(LuaJsonTest, ChunkBoundaries) { auto engine = LuaEngine::create(); auto context = engine->createContext(); context.load( R"SCRIPT( function func() return env.thing() end )SCRIPT"); context.load( R"SCRIPT( env = {} function env.thing() local temp = { foo = extern.var } return temp.foo end )SCRIPT"); context.setPath("extern", JsonObject{{"var", 1}}); EXPECT_EQ(context.invokePath("func"), 1); } TEST(LuaJsonTest, CustomObjectType) { auto engine = LuaEngine::create(); auto context = engine->createContext(); context.load( R"SCRIPT( function createObject() map = jobject() map.foo = 'hello' map.bar = nil map.baz = nil return map end function handleObject(arg) arg.bar = 'noodles' arg.test1 = jarray() arg.test2 = jobject() return arg end function iteratePairs() local map = jobject() map.foo = 1 map.foo = nil map.bar = 1 local keys = {} for key, val in pairs(map) do table.insert(keys, key) end return keys end function nilsRemoved() local map = jobject() map.foo = 1 map.foo = nil return rawget(map, "foo") end function removeObject(arg, key) jremove(arg, key) return arg end )SCRIPT"); JsonObject test = context.invokePath("createObject"); JsonObject comp = {{"foo", "hello"}, {"bar", Json()}, {"baz", Json()}}; EXPECT_EQ(test, comp); test = context.invokePath("handleObject", JsonObject{ {"foo", JsonArray()}, {"bar", Json()}, {"baz", "hunky dory"}, {"baf", Json()} }); comp = { {"foo", JsonArray()}, {"bar", "noodles"}, {"baz", "hunky dory"}, {"baf", Json()}, {"test1", JsonArray()}, {"test2", JsonObject()} }; EXPECT_EQ(test, comp); JsonArray testArray = context.invokePath("iteratePairs"); JsonArray compArray = {"bar"}; EXPECT_EQ(testArray, compArray); Json testValue = context.invokePath("nilsRemoved"); EXPECT_EQ(testValue, Json()); Json testValue2 = context.invokePath("removeObject", JsonObject{{"foo", 1}, {"bar", Json()}, {"baz", Json()}}, "bar"); Json compValue2 = JsonObject{{"foo", 1}, {"baz", Json()}}; EXPECT_EQ(testValue2, compValue2); } TEST(LuaJsonTest, CustomArrayType) { auto engine = LuaEngine::create(); auto context = engine->createContext(); context.load( R"SCRIPT( function createArray() list = jarray() list[1] = 1 list[2] = 1 list[3] = 1 list[7] = 1 list[12] = nil return list end function handleArray(arg) arg[1] = 'noodles' arg[4] = jarray() arg[9] = jobject() arg[10] = nil return arg end function iteratePairs() local list = jarray() list[1] = 1 list[5] = nil list[4] = 1 list[9] = nil local keys = {} for key, val in pairs(list) do table.insert(keys, key) end return keys end function resizeArray(arg, size) jresize(arg, size) return arg end function listSize(list) return jsize(list) end function listSize2() return jsize({1, 1, 1, 1, 1}) end )SCRIPT"); JsonArray test = context.invokePath("createArray"); JsonArray comp = { 1, 1, 1, {}, {}, {}, 1, {}, {}, {}, {}, {}, }; EXPECT_EQ(test, comp); test = context.invokePath("handleArray", JsonArray{ 2, {}, 5, 6, {}, {}, "omg", }); comp = { "noodles", {}, 5, JsonArray{}, {}, {}, "omg", {}, JsonObject{}, {}, }; EXPECT_EQ(test, comp); JsonArray testArray = context.invokePath("iteratePairs"); JsonArray compArray = {1, 4}; EXPECT_EQ(testArray, compArray); JsonArray testArray2 = context.invokePath("resizeArray", JsonArray{1, 2, 3, 4, 5, Json(), Json(), 8}, 4); JsonArray compArray2 = {1, 2, 3, 4}; EXPECT_EQ(testArray2, compArray2); JsonArray testArray3 = context.invokePath("resizeArray", JsonArray{1, 2, 3, 4}, 6); JsonArray compArray3 = {1, 2, 3, 4, Json(), Json()}; EXPECT_EQ(testArray3, compArray3); Json test4 = context.invokePath("listSize", JsonArray{1, 2, 3, 4, Json(), Json(), Json()}); EXPECT_EQ(test4, 7); EXPECT_EQ(context.invokePath("listSize2"), Json(5)); } TEST(LuaJsonTest, CustomArrayType2) { auto engine = LuaEngine::create(); auto context = engine->createContext(); context.load( R"SCRIPT( function doTest() sampleTable = jobject() sampleTable[18] = 0 sampleTable[37] = 0 targetTable = jobject() for k, v in pairs(sampleTable) do targetTable[k] = v end return targetTable end function arrayLogic1() l = {} l[1] = "foo" l[2] = "bar" return l end function arrayLogic2() l = {} l[1] = "foo" l[2.1] = "bar" return l end function arrayLogic3() l = jarray() l[1] = "foo" l[2] = "bar" return l end )SCRIPT"); JsonObject test = context.invokePath("doTest"); JsonObject comp = {{"18", 0}, {"37", 0}}; EXPECT_EQ(test, comp); Json arrayTest1 = context.invokePath("arrayLogic1"); Json arrayComp1 = JsonArray{"foo", "bar"}; EXPECT_EQ(arrayTest1, arrayComp1); Json arrayTest2 = context.invokePath("arrayLogic2"); Json arrayComp2 = JsonObject{{"1", "foo"}, {"2.1", "bar"}}; EXPECT_EQ(arrayTest2, arrayComp2); Json arrayTest3 = context.invokePath("arrayLogic3"); Json arrayComp3 = JsonArray{"foo", "bar"}; EXPECT_EQ(arrayTest3, arrayComp3); } TEST(LuaJsonTest, IntFloat) { auto engine = LuaEngine::create(); auto context = engine->createContext(); context.load( R"SCRIPT( function returnFloat() return 1.0 end function returnInt() return 1 end function printNumber(n) return tostring(n) end )SCRIPT"); EXPECT_TRUE(context.invokePath("returnFloat").isType(Json::Type::Float)); EXPECT_TRUE(context.invokePath("returnInt").isType(Json::Type::Int)); EXPECT_EQ(context.invokePath("printNumber", 1.0), "1.0"); EXPECT_EQ(context.invokePath("printNumber", 1), "1"); }