66ebb47370eb41e719ff5e46089ceaae0efea1bc
[platform/kernel/linux-rpi.git] / tools / testing / selftests / kdbus / test-names.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <time.h>
4 #include <fcntl.h>
5 #include <stdlib.h>
6 #include <stddef.h>
7 #include <unistd.h>
8 #include <stdint.h>
9 #include <errno.h>
10 #include <assert.h>
11 #include <limits.h>
12 #include <getopt.h>
13 #include <stdbool.h>
14
15 #include "kdbus-api.h"
16 #include "kdbus-util.h"
17 #include "kdbus-enum.h"
18 #include "kdbus-test.h"
19
20 static int conn_is_name_owner(const struct kdbus_conn *conn,
21                               const char *needle)
22 {
23         struct kdbus_cmd_list cmd_list = { .size = sizeof(cmd_list) };
24         struct kdbus_info *name, *list;
25         bool found = false;
26         int ret;
27
28         cmd_list.flags = KDBUS_LIST_NAMES;
29
30         ret = kdbus_cmd_list(conn->fd, &cmd_list);
31         ASSERT_RETURN(ret == 0);
32
33         list = (struct kdbus_info *)(conn->buf + cmd_list.offset);
34         KDBUS_FOREACH(name, list, cmd_list.list_size) {
35                 struct kdbus_item *item;
36                 const char *n = NULL;
37
38                 KDBUS_ITEM_FOREACH(item, name, items)
39                         if (item->type == KDBUS_ITEM_OWNED_NAME)
40                                 n = item->name.name;
41
42                 if (name->id == conn->id &&
43                     n && strcmp(needle, n) == 0) {
44                         found = true;
45                         break;
46                 }
47         }
48
49         ret = kdbus_free(conn, cmd_list.offset);
50         ASSERT_RETURN(ret == 0);
51
52         return found ? 0 : -1;
53 }
54
55 int kdbus_test_name_basic(struct kdbus_test_env *env)
56 {
57         struct kdbus_conn *conn;
58         char *name, *dot_name, *invalid_name, *wildcard_name;
59         int ret;
60
61         name = "foo.bla.blaz";
62         dot_name = ".bla.blaz";
63         invalid_name = "foo";
64         wildcard_name = "foo.bla.bl.*";
65
66         /* create a 2nd connection */
67         conn = kdbus_hello(env->buspath, 0, NULL, 0);
68         ASSERT_RETURN(conn != NULL);
69
70         /* acquire name "foo.bar.xxx" name */
71         ret = kdbus_name_acquire(conn, "foo.bar.xxx", NULL);
72         ASSERT_RETURN(ret == 0);
73
74         /* Name is not valid, must fail */
75         ret = kdbus_name_acquire(env->conn, dot_name, NULL);
76         ASSERT_RETURN(ret == -EINVAL);
77
78         ret = kdbus_name_acquire(env->conn, invalid_name, NULL);
79         ASSERT_RETURN(ret == -EINVAL);
80
81         ret = kdbus_name_acquire(env->conn, wildcard_name, NULL);
82         ASSERT_RETURN(ret == -EINVAL);
83
84         /* check that we can acquire a name */
85         ret = kdbus_name_acquire(env->conn, name, NULL);
86         ASSERT_RETURN(ret == 0);
87
88         ret = conn_is_name_owner(env->conn, name);
89         ASSERT_RETURN(ret == 0);
90
91         /* ... and release it again */
92         ret = kdbus_name_release(env->conn, name);
93         ASSERT_RETURN(ret == 0);
94
95         ret = conn_is_name_owner(env->conn, name);
96         ASSERT_RETURN(ret != 0);
97
98         /* check that we can't release it again */
99         ret = kdbus_name_release(env->conn, name);
100         ASSERT_RETURN(ret == -ESRCH);
101
102         /* check that we can't release a name that we don't own */
103         ret = kdbus_name_release(env->conn, "foo.bar.xxx");
104         ASSERT_RETURN(ret == -EADDRINUSE);
105
106         /* Name is not valid, must fail */
107         ret = kdbus_name_release(env->conn, dot_name);
108         ASSERT_RETURN(ret == -ESRCH);
109
110         ret = kdbus_name_release(env->conn, invalid_name);
111         ASSERT_RETURN(ret == -ESRCH);
112
113         ret = kdbus_name_release(env->conn, wildcard_name);
114         ASSERT_RETURN(ret == -ESRCH);
115
116         kdbus_conn_free(conn);
117
118         return TEST_OK;
119 }
120
121 int kdbus_test_name_conflict(struct kdbus_test_env *env)
122 {
123         struct kdbus_conn *conn;
124         char *name;
125         int ret;
126
127         name = "foo.bla.blaz";
128
129         /* create a 2nd connection */
130         conn = kdbus_hello(env->buspath, 0, NULL, 0);
131         ASSERT_RETURN(conn != NULL);
132
133         /* allow the new connection to own the same name */
134         /* acquire name from the 1st connection */
135         ret = kdbus_name_acquire(env->conn, name, NULL);
136         ASSERT_RETURN(ret == 0);
137
138         ret = conn_is_name_owner(env->conn, name);
139         ASSERT_RETURN(ret == 0);
140
141         /* check that we can't acquire it again from the 1st connection */
142         ret = kdbus_name_acquire(env->conn, name, NULL);
143         ASSERT_RETURN(ret == -EALREADY);
144
145         /* check that we also can't acquire it again from the 2nd connection */
146         ret = kdbus_name_acquire(conn, name, NULL);
147         ASSERT_RETURN(ret == -EEXIST);
148
149         kdbus_conn_free(conn);
150
151         return TEST_OK;
152 }
153
154 int kdbus_test_name_queue(struct kdbus_test_env *env)
155 {
156         struct kdbus_conn *conn;
157         const char *name;
158         uint64_t flags;
159         int ret;
160
161         name = "foo.bla.blaz";
162
163         flags = KDBUS_NAME_ALLOW_REPLACEMENT;
164
165         /* create a 2nd connection */
166         conn = kdbus_hello(env->buspath, 0, NULL, 0);
167         ASSERT_RETURN(conn != NULL);
168
169         /* allow the new connection to own the same name */
170         /* acquire name from the 1st connection */
171         ret = kdbus_name_acquire(env->conn, name, &flags);
172         ASSERT_RETURN(ret == 0);
173
174         ret = conn_is_name_owner(env->conn, name);
175         ASSERT_RETURN(ret == 0);
176
177         /* queue the 2nd connection as waiting owner */
178         flags = KDBUS_NAME_QUEUE;
179         ret = kdbus_name_acquire(conn, name, &flags);
180         ASSERT_RETURN(ret == 0);
181         ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE);
182
183         /* release name from 1st connection */
184         ret = kdbus_name_release(env->conn, name);
185         ASSERT_RETURN(ret == 0);
186
187         /* now the name should be owned by the 2nd connection */
188         ret = conn_is_name_owner(conn, name);
189         ASSERT_RETURN(ret == 0);
190
191         kdbus_conn_free(conn);
192
193         return TEST_OK;
194 }