summaryrefslogtreecommitdiff
path: root/t/proxyunits.lua
diff options
context:
space:
mode:
Diffstat (limited to 't/proxyunits.lua')
-rw-r--r--t/proxyunits.lua234
1 files changed, 234 insertions, 0 deletions
diff --git a/t/proxyunits.lua b/t/proxyunits.lua
new file mode 100644
index 0000000..6b492b4
--- /dev/null
+++ b/t/proxyunits.lua
@@ -0,0 +1,234 @@
+mcp.backend_read_timeout(0.5)
+
+function mcp_config_pools(oldss)
+ local srv = mcp.backend
+
+ -- Single backend for zones to ease testing.
+ -- For purposes of this config the proxy is always "zone 1" (z1)
+ local b1 = srv('b1', '127.0.0.1', 11411)
+ local b2 = srv('b2', '127.0.0.1', 11412)
+ local b3 = srv('b3', '127.0.0.1', 11413)
+
+ local b1z = {b1}
+ local b2z = {b2}
+ local b3z = {b3}
+
+ -- convert the backends to pools.
+ -- as per a normal full config see simple.lua or t/startfile.lua
+ local zones = {
+ z1 = mcp.pool(b1z),
+ z2 = mcp.pool(b2z),
+ z3 = mcp.pool(b3z),
+ }
+
+ return zones
+end
+
+-- WORKER CODE:
+
+-- Using a very simple route handler only to allow testing the three
+-- workarounds in the same configuration file.
+function prefix_factory(pattern, list, default)
+ local p = pattern
+ local l = list
+ local d = default
+ return function(r)
+ local route = l[string.match(r:key(), p)]
+ if route == nil then
+ return d(r)
+ end
+ return route(r)
+ end
+end
+
+-- just for golfing the code in mcp_config_routes()
+function toproute_factory(pfx, label)
+ local err = "SERVER_ERROR no " .. label .. " route\r\n"
+ return prefix_factory("^/(%a+)/", pfx, function(r) return err end)
+end
+
+-- Do specialized testing based on the key prefix.
+function mcp_config_routes(zones)
+ local pfx_get = {}
+ local pfx_set = {}
+ local pfx_touch = {}
+ local pfx_gets = {}
+ local pfx_gat = {}
+ local pfx_gats = {}
+ local pfx_cas = {}
+ local pfx_add = {}
+ local pfx_delete = {}
+ local pfx_incr = {}
+ local pfx_decr = {}
+ local pfx_append = {}
+ local pfx_prepend = {}
+ local pfx_mg = {}
+ local pfx_ms = {}
+ local pfx_md = {}
+ local pfx_ma = {}
+
+ local basic = function(r)
+ return zones.z1(r)
+ end
+
+ pfx_get["b"] = basic
+ pfx_set["b"] = basic
+ pfx_touch["b"] = basic
+ pfx_gets["b"] = basic
+ pfx_gat["b"] = basic
+ pfx_gats["b"] = basic
+ pfx_cas["b"] = basic
+ pfx_add["b"] = basic
+ pfx_delete["b"] = basic
+ pfx_incr["b"] = basic
+ pfx_decr["b"] = basic
+ pfx_append["b"] = basic
+ pfx_prepend["b"] = basic
+ pfx_mg["b"] = basic
+ pfx_ms["b"] = basic
+ pfx_md["b"] = basic
+ pfx_ma["b"] = basic
+
+ -- show that we fetched the key by generating our own response string.
+ pfx_get["getkey"] = function(r)
+ return "VALUE |" .. r:key() .. " 0 2\r\nts\r\nEND\r\n"
+ end
+
+ pfx_get["rtrimkey"] = function(r)
+ r:rtrimkey(4)
+ return zones.z1(r)
+ end
+
+ pfx_get["ltrimkey"] = function(r)
+ r:ltrimkey(10)
+ return zones.z1(r)
+ end
+
+ -- Basic test for routing requests to specific pools.
+ -- Not sure how this could possibly break but testing for completeness.
+ pfx_get["zonetest"] = function(r)
+ local key = r:key()
+ if key == "/zonetest/a" then
+ return zones.z1(r)
+ elseif key == "/zonetest/b" then
+ return zones.z2(r)
+ elseif key == "/zonetest/c" then
+ return zones.z3(r)
+ else
+ return "END\r\n"
+ end
+ end
+
+ pfx_get["logtest"] = function(r)
+ mcp.log("testing manual log messages")
+ return "END\r\n"
+ end
+
+ pfx_get["logreqtest"] = function(r)
+ local res = zones.z1(r)
+ mcp.log_req(r, res, "logreqtest")
+ return res
+ end
+
+ -- tell caller what we got back via a fake response
+ pfx_get["awaitbasic"] = function(r)
+ local vals = {}
+ local rtable = mcp.await(r, { zones.z1, zones.z2, zones.z3 })
+
+ for i, res in pairs(rtable) do
+ if res:hit() == true then
+ vals[i] = "hit"
+ elseif res:ok() == true then
+ vals[i] = "ok"
+ else
+ vals[i] = "err"
+ end
+ end
+
+ local val = table.concat(vals, " ")
+ local vlen = string.len(val)
+ -- convenience functions for creating responses would be nice :)
+ return "VALUE " .. r:key() .. " 0 " .. vlen .. "\r\n" .. val .. "\r\nEND\r\n"
+ end
+
+ pfx_get["awaitone"] = function(r)
+ local mode = string.sub(r:key(), -1, -1)
+ local num = 0
+ if mode == "a" then
+ num = 1
+ elseif mode == "b" then
+ num = 2
+ end
+ local rtable = mcp.await(r, { zones.z1, zones.z2, zones.z3 }, num)
+
+ local count = 0
+ for i, res in pairs(rtable) do
+ count = count + 1
+ end
+
+ local vlen = string.len(count)
+ return "VALUE " .. r:key() .. " 0 " .. vlen .. "\r\n" .. count .. "\r\nEND\r\n"
+ end
+
+ -- should be the same as awaitone
+ pfx_get["awaitgood"] = function(r)
+ local mode = string.sub(r:key(), -1, -1)
+ local num = 0
+ if mode == "a" then
+ num = 1
+ elseif mode == "b" then
+ num = 2
+ end
+ local rtable = mcp.await(r, { zones.z1, zones.z2, zones.z3 }, num, mcp.AWAIT_GOOD)
+
+ local count = 0
+ for i, res in pairs(rtable) do
+ count = count + 1
+ end
+
+ local vlen = string.len(count)
+ return "VALUE " .. r:key() .. " 0 " .. vlen .. "\r\n" .. count .. "\r\nEND\r\n"
+ end
+
+ -- not sure if anything else should be checked here? if err or not?
+ pfx_get["awaitany"] = function(r)
+ local rtable = mcp.await(r, { zones.z1, zones.z2, zones.z3 }, 2, mcp.AWAIT_ANY)
+ local count = 0
+ for i, res in pairs(rtable) do
+ count = count + 1
+ end
+
+ local vlen = string.len(count)
+ return "VALUE " .. r:key() .. " 0 " .. vlen .. "\r\n" .. count .. "\r\nEND\r\n"
+ end
+
+ pfx_get["awaitbg"] = function(r)
+ local rtable = mcp.await(r, { zones.z1, zones.z2, zones.z3 }, 1, mcp.AWAIT_BACKGROUND)
+ local count = 0
+ for i, res in pairs(rtable) do
+ count = count + 1
+ end
+
+ local vlen = string.len(count)
+ return "VALUE " .. r:key() .. " 0 " .. vlen .. "\r\n" .. count .. "\r\nEND\r\n"
+ end
+
+ mcp.attach(mcp.CMD_GET, toproute_factory(pfx_get, "get"))
+ mcp.attach(mcp.CMD_SET, toproute_factory(pfx_set, "set"))
+ mcp.attach(mcp.CMD_TOUCH, toproute_factory(pfx_touch, "touch"))
+ mcp.attach(mcp.CMD_GETS, toproute_factory(pfx_gets, "gets"))
+ mcp.attach(mcp.CMD_GAT, toproute_factory(pfx_gat, "gat"))
+ mcp.attach(mcp.CMD_GATS, toproute_factory(pfx_gats, "gats"))
+ mcp.attach(mcp.CMD_CAS, toproute_factory(pfx_cas, "cas"))
+ mcp.attach(mcp.CMD_ADD, toproute_factory(pfx_add, "add"))
+ mcp.attach(mcp.CMD_DELETE, toproute_factory(pfx_delete, "delete"))
+ mcp.attach(mcp.CMD_INCR, toproute_factory(pfx_incr, "incr"))
+ mcp.attach(mcp.CMD_DECR, toproute_factory(pfx_decr, "decr"))
+ mcp.attach(mcp.CMD_APPEND, toproute_factory(pfx_append, "append"))
+ mcp.attach(mcp.CMD_PREPEND, toproute_factory(pfx_prepend, "prepend"))
+ mcp.attach(mcp.CMD_MG, toproute_factory(pfx_mg, "mg"))
+ mcp.attach(mcp.CMD_MS, toproute_factory(pfx_ms, "ms"))
+ mcp.attach(mcp.CMD_MD, toproute_factory(pfx_md, "md"))
+ mcp.attach(mcp.CMD_MA, toproute_factory(pfx_ma, "ma"))
+
+end