test: one engine pump and one preedit check for the white-box suites
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.
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
#include "strans.c"
|
#include "strans.c"
|
||||||
#include "cutest/cutest.h"
|
#include "test.h"
|
||||||
|
|
||||||
extern Lang testvi;
|
|
||||||
|
|
||||||
Str mkstr(char*);
|
|
||||||
int checkstr(struct ct*, char*, char*, Str*);
|
|
||||||
|
|
||||||
static int typekeys(struct ct*, char*, Str*);
|
static int typekeys(struct ct*, char*, Str*);
|
||||||
static int draindraw(Drawcmd*);
|
static int draindraw(Drawcmd*);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
#include "ibus.c"
|
#include "ibus.c"
|
||||||
#include "cutest/cutest.h"
|
#include "test.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
void testengineinit(int);
|
|
||||||
void testenginehandle(Keyreq*);
|
|
||||||
void* testengineowner(void);
|
|
||||||
void testenginepreedit(Str*);
|
|
||||||
void testenginecaret(Caret*);
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@@ -18,12 +13,9 @@ typedef struct Ibusfix Ibusfix;
|
|||||||
struct Ibusfix
|
struct Ibusfix
|
||||||
{
|
{
|
||||||
Channel *oldreply;
|
Channel *oldreply;
|
||||||
Channel *trace;
|
Pump pump;
|
||||||
Channel *stop;
|
|
||||||
Channel *done;
|
|
||||||
DBusConnection *c1;
|
DBusConnection *c1;
|
||||||
DBusConnection *c2;
|
DBusConnection *c2;
|
||||||
int pumpactive;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -164,32 +156,6 @@ cleanup:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
enginepump(void *arg)
|
|
||||||
{
|
|
||||||
Ibusfix *f;
|
|
||||||
Keyreq req;
|
|
||||||
uchar token;
|
|
||||||
Alt alts[] = {
|
|
||||||
{keyc, &req, CHANRCV, nil},
|
|
||||||
{nil, &token, CHANRCV, nil},
|
|
||||||
{nil, nil, CHANEND, nil},
|
|
||||||
};
|
|
||||||
|
|
||||||
f = arg;
|
|
||||||
alts[1].c = f->stop;
|
|
||||||
for(;;)
|
|
||||||
switch(alt(alts)){
|
|
||||||
case 0:
|
|
||||||
chansend(f->trace, &req);
|
|
||||||
testenginehandle(&req);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
chansend(f->done, &token);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ibusbegin(struct ct *t, Ibusfix *f)
|
ibusbegin(struct ct *t, Ibusfix *f)
|
||||||
{
|
{
|
||||||
@@ -205,33 +171,22 @@ ibusbegin(struct ct *t, Ibusfix *f)
|
|||||||
testengineinit(LangEN);
|
testengineinit(LangEN);
|
||||||
f->oldreply = replyc;
|
f->oldreply = replyc;
|
||||||
replyc = chancreate(sizeof(Keyres), 0);
|
replyc = chancreate(sizeof(Keyres), 0);
|
||||||
f->trace = chancreate(sizeof(Keyreq), Maxcontexts);
|
pumpstart(&f->pump, Maxcontexts);
|
||||||
f->stop = chancreate(sizeof(uchar), 0);
|
|
||||||
f->done = chancreate(sizeof(uchar), 0);
|
|
||||||
f->pumpactive = threadcreate(enginepump, f, 8192) >= 0;
|
|
||||||
f->c1 = malloc(1);
|
f->c1 = malloc(1);
|
||||||
f->c2 = malloc(1);
|
f->c2 = malloc(1);
|
||||||
return CT_CHECK(t, f->pumpactive && f->c1 != nil && f->c2 != nil);
|
return CT_CHECK(t, f->c1 != nil && f->c2 != nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ibusend(Ibusfix *f)
|
ibusend(Ibusfix *f)
|
||||||
{
|
{
|
||||||
Drawcmd dc;
|
Drawcmd dc;
|
||||||
Keyreq req;
|
|
||||||
uchar token;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(f->pumpactive){
|
|
||||||
for(i = 0; i < nelem(contexts); i++)
|
for(i = 0; i < nelem(contexts); i++)
|
||||||
if(contexts[i].conn != nil)
|
if(contexts[i].conn != nil)
|
||||||
dropcontext(&contexts[i]);
|
dropcontext(&contexts[i]);
|
||||||
while(channbrecv(f->trace, &req) > 0)
|
pumpstop(&f->pump);
|
||||||
;
|
|
||||||
token = 0;
|
|
||||||
chansend(f->stop, &token);
|
|
||||||
chanrecv(f->done, &token);
|
|
||||||
}
|
|
||||||
memset(contexts, 0, sizeof contexts);
|
memset(contexts, 0, sizeof contexts);
|
||||||
memset(conns, 0, sizeof conns);
|
memset(conns, 0, sizeof conns);
|
||||||
nconns = 0;
|
nconns = 0;
|
||||||
@@ -243,9 +198,6 @@ ibusend(Ibusfix *f)
|
|||||||
free(f->c2);
|
free(f->c2);
|
||||||
chanfree(replyc);
|
chanfree(replyc);
|
||||||
replyc = f->oldreply;
|
replyc = f->oldreply;
|
||||||
chanfree(f->trace);
|
|
||||||
chanfree(f->stop);
|
|
||||||
chanfree(f->done);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Keyreq
|
static Keyreq
|
||||||
@@ -254,7 +206,7 @@ nexttrace(struct ct *t, Ibusfix *f, int op, Ictx *ctx)
|
|||||||
Keyreq req;
|
Keyreq req;
|
||||||
|
|
||||||
memset(&req, 0, sizeof req);
|
memset(&req, 0, sizeof req);
|
||||||
if(!CT_CHECK(t, channbrecv(f->trace, &req) > 0))
|
if(!CT_CHECK(t, channbrecv(f->pump.trace, &req) > 0))
|
||||||
return req;
|
return req;
|
||||||
CT_EQ_INT(t, op, req.op);
|
CT_EQ_INT(t, op, req.op);
|
||||||
CT_EQ_PTR(t, ctx, req.owner);
|
CT_EQ_PTR(t, ctx, req.owner);
|
||||||
@@ -269,27 +221,7 @@ notrace(struct ct *t, Ibusfix *f)
|
|||||||
{
|
{
|
||||||
Keyreq req;
|
Keyreq req;
|
||||||
|
|
||||||
CT_CHECK(t, channbrecv(f->trace, &req) <= 0);
|
CT_CHECK(t, channbrecv(f->pump.trace, &req) <= 0);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
checkpreedit(struct ct *t, char *want, Keyres *res)
|
|
||||||
{
|
|
||||||
char got[Maxutf];
|
|
||||||
|
|
||||||
stoutf(&res->preedit, got, sizeof got);
|
|
||||||
CT_EQ_STR(t, want, got);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
checkenginepreedit(struct ct *t, char *want)
|
|
||||||
{
|
|
||||||
char got[Maxutf];
|
|
||||||
Str preedit;
|
|
||||||
|
|
||||||
testenginepreedit(&preedit);
|
|
||||||
stoutf(&preedit, got, sizeof got);
|
|
||||||
CT_EQ_STR(t, want, got);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Keyres
|
static Keyres
|
||||||
@@ -321,7 +253,7 @@ ibus_capability_policy(struct ct *t)
|
|||||||
res = contextkey(t, &f, a, 'n', Testctrlmask);
|
res = contextkey(t, &f, a, 'n', Testctrlmask);
|
||||||
CT_CHECK(t, res.eaten);
|
CT_CHECK(t, res.eaten);
|
||||||
res = contextkey(t, &f, a, 'k', 0);
|
res = contextkey(t, &f, a, 'k', 0);
|
||||||
checkpreedit(t, "k", &res);
|
checkstr(t, "preedit", "k", &res.preedit);
|
||||||
CT_EQ_PTR(t, a, testengineowner());
|
CT_EQ_PTR(t, a, testengineowner());
|
||||||
|
|
||||||
a->cap = Cclientpreedit;
|
a->cap = Cclientpreedit;
|
||||||
@@ -329,7 +261,7 @@ ibus_capability_policy(struct ct *t)
|
|||||||
sendrequest(a, Keycap, 0, 0, &res);
|
sendrequest(a, Keycap, 0, 0, &res);
|
||||||
nexttrace(t, &f, Keycap, a);
|
nexttrace(t, &f, Keycap, a);
|
||||||
CT_CHECK(t, res.eaten);
|
CT_CHECK(t, res.eaten);
|
||||||
checkpreedit(t, "k", &res);
|
checkstr(t, "preedit", "k", &res.preedit);
|
||||||
|
|
||||||
b->focused = 1;
|
b->focused = 1;
|
||||||
b->cap = Cclientpreedit;
|
b->cap = Cclientpreedit;
|
||||||
@@ -345,7 +277,7 @@ ibus_capability_policy(struct ct *t)
|
|||||||
sendrequest(a, Keycap, 0, 0, &res);
|
sendrequest(a, Keycap, 0, 0, &res);
|
||||||
nexttrace(t, &f, Keycap, a);
|
nexttrace(t, &f, Keycap, a);
|
||||||
CT_CHECK(t, res.eaten);
|
CT_CHECK(t, res.eaten);
|
||||||
checkpreedit(t, "k", &res);
|
checkstr(t, "preedit", "k", &res.preedit);
|
||||||
cleanup:
|
cleanup:
|
||||||
ibusend(&f);
|
ibusend(&f);
|
||||||
}
|
}
|
||||||
@@ -382,7 +314,7 @@ ibus_private_input_policy(struct ct *t)
|
|||||||
ctx->hints = 0;
|
ctx->hints = 0;
|
||||||
contextkey(t, &f, ctx, 'n', Testctrlmask);
|
contextkey(t, &f, ctx, 'n', Testctrlmask);
|
||||||
res = contextkey(t, &f, ctx, 'k', 0);
|
res = contextkey(t, &f, ctx, 'k', 0);
|
||||||
checkpreedit(t, "k", &res);
|
checkstr(t, "preedit", "k", &res.preedit);
|
||||||
ctx->purpose = Ibuspurposepassword;
|
ctx->purpose = Ibuspurposepassword;
|
||||||
memset(&res, 0, sizeof res);
|
memset(&res, 0, sizeof res);
|
||||||
CT_CHECK(t, !processkey(ctx, 'x', 0, &res));
|
CT_CHECK(t, !processkey(ctx, 'x', 0, &res));
|
||||||
@@ -393,7 +325,7 @@ ibus_private_input_policy(struct ct *t)
|
|||||||
ctx->purpose = 0;
|
ctx->purpose = 0;
|
||||||
ctx->hints = 1<<11;
|
ctx->hints = 1<<11;
|
||||||
res = contextkey(t, &f, ctx, 'a', 0);
|
res = contextkey(t, &f, ctx, 'a', 0);
|
||||||
checkpreedit(t, "か", &res);
|
checkstr(t, "preedit", "か", &res.preedit);
|
||||||
cleanup:
|
cleanup:
|
||||||
ibusend(&f);
|
ibusend(&f);
|
||||||
}
|
}
|
||||||
@@ -450,11 +382,11 @@ ibus_context_lifecycle(struct ct *t)
|
|||||||
CT_CHECK(t, res.eaten);
|
CT_CHECK(t, res.eaten);
|
||||||
contextkey(t, &f, a, 'k', 0);
|
contextkey(t, &f, a, 'k', 0);
|
||||||
res = contextkey(t, &f, a, 'a', 0);
|
res = contextkey(t, &f, a, 'a', 0);
|
||||||
checkpreedit(t, "か", &res);
|
checkstr(t, "preedit", "か", &res.preedit);
|
||||||
|
|
||||||
b->focused = 1;
|
b->focused = 1;
|
||||||
res = contextkey(t, &f, b, 'n', 0);
|
res = contextkey(t, &f, b, 'n', 0);
|
||||||
checkpreedit(t, "ん", &res);
|
checkstr(t, "preedit", "ん", &res.preedit);
|
||||||
CT_EQ_PTR(t, b, testengineowner());
|
CT_EQ_PTR(t, b, testengineowner());
|
||||||
|
|
||||||
setcursor(b, 50, 60, 12);
|
setcursor(b, 50, 60, 12);
|
||||||
@@ -468,7 +400,7 @@ ibus_context_lifecycle(struct ct *t)
|
|||||||
memset(&res, 0, sizeof res);
|
memset(&res, 0, sizeof res);
|
||||||
sendrequest(a, Keyreset, 0, 0, &res);
|
sendrequest(a, Keyreset, 0, 0, &res);
|
||||||
nexttrace(t, &f, Keyreset, a);
|
nexttrace(t, &f, Keyreset, a);
|
||||||
checkpreedit(t, "", &res);
|
checkstr(t, "preedit", "", &res.preedit);
|
||||||
checkenginepreedit(t, "ん");
|
checkenginepreedit(t, "ん");
|
||||||
CT_EQ_PTR(t, b, testengineowner());
|
CT_EQ_PTR(t, b, testengineowner());
|
||||||
|
|
||||||
@@ -536,17 +468,17 @@ ibus_active_release_lifecycle(struct ct *t)
|
|||||||
ctx->focused = 1;
|
ctx->focused = 1;
|
||||||
contextkey(t, &f, ctx, 'n', Testctrlmask);
|
contextkey(t, &f, ctx, 'n', Testctrlmask);
|
||||||
res = contextkey(t, &f, ctx, 'n', 0);
|
res = contextkey(t, &f, ctx, 'n', 0);
|
||||||
checkpreedit(t, "ん", &res);
|
checkstr(t, "preedit", "ん", &res.preedit);
|
||||||
|
|
||||||
memset(&res, 0, sizeof res);
|
memset(&res, 0, sizeof res);
|
||||||
sendrequest(ctx, Keyreset, 0, 0, &res);
|
sendrequest(ctx, Keyreset, 0, 0, &res);
|
||||||
nexttrace(t, &f, Keyreset, ctx);
|
nexttrace(t, &f, Keyreset, ctx);
|
||||||
checkpreedit(t, "", &res);
|
checkstr(t, "preedit", "", &res.preedit);
|
||||||
checkenginepreedit(t, "");
|
checkenginepreedit(t, "");
|
||||||
CT_CHECK(t, ctx->focused);
|
CT_CHECK(t, ctx->focused);
|
||||||
CT_EQ_PTR(t, ctx, testengineowner());
|
CT_EQ_PTR(t, ctx, testengineowner());
|
||||||
res = contextkey(t, &f, ctx, 'k', 0);
|
res = contextkey(t, &f, ctx, 'k', 0);
|
||||||
checkpreedit(t, "k", &res);
|
checkstr(t, "preedit", "k", &res.preedit);
|
||||||
CT_EQ_PTR(t, ctx, testengineowner());
|
CT_EQ_PTR(t, ctx, testengineowner());
|
||||||
|
|
||||||
releasecontext(ctx);
|
releasecontext(ctx);
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
#undef accept
|
#undef accept
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
#include <xcb-imdkit/encoding.h>
|
#include <xcb-imdkit/encoding.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static Str
|
static Str
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|||||||
@@ -4,24 +4,18 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "srv.c"
|
#include "srv.c"
|
||||||
#include "cutest/cutest.h"
|
#include "test.h"
|
||||||
|
|
||||||
void testengineinit(int);
|
|
||||||
void testenginehandle(Keyreq*);
|
|
||||||
void* testengineowner(void);
|
|
||||||
void testenginepreedit(Str*);
|
|
||||||
|
|
||||||
#undef recv
|
#undef recv
|
||||||
|
|
||||||
typedef struct Enginegate Enginegate;
|
typedef struct Serverfix Serverfix;
|
||||||
typedef struct Testclient Testclient;
|
typedef struct Testclient Testclient;
|
||||||
|
|
||||||
struct Enginegate
|
/* A held pump plus a private client-slot channel of the wanted depth. */
|
||||||
|
struct Serverfix
|
||||||
{
|
{
|
||||||
Channel *seen;
|
Pump pump;
|
||||||
Channel *go;
|
Channel *oldclientc;
|
||||||
Channel *stop;
|
|
||||||
Channel *done;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Testclient
|
struct Testclient
|
||||||
@@ -34,30 +28,30 @@ struct Testclient
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
enginegate(void *arg)
|
serverbegin(Serverfix *f, int nclients)
|
||||||
{
|
{
|
||||||
Enginegate *g;
|
Drawcmd dc;
|
||||||
Keyreq req;
|
|
||||||
uchar token;
|
uchar token;
|
||||||
Alt alts[] = {
|
|
||||||
{keyc, &req, CHANRCV, nil},
|
|
||||||
{nil, &token, CHANRCV, nil},
|
|
||||||
{nil, nil, CHANEND, nil},
|
|
||||||
};
|
|
||||||
|
|
||||||
g = arg;
|
f->oldclientc = clientc;
|
||||||
alts[1].c = g->stop;
|
while(channbrecv(drawc, &dc) > 0)
|
||||||
for(;;)
|
;
|
||||||
switch(alt(alts)){
|
clientc = chancreate(sizeof token, nclients);
|
||||||
case 0:
|
testengineinit(LangJP);
|
||||||
chansend(g->seen, &req);
|
pumpstart(&f->pump, 0);
|
||||||
chanrecv(g->go, &token);
|
pumphold(&f->pump, Pumpall);
|
||||||
testenginehandle(&req);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
chansend(g->done, &token);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
serverend(Serverfix *f)
|
||||||
|
{
|
||||||
|
Drawcmd dc;
|
||||||
|
|
||||||
|
pumpstop(&f->pump);
|
||||||
|
chanfree(clientc);
|
||||||
|
clientc = f->oldclientc;
|
||||||
|
while(channbrecv(drawc, &dc) > 0)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -142,30 +136,30 @@ sendreset(struct ct *t, Testclient *client, int want)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Keyreq
|
static Keyreq
|
||||||
nextrequestcap(struct ct *t, Enginegate *g, int op, int cap)
|
nextrequestcap(struct ct *t, Pump *p, int op, int cap)
|
||||||
{
|
{
|
||||||
Keyreq req;
|
Keyreq req;
|
||||||
|
|
||||||
memset(&req, 0, sizeof req);
|
memset(&req, 0, sizeof req);
|
||||||
chanrecv(g->seen, &req);
|
chanrecv(p->trace, &req);
|
||||||
CT_EQ_INT(t, op, req.op);
|
CT_EQ_INT(t, op, req.op);
|
||||||
CT_EQ_INT(t, cap, req.cap);
|
CT_EQ_INT(t, cap, req.cap);
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Keyreq
|
static Keyreq
|
||||||
nextrequest(struct ct *t, Enginegate *g, int op)
|
nextrequest(struct ct *t, Pump *p, int op)
|
||||||
{
|
{
|
||||||
return nextrequestcap(t, g, op, Cclientpreedit);
|
return nextrequestcap(t, p, op, Cclientpreedit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
allowrequest(Enginegate *g)
|
allowrequest(Pump *p)
|
||||||
{
|
{
|
||||||
uchar token;
|
uchar token;
|
||||||
|
|
||||||
token = 0;
|
token = 0;
|
||||||
chansend(g->go, &token);
|
chansend(p->go, &token);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -222,126 +216,111 @@ waitclient(struct ct *t, Testclient *client)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
disconnectclient(struct ct *t, Enginegate *g, Testclient *client, void *owner)
|
disconnectclient(struct ct *t, Pump *p, Testclient *client, void *owner)
|
||||||
{
|
{
|
||||||
Keyreq req;
|
Keyreq req;
|
||||||
uchar token;
|
uchar token;
|
||||||
|
|
||||||
close(client->peer);
|
close(client->peer);
|
||||||
client->peer = -1;
|
client->peer = -1;
|
||||||
req = nextrequest(t, g, Keyrelease);
|
req = nextrequest(t, p, Keyrelease);
|
||||||
if(owner != nil)
|
if(owner != nil)
|
||||||
CT_EQ_PTR(t, owner, req.owner);
|
CT_EQ_PTR(t, owner, req.owner);
|
||||||
CT_CHECK(t, channbrecv(client->done, &token) <= 0);
|
CT_CHECK(t, channbrecv(client->done, &token) <= 0);
|
||||||
allowrequest(g);
|
allowrequest(p);
|
||||||
waitclient(t, client);
|
waitclient(t, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
server_connection_ownership(struct ct *t)
|
server_connection_ownership(struct ct *t)
|
||||||
{
|
{
|
||||||
Channel *oldclientc;
|
Serverfix f;
|
||||||
Enginegate gate;
|
|
||||||
Testclient a, b, c;
|
Testclient a, b, c;
|
||||||
Keyreq req;
|
Keyreq req;
|
||||||
Drawcmd dc;
|
|
||||||
Str shown;
|
Str shown;
|
||||||
char preedit[Ipcfieldmax+1];
|
char preedit[Ipcfieldmax+1];
|
||||||
void *aowner, *bowner, *cowner;
|
void *aowner, *bowner, *cowner;
|
||||||
uchar byte, token;
|
uchar byte, token;
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
int gateactive;
|
|
||||||
|
|
||||||
memset(&gate, 0, sizeof gate);
|
|
||||||
memset(&a, 0, sizeof a);
|
memset(&a, 0, sizeof a);
|
||||||
memset(&b, 0, sizeof b);
|
memset(&b, 0, sizeof b);
|
||||||
memset(&c, 0, sizeof c);
|
memset(&c, 0, sizeof c);
|
||||||
a.fd = a.peer = b.fd = b.peer = c.fd = c.peer = -1;
|
a.fd = a.peer = b.fd = b.peer = c.fd = c.peer = -1;
|
||||||
aowner = bowner = cowner = nil;
|
aowner = bowner = cowner = nil;
|
||||||
oldclientc = clientc;
|
serverbegin(&f, 3);
|
||||||
while(channbrecv(drawc, &dc) > 0)
|
|
||||||
;
|
|
||||||
clientc = chancreate(sizeof token, 3);
|
|
||||||
gate.seen = chancreate(sizeof(Keyreq), 0);
|
|
||||||
gate.go = chancreate(sizeof token, 0);
|
|
||||||
gate.stop = chancreate(sizeof token, 0);
|
|
||||||
gate.done = chancreate(sizeof token, 0);
|
|
||||||
testengineinit(LangJP);
|
|
||||||
gateactive = proccreate(enginegate, &gate, 8192) >= 0;
|
|
||||||
if(!CT_CHECK(t, gateactive))
|
|
||||||
goto cleanup;
|
|
||||||
if(!startclient(t, &a) || !startclient(t, &b))
|
if(!startclient(t, &a) || !startclient(t, &b))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if(!sendkey(t, &a, 1, 0, 'k'))
|
if(!sendkey(t, &a, 1, 0, 'k'))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
aowner = req.owner;
|
aowner = req.owner;
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_CHECK(t, readreply(t, &a, 1, preedit));
|
CT_CHECK(t, readreply(t, &a, 1, preedit));
|
||||||
CT_EQ_STR(t, "k", preedit);
|
CT_EQ_STR(t, "k", preedit);
|
||||||
if(!sendkey(t, &a, 1, 0, 'a'))
|
if(!sendkey(t, &a, 1, 0, 'a'))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
CT_EQ_PTR(t, aowner, req.owner);
|
CT_EQ_PTR(t, aowner, req.owner);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_CHECK(t, readreply(t, &a, 1, preedit));
|
CT_CHECK(t, readreply(t, &a, 1, preedit));
|
||||||
CT_EQ_STR(t, "か", preedit);
|
CT_EQ_STR(t, "か", preedit);
|
||||||
CT_EQ_PTR(t, aowner, testengineowner());
|
CT_EQ_PTR(t, aowner, testengineowner());
|
||||||
|
|
||||||
if(!sendkey(t, &b, 1, 0, 'n'))
|
if(!sendkey(t, &b, 1, 0, 'n'))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
bowner = req.owner;
|
bowner = req.owner;
|
||||||
CT_CHECK(t, bowner != aowner);
|
CT_CHECK(t, bowner != aowner);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_CHECK(t, readreply(t, &b, 1, preedit));
|
CT_CHECK(t, readreply(t, &b, 1, preedit));
|
||||||
CT_EQ_STR(t, "ん", preedit);
|
CT_EQ_STR(t, "ん", preedit);
|
||||||
CT_EQ_PTR(t, bowner, testengineowner());
|
CT_EQ_PTR(t, bowner, testengineowner());
|
||||||
|
|
||||||
if(!sendreset(t, &a, 1))
|
if(!sendreset(t, &a, 1))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keyreset);
|
req = nextrequest(t, &f.pump, Keyreset);
|
||||||
CT_EQ_PTR(t, aowner, req.owner);
|
CT_EQ_PTR(t, aowner, req.owner);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_CHECK(t, readreply(t, &a, 1, preedit));
|
CT_CHECK(t, readreply(t, &a, 1, preedit));
|
||||||
CT_EQ_STR(t, "", preedit);
|
CT_EQ_STR(t, "", preedit);
|
||||||
CT_EQ_PTR(t, bowner, testengineowner());
|
CT_EQ_PTR(t, bowner, testengineowner());
|
||||||
if(!sendkey(t, &b, 1, 0, Kmodfirst))
|
if(!sendkey(t, &b, 1, 0, Kmodfirst))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_CHECK(t, !readreply(t, &b, 1, preedit));
|
CT_CHECK(t, !readreply(t, &b, 1, preedit));
|
||||||
CT_EQ_STR(t, "ん", preedit);
|
CT_EQ_STR(t, "ん", preedit);
|
||||||
|
|
||||||
disconnectclient(t, &gate, &a, aowner);
|
disconnectclient(t, &f.pump, &a, aowner);
|
||||||
CT_EQ_PTR(t, bowner, testengineowner());
|
CT_EQ_PTR(t, bowner, testengineowner());
|
||||||
if(!sendkey(t, &b, 1, 0, 'y'))
|
if(!sendkey(t, &b, 1, 0, 'y'))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_CHECK(t, readreply(t, &b, 1, preedit));
|
CT_CHECK(t, readreply(t, &b, 1, preedit));
|
||||||
if(!sendkey(t, &b, 1, 0, 'a'))
|
if(!sendkey(t, &b, 1, 0, 'a'))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_CHECK(t, readreply(t, &b, 1, preedit));
|
CT_CHECK(t, readreply(t, &b, 1, preedit));
|
||||||
CT_EQ_STR(t, "にゃ", preedit);
|
CT_EQ_STR(t, "にゃ", preedit);
|
||||||
|
|
||||||
if(!sendreset(t, &b, 1))
|
if(!sendreset(t, &b, 1))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keyreset);
|
req = nextrequest(t, &f.pump, Keyreset);
|
||||||
CT_EQ_PTR(t, bowner, req.owner);
|
CT_EQ_PTR(t, bowner, req.owner);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_CHECK(t, readreply(t, &b, 1, preedit));
|
CT_CHECK(t, readreply(t, &b, 1, preedit));
|
||||||
CT_EQ_STR(t, "", preedit);
|
CT_EQ_STR(t, "", preedit);
|
||||||
CT_EQ_PTR(t, bowner, testengineowner());
|
CT_EQ_PTR(t, bowner, testengineowner());
|
||||||
|
|
||||||
if(!sendkey(t, &b, 0, 0, 'k'))
|
if(!sendkey(t, &b, 0, 0, 'k'))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequestcap(t, &gate, Keypress, 0);
|
req = nextrequestcap(t, &f.pump, Keypress, 0);
|
||||||
CT_EQ_PTR(t, bowner, req.owner);
|
CT_EQ_PTR(t, bowner, req.owner);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_CHECK(t, readreply(t, &b, 0, preedit));
|
CT_CHECK(t, readreply(t, &b, 0, preedit));
|
||||||
errno = 0;
|
errno = 0;
|
||||||
n = recv(b.peer, &byte, 1, MSG_PEEK|MSG_DONTWAIT);
|
n = recv(b.peer, &byte, 1, MSG_PEEK|MSG_DONTWAIT);
|
||||||
@@ -350,12 +329,12 @@ server_connection_ownership(struct ct *t)
|
|||||||
CT_EQ_PTR(t, bowner, testengineowner());
|
CT_EQ_PTR(t, bowner, testengineowner());
|
||||||
if(!sendkey(t, &b, 1, 0, 'a'))
|
if(!sendkey(t, &b, 1, 0, 'a'))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_CHECK(t, readreply(t, &b, 1, preedit));
|
CT_CHECK(t, readreply(t, &b, 1, preedit));
|
||||||
CT_EQ_STR(t, "か", preedit);
|
CT_EQ_STR(t, "か", preedit);
|
||||||
|
|
||||||
disconnectclient(t, &gate, &b, bowner);
|
disconnectclient(t, &f.pump, &b, bowner);
|
||||||
CT_EQ_PTR(t, nil, testengineowner());
|
CT_EQ_PTR(t, nil, testengineowner());
|
||||||
testenginepreedit(&shown);
|
testenginepreedit(&shown);
|
||||||
CT_EQ_INT(t, 0, shown.n);
|
CT_EQ_INT(t, 0, shown.n);
|
||||||
@@ -364,72 +343,45 @@ server_connection_ownership(struct ct *t)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
if(!sendkey(t, &c, 1, 0, 'k'))
|
if(!sendkey(t, &c, 1, 0, 'k'))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
cowner = req.owner;
|
cowner = req.owner;
|
||||||
close(c.peer);
|
close(c.peer);
|
||||||
c.peer = -1;
|
c.peer = -1;
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
req = nextrequest(t, &gate, Keyrelease);
|
req = nextrequest(t, &f.pump, Keyrelease);
|
||||||
CT_EQ_PTR(t, cowner, req.owner);
|
CT_EQ_PTR(t, cowner, req.owner);
|
||||||
CT_EQ_PTR(t, cowner, testengineowner());
|
CT_EQ_PTR(t, cowner, testengineowner());
|
||||||
CT_CHECK(t, channbrecv(c.done, &token) <= 0);
|
CT_CHECK(t, channbrecv(c.done, &token) <= 0);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
waitclient(t, &c);
|
waitclient(t, &c);
|
||||||
CT_EQ_PTR(t, nil, testengineowner());
|
CT_EQ_PTR(t, nil, testengineowner());
|
||||||
CT_CHECK(t, channbrecv(clientc, &token) <= 0);
|
CT_CHECK(t, channbrecv(clientc, &token) <= 0);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if(a.peer >= 0)
|
if(a.peer >= 0)
|
||||||
disconnectclient(t, &gate, &a, aowner);
|
disconnectclient(t, &f.pump, &a, aowner);
|
||||||
if(b.peer >= 0)
|
if(b.peer >= 0)
|
||||||
disconnectclient(t, &gate, &b, bowner);
|
disconnectclient(t, &f.pump, &b, bowner);
|
||||||
if(c.peer >= 0)
|
if(c.peer >= 0)
|
||||||
disconnectclient(t, &gate, &c, cowner);
|
disconnectclient(t, &f.pump, &c, cowner);
|
||||||
if(gateactive){
|
serverend(&f);
|
||||||
token = 0;
|
|
||||||
chansend(gate.stop, &token);
|
|
||||||
chanrecv(gate.done, &token);
|
|
||||||
}
|
|
||||||
chanfree(gate.seen);
|
|
||||||
chanfree(gate.go);
|
|
||||||
chanfree(gate.stop);
|
|
||||||
chanfree(gate.done);
|
|
||||||
chanfree(clientc);
|
|
||||||
clientc = oldclientc;
|
|
||||||
while(channbrecv(drawc, &dc) > 0)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
server_extension_stream(struct ct *t)
|
server_extension_stream(struct ct *t)
|
||||||
{
|
{
|
||||||
Channel *oldclientc;
|
Serverfix f;
|
||||||
Enginegate gate;
|
|
||||||
Testclient a, b;
|
Testclient a, b;
|
||||||
Keyreq req;
|
Keyreq req;
|
||||||
Drawcmd dc;
|
uchar frame[Ipccaretsz];
|
||||||
uchar frame[Ipccaretsz], token;
|
|
||||||
char preedit[Ipcfieldmax+1];
|
char preedit[Ipcfieldmax+1];
|
||||||
void *aowner, *bowner;
|
void *aowner, *bowner;
|
||||||
int gateactive;
|
|
||||||
|
|
||||||
memset(&gate, 0, sizeof gate);
|
|
||||||
memset(&a, 0, sizeof a);
|
memset(&a, 0, sizeof a);
|
||||||
memset(&b, 0, sizeof b);
|
memset(&b, 0, sizeof b);
|
||||||
a.fd = a.peer = b.fd = b.peer = -1;
|
a.fd = a.peer = b.fd = b.peer = -1;
|
||||||
aowner = bowner = nil;
|
aowner = bowner = nil;
|
||||||
oldclientc = clientc;
|
serverbegin(&f, 2);
|
||||||
while(channbrecv(drawc, &dc) > 0)
|
|
||||||
;
|
|
||||||
clientc = chancreate(sizeof token, 2);
|
|
||||||
gate.seen = chancreate(sizeof(Keyreq), 0);
|
|
||||||
gate.go = chancreate(sizeof token, 0);
|
|
||||||
gate.stop = chancreate(sizeof token, 0);
|
|
||||||
gate.done = chancreate(sizeof token, 0);
|
|
||||||
testengineinit(LangJP);
|
|
||||||
gateactive = proccreate(enginegate, &gate, 8192) >= 0;
|
|
||||||
if(!CT_CHECK(t, gateactive))
|
|
||||||
goto cleanup;
|
|
||||||
if(!startclient(t, &a))
|
if(!startclient(t, &a))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@@ -437,36 +389,36 @@ server_extension_stream(struct ct *t)
|
|||||||
ipcpackcap(frame, Cclientpreedit);
|
ipcpackcap(frame, Cclientpreedit);
|
||||||
if(!sendframe(t, &a, frame, Ipcreqsz, 1))
|
if(!sendframe(t, &a, frame, Ipcreqsz, 1))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keycap);
|
req = nextrequest(t, &f.pump, Keycap);
|
||||||
aowner = req.owner;
|
aowner = req.owner;
|
||||||
CT_EQ_PTR(t, nil, testengineowner());
|
CT_EQ_PTR(t, nil, testengineowner());
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit));
|
CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit));
|
||||||
CT_EQ_STR(t, "", preedit);
|
CT_EQ_STR(t, "", preedit);
|
||||||
|
|
||||||
ipcpackcaret(frame, 1, -101, -7, 23);
|
ipcpackcaret(frame, 1, -101, -7, 23);
|
||||||
if(!sendframe(t, &a, frame, Ipccaretsz, 1))
|
if(!sendframe(t, &a, frame, Ipccaretsz, 1))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keycaret);
|
req = nextrequest(t, &f.pump, Keycaret);
|
||||||
CT_EQ_PTR(t, aowner, req.owner);
|
CT_EQ_PTR(t, aowner, req.owner);
|
||||||
CT_EQ_INT(t, 1, req.caret.valid);
|
CT_EQ_INT(t, 1, req.caret.valid);
|
||||||
CT_EQ_INT(t, -101, req.caret.x);
|
CT_EQ_INT(t, -101, req.caret.x);
|
||||||
CT_EQ_INT(t, -7, req.caret.y);
|
CT_EQ_INT(t, -7, req.caret.y);
|
||||||
CT_EQ_INT(t, 23, req.caret.h);
|
CT_EQ_INT(t, 23, req.caret.h);
|
||||||
CT_EQ_PTR(t, nil, testengineowner());
|
CT_EQ_PTR(t, nil, testengineowner());
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
checknoreply(t, &a);
|
checknoreply(t, &a);
|
||||||
|
|
||||||
ipcpackreq(frame, 1, 0, 'k');
|
ipcpackreq(frame, 1, 0, 'k');
|
||||||
if(!sendframe(t, &a, frame, Ipcreqsz, 1))
|
if(!sendframe(t, &a, frame, Ipcreqsz, 1))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
CT_EQ_PTR(t, aowner, req.owner);
|
CT_EQ_PTR(t, aowner, req.owner);
|
||||||
CT_EQ_INT(t, 1, req.caret.valid);
|
CT_EQ_INT(t, 1, req.caret.valid);
|
||||||
CT_EQ_INT(t, -101, req.caret.x);
|
CT_EQ_INT(t, -101, req.caret.x);
|
||||||
CT_EQ_INT(t, -7, req.caret.y);
|
CT_EQ_INT(t, -7, req.caret.y);
|
||||||
CT_EQ_INT(t, 23, req.caret.h);
|
CT_EQ_INT(t, 23, req.caret.h);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit));
|
CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit));
|
||||||
CT_EQ_STR(t, "k", preedit);
|
CT_EQ_STR(t, "k", preedit);
|
||||||
CT_EQ_PTR(t, aowner, testengineowner());
|
CT_EQ_PTR(t, aowner, testengineowner());
|
||||||
@@ -474,108 +426,81 @@ server_extension_stream(struct ct *t)
|
|||||||
ipcpackcap(frame, 0);
|
ipcpackcap(frame, 0);
|
||||||
if(!sendframe(t, &a, frame, Ipcreqsz, 0))
|
if(!sendframe(t, &a, frame, Ipcreqsz, 0))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequestcap(t, &gate, Keycap, 0);
|
req = nextrequestcap(t, &f.pump, Keycap, 0);
|
||||||
CT_EQ_PTR(t, aowner, req.owner);
|
CT_EQ_PTR(t, aowner, req.owner);
|
||||||
CT_EQ_INT(t, 1, req.caret.valid);
|
CT_EQ_INT(t, 1, req.caret.valid);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_EQ_INT(t, 1, readreply(t, &a, 0, preedit));
|
CT_EQ_INT(t, 1, readreply(t, &a, 0, preedit));
|
||||||
|
|
||||||
/* Reset is still the old six-byte frame and does not discard caret. */
|
/* Reset is still the old six-byte frame and does not discard caret. */
|
||||||
ipcpackreset(frame, 0);
|
ipcpackreset(frame, 0);
|
||||||
if(!sendframe(t, &a, frame, Ipcreqsz, 1))
|
if(!sendframe(t, &a, frame, Ipcreqsz, 1))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequestcap(t, &gate, Keyreset, 0);
|
req = nextrequestcap(t, &f.pump, Keyreset, 0);
|
||||||
CT_EQ_PTR(t, aowner, req.owner);
|
CT_EQ_PTR(t, aowner, req.owner);
|
||||||
CT_EQ_INT(t, 1, req.caret.valid);
|
CT_EQ_INT(t, 1, req.caret.valid);
|
||||||
CT_EQ_INT(t, -101, req.caret.x);
|
CT_EQ_INT(t, -101, req.caret.x);
|
||||||
CT_EQ_INT(t, -7, req.caret.y);
|
CT_EQ_INT(t, -7, req.caret.y);
|
||||||
CT_EQ_INT(t, 23, req.caret.h);
|
CT_EQ_INT(t, 23, req.caret.h);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_EQ_INT(t, 1, readreply(t, &a, 0, preedit));
|
CT_EQ_INT(t, 1, readreply(t, &a, 0, preedit));
|
||||||
|
|
||||||
ipcpackcap(frame, Cclientpreedit);
|
ipcpackcap(frame, Cclientpreedit);
|
||||||
if(!sendframe(t, &a, frame, Ipcreqsz, 0))
|
if(!sendframe(t, &a, frame, Ipcreqsz, 0))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keycap);
|
req = nextrequest(t, &f.pump, Keycap);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit));
|
CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit));
|
||||||
CT_EQ_STR(t, "", preedit);
|
CT_EQ_STR(t, "", preedit);
|
||||||
ipcpackreq(frame, 1, 0, 'n');
|
ipcpackreq(frame, 1, 0, 'n');
|
||||||
if(!sendframe(t, &a, frame, Ipcreqsz, 0))
|
if(!sendframe(t, &a, frame, Ipcreqsz, 0))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
CT_EQ_INT(t, 1, req.caret.valid);
|
CT_EQ_INT(t, 1, req.caret.valid);
|
||||||
CT_EQ_INT(t, -101, req.caret.x);
|
CT_EQ_INT(t, -101, req.caret.x);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit));
|
CT_EQ_INT(t, 1, readreply(t, &a, 1, preedit));
|
||||||
CT_EQ_STR(t, "ん", preedit);
|
CT_EQ_STR(t, "ん", preedit);
|
||||||
|
|
||||||
disconnectclient(t, &gate, &a, aowner);
|
disconnectclient(t, &f.pump, &a, aowner);
|
||||||
|
|
||||||
/* Disconnect drops state; a legacy client gets the historical defaults. */
|
/* Disconnect drops state; a legacy client gets the historical defaults. */
|
||||||
if(!startclient(t, &b) || !sendkey(t, &b, 1, 0, 'k'))
|
if(!startclient(t, &b) || !sendkey(t, &b, 1, 0, 'k'))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
bowner = req.owner;
|
bowner = req.owner;
|
||||||
CT_EQ_INT(t, 0, req.caret.valid);
|
CT_EQ_INT(t, 0, req.caret.valid);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_EQ_INT(t, 1, readreply(t, &b, 1, preedit));
|
CT_EQ_INT(t, 1, readreply(t, &b, 1, preedit));
|
||||||
CT_EQ_STR(t, "k", preedit);
|
CT_EQ_STR(t, "k", preedit);
|
||||||
|
|
||||||
disconnectclient(t, &gate, &b, bowner);
|
disconnectclient(t, &f.pump, &b, bowner);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if(a.peer >= 0)
|
if(a.peer >= 0)
|
||||||
disconnectclient(t, &gate, &a, aowner);
|
disconnectclient(t, &f.pump, &a, aowner);
|
||||||
if(b.peer >= 0)
|
if(b.peer >= 0)
|
||||||
disconnectclient(t, &gate, &b, bowner);
|
disconnectclient(t, &f.pump, &b, bowner);
|
||||||
if(gateactive){
|
serverend(&f);
|
||||||
token = 0;
|
|
||||||
chansend(gate.stop, &token);
|
|
||||||
chanrecv(gate.done, &token);
|
|
||||||
}
|
|
||||||
chanfree(gate.seen);
|
|
||||||
chanfree(gate.go);
|
|
||||||
chanfree(gate.stop);
|
|
||||||
chanfree(gate.done);
|
|
||||||
chanfree(clientc);
|
|
||||||
clientc = oldclientc;
|
|
||||||
while(channbrecv(drawc, &dc) > 0)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
server_rejects_unknown_extension(struct ct *t)
|
server_rejects_unknown_extension(struct ct *t)
|
||||||
{
|
{
|
||||||
Channel *oldclientc;
|
Serverfix f;
|
||||||
Enginegate gate;
|
|
||||||
Testclient badver, badop, good;
|
Testclient badver, badop, good;
|
||||||
Keyreq req;
|
Keyreq req;
|
||||||
Drawcmd dc;
|
uchar frame[Ipccaretsz];
|
||||||
uchar frame[Ipccaretsz], token;
|
|
||||||
char preedit[Ipcfieldmax+1];
|
char preedit[Ipcfieldmax+1];
|
||||||
void *owner;
|
void *owner;
|
||||||
int gateactive;
|
|
||||||
|
|
||||||
memset(&gate, 0, sizeof gate);
|
|
||||||
memset(&badver, 0, sizeof badver);
|
memset(&badver, 0, sizeof badver);
|
||||||
memset(&badop, 0, sizeof badop);
|
memset(&badop, 0, sizeof badop);
|
||||||
memset(&good, 0, sizeof good);
|
memset(&good, 0, sizeof good);
|
||||||
badver.fd = badver.peer = badop.fd = badop.peer = -1;
|
badver.fd = badver.peer = badop.fd = badop.peer = -1;
|
||||||
good.fd = good.peer = -1;
|
good.fd = good.peer = -1;
|
||||||
owner = nil;
|
owner = nil;
|
||||||
oldclientc = clientc;
|
serverbegin(&f, 3);
|
||||||
while(channbrecv(drawc, &dc) > 0)
|
|
||||||
;
|
|
||||||
clientc = chancreate(sizeof token, 3);
|
|
||||||
gate.seen = chancreate(sizeof(Keyreq), 0);
|
|
||||||
gate.go = chancreate(sizeof token, 0);
|
|
||||||
gate.stop = chancreate(sizeof token, 0);
|
|
||||||
gate.done = chancreate(sizeof token, 0);
|
|
||||||
testengineinit(LangJP);
|
|
||||||
gateactive = proccreate(enginegate, &gate, 8192) >= 0;
|
|
||||||
if(!CT_CHECK(t, gateactive))
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
if(!startclient(t, &badver))
|
if(!startclient(t, &badver))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -583,8 +508,8 @@ server_rejects_unknown_extension(struct ct *t)
|
|||||||
frame[1]++;
|
frame[1]++;
|
||||||
if(!sendframe(t, &badver, frame, sizeof frame, 0))
|
if(!sendframe(t, &badver, frame, sizeof frame, 0))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keyrelease);
|
req = nextrequest(t, &f.pump, Keyrelease);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
waitclient(t, &badver);
|
waitclient(t, &badver);
|
||||||
close(badver.peer);
|
close(badver.peer);
|
||||||
badver.peer = -1;
|
badver.peer = -1;
|
||||||
@@ -595,8 +520,8 @@ server_rejects_unknown_extension(struct ct *t)
|
|||||||
frame[2]++;
|
frame[2]++;
|
||||||
if(!sendframe(t, &badop, frame, sizeof frame, 1))
|
if(!sendframe(t, &badop, frame, sizeof frame, 1))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keyrelease);
|
req = nextrequest(t, &f.pump, Keyrelease);
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
waitclient(t, &badop);
|
waitclient(t, &badop);
|
||||||
close(badop.peer);
|
close(badop.peer);
|
||||||
badop.peer = -1;
|
badop.peer = -1;
|
||||||
@@ -604,31 +529,19 @@ server_rejects_unknown_extension(struct ct *t)
|
|||||||
/* A malformed peer must not disturb another client connection. */
|
/* A malformed peer must not disturb another client connection. */
|
||||||
if(!startclient(t, &good) || !sendkey(t, &good, 1, 0, 'k'))
|
if(!startclient(t, &good) || !sendkey(t, &good, 1, 0, 'k'))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
req = nextrequest(t, &gate, Keypress);
|
req = nextrequest(t, &f.pump, Keypress);
|
||||||
owner = req.owner;
|
owner = req.owner;
|
||||||
allowrequest(&gate);
|
allowrequest(&f.pump);
|
||||||
CT_EQ_INT(t, 1, readreply(t, &good, 1, preedit));
|
CT_EQ_INT(t, 1, readreply(t, &good, 1, preedit));
|
||||||
CT_EQ_STR(t, "k", preedit);
|
CT_EQ_STR(t, "k", preedit);
|
||||||
disconnectclient(t, &gate, &good, owner);
|
disconnectclient(t, &f.pump, &good, owner);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if(badver.peer >= 0)
|
if(badver.peer >= 0)
|
||||||
disconnectclient(t, &gate, &badver, nil);
|
disconnectclient(t, &f.pump, &badver, nil);
|
||||||
if(badop.peer >= 0)
|
if(badop.peer >= 0)
|
||||||
disconnectclient(t, &gate, &badop, nil);
|
disconnectclient(t, &f.pump, &badop, nil);
|
||||||
if(good.peer >= 0)
|
if(good.peer >= 0)
|
||||||
disconnectclient(t, &gate, &good, owner);
|
disconnectclient(t, &f.pump, &good, owner);
|
||||||
if(gateactive){
|
serverend(&f);
|
||||||
token = 0;
|
|
||||||
chansend(gate.stop, &token);
|
|
||||||
chanrecv(gate.done, &token);
|
|
||||||
}
|
|
||||||
chanfree(gate.seen);
|
|
||||||
chanfree(gate.go);
|
|
||||||
chanfree(gate.stop);
|
|
||||||
chanfree(gate.done);
|
|
||||||
chanfree(clientc);
|
|
||||||
clientc = oldclientc;
|
|
||||||
while(channbrecv(drawc, &dc) > 0)
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
36
tests/test.h
36
tests/test.h
@@ -1,11 +1,43 @@
|
|||||||
|
/* Included after dat.h and fn.h (or after the source under test). */
|
||||||
#include "cutest/cutest.h"
|
#include "cutest/cutest.h"
|
||||||
#include "dat.h"
|
|
||||||
#include "fn.h"
|
|
||||||
|
|
||||||
extern Lang testvi;
|
extern Lang testvi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A test's stand-in for imthread: handles engine requests from keyc,
|
||||||
|
* tracing each one first. Requests whose op is holdop (every request
|
||||||
|
* when holdop is Pumpall) wait on go before the engine sees them.
|
||||||
|
*/
|
||||||
|
typedef struct Pump Pump;
|
||||||
|
struct Pump
|
||||||
|
{
|
||||||
|
Channel *trace;
|
||||||
|
Channel *go;
|
||||||
|
Channel *stop;
|
||||||
|
Channel *done;
|
||||||
|
int holdop;
|
||||||
|
int active;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Pumpnone = -1,
|
||||||
|
Pumpall = -2,
|
||||||
|
};
|
||||||
|
|
||||||
Str mkstr(char*);
|
Str mkstr(char*);
|
||||||
int checkstr(struct ct*, char*, char*, Str*);
|
int checkstr(struct ct*, char*, char*, Str*);
|
||||||
|
void checkenginepreedit(struct ct*, char*);
|
||||||
|
void pumpstart(Pump*, int);
|
||||||
|
void pumphold(Pump*, int);
|
||||||
|
void pumpstop(Pump*);
|
||||||
|
|
||||||
|
/* Engine internals reached through engine_test.c. */
|
||||||
|
void testengineinit(int);
|
||||||
|
void testenginehandle(Keyreq*);
|
||||||
|
void* testengineowner(void);
|
||||||
|
void testenginepreedit(Str*);
|
||||||
|
void testenginecaret(Caret*);
|
||||||
|
|
||||||
void str_init_utf8(struct ct*);
|
void str_init_utf8(struct ct*);
|
||||||
void str_edit_and_alias(struct ct*);
|
void str_edit_and_alias(struct ct*);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
Str
|
Str
|
||||||
@@ -20,3 +22,83 @@ checkstr(struct ct *t, char *where, char *want, Str *got)
|
|||||||
return CT_ERRORF(t, "%s: want \"%s\", got \"%s\"",
|
return CT_ERRORF(t, "%s: want \"%s\", got \"%s\"",
|
||||||
where, want, buf);
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#define CT_IMPLEMENTATION
|
#define CT_IMPLEMENTATION
|
||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include "dat.h"
|
||||||
|
#include "fn.h"
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ static int wireflush(xcb_connection_t*);
|
|||||||
#undef xcb_translate_coordinates
|
#undef xcb_translate_coordinates
|
||||||
#undef xcb_translate_coordinates_reply
|
#undef xcb_translate_coordinates_reply
|
||||||
#undef xcb_flush
|
#undef xcb_flush
|
||||||
#include "cutest/cutest.h"
|
#include "test.h"
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@@ -384,22 +384,11 @@ testkeystate(char *layout)
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void testengineinit(int);
|
|
||||||
void testenginehandle(Keyreq*);
|
|
||||||
void* testengineowner(void);
|
|
||||||
void testenginepreedit(Str*);
|
|
||||||
|
|
||||||
typedef struct Ximfix Ximfix;
|
typedef struct Ximfix Ximfix;
|
||||||
struct Ximfix
|
struct Ximfix
|
||||||
{
|
{
|
||||||
Channel *oldreply;
|
Channel *oldreply;
|
||||||
Channel *trace;
|
Pump pump;
|
||||||
Channel *stop;
|
|
||||||
Channel *done;
|
|
||||||
Channel *waiting;
|
|
||||||
Channel *ack;
|
|
||||||
int holdrelease;
|
|
||||||
int pumpactive;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Freejob Freejob;
|
typedef struct Freejob Freejob;
|
||||||
@@ -409,37 +398,6 @@ struct Freejob
|
|||||||
Channel *done;
|
Channel *done;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
enginepump(void *arg)
|
|
||||||
{
|
|
||||||
Ximfix *f;
|
|
||||||
Keyreq req;
|
|
||||||
uchar token;
|
|
||||||
Alt alts[] = {
|
|
||||||
{keyc, &req, CHANRCV, nil},
|
|
||||||
{nil, &token, CHANRCV, nil},
|
|
||||||
{nil, nil, CHANEND, nil},
|
|
||||||
};
|
|
||||||
|
|
||||||
f = arg;
|
|
||||||
alts[1].c = f->stop;
|
|
||||||
for(;;)
|
|
||||||
switch(alt(alts)){
|
|
||||||
case 0:
|
|
||||||
chansend(f->trace, &req);
|
|
||||||
if(f->holdrelease && req.op == Keyrelease){
|
|
||||||
token = 0;
|
|
||||||
chansend(f->waiting, &token);
|
|
||||||
chanrecv(f->ack, &token);
|
|
||||||
}
|
|
||||||
testenginehandle(&req);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
chansend(f->done, &token);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ximbegin(struct ct *t, Ximfix *f, int lang)
|
ximbegin(struct ct *t, Ximfix *f, int lang)
|
||||||
{
|
{
|
||||||
@@ -451,38 +409,22 @@ ximbegin(struct ct *t, Ximfix *f, int lang)
|
|||||||
testengineinit(lang);
|
testengineinit(lang);
|
||||||
f->oldreply = replyc;
|
f->oldreply = replyc;
|
||||||
replyc = chancreate(sizeof(Keyres), 0);
|
replyc = chancreate(sizeof(Keyres), 0);
|
||||||
f->trace = chancreate(sizeof(Keyreq), 16);
|
pumpstart(&f->pump, 16);
|
||||||
f->stop = chancreate(sizeof(uchar), 0);
|
USED(t);
|
||||||
f->done = chancreate(sizeof(uchar), 0);
|
return 1;
|
||||||
f->waiting = chancreate(sizeof(uchar), 0);
|
|
||||||
f->ack = chancreate(sizeof(uchar), 0);
|
|
||||||
f->pumpactive = threadcreate(enginepump, f, 8192) >= 0;
|
|
||||||
return CT_CHECK(t, replyc != nil && f->trace != nil &&
|
|
||||||
f->stop != nil && f->done != nil && f->waiting != nil &&
|
|
||||||
f->ack != nil && f->pumpactive);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ximend(Ximfix *f)
|
ximend(Ximfix *f)
|
||||||
{
|
{
|
||||||
Drawcmd dc;
|
Drawcmd dc;
|
||||||
uchar token;
|
|
||||||
|
|
||||||
if(f->pumpactive){
|
pumpstop(&f->pump);
|
||||||
token = 0;
|
|
||||||
chansend(f->stop, &token);
|
|
||||||
chanrecv(f->done, &token);
|
|
||||||
}
|
|
||||||
testengineinit(LangEN);
|
testengineinit(LangEN);
|
||||||
while(channbrecv(drawc, &dc) > 0)
|
while(channbrecv(drawc, &dc) > 0)
|
||||||
;
|
;
|
||||||
chanfree(replyc);
|
chanfree(replyc);
|
||||||
replyc = f->oldreply;
|
replyc = f->oldreply;
|
||||||
chanfree(f->trace);
|
|
||||||
chanfree(f->stop);
|
|
||||||
chanfree(f->done);
|
|
||||||
chanfree(f->waiting);
|
|
||||||
chanfree(f->ack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Keyreq
|
static Keyreq
|
||||||
@@ -491,7 +433,7 @@ nexttracecap(struct ct *t, Ximfix *f, int op, Ic *owner, int cap)
|
|||||||
Keyreq req;
|
Keyreq req;
|
||||||
|
|
||||||
memset(&req, 0, sizeof req);
|
memset(&req, 0, sizeof req);
|
||||||
if(!CT_CHECK(t, channbrecv(f->trace, &req) > 0))
|
if(!CT_CHECK(t, channbrecv(f->pump.trace, &req) > 0))
|
||||||
return req;
|
return req;
|
||||||
CT_EQ_INT(t, op, req.op);
|
CT_EQ_INT(t, op, req.op);
|
||||||
CT_EQ_PTR(t, owner, req.owner);
|
CT_EQ_PTR(t, owner, req.owner);
|
||||||
@@ -511,25 +453,7 @@ notrace(struct ct *t, Ximfix *f)
|
|||||||
{
|
{
|
||||||
Keyreq req;
|
Keyreq req;
|
||||||
|
|
||||||
CT_CHECK(t, channbrecv(f->trace, &req) <= 0);
|
CT_CHECK(t, channbrecv(f->pump.trace, &req) <= 0);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
checkstr(struct ct *t, char *want, Str *got)
|
|
||||||
{
|
|
||||||
char buf[Maxutf];
|
|
||||||
|
|
||||||
stoutf(got, buf, sizeof buf);
|
|
||||||
CT_EQ_STR(t, want, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
checkenginepreedit(struct ct *t, char *want)
|
|
||||||
{
|
|
||||||
Str preedit;
|
|
||||||
|
|
||||||
testenginepreedit(&preedit);
|
|
||||||
checkstr(t, want, &preedit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -556,13 +480,13 @@ xim_adapter_key_contract(struct ct *t)
|
|||||||
keypress(&state, 'a', 0, &res);
|
keypress(&state, 'a', 0, &res);
|
||||||
nexttrace(t, &f, Keypress, &state);
|
nexttrace(t, &f, Keypress, &state);
|
||||||
CT_CHECK(t, res.eaten);
|
CT_CHECK(t, res.eaten);
|
||||||
checkstr(t, "か", &res.preedit);
|
checkstr(t, "preedit", "か", &res.preedit);
|
||||||
|
|
||||||
keypress(&state, Kspec|0x57, 0, &res);
|
keypress(&state, Kspec|0x57, 0, &res);
|
||||||
nexttrace(t, &f, Keypress, &state);
|
nexttrace(t, &f, Keypress, &state);
|
||||||
CT_CHECK(t, !res.eaten);
|
CT_CHECK(t, !res.eaten);
|
||||||
checkstr(t, "か", &res.commit);
|
checkstr(t, "preedit", "か", &res.commit);
|
||||||
checkstr(t, "", &res.preedit);
|
checkstr(t, "preedit", "", &res.preedit);
|
||||||
cleanup:
|
cleanup:
|
||||||
ximend(&f);
|
ximend(&f);
|
||||||
}
|
}
|
||||||
@@ -586,7 +510,7 @@ xim_adapter_release_lifecycle(struct ct *t)
|
|||||||
nexttrace(t, &f, Keypress, &a);
|
nexttrace(t, &f, Keypress, &a);
|
||||||
keypress(&b, 'n', 0, &res);
|
keypress(&b, 'n', 0, &res);
|
||||||
nexttrace(t, &f, Keypress, &b);
|
nexttrace(t, &f, Keypress, &b);
|
||||||
checkstr(t, "ん", &res.preedit);
|
checkstr(t, "preedit", "ん", &res.preedit);
|
||||||
CT_EQ_PTR(t, &b, testengineowner());
|
CT_EQ_PTR(t, &b, testengineowner());
|
||||||
|
|
||||||
/* ResetIC and focus loss use the same idempotent release path. */
|
/* ResetIC and focus loss use the same idempotent release path. */
|
||||||
@@ -648,6 +572,7 @@ xim_adapter_free_waits_for_release(struct ct *t)
|
|||||||
Freejob job;
|
Freejob job;
|
||||||
Ic *state;
|
Ic *state;
|
||||||
Channel *freed;
|
Channel *freed;
|
||||||
|
Keyreq req;
|
||||||
Keyres res;
|
Keyres res;
|
||||||
uchar token;
|
uchar token;
|
||||||
int workeractive;
|
int workeractive;
|
||||||
@@ -665,18 +590,21 @@ xim_adapter_free_waits_for_release(struct ct *t)
|
|||||||
ics = state;
|
ics = state;
|
||||||
keypress(state, 'n', 0, &res);
|
keypress(state, 'n', 0, &res);
|
||||||
nexttrace(t, &f, Keypress, state);
|
nexttrace(t, &f, Keypress, state);
|
||||||
f.holdrelease = 1;
|
/* Hold the release: the free must not complete before the engine
|
||||||
|
* acknowledges it, since the engine still points at this Ic. */
|
||||||
|
pumphold(&f.pump, Keyrelease);
|
||||||
job.state = state;
|
job.state = state;
|
||||||
job.done = freed;
|
job.done = freed;
|
||||||
workeractive = threadcreate(freeworker, &job, 8192) >= 0;
|
workeractive = threadcreate(freeworker, &job, 8192) >= 0;
|
||||||
if(!CT_CHECK(t, workeractive))
|
if(!CT_CHECK(t, workeractive))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
chanrecv(f.waiting, &token);
|
chanrecv(f.pump.trace, &req);
|
||||||
nexttrace(t, &f, Keyrelease, state);
|
CT_EQ_INT(t, Keyrelease, req.op);
|
||||||
|
CT_EQ_PTR(t, state, req.owner);
|
||||||
CT_CHECK(t, channbrecv(freed, &token) <= 0);
|
CT_CHECK(t, channbrecv(freed, &token) <= 0);
|
||||||
CT_EQ_PTR(t, state, ics);
|
CT_EQ_PTR(t, state, ics);
|
||||||
CT_EQ_PTR(t, state, testengineowner());
|
CT_EQ_PTR(t, state, testengineowner());
|
||||||
chansend(f.ack, &token);
|
chansend(f.pump.go, &token);
|
||||||
chanrecv(freed, &token);
|
chanrecv(freed, &token);
|
||||||
workeractive = 0;
|
workeractive = 0;
|
||||||
state = nil;
|
state = nil;
|
||||||
@@ -684,7 +612,7 @@ xim_adapter_free_waits_for_release(struct ct *t)
|
|||||||
CT_EQ_PTR(t, nil, testengineowner());
|
CT_EQ_PTR(t, nil, testengineowner());
|
||||||
cleanup:
|
cleanup:
|
||||||
if(workeractive){
|
if(workeractive){
|
||||||
chansend(f.ack, &token);
|
chansend(f.pump.go, &token);
|
||||||
chanrecv(freed, &token);
|
chanrecv(freed, &token);
|
||||||
state = nil;
|
state = nil;
|
||||||
}
|
}
|
||||||
@@ -985,7 +913,7 @@ xim_adapter_callback_cleanup(struct ct *t)
|
|||||||
CT_EQ_INT(t, Wdone, wirecalls[3].op);
|
CT_EQ_INT(t, Wdone, wirecalls[3].op);
|
||||||
keypress(&state, 'n', 0, &res);
|
keypress(&state, 'n', 0, &res);
|
||||||
nexttrace(t, &f, Keypress, &state);
|
nexttrace(t, &f, Keypress, &state);
|
||||||
checkstr(t, "ん", &res.preedit);
|
checkstr(t, "preedit", "ん", &res.preedit);
|
||||||
release(&state);
|
release(&state);
|
||||||
nexttrace(t, &f, Keyrelease, &state);
|
nexttrace(t, &f, Keyrelease, &state);
|
||||||
preowner = nil;
|
preowner = nil;
|
||||||
@@ -1111,7 +1039,7 @@ xim_adapter_callback_owner_loss(struct ct *t)
|
|||||||
chansend(keyc, &req);
|
chansend(keyc, &req);
|
||||||
chanrecv(replyc, &res);
|
chanrecv(replyc, &res);
|
||||||
memset(&trace, 0, sizeof trace);
|
memset(&trace, 0, sizeof trace);
|
||||||
CT_CHECK(t, channbrecv(f.trace, &trace) > 0);
|
CT_CHECK(t, channbrecv(f.pump.trace, &trace) > 0);
|
||||||
CT_EQ_INT(t, Keypress, trace.op);
|
CT_EQ_INT(t, Keypress, trace.op);
|
||||||
CT_EQ_PTR(t, &foreign, trace.owner);
|
CT_EQ_PTR(t, &foreign, trace.owner);
|
||||||
CT_EQ_PTR(t, &foreign, testengineowner());
|
CT_EQ_PTR(t, &foreign, testengineowner());
|
||||||
@@ -1148,7 +1076,7 @@ xim_adapter_callback_owner_loss(struct ct *t)
|
|||||||
chansend(keyc, &req);
|
chansend(keyc, &req);
|
||||||
chanrecv(replyc, &res);
|
chanrecv(replyc, &res);
|
||||||
memset(&trace, 0, sizeof trace);
|
memset(&trace, 0, sizeof trace);
|
||||||
CT_CHECK(t, channbrecv(f.trace, &trace) > 0);
|
CT_CHECK(t, channbrecv(f.pump.trace, &trace) > 0);
|
||||||
CT_EQ_INT(t, Keyrelease, trace.op);
|
CT_EQ_INT(t, Keyrelease, trace.op);
|
||||||
CT_EQ_PTR(t, &foreign, trace.owner);
|
CT_EQ_PTR(t, &foreign, trace.owner);
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|||||||
Reference in New Issue
Block a user