test: cover IPC response framing
This commit is contained in:
164
tests/ipc_test.c
164
tests/ipc_test.c
@@ -1,6 +1,7 @@
|
|||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
@@ -51,3 +52,166 @@ ipc_runtime_path(struct ct *t)
|
|||||||
}else
|
}else
|
||||||
unsetenv("XDG_RUNTIME_DIR");
|
unsetenv("XDG_RUNTIME_DIR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipc_response_pack_boundaries(struct ct *t)
|
||||||
|
{
|
||||||
|
static const uchar withpre[] = { 1, 1, 0, 'A', 2, 0, 'x', 'y' };
|
||||||
|
static const uchar withoutpre[] = { 1, 1, 0, 'A' };
|
||||||
|
uchar out[Ipcmaxresp+1], field[Ipcfieldmax];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = ipcpackresp(out, sizeof out, 7, "A", 1, "xy", 2, 1);
|
||||||
|
CT_EQ_INT(t, sizeof withpre, n);
|
||||||
|
CT_EQ_MEM(t, withpre, out, sizeof withpre);
|
||||||
|
n = ipcpackresp(out, sizeof out, 1, "A", 1, "xy", 2, 0);
|
||||||
|
CT_EQ_INT(t, sizeof withoutpre, n);
|
||||||
|
CT_EQ_MEM(t, withoutpre, out, sizeof withoutpre);
|
||||||
|
n = ipcpackresp(out, sizeof out, 0, nil, 0, nil, 0, 1);
|
||||||
|
CT_EQ_INT(t, Ipcresphdrsz + Ipclensz, n);
|
||||||
|
|
||||||
|
memset(field, 'x', sizeof field);
|
||||||
|
memset(out, 0xa5, sizeof out);
|
||||||
|
n = ipcpackresp(out, Ipcmaxresp, 1,
|
||||||
|
(char*)field, sizeof field, (char*)field, sizeof field, 1);
|
||||||
|
CT_EQ_INT(t, Ipcmaxresp, n);
|
||||||
|
CT_EQ_INT(t, 0, out[1]);
|
||||||
|
CT_EQ_INT(t, 1, out[2]);
|
||||||
|
CT_EQ_INT(t, 0, out[3+Ipcfieldmax]);
|
||||||
|
CT_EQ_INT(t, 1, out[4+Ipcfieldmax]);
|
||||||
|
CT_EQ_INT(t, 0xa5, out[Ipcmaxresp]);
|
||||||
|
CT_EQ_INT(t, -1, ipcpackresp(out, Ipcmaxresp-1, 1,
|
||||||
|
(char*)field, sizeof field, (char*)field, sizeof field, 1));
|
||||||
|
CT_EQ_INT(t, -1, ipcpackresp(out, sizeof out, 0,
|
||||||
|
nil, 1, nil, 0, 0));
|
||||||
|
CT_EQ_INT(t, -1, ipcpackresp(out, sizeof out, 0,
|
||||||
|
nil, 0, nil, 1, 1));
|
||||||
|
CT_EQ_INT(t, -1, ipcpackresp(out, sizeof out, 0,
|
||||||
|
(char*)field, Ipcfieldmax+1, nil, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipc_response_empty_and_preedit(struct ct *t)
|
||||||
|
{
|
||||||
|
uchar first[Ipcmaxresp], second[Ipcmaxresp];
|
||||||
|
char commit[16], preedit[16];
|
||||||
|
Ipcresp resp;
|
||||||
|
int fd[2], nfirst, nsecond;
|
||||||
|
|
||||||
|
nfirst = ipcpackresp(first, sizeof first, 0, nil, 0, nil, 0, 0);
|
||||||
|
nsecond = ipcpackresp(second, sizeof second, 1,
|
||||||
|
"go", 2, "kana", 4, 1);
|
||||||
|
if(!CT_CHECK(t, nfirst > 0 && nsecond > 0))
|
||||||
|
return;
|
||||||
|
if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0){
|
||||||
|
CT_ERRORF(t, "socketpair failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(CT_EQ_INT(t, 0, ipcsend(fd[0], first, nfirst)) &&
|
||||||
|
CT_EQ_INT(t, 0, ipcsend(fd[0], second, nsecond)) &&
|
||||||
|
CT_EQ_INT(t, 0, ipcreadresp(fd[1], 0, commit, sizeof commit,
|
||||||
|
nil, 0, &resp))){
|
||||||
|
CT_EQ_INT(t, 0, resp.eaten);
|
||||||
|
CT_EQ_SIZE(t, 0, resp.ncommit);
|
||||||
|
CT_EQ_SIZE(t, 0, resp.npreedit);
|
||||||
|
CT_EQ_STR(t, "", commit);
|
||||||
|
}
|
||||||
|
if(CT_EQ_INT(t, 0, ipcreadresp(fd[1], 1, commit, sizeof commit,
|
||||||
|
preedit, sizeof preedit, &resp))){
|
||||||
|
CT_EQ_INT(t, 1, resp.eaten);
|
||||||
|
CT_EQ_SIZE(t, 2, resp.ncommit);
|
||||||
|
CT_EQ_SIZE(t, 4, resp.npreedit);
|
||||||
|
CT_EQ_STR(t, "go", commit);
|
||||||
|
CT_EQ_STR(t, "kana", preedit);
|
||||||
|
}
|
||||||
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipc_response_max_and_drain(struct ct *t)
|
||||||
|
{
|
||||||
|
uchar first[Ipcmaxresp], second[Ipcmaxresp], field[Ipcfieldmax];
|
||||||
|
char commit[8], preedit[8];
|
||||||
|
Ipcresp resp;
|
||||||
|
int fd[2], nfirst, nsecond;
|
||||||
|
|
||||||
|
memset(field, 'x', sizeof field);
|
||||||
|
nfirst = ipcpackresp(first, sizeof first, 1,
|
||||||
|
(char*)field, sizeof field, (char*)field, sizeof field, 1);
|
||||||
|
nsecond = ipcpackresp(second, sizeof second, 0, "ok", 2, nil, 0, 0);
|
||||||
|
if(!CT_CHECK(t, nfirst == Ipcmaxresp && nsecond > 0))
|
||||||
|
return;
|
||||||
|
if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0){
|
||||||
|
CT_ERRORF(t, "socketpair failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(CT_EQ_INT(t, 0, ipcsend(fd[0], first, nfirst)) &&
|
||||||
|
CT_EQ_INT(t, 0, ipcsend(fd[0], second, nsecond)) &&
|
||||||
|
CT_EQ_INT(t, 0, ipcreadresp(fd[1], 1, commit, sizeof commit,
|
||||||
|
preedit, sizeof preedit, &resp))){
|
||||||
|
CT_EQ_SIZE(t, Ipcfieldmax, resp.ncommit);
|
||||||
|
CT_EQ_SIZE(t, Ipcfieldmax, resp.npreedit);
|
||||||
|
CT_EQ_STR(t, "xxxxxxx", commit);
|
||||||
|
CT_EQ_STR(t, "xxxxxxx", preedit);
|
||||||
|
}
|
||||||
|
if(CT_EQ_INT(t, 0, ipcreadresp(fd[1], 0, commit, sizeof commit,
|
||||||
|
nil, 0, &resp)))
|
||||||
|
CT_EQ_STR(t, "ok", commit);
|
||||||
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipc_response_fragmented_and_truncated(struct ct *t)
|
||||||
|
{
|
||||||
|
uchar frame[Ipcmaxresp];
|
||||||
|
char commit[8], preedit[8];
|
||||||
|
Ipcresp resp;
|
||||||
|
int fd[2], i, n;
|
||||||
|
|
||||||
|
n = ipcpackresp(frame, sizeof frame, 1, "abc", 3, "xy", 2, 1);
|
||||||
|
if(!CT_CHECK(t, n > 0))
|
||||||
|
return;
|
||||||
|
if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0){
|
||||||
|
CT_ERRORF(t, "socketpair failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
if(ipcsend(fd[0], frame+i, 1) < 0){
|
||||||
|
CT_ERRORF(t, "fragment send failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(i == n && CT_EQ_INT(t, 0, ipcreadresp(fd[1], 1,
|
||||||
|
commit, sizeof commit, preedit, sizeof preedit, &resp))){
|
||||||
|
CT_EQ_STR(t, "abc", commit);
|
||||||
|
CT_EQ_STR(t, "xy", preedit);
|
||||||
|
}
|
||||||
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
|
||||||
|
if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0){
|
||||||
|
CT_ERRORF(t, "socketpair failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CT_EQ_INT(t, 0, ipcsend(fd[0], frame, n-1));
|
||||||
|
shutdown(fd[0], SHUT_WR);
|
||||||
|
CT_EQ_INT(t, -1, ipcreadresp(fd[1], 1, commit, sizeof commit,
|
||||||
|
preedit, sizeof preedit, &resp));
|
||||||
|
close(fd[0]);
|
||||||
|
close(fd[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipc_broken_peer_send(struct ct *t)
|
||||||
|
{
|
||||||
|
int fd[2];
|
||||||
|
|
||||||
|
if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0){
|
||||||
|
CT_ERRORF(t, "socketpair failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
close(fd[1]);
|
||||||
|
CT_EQ_INT(t, -1, ipcsend(fd[0], "x", 1));
|
||||||
|
close(fd[0]);
|
||||||
|
}
|
||||||
|
|||||||
@@ -65,5 +65,10 @@ void dictionary_misses_clear_result(struct ct*);
|
|||||||
void dictionary_emoji_identity(struct ct*);
|
void dictionary_emoji_identity(struct ct*);
|
||||||
void ipc_masks_modifiers(struct ct*);
|
void ipc_masks_modifiers(struct ct*);
|
||||||
void ipc_runtime_path(struct ct*);
|
void ipc_runtime_path(struct ct*);
|
||||||
|
void ipc_response_pack_boundaries(struct ct*);
|
||||||
|
void ipc_response_empty_and_preedit(struct ct*);
|
||||||
|
void ipc_response_max_and_drain(struct ct*);
|
||||||
|
void ipc_response_fragmented_and_truncated(struct ct*);
|
||||||
|
void ipc_broken_peer_send(struct ct*);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -114,6 +114,11 @@ static const struct ct_test tests[] = {
|
|||||||
{ "dict/emoji-identity", dictionary_emoji_identity },
|
{ "dict/emoji-identity", dictionary_emoji_identity },
|
||||||
{ "ipc/masks-modifiers", ipc_masks_modifiers },
|
{ "ipc/masks-modifiers", ipc_masks_modifiers },
|
||||||
{ "ipc/runtime-path", ipc_runtime_path },
|
{ "ipc/runtime-path", ipc_runtime_path },
|
||||||
|
{ "ipc/response-pack-boundaries", ipc_response_pack_boundaries },
|
||||||
|
{ "ipc/response-empty-preedit", ipc_response_empty_and_preedit },
|
||||||
|
{ "ipc/response-max-drain", ipc_response_max_and_drain },
|
||||||
|
{ "ipc/response-fragmented-truncated", ipc_response_fragmented_and_truncated },
|
||||||
|
{ "ipc/broken-peer-send", ipc_broken_peer_send },
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user