const char *desc;
int (*func)(struct kdbus_test_env *env);
unsigned int flags;
+ unsigned timeout;
};
struct kdbus_test_args {
int wait;
int fork;
int tap_output;
+ unsigned nTests;
+ char const * const *tests;
char *module;
char *root;
- char *test;
char *busname;
};
.desc = "bus make functions",
.func = kdbus_test_bus_make,
.flags = 0,
+ .timeout = 10,
},
{
.name = "hello",
.desc = "the HELLO command",
.func = kdbus_test_hello,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "byebye",
.desc = "the BYEBYE command",
.func = kdbus_test_byebye,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "chat",
.desc = "a chat pattern",
.func = kdbus_test_chat,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "daemon",
.desc = "a simple daemon",
.func = kdbus_test_daemon,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "fd-passing",
.desc = "file descriptor passing",
.func = kdbus_test_fd_passing,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "endpoint",
.desc = "custom endpoint",
.func = kdbus_test_custom_endpoint,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "monitor",
.desc = "monitor functionality",
.func = kdbus_test_monitor,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "name-basics",
.desc = "basic name registry functions",
.func = kdbus_test_name_basic,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "name-conflict",
.desc = "name registry conflict details",
.func = kdbus_test_name_conflict,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "name-queue",
.desc = "queuing of names",
.func = kdbus_test_name_queue,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "name-takeover",
.desc = "takeover of names",
.func = kdbus_test_name_takeover,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "message-basic",
.desc = "basic message handling",
.func = kdbus_test_message_basic,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "message-prio",
.desc = "handling of messages with priority",
.func = kdbus_test_message_prio,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "activator-quota",
.desc = "activator message quotas are enforced",
.func = kdbus_test_activator_quota,
.flags = TEST_CREATE_BUS,
+ .timeout = 60,
},
{
.name = "message-quota",
.desc = "message quotas are enforced",
.func = kdbus_test_message_quota,
.flags = TEST_CREATE_BUS,
+ .timeout = 30,
},
{
.name = "memory-access",
.desc = "memory access",
.func = kdbus_test_memory_access,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "timeout",
.desc = "timeout",
.func = kdbus_test_timeout,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "sync-byebye",
.desc = "synchronous replies vs. BYEBYE",
.func = kdbus_test_sync_byebye,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "sync-reply",
.desc = "synchronous replies",
.func = kdbus_test_sync_reply,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "big-meta",
.desc = "big metadata",
.func = kdbus_test_big_metadata,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "message-free",
.desc = "freeing of memory",
.func = kdbus_test_free,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "connection-info",
.desc = "retrieving connection information",
.func = kdbus_test_conn_info,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "connection-update",
.desc = "updating connection information",
.func = kdbus_test_conn_update,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "writable-pool",
.desc = "verifying pools are never writable",
.func = kdbus_test_writable_pool,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "policy",
.desc = "policy",
.func = kdbus_test_policy,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "policy-priv",
.desc = "unprivileged bus access",
.func = kdbus_test_policy_priv,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "policy-ns",
.desc = "policy in user namespaces",
.func = kdbus_test_policy_ns,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "metadata",
.desc = "metadata",
.func = kdbus_test_metadata,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "metadata-conn-info",
.desc = "metadata in connection-info",
.func = kdbus_test_metadata_conn_info,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "metadata-ns",
.desc = "metadata in different namespaces",
.func = kdbus_test_metadata_ns,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "match-id-add",
.desc = "adding of matches by id",
.func = kdbus_test_match_id_add,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "match-id-remove",
.desc = "removing of matches by id",
.func = kdbus_test_match_id_remove,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "match-replace",
.desc = "replace of matches with the same cookie",
.func = kdbus_test_match_replace,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "match-name-add",
.desc = "adding of matches by name",
.func = kdbus_test_match_name_add,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "match-name-remove",
.desc = "removing of matches by name",
.func = kdbus_test_match_name_remove,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "match-name-change",
.desc = "matching for name changes",
.func = kdbus_test_match_name_change,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "match-bloom",
.desc = "matching with bloom filters",
.func = kdbus_test_match_bloom,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "match-all",
.desc = "itemless catch-all matching",
.func = kdbus_test_match_itemless,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "activator",
.desc = "activator connections",
.func = kdbus_test_activator,
.flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
+ .timeout = 10,
},
{
.name = "benchmark",
.desc = "benchmark",
.func = kdbus_test_benchmark,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "benchmark-nomemfds",
.desc = "benchmark without using memfds",
.func = kdbus_test_benchmark_nomemfds,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
{
.name = "benchmark-uds",
.desc = "benchmark comparison to UDS",
.func = kdbus_test_benchmark_uds,
.flags = TEST_CREATE_BUS,
+ .timeout = 10,
},
};
static wur int test_run_forked(const struct kdbus_test *t,
const struct kdbus_test_args *kdbus_args,
- int wait)
+ int _wait)
{
- int ret;
- pid_t pid;
+ int ret, result;
+ pid_t pid, timer_pid;
pid = fork();
if (pid < 0) {
return TEST_ERR;
} else if (pid == 0) {
- ret = test_run(t, kdbus_args, wait);
- _exit(ret);
+ ret = test_run(t, kdbus_args, _wait);
+ exit(ret);
}
- pid = waitpid(pid, &ret, 0);
- if (pid <= 0)
- return TEST_ERR;
- else if (!WIFEXITED(ret))
+ timer_pid = fork();
+ if (timer_pid < 0) {
return TEST_ERR;
- else
- return WEXITSTATUS(ret);
+ } else if (timer_pid == 0) {
+ sleep(t->timeout);
+ exit(1);
+ }
+
+ result = -1;
+ for (;;) {
+ pid_t wpid = wait(&ret);
+ if (wpid <= 0)
+ return TEST_ERR;
+ if (result >= 0)
+ break;
+ result = !WIFEXITED(ret) || WEXITSTATUS(ret) ? TEST_ERR + (timer_pid==wpid) : TEST_OK;
+ kill(wpid ^ pid ^ timer_pid, SIGKILL);
+ }
+
+ return result;
}
static void print_test_result(int ret)
}
}
+static void print_res(struct kdbus_test const *t, int ret) {
+ printf("%s;%s\n", t->name, !ret ? "PASS" : TEST_TIME==ret ? "FAIL;TIMEOUT" : "FAIL");
+}
+
static wur int start_all_tests(struct kdbus_test_args const *kdbus_args)
{
int ret;
skip_cnt++;
break;
case TEST_ERR:
+ case TEST_TIME:
fail_cnt++;
break;
}
if (kdbus_args->tap_output) {
print("%sok %d - %s%s (%s)\n",
- (ret == TEST_ERR) ? "not " : "", i + 1,
+ (ret >= TEST_ERR) ? "not " : "", i + 1,
(ret == TEST_SKIP) ? "# SKIP " : "",
t->desc, t->name);
fflush(stdout);
} else {
print_test_result(ret);
+ print_res(t, ret);
print("\n");
}
}
return fail_cnt > 0 ? TEST_ERR : TEST_OK;
}
-static wur int start_one_test(struct kdbus_test_args const *kdbus_args)
+static wur int start_some_tests(struct kdbus_test_args const *kdbus_args)
{
int i, ret;
bool test_found = false;
+ unsigned j=0, nTests = kdbus_args->nTests;
+
+ do {
+ char const *tName = kdbus_args->tests[j];
+ for (i = 0; i < N_TESTS; i++) {
+ const struct kdbus_test *t = tests + i;
+
+ if (strcmp(t->name, tName))
+ continue;
+
+ do {
+ test_found = true;
+ if (kdbus_args->fork)
+ ret = test_run_forked(t, kdbus_args,
+ kdbus_args->wait);
+ else
+ ret = test_run(t, kdbus_args,
+ kdbus_args->wait);
+
+ print("Testing %s: ", t->desc);
+ print_test_result(ret);
+ print_res(t, ret);
+ print("\n");
+
+ if (ret != TEST_OK)
+ break;
+ } while (kdbus_args->loop);
+ }
- for (i = 0; i < N_TESTS; i++) {
- const struct kdbus_test *t = tests + i;
-
- if (strcmp(t->name, kdbus_args->test))
- continue;
-
- do {
- test_found = true;
- if (kdbus_args->fork)
- ret = test_run_forked(t, kdbus_args,
- kdbus_args->wait);
- else
- ret = test_run(t, kdbus_args,
- kdbus_args->wait);
-
- print("Testing %s: ", t->desc);
- print_test_result(ret);
- print("\n");
-
- if (ret != TEST_OK)
- break;
- } while (kdbus_args->loop);
-
- return ret;
- }
-
- if (!test_found) {
- print("Unknown test-id '%s'\n", kdbus_args->test);
- return TEST_ERR;
- }
+ if (!test_found) {
+ print("%s;UNKNOWN\n", tName);
+ }
+ } while (++j < nTests);
- return TEST_OK;
+ return ret;
}
static void usage(const char *argv0)
"\t-x, --loop Run in a loop\n"
"\t-f, --fork Fork before running a test\n"
"\t-h, --help Print this help\n"
- "\t-r, --root <root> Toplevel of the kdbus hierarchy\n"
+ "\t-R, --root <root> Toplevel of the kdbus hierarchy\n"
"\t-t, --test <test-id> Run one specific test only, in verbose mode\n"
"\t-b, --bus <busname> Instead of generating a random bus name, take <busname>.\n"
"\t-w, --wait <secs> Wait <secs> before actually starting test\n"
return TEST_ERR;
}
- if (kdbus_args->test) {
- ret = start_one_test(kdbus_args);
+ if (kdbus_args->nTests) {
+ ret = start_some_tests(kdbus_args);
} else {
do {
ret = start_all_tests(kdbus_args);
if (ret < 0) {
ret = -errno;
print("error prctl(): %d (%m)\n", ret);
- _exit(TEST_ERR);
+ exit(TEST_ERR);
}
/* reset sighandlers of childs */
if (ret < 0) {
ret = -errno;
print("sigaction() failed: %d (%m)\n", ret);
- _exit(TEST_ERR);
+ exit(TEST_ERR);
}
ret = eventfd_read(efd, &event_status);
if (ret < 0 || event_status != 1) {
print("error eventfd_read()\n");
- _exit(TEST_ERR);
+ exit(TEST_ERR);
}
if (kdbus_args->mntns) {
ret = test_prepare_mounts(kdbus_args);
if (ret < 0) {
print("error preparing mounts\n");
- _exit(TEST_ERR);
+ exit(TEST_ERR);
}
}
ret = run_tests(kdbus_args);
- _exit(ret);
+ exit(ret);
}
/* Setup userns mapping */
static const struct option options[] = {
{ "loop", no_argument, NULL, 'x' },
{ "help", no_argument, NULL, 'h' },
- { "root", required_argument, NULL, 'r' },
- { "test", required_argument, NULL, 't' },
+ { "root", required_argument, NULL, 'R' },
+ { "test", no_argument, NULL, 't' },
{ "bus", required_argument, NULL, 'b' },
{ "wait", required_argument, NULL, 'w' },
{ "fork", no_argument, NULL, 'f' },
srand(time(NULL));
- while ((t = getopt_long(argc, argv, "hxfm:r:t:b:w:a:l", options, NULL)) >= 0) {
+ bool gotT = 0;
+
+ while ((t = getopt_long(argc, argv, "hxftm:R:b:w:a:l", options, NULL)) >= 0) {
switch (t) {
case 'x':
kdbus_args.loop = 1;
kdbus_args.module = optarg;
break;
- case 'r':
+ case 'R':
kdbus_args.root = optarg;
break;
case 't':
- kdbus_args.test = optarg;
+ gotT = 1;
break;
case 'b':
case 'l':
{
- int i = 0;
+ unsigned i = 0;
do {
const struct kdbus_test *t = &tests[i];
printf("%s;%s\n", t->name, t->desc);
} while (++i < TABSIZE(tests)-1);
-
}
return 0;
kdbus_args.gid_map = optarg;
break;
- default:
case 'h':
usage(argv[0]);
+
+ default:
+ kdbus_args.tests = (char const * const *)&argv[optind];
+ if (1 < (kdbus_args.nTests = argc-optind) || !gotT)
+ kdbus_args.fork = 1;
}
}