tests: Generalize test client and add helpers for launching it
This commit is contained in:
+12
-42
@@ -21,45 +21,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "test-runner.h"
|
#include "test-runner.h"
|
||||||
|
|
||||||
|
|
||||||
struct context {
|
struct context {
|
||||||
struct weston_process proc;
|
|
||||||
struct weston_compositor *compositor;
|
struct weston_compositor *compositor;
|
||||||
struct wl_listener client_destroy_listener;
|
struct test_client *client;
|
||||||
struct wl_listener compositor_destroy_listener;
|
struct wl_listener compositor_destroy_listener;
|
||||||
int status;
|
int status;
|
||||||
int got_client_destroy;
|
|
||||||
int done;
|
int done;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
cleanup(struct weston_process *proc, int status)
|
|
||||||
{
|
|
||||||
struct context *context = container_of(proc, struct context, proc);
|
|
||||||
|
|
||||||
fprintf(stderr, "child exited, status %d\n", status);
|
|
||||||
|
|
||||||
wl_display_terminate(context->compositor->wl_display);
|
|
||||||
context->status = status;
|
|
||||||
context->done = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
client_destroy(struct wl_listener *listener, void *data)
|
|
||||||
{
|
|
||||||
struct context *context =
|
|
||||||
container_of(listener, struct context,
|
|
||||||
client_destroy_listener);
|
|
||||||
|
|
||||||
context->got_client_destroy = 1;
|
|
||||||
|
|
||||||
fprintf(stderr, "notify child destroy\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
compositor_destroy(struct wl_listener *listener, void *data)
|
compositor_destroy(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
@@ -68,34 +45,27 @@ compositor_destroy(struct wl_listener *listener, void *data)
|
|||||||
compositor_destroy_listener);
|
compositor_destroy_listener);
|
||||||
|
|
||||||
fprintf(stderr, "notify compositor destroy, status %d, done %d\n",
|
fprintf(stderr, "notify compositor destroy, status %d, done %d\n",
|
||||||
context->status, context->done);
|
context->client->status, context->client->done);
|
||||||
|
|
||||||
assert(context->status == 0);
|
assert(context->client->status == 0);
|
||||||
assert(context->got_client_destroy);
|
assert(context->client->done);
|
||||||
assert(context->done);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(client_test)
|
TEST(client_test)
|
||||||
{
|
{
|
||||||
struct context *context;
|
struct context *context;
|
||||||
char path[256];
|
|
||||||
struct wl_client *client;
|
|
||||||
|
|
||||||
snprintf(path, sizeof path, "%s/test-client", getenv("abs_builddir"));
|
|
||||||
fprintf(stderr, "launching %s\n", path);
|
|
||||||
|
|
||||||
context = malloc(sizeof *context);
|
context = malloc(sizeof *context);
|
||||||
assert(context);
|
assert(context);
|
||||||
context->compositor = compositor;
|
context->compositor = compositor;
|
||||||
context->done = 0;
|
context->done = 0;
|
||||||
context->got_client_destroy = 0;
|
context->client = test_client_launch(compositor);
|
||||||
client = weston_client_launch(compositor,
|
context->client->terminate = 1;
|
||||||
&context->proc, path, cleanup);
|
|
||||||
context->client_destroy_listener.notify = client_destroy;
|
|
||||||
wl_client_add_destroy_listener(client,
|
|
||||||
&context->client_destroy_listener);
|
|
||||||
|
|
||||||
context->compositor_destroy_listener.notify = compositor_destroy;
|
context->compositor_destroy_listener.notify = compositor_destroy;
|
||||||
wl_signal_add(&compositor->destroy_signal,
|
wl_signal_add(&compositor->destroy_signal,
|
||||||
&context->compositor_destroy_listener);
|
&context->compositor_destroy_listener);
|
||||||
|
|
||||||
|
test_client_send(context->client, "bye\n");
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-1
@@ -21,6 +21,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
@@ -33,6 +36,8 @@ handle_global(struct wl_display *display, uint32_t id,
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
|
char buf[256], *p;
|
||||||
|
int ret, fd;
|
||||||
|
|
||||||
display = wl_display_connect(NULL);
|
display = wl_display_connect(NULL);
|
||||||
assert(display);
|
assert(display);
|
||||||
@@ -41,5 +46,27 @@ int main(int argc, char *argv[])
|
|||||||
wl_display_iterate(display, WL_DISPLAY_READABLE);
|
wl_display_iterate(display, WL_DISPLAY_READABLE);
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(display);
|
||||||
|
|
||||||
return 0;
|
fd = 0;
|
||||||
|
p = getenv("TEST_SOCKET");
|
||||||
|
if (p)
|
||||||
|
fd = strtol(p, NULL, 0);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ret = read(fd, buf, sizeof buf);
|
||||||
|
if (ret == -1) {
|
||||||
|
fprintf(stderr, "read error: fd %d, %m\n", fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "test-client: got %.*s\n", ret - 1, buf, ret);
|
||||||
|
|
||||||
|
if (strncmp(buf, "bye\n", ret) == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "unknown command %.*s\n", ret, buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,13 +25,75 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include "test-runner.h"
|
#include "test-runner.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_client_cleanup(struct weston_process *proc, int status)
|
||||||
|
{
|
||||||
|
struct test_client *client =
|
||||||
|
container_of(proc, struct test_client, proc);
|
||||||
|
|
||||||
|
fprintf(stderr, "test client exited, status %d\n", status);
|
||||||
|
|
||||||
|
client->status = status;
|
||||||
|
client->done = 1;
|
||||||
|
|
||||||
|
if (client->terminate)
|
||||||
|
wl_display_terminate(client->compositor->wl_display);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct test_client *
|
||||||
|
test_client_launch(struct weston_compositor *compositor)
|
||||||
|
{
|
||||||
|
struct test_client *client;
|
||||||
|
int ret, sv[2], client_fd;
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
client = malloc(sizeof *client);
|
||||||
|
assert(client);
|
||||||
|
ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv);
|
||||||
|
assert(ret == 0);
|
||||||
|
|
||||||
|
client_fd = dup(sv[0]);
|
||||||
|
assert(client_fd >= 0);
|
||||||
|
snprintf(buf, sizeof buf, "%d", client_fd);
|
||||||
|
setenv("TEST_SOCKET", buf, 1);
|
||||||
|
snprintf(buf, sizeof buf, "%s/test-client", getenv("abs_builddir"));
|
||||||
|
fprintf(stderr, "launching %s\n", buf);
|
||||||
|
|
||||||
|
client->terminate = 0;
|
||||||
|
client->compositor = compositor;
|
||||||
|
client->client = weston_client_launch(compositor,
|
||||||
|
&client->proc, buf,
|
||||||
|
test_client_cleanup);
|
||||||
|
assert(client->client);
|
||||||
|
close(sv[0]);
|
||||||
|
client->fd = sv[1];
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_client_send(struct test_client *client, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
len = vsnprintf(buf, sizeof buf, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
assert(write(client->fd, buf, len) == len);
|
||||||
|
}
|
||||||
|
|
||||||
extern const struct test __start_test_section, __stop_test_section;
|
extern const struct test __start_test_section, __stop_test_section;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -22,4 +22,17 @@ struct test {
|
|||||||
\
|
\
|
||||||
static void name(struct weston_compositor *compositor)
|
static void name(struct weston_compositor *compositor)
|
||||||
|
|
||||||
|
struct test_client {
|
||||||
|
struct weston_compositor *compositor;
|
||||||
|
struct wl_client *client;
|
||||||
|
struct weston_process proc;
|
||||||
|
int fd;
|
||||||
|
int done;
|
||||||
|
int status;
|
||||||
|
int terminate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_client *test_client_launch(struct weston_compositor *compositor);
|
||||||
|
void test_client_send(struct test_client *client, const char *fmt, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user