summaryrefslogtreecommitdiff
path: root/server/src/luaquerymapper.cc
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/luaquerymapper.cc')
-rw-r--r--server/src/luaquerymapper.cc121
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;
}