tests: cover ibus connection capacity recovery

This commit is contained in:
2026-08-14 00:44:49 +09:00
parent 91b3042e66
commit 0f8396915b

View File

@@ -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;
} }