diff options
Diffstat (limited to 'server/src/luaquerymapper.cc')
-rw-r--r-- | server/src/luaquerymapper.cc | 121 |
1 files changed, 89 insertions, 32 deletions
diff --git a/server/src/luaquerymapper.cc b/server/src/luaquerymapper.cc index d6ec531..7ee43ff 100644 --- a/server/src/luaquerymapper.cc +++ b/server/src/luaquerymapper.cc @@ -28,8 +28,6 @@ #include <sstream> -#include "exception.h" - static std::string loadresultstring(QueryResult &res, std::string group = "") { std::string s; @@ -46,7 +44,7 @@ static std::string loadresultstring(QueryResult &res, std::string group = "") std::map< std::string, QueryResult >::iterator g = res.groups.begin(); while(g != res.groups.end()) { - if(group + (*g).first != "") s += group + (*g).first + " = {}\n"; + s += group + (*g).first + " = {}\n"; s += loadresultstring((*g).second, group + (*g).first + "."); g++; } @@ -54,8 +52,10 @@ static std::string loadresultstring(QueryResult &res, std::string group = "") return s; } -LUAQueryMapper::LUAQueryMapper() +LUAQueryMapper::LUAQueryMapper() throw(Exception) { + clean_top = -1; + L = luaL_newstate(); if(L == NULL) { error("Could not create LUA state."); @@ -69,16 +69,15 @@ LUAQueryMapper::LUAQueryMapper() LUAQueryMapper::~LUAQueryMapper() { - lua_close(L); + if(L) lua_close(L); } -void LUAQueryMapper::addQueryResult(QueryResult &result) +void LUAQueryMapper::addQueryResult(QueryResult &result) throw(Exception) { std::string preload = loadresultstring(result); PRACRO_DEBUG(querymapper, "Preload:\n%s\n", preload.c_str()); - if(luaL_loadbuffer(L, preload.c_str(), preload.size(), "preload")) { error(lua_tostring(L, lua_gettop(L))); return; @@ -93,7 +92,7 @@ void LUAQueryMapper::addQueryResult(QueryResult &result) clean_top = lua_gettop(L); } -Value LUAQueryMapper::map(const std::string &mapper) +Value LUAQueryMapper::map(const std::string &mapper) throw(Exception) { Value v; @@ -123,17 +122,13 @@ Value LUAQueryMapper::map(const std::string &mapper) // Check if app messed up the stack. if(lua_gettop(L) != clean_top + 3) { - error("Wrong number of return values in " + mapper); - lua_pop(L, lua_gettop(L) - clean_top); + error("Wrong number of return values (should be value, timestamp, source) in " + mapper); return v; } - // value, timestamp, source - // Check if the types are right if(lua_isstring(L, lua_gettop(L)) == false) { error("Source is not a string in " + mapper); - lua_pop(L, 3); return v; } v.source = lua_tostring(L, lua_gettop(L)); @@ -142,7 +137,6 @@ Value LUAQueryMapper::map(const std::string &mapper) // Check if the types are right if(lua_isnumber(L, lua_gettop(L)) == false) { error("Timestamp is not an integer in " + mapper); - lua_pop(L, 2); return v; } v.timestamp = lua_tointeger(L, lua_gettop(L)); @@ -151,7 +145,6 @@ Value LUAQueryMapper::map(const std::string &mapper) // Check if the types are right if(lua_isstring(L, lua_gettop(L)) == false) { error("Value is not a string in " + mapper); - lua_pop(L, 1); return v; } v.value = lua_tostring(L, lua_gettop(L)); @@ -163,42 +156,106 @@ Value LUAQueryMapper::map(const std::string &mapper) return v; } -void LUAQueryMapper::error(std::string message) +void LUAQueryMapper::error(std::string message) throw(Exception) { + if(clean_top != -1) lua_pop(L, lua_gettop(L) - clean_top); // Clean up stack throw Exception("ERROR in LUAQueryMapper: " + message); } #ifdef TEST_LUAQUERYMAPPER -#include "queryhandlerpentominos.h" -#include "queryparser.h" -#include "tcpsocket.h" - int main() { - TCPSocket s; - s.connect("localhost", 11108); - - QueryHandlerPentominos qh(&s, "2003791613"); + QueryResult res; - Query q1; - q1.attributes["device_id"] = "lensmeter"; - q1.attributes["device_type"] = "lensmeter"; + time_t now = time(NULL); - QueryResult res = qh.exec(q1); + res.groups["test"].timestamp = now; + res.groups["test"].source = "test app"; + res.groups["test"].values["somevalue"] = "hello world"; + res.groups["test"].values["pi"] = "3.1416"; printf("%s\n", loadresultstring(res).c_str()); LUAQueryMapper mapper; mapper.addQueryResult(res); - std::string luamap = "return status.errstr.value, 0, 0"; + // Test simple value forwarding + std::string luamap = "return test.somevalue.value, test.somevalue.timestamp, test.somevalue.source"; Value value = mapper.map(luamap); - printf("%s : %s, %lu\n", luamap.c_str(), value.value.c_str(), value.timestamp); + printf("%s =>\n %s, %lu, %s\n", luamap.c_str(), value.value.c_str(), value.timestamp, value.source.c_str()); + if(value.value != "hello world" || value.timestamp != now || value.source != "test app") + return 1; + + // Do some calculations + luamap = "return 2 * tonumber(test.pi.value), test.pi.timestamp, test.pi.source"; + value = mapper.map(luamap); + printf("%s =>\n %s, %lu, %s\n", luamap.c_str(), value.value.c_str(), value.timestamp, value.source.c_str()); + if(value.value != "6.2832" || value.timestamp != now || value.source != "test app") + return 1; + + // Attempt to access nonexisting value (should throw an exception) + try { + luamap = "return test.somevalue2.value, test.somevalue2.timestamp, test.somevalue2.source"; + value = mapper.map(luamap); + printf("%s =>\n %s, %lu, %s\n", luamap.c_str(), value.value.c_str(), value.timestamp, value.source.c_str()); + if(value.value != "hello world" || value.timestamp != now || value.source != "test app") + return 1; + } catch(Exception &e) { + printf("ERROR: %s\n", e.what()); + goto onandon; + } + return 1; + onandon: + + // Attempt to access nonexisting group (should throw an exception) + try { + luamap = "return test2.somevalue.value, test2.somevalue.timestamp, test2.somevalue.source"; + value = mapper.map(luamap); + printf("%s =>\n %s, %lu, %s\n", luamap.c_str(), value.value.c_str(), value.timestamp, value.source.c_str()); + if(value.value != "hello world" || value.timestamp != now || value.source != "test app") + return 1; + } catch(Exception &e) { + printf("ERROR: %s\n", e.what()); + goto stillonandon; + } + return 1; + stillonandon: + + // Switch order of return vars (should throw an exception) + try { + luamap = "return test.somevalue.source, test.somevalue.value, test.somevalue.timestamp"; + value = mapper.map(luamap); + printf("%s =>\n %s, %lu, %s\n", luamap.c_str(), value.value.c_str(), value.timestamp, value.source.c_str()); + if(value.value != "hello world" || value.timestamp != now || value.source != "test app") + return 1; + } catch(Exception &e) { + printf("ERROR: %s\n", e.what()); + goto onandonagain; + } + return 1; + onandonagain: + + // Syntax error (should throw an exception) + try { + luamap = "this(is{] not() - a != legal lua program!]"; + value = mapper.map(luamap); + printf("%s =>\n %s, %lu, %s\n", luamap.c_str(), value.value.c_str(), value.timestamp, value.source.c_str()); + if(value.value != "hello world" || value.timestamp != now || value.source != "test app") + return 1; + } catch(Exception &e) { + printf("ERROR: %s\n", e.what()); + goto stillonandonagain; + } + return 1; + stillonandonagain: - luamap = "return math.sin(status.errstr.timestamp) * 2, 0, 0"; + // And finally test if we haven't broken enything while being hostile to the lua engine... + luamap = "return test.somevalue.value, test.somevalue.timestamp, test.somevalue.source"; value = mapper.map(luamap); - printf("%s : %s, %lu\n", luamap.c_str(), value.value.c_str(), value.timestamp); + printf("%s =>\n %s, %lu, %s\n", luamap.c_str(), value.value.c_str(), value.timestamp, value.source.c_str()); + if(value.value != "hello world" || value.timestamp != now || value.source != "test app") + return 1; return 0; } |