tests: cover ibus connection capacity recovery
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
Maxconnections = 16,
|
||||||
Calltimeout = 4000,
|
Calltimeout = 4000,
|
||||||
Starttimeout = 8000,
|
Starttimeout = 8000,
|
||||||
Stoptimeout = 3000,
|
Stoptimeout = 3000,
|
||||||
@@ -626,6 +627,67 @@ closebus(DBusConnection **conn, Siglog *log)
|
|||||||
*conn = NULL;
|
*conn = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
overflowrejected(char *address)
|
||||||
|
{
|
||||||
|
DBusConnection *conn;
|
||||||
|
DBusError err;
|
||||||
|
struct pollfd pfd;
|
||||||
|
int fd, n, ok, timeout;
|
||||||
|
int64_t deadline;
|
||||||
|
|
||||||
|
dbus_error_init(&err);
|
||||||
|
conn = dbus_connection_open_private(address, &err);
|
||||||
|
if(conn == NULL){
|
||||||
|
if(!dbus_error_is_set(&err)){
|
||||||
|
dbus_error_free(&err);
|
||||||
|
return fail("overflow connection failed without a D-Bus error");
|
||||||
|
}
|
||||||
|
dbus_error_free(&err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
dbus_error_free(&err);
|
||||||
|
dbus_connection_set_exit_on_disconnect(conn, FALSE);
|
||||||
|
if(!dbus_connection_get_unix_fd(conn, &fd)){
|
||||||
|
dbus_connection_close(conn);
|
||||||
|
dbus_connection_unref(conn);
|
||||||
|
return fail("overflow connection has no Unix descriptor");
|
||||||
|
}
|
||||||
|
ok = 0;
|
||||||
|
deadline = nowms() + Calltimeout;
|
||||||
|
for(;;){
|
||||||
|
if(!dbus_connection_get_is_connected(conn)){
|
||||||
|
ok = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
timeout = leftms(deadline);
|
||||||
|
if(timeout == 0){
|
||||||
|
fail("overflow IBus connection was not rejected");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pfd.fd = fd;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
pfd.revents = 0;
|
||||||
|
n = poll(&pfd, 1, timeout);
|
||||||
|
if(n < 0 && errno == EINTR)
|
||||||
|
continue;
|
||||||
|
if(n < 0){
|
||||||
|
fail("poll overflow IBus connection: %s", strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(n == 0)
|
||||||
|
continue;
|
||||||
|
if(pfd.revents & POLLNVAL){
|
||||||
|
fail("overflow IBus descriptor became invalid");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dbus_connection_read_write_dispatch(conn, 0);
|
||||||
|
}
|
||||||
|
dbus_connection_close(conn);
|
||||||
|
dbus_connection_unref(conn);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
static DBusMessage*
|
static DBusMessage*
|
||||||
method(char *path, char *iface, char *member)
|
method(char *path, char *iface, char *member)
|
||||||
{
|
{
|
||||||
@@ -642,9 +704,11 @@ static DBusMessage*
|
|||||||
sendcall(DBusConnection *conn, DBusMessage *m)
|
sendcall(DBusConnection *conn, DBusMessage *m)
|
||||||
{
|
{
|
||||||
DBusMessage *reply;
|
DBusMessage *reply;
|
||||||
DBusError err;
|
DBusPendingCall *pending;
|
||||||
char member[64], path[128];
|
char member[64], path[128];
|
||||||
const char *s;
|
const char *s;
|
||||||
|
int timeout;
|
||||||
|
int64_t deadline;
|
||||||
|
|
||||||
if(m == NULL)
|
if(m == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -652,21 +716,39 @@ sendcall(DBusConnection *conn, DBusMessage *m)
|
|||||||
snprintf(member, sizeof member, "%s", s != NULL ? s : "method");
|
snprintf(member, sizeof member, "%s", s != NULL ? s : "method");
|
||||||
s = dbus_message_get_path(m);
|
s = dbus_message_get_path(m);
|
||||||
snprintf(path, sizeof path, "%s", s != NULL ? s : "path");
|
snprintf(path, sizeof path, "%s", s != NULL ? s : "path");
|
||||||
dbus_error_init(&err);
|
pending = NULL;
|
||||||
reply = dbus_connection_send_with_reply_and_block(conn, m,
|
if(!dbus_connection_send_with_reply(conn, m, &pending, Calltimeout) ||
|
||||||
Calltimeout, &err);
|
pending == NULL){
|
||||||
dbus_message_unref(m);
|
dbus_message_unref(m);
|
||||||
if(reply == NULL){
|
fail("queue %s on %s: out of memory", member, path);
|
||||||
fail("%s on %s: %s: %s", member, path,
|
return NULL;
|
||||||
err.name != NULL ? err.name : "D-Bus error",
|
}
|
||||||
err.message != NULL ? err.message : "no reply");
|
dbus_message_unref(m);
|
||||||
dbus_error_free(&err);
|
deadline = nowms() + Calltimeout;
|
||||||
|
while(!dbus_pending_call_get_completed(pending)){
|
||||||
|
timeout = leftms(deadline);
|
||||||
|
if(timeout == 0){
|
||||||
|
fail("timed out waiting for %s on %s", member, path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if(!dbus_connection_read_write_dispatch(conn, timeout)){
|
||||||
|
fail("connection closed waiting for %s on %s", member, path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply = dbus_pending_call_steal_reply(pending);
|
||||||
|
dbus_pending_call_unref(pending);
|
||||||
|
if(reply == NULL){
|
||||||
|
fail("%s on %s completed without a reply", member, path);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
dbus_error_free(&err);
|
|
||||||
while(dbus_connection_get_dispatch_status(conn) == DBUS_DISPATCH_DATA_REMAINS)
|
while(dbus_connection_get_dispatch_status(conn) == DBUS_DISPATCH_DATA_REMAINS)
|
||||||
dbus_connection_dispatch(conn);
|
dbus_connection_dispatch(conn);
|
||||||
return reply;
|
return reply;
|
||||||
|
fail:
|
||||||
|
dbus_pending_call_cancel(pending);
|
||||||
|
dbus_pending_call_unref(pending);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -930,6 +1012,67 @@ expectkey(DBusConnection *conn, Siglog *log, char *path,
|
|||||||
text[0] != '\0', where);
|
text[0] != '\0', where);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
runconnectioncapacity(Daemon *d)
|
||||||
|
{
|
||||||
|
DBusConnection *conn[Maxconnections];
|
||||||
|
Siglog logs[Maxconnections];
|
||||||
|
char names[Maxconnections][32];
|
||||||
|
char paths[Maxconnections][96];
|
||||||
|
int i, ok;
|
||||||
|
|
||||||
|
for(i = 0; i < Maxconnections; i++)
|
||||||
|
conn[i] = NULL;
|
||||||
|
memset(logs, 0, sizeof logs);
|
||||||
|
ok = 0;
|
||||||
|
for(i = 0; i < Maxconnections; i++){
|
||||||
|
conn[i] = openbus(d->address, &logs[i]);
|
||||||
|
if(conn[i] == NULL || !hello(conn[i], names[i], sizeof names[i]) ||
|
||||||
|
!createcontext(conn[i], paths[i], sizeof paths[i]) ||
|
||||||
|
!emptycall(conn[i], &logs[i], paths[i], "FocusIn") ||
|
||||||
|
!nosignal(&logs[i], "connection capacity FocusIn") ||
|
||||||
|
!expectkey(conn[i], &logs[i], paths[i], 0xffe1, 0, 0, "",
|
||||||
|
"connection capacity key"))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if(!overflowrejected(d->address))
|
||||||
|
goto out;
|
||||||
|
for(i = 0; i < Maxconnections; i++)
|
||||||
|
if(!expectkey(conn[i], &logs[i], paths[i], 0xffe1, 0, 0, "",
|
||||||
|
"accepted connection after rejection"))
|
||||||
|
goto out;
|
||||||
|
closebus(&conn[Maxconnections-1], &logs[Maxconnections-1]);
|
||||||
|
if(!expectkey(conn[0], &logs[0], paths[0], 0xffe1, 0, 0, "",
|
||||||
|
"connection close barrier"))
|
||||||
|
goto out;
|
||||||
|
conn[Maxconnections-1] = openbus(d->address,
|
||||||
|
&logs[Maxconnections-1]);
|
||||||
|
if(conn[Maxconnections-1] == NULL ||
|
||||||
|
!hello(conn[Maxconnections-1], names[Maxconnections-1],
|
||||||
|
sizeof names[Maxconnections-1]) ||
|
||||||
|
!createcontext(conn[Maxconnections-1], paths[Maxconnections-1],
|
||||||
|
sizeof paths[Maxconnections-1]) ||
|
||||||
|
!emptycall(conn[Maxconnections-1], &logs[Maxconnections-1],
|
||||||
|
paths[Maxconnections-1], "FocusIn") ||
|
||||||
|
!nosignal(&logs[Maxconnections-1], "recovered connection FocusIn") ||
|
||||||
|
!expectkey(conn[Maxconnections-1], &logs[Maxconnections-1],
|
||||||
|
paths[Maxconnections-1], 'n', Ctrlmask, 1, "",
|
||||||
|
"recovered connection select Japanese") ||
|
||||||
|
!expectkey(conn[Maxconnections-1], &logs[Maxconnections-1],
|
||||||
|
paths[Maxconnections-1], 'k', 0, 1, "k",
|
||||||
|
"recovered connection key"))
|
||||||
|
goto out;
|
||||||
|
for(i = 0; i < Maxconnections-1; i++)
|
||||||
|
if(!expectkey(conn[i], &logs[i], paths[i], 0xffe1, 0, 0, "",
|
||||||
|
"accepted connection after recovery"))
|
||||||
|
goto out;
|
||||||
|
ok = 1;
|
||||||
|
out:
|
||||||
|
for(i = 0; i < Maxconnections; i++)
|
||||||
|
closebus(&conn[i], &logs[i]);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
runlifecycle(Daemon *d)
|
runlifecycle(Daemon *d)
|
||||||
{
|
{
|
||||||
@@ -1060,6 +1203,8 @@ main(int argc, char **argv)
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
ok = startdaemon(&daemon, argv[1], argv[2]);
|
ok = startdaemon(&daemon, argv[1], argv[2]);
|
||||||
|
if(ok)
|
||||||
|
ok = runconnectioncapacity(&daemon);
|
||||||
if(ok)
|
if(ok)
|
||||||
ok = runlifecycle(&daemon);
|
ok = runlifecycle(&daemon);
|
||||||
if(!ok)
|
if(!ok)
|
||||||
@@ -1068,6 +1213,6 @@ main(int argc, char **argv)
|
|||||||
ok = 0;
|
ok = 0;
|
||||||
if(!ok)
|
if(!ok)
|
||||||
return 1;
|
return 1;
|
||||||
printf("ibus live lifecycle: ok\n");
|
printf("ibus live lifecycle and connection capacity: ok\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user