Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
write tests, fix bugs, repeat.
Browse files Browse the repository at this point in the history
dormando committed Apr 4, 2024
1 parent 813ce48 commit cb903b4
Showing 3 changed files with 143 additions and 5 deletions.
4 changes: 2 additions & 2 deletions proxy_luafgen.c
Original file line number Diff line number Diff line change
@@ -1146,7 +1146,7 @@ void mcp_run_rcontext_handle(mcp_rcontext_t *rctx, int handle) {
static inline void _mcplib_set_rctx_alarm(lua_State *L, mcp_rcontext_t *rctx, int arg) {
int isnum = 0;
// TODO: keep this float conversion or milliseconds directly?
lua_Number secondsf = lua_tonumberx(L, 4, &isnum);
lua_Number secondsf = lua_tonumberx(L, arg, &isnum);
if (!isnum) {
proxy_lua_error(L, "timeout argument to wait_cond must be a number");
return;
@@ -1249,7 +1249,7 @@ int mcplib_rcontext_enqueue_and_wait(lua_State *L) {
}

if (!isnum) {
proxy_lua_error(L, "invalid handle passed to wait_handle");
proxy_lua_error(L, "invalid handle passed to enqueue_and_wait");
return 0;
}

83 changes: 83 additions & 0 deletions t/proxyrctxtimeout.lua
Original file line number Diff line number Diff line change
@@ -41,11 +41,94 @@ function cond_timeout(p)
return fgen
end

function enqueue_timeout(p)
local fgen = mcp.funcgen_new()
local near = fgen:new_handle(p.z1)
local far = { fgen:new_handle(p.z2),
fgen:new_handle(p.z3) }

local all = { near, far[1], far[2] }
fgen:ready({ n = "enqueue_timeout", f = function(rctx)
return function(r)
local nres, timeout = rctx:enqueue_and_wait(r, near, 0.5)

if timeout then
rctx:enqueue(r, far)
local done = rctx:wait_cond(1, mcp.WAIT_GOOD)
for x=1,#all do
local res = rctx:res_any(all[x])
if res then
return res
end
end
return "SERVER_ERROR no responses\r\n"
else
return nres
end
end
end})
return fgen
end

function wait_handle_timeout(p)
local fgen = mcp.funcgen_new()
local near = fgen:new_handle(p.z1)
local far = { fgen:new_handle(p.z2),
fgen:new_handle(p.z3) }

local all = { near, far[1], far[2] }
fgen:ready({ n = "handle_timeout", f = function(rctx)
return function(r)
rctx:enqueue(r, near)
local nres, timeout = rctx:wait_handle(near, 0.5)

if timeout then
rctx:enqueue(r, far)
local done = rctx:wait_cond(1, mcp.WAIT_GOOD)
for x=1,#all do
local res = rctx:res_any(all[x])
if res then
return res
end
end
return "SERVER_ERROR no responses\r\n"
else
return nres
end
end
end})
return fgen
end

function wait_more(p)
local fgen = mcp.funcgen_new()
local near = fgen:new_handle(p.z1)

fgen:ready({ n = "wait_more", f = function(rctx)
return function(r)
rctx:enqueue(r, near)
local nres, timeout = rctx:wait_handle(near, 0.25)

-- wait on the same handle twice.
if timeout then
local xres = rctx:wait_handle(near)
return xres
else
return "SERVER_ERROR no timeout\r\n"
end
end
end})
return fgen
end

-- TODO: different cond_timeout test with 2/3 instead of 1

function mcp_config_routes(p)
local map = {
["cond_timeout"] = cond_timeout(p),
["enqueue_timeout"] = enqueue_timeout(p),
["handle_timeout"] = wait_handle_timeout(p),
["wait_more"] = wait_more(p),
}

-- defaults are fine. "prefix/etc"
61 changes: 58 additions & 3 deletions t/proxyrctxtimeout.t
Original file line number Diff line number Diff line change
@@ -27,20 +27,75 @@ $ps->autoflush(1);
$t->set_c($ps);
$t->accept_backends();

subtest 'cond_timeout' => sub {
subtest 'no timeout' => sub {
# first response is good
$t->c_send("mg cond_timeout/foo\r\n");
$t->be_recv_c(0);
$t->be_send(0, "HD\r\n");
$t->c_recv_be();
$t->clear();
};

# first response times out.
subtest 'first req times out' => sub {
$t->c_send("mg cond_timeout/boo t\r\n");
$t->be_recv_c([1,2], "far backends received requests");
$t->be_recv_c(0, "near req still arrived");
$t->be_send([1,2], "HD t90\r\n");
# This should delay, then complete.
$t->c_recv_be();
# Should get eaten.
$t->be_send(0, "HD t40\r\n");
$t->clear();
};

subtest 'first req times out, but still returns' => sub {
$t->c_send("mg cond_timeout/qoo t\r\n");
$t->be_recv_c([1,2], "near timeout, far received req");
$t->be_recv_c(0, "near received request");

$t->be_send(0, "HD t14\r\n");
$t->c_recv_be("near timed out but client got its response");
# returned but doesn't go anywhere.
$t->be_send([1,2], "HD t17\r\n");
$t->clear();
};

subtest 'enqueue_timeout' => sub {
$t->c_send("mg enqueue_timeout/foo t\r\n");
$t->be_recv_c([1,2], "near timeout, far received req");
$t->be_recv_c(0, "near req still arrived");
$t->be_send([1,2], "HD t91\r\n");
$t->c_recv_be();
$t->be_send(0, "HD t15\r\n");
$t->clear();
};

subtest 'handle_timeout' => sub {
$t->c_send("mg handle_timeout/foo t\r\n");
$t->be_recv_c([1,2], "near timeout, far received req");
$t->be_recv_c(0, "near req still arrived");
$t->be_send([1,2], "HD t92\r\n");
$t->c_recv_be();
$t->be_send(0, "HD t16\r\n");
$t->clear();
};

subtest 'wait on the same handle twice' => sub {
$t->c_send("mg wait_more/foo t\r\n");
$t->be_recv_c(0, "near got request");
# Let it internally time out.
sleep 0.75;
pass("short sleep");
$t->be_send(0, "HD t93\r\n");
$t->c_recv_be();
$t->clear();
};

subtest 'wait handle no timeout' => sub {
$t->c_send("mg wait_more/foo t\r\n");
$t->be_recv_c(0, "near got request");
$t->be_send(0, "HD t93\r\n");
$t->c_recv("SERVER_ERROR no timeout\r\n", "client received SERVER_ERROR");
$t->clear();
};

done_testing();

0 comments on commit cb903b4

Please sign in to comment.