From f3ba95101aabd9c308ef746db32c6eb7536a5a7f Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 21 Jul 2012 17:53:28 +0100 Subject: SUPPLE.REQUEST: Support requests, responses and deserialising, and test it all --- Makefile | 2 +- lib/supple/request.lua | 82 ++++++++++++++++++++++++++++++++++++++++++++ test/test-supple.request.lua | 66 +++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a90727b..60a1d7e 100644 --- a/Makefile +++ b/Makefile @@ -69,7 +69,7 @@ test: build $(LUA) test/test-$${MOD}.lua; \ test "x$$?" = "x0" || ERR=1; \ done; \ - $(LUA) extras/luacov/src/bin/luacov -X luacov. -X test. $(LMODULES); \ + $(LUA) extras/luacov/src/bin/luacov -X luacov. -X test. $(TEST_MODULES); \ exit $$ERR .PHONY: interactive diff --git a/lib/supple/request.lua b/lib/supple/request.lua index 7f01e99..ab8388a 100644 --- a/lib/supple/request.lua +++ b/lib/supple/request.lua @@ -10,7 +10,14 @@ -- For licence terms, see COPYING -- +local capi = require 'supple.capi' +local objects = require 'supple.objects' + local tconcat = table.concat +local ipairs = ipairs +local select = select +local loadstring = loadstring +local setfenv = setfenv local function serialise_error(errstr, traceback) return tconcat { @@ -20,13 +27,88 @@ local function serialise_error(errstr, traceback) } end +local function _serialise_object(obj, ret) + ret[#ret+1] = "{" + local comma = "" + if obj.type then + ret[#ret+1] = ("type=%q"):format(obj.type) + comma = "," + end + ret[#ret+1] = ("%stag=%q"):format(comma, obj.tag) + if obj.methods then + ret[#ret+1] = ",methods={" + comma = "" + for _, meth in ipairs(obj.methods) do + ret[#ret+1] = ("%s%q"):format(comma, meth) + comma = "," + end + ret[#ret+1] = "}" + end + ret[#ret+1] = "}" +end + local function serialise_request(obj, method, ...) + assert(capi.rawtype(obj) == "string") + assert(capi.rawtype(method) == "string") + local args = { n = select("#", ...), ... } + local ret = { + ("object=%q,"):format(obj), + ("method=%q,"):format(method), + ("args={n=%d"):format(args.n) + } + + for i = 1, args.n do + local v = objects.give(args[i]) + if capi.rawtype(v) == "string" then + ret[#ret+1] = (",%q"):format(v) + elseif capi.rawtype(v) == "table" then + ret[#ret+1] = "," + _serialise_object(v, ret) + else + ret[#ret+1] = "," .. tostring(v) + end + end + + ret[#ret+1] = "}" + return tconcat(ret) end local function serialise_response(...) + local args = { n = select("#", ...), ... } + local ret = { + "error=false,", + ("results={n=%d"):format(args.n) + } + + for i = 1, args.n do + local v = objects.give(args[i]) + if capi.rawtype(v) == "string" then + ret[#ret+1] = (",%q"):format(v) + elseif capi.rawtype(v) == "table" then + ret[#ret+1] = "," + _serialise_object(v, ret) + else + ret[#ret+1] = "," .. tostring(v) + end + end + + ret[#ret+1] = "}" + return tconcat(ret) end local function deserialise_entity(entity) + local str = ("return {%s}"):format(entity) + local fn = assert(loadstring(str)) + setfenv(fn, {}) + local res = fn() + local walk = res.args or res.results + if walk then + assert(walk.n, "Elements missing 'n'") + for i = 1, walk.n do + walk[i] = objects.receive(walk[i]) + end + end + return res end return { diff --git a/test/test-supple.request.lua b/test/test-supple.request.lua index 5413cd8..6ed5f5b 100644 --- a/test/test-supple.request.lua +++ b/test/test-supple.request.lua @@ -12,6 +12,7 @@ local luacov = require 'luacov' local request = require 'supple.request' +local objects = require 'supple.objects' local testnames = {} @@ -34,7 +35,72 @@ function suite.serialise_error() local err = request.error("m","tb") assert(err == [[error=true,message="m",traceback="tb"]], "Error did not serialise properly") +end + +function suite.serialise_request_simple() + local req = request.request("TAG", "METH", "arg1", true) + local tab = assert(loadstring("return {" .. req .. "}"))() + assert(tab.object == "TAG", "object tag not passed") + assert(tab.method == "METH", "method name not passed") + assert(tab.args.n == 2, "argument count not passed") + assert(tab.args[1] == "arg1", "arg1 not passed") + assert(tab.args[2] == true, "arg2 not passed") +end + +function suite.serialise_request_simple_table() + local argtab = {} + local req = request.request("TAG", "METH", argtab) + local tab = assert(loadstring("return {" .. req .. "}"))() + assert(tab.object == "TAG", "object tag not passed") + assert(tab.method == "METH", "method name not passed") + assert(tab.args.n == 1, "argument count not passed") + -- Best check that the received arg unwraps nicely + assert(objects.receive(tab.args[1]) == argtab, "arg did not unwrap") +end + +function suite.serialise_request_table_with_index() + local argtab = setmetatable({}, { __index = {} }) + local req = request.request("TAG", "METH", argtab) + local tab = assert(loadstring("return {" .. req .. "}"))() + assert(tab.object == "TAG", "object tag not passed") + assert(tab.method == "METH", "method name not passed") + assert(tab.args.n == 1, "argument count not passed") + assert(tab.args[1].methods[1] == "__index", "metamethod didn't pass") + -- Best check that the received arg unwraps nicely + assert(objects.receive(tab.args[1]) == argtab, "arg did not unwrap") +end + +function suite.serialise_response_simple() + local req = request.response("foo",12) + local tab = assert(loadstring("return {" .. req .. "}"))() + assert(tab.error == false, "error wasn't false") + assert(type(tab.results) == "table", "results were missing") + assert(tab.results.n == 2, "Result count not passed") + assert(tab.results[1] == "foo", "result 1 not passed") + assert(tab.results[2] == 12, "result 2 not passed") +end + +function suite.serialise_response_table() + local argtab = {} + local req = request.response(argtab) + local tab = assert(loadstring("return {" .. req .. "}"))() + assert(tab.error == false, "error wasn't false") + assert(type(tab.results) == "table", "results were missing") + assert(tab.results.n == 1, "Result count not passed") + assert(type(tab.results[1]) == "table", "result 1 not passed") + assert(objects.receive(tab.results[1]) == argtab, + "arg did not unwrap") +end +function suite.deserialise() + local argtab = {} + local req = request.response(argtab) + local tab = request.deserialise(req) + assert(tab.error == false, "error wasn't false") + assert(type(tab.results) == "table", "results were missing") + assert(tab.results.n == 1, "Result count not passed") + assert(type(tab.results[1]) == "table", "result 1 not passed") + assert(tab.results[1] == argtab, "arg did not unwrap") end local count_ok = 0 -- cgit v1.2.1