summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/kdbus/test-timeout.c
blob: cfd193066a646ef600934a291c7fd439dfab18dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <stdint.h>
#include <errno.h>
#include <assert.h>
#include <poll.h>
#include <stdbool.h>

#include "kdbus-api.h"
#include "kdbus-test.h"
#include "kdbus-util.h"
#include "kdbus-enum.h"

int timeout_msg_recv(struct kdbus_conn *conn, uint64_t *expected)
{
	struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
	struct kdbus_msg *msg;
	int ret;

	ret = kdbus_cmd_recv(conn->fd, &recv);
	if (ret < 0) {
		kdbus_printf("error receiving message: %d (%m)\n", ret);
		return ret;
	}

	msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);

	ASSERT_RETURN_VAL(msg->payload_type == KDBUS_PAYLOAD_KERNEL, -EINVAL);
	ASSERT_RETURN_VAL(msg->src_id == KDBUS_SRC_ID_KERNEL, -EINVAL);
	ASSERT_RETURN_VAL(msg->dst_id == conn->id, -EINVAL);

	*expected &= ~(1ULL << msg->cookie_reply);
	kdbus_printf("Got message timeout for cookie %llu\n",
		     msg->cookie_reply);

	ret = kdbus_free(conn, recv.msg.offset);
	if (ret < 0)
		return ret;

	return 0;
}

int kdbus_test_timeout(struct kdbus_test_env *env)
{
	struct kdbus_conn *conn_a, *conn_b;
	struct pollfd fd;
	int ret, i, n_msgs = 4;
	uint64_t expected = 0;
	uint64_t cookie = 0xdeadbeef;

	conn_a = kdbus_hello(env->buspath, 0, NULL, 0);
	conn_b = kdbus_hello(env->buspath, 0, NULL, 0);
	ASSERT_RETURN(conn_a && conn_b);

	fd.fd = conn_b->fd;

	/*
	 * send messages that expect a reply (within 100 msec),
	 * but never answer it.
	 */
	for (i = 0; i < n_msgs; i++, cookie++) {
		kdbus_printf("Sending message with cookie %llu ...\n",
			     (unsigned long long)cookie);
		ASSERT_RETURN(kdbus_msg_send(conn_b, NULL, cookie,
			      KDBUS_MSG_EXPECT_REPLY,
			      (i + 1) * 100ULL * 1000000ULL, 0,
			      conn_a->id) == 0);
		expected |= 1ULL << cookie;
	}

	for (;;) {
		fd.events = POLLIN | POLLPRI | POLLHUP;
		fd.revents = 0;

		ret = poll(&fd, 1, (n_msgs + 1) * 100);
		if (ret == 0)
			kdbus_printf("--- timeout\n");
		if (ret <= 0)
			break;

		if (fd.revents & POLLIN)
			ASSERT_RETURN(!timeout_msg_recv(conn_b, &expected));

		if (expected == 0)
			break;
	}

	ASSERT_RETURN(expected == 0);

	kdbus_conn_free(conn_a);
	kdbus_conn_free(conn_b);

	return TEST_OK;
}