server_test, ibus_test and xim_adapter_test each ran their own copy of the same alt loop that stands in for imthread, and two of them had private checkstr/checkenginepreedit variants. test_util.c now provides Pump (trace, optional hold on a chosen op, stop) in its own proc so a test may block in socket I/O while the engine runs, and test.h declares the engine hooks once; every .c includes dat.h and fn.h itself as the rest of the tree does. server_test's three copies of fixture setup and teardown became serverbegin/serverend.
105 lines
1.8 KiB
C
105 lines
1.8 KiB
C
#include "dat.h"
|
|
#include "fn.h"
|
|
#include "test.h"
|
|
|
|
Str
|
|
mkstr(char *s)
|
|
{
|
|
Str r;
|
|
|
|
sinit(&r, s, strlen(s));
|
|
return r;
|
|
}
|
|
|
|
int
|
|
checkstr(struct ct *t, char *where, char *want, Str *got)
|
|
{
|
|
char buf[Maxutf];
|
|
|
|
stoutf(got, buf, sizeof buf);
|
|
if(strcmp(want, buf) == 0)
|
|
return 1;
|
|
return CT_ERRORF(t, "%s: want \"%s\", got \"%s\"",
|
|
where, want, buf);
|
|
}
|
|
|
|
void
|
|
checkenginepreedit(struct ct *t, char *want)
|
|
{
|
|
Str preedit;
|
|
|
|
testenginepreedit(&preedit);
|
|
checkstr(t, "engine preedit", want, &preedit);
|
|
}
|
|
|
|
static void
|
|
pumpthread(void *arg)
|
|
{
|
|
Pump *p;
|
|
Keyreq req;
|
|
uchar token;
|
|
Alt alts[] = {
|
|
{nil, &req, CHANRCV, nil},
|
|
{nil, &token, CHANRCV, nil},
|
|
{nil, nil, CHANEND, nil},
|
|
};
|
|
|
|
p = arg;
|
|
alts[0].c = keyc;
|
|
alts[1].c = p->stop;
|
|
for(;;)
|
|
switch(alt(alts)){
|
|
case 0:
|
|
chansend(p->trace, &req);
|
|
if(p->holdop == Pumpall || p->holdop == req.op)
|
|
chanrecv(p->go, &token);
|
|
testenginehandle(&req);
|
|
break;
|
|
case 1:
|
|
chansend(p->done, &token);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* ntrace is the trace channel's depth: 0 makes every trace a rendezvous. */
|
|
void
|
|
pumpstart(Pump *p, int ntrace)
|
|
{
|
|
memset(p, 0, sizeof *p);
|
|
p->trace = chancreate(sizeof(Keyreq), ntrace);
|
|
p->go = chancreate(sizeof(uchar), 0);
|
|
p->stop = chancreate(sizeof(uchar), 0);
|
|
p->done = chancreate(sizeof(uchar), 0);
|
|
p->holdop = Pumpnone;
|
|
/* Its own proc: tests block in socket I/O while the engine runs. */
|
|
proccreate(pumpthread, p, 8192);
|
|
p->active = 1;
|
|
}
|
|
|
|
void
|
|
pumphold(Pump *p, int op)
|
|
{
|
|
p->holdop = op;
|
|
}
|
|
|
|
/* Every held request must have been let go before stopping. */
|
|
void
|
|
pumpstop(Pump *p)
|
|
{
|
|
Keyreq req;
|
|
uchar token;
|
|
|
|
if(!p->active)
|
|
return;
|
|
while(channbrecv(p->trace, &req) > 0)
|
|
;
|
|
token = 0;
|
|
chansend(p->stop, &token);
|
|
chanrecv(p->done, &token);
|
|
chanfree(p->trace);
|
|
chanfree(p->go);
|
|
chanfree(p->stop);
|
|
chanfree(p->done);
|
|
p->active = 0;
|
|
}
|