kdbus: test suite changed to common format
[platform/kernel/linux-exynos.git] / tools / testing / selftests / kdbus / test-match.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <fcntl.h>
4 #include <stdlib.h>
5 #include <stddef.h>
6 #include <unistd.h>
7 #include <stdint.h>
8 #include <errno.h>
9 #include <assert.h>
10 #include <stdbool.h>
11
12 #include "kdbus-api.h"
13 #include "kdbus-util.h"
14 #include "kdbus-enum.h"
15 #include "kdbus-test.h"
16
17 static wur int add_id_match_(struct kdbus_conn *conn, uint64_t flags, uint64_t notification_type, uint64_t id)
18 {
19         struct {
20                 struct kdbus_cmd_match cmd;
21                 struct {
22                         uint64_t size;
23                         uint64_t type;
24                         struct kdbus_notify_id_change chg;
25                 } item;
26         } buf;
27         memset(&buf, 0, sizeof(buf));
28         buf.cmd.size = sizeof(buf);
29         buf.cmd.cookie = 0xdeafbeefdeaddead;
30         buf.cmd.flags = flags;
31         buf.item.size = sizeof(buf.item);
32         buf.item.type = notification_type;
33         buf.item.chg.id = id;
34         ASSERT_ZERO(kdbus_cmd_match_add(conn->fd, &buf.cmd));
35         return 0;
36 }
37 #define ADD_ID_MATCH(CONN,FLAGS,NOTIFICATION_TYPE,ID)\
38         ASSERT_ZERO(add_id_match_((CONN),(FLAGS),KDBUS_ITEM_ID_##NOTIFICATION_TYPE,(ID)))
39
40 wur int kdbus_test_match_id_add(struct kdbus_test_env *env)
41 {
42         struct kdbus_conn *conn;
43         struct kdbus_msg *msg;
44
45         /* match on id add */
46         ADD_ID_MATCH(env->conn, 0, ADD, KDBUS_MATCH_ID_ANY);
47
48         /* create 2nd connection */
49         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
50
51         /* 1st connection should have received a notification */
52         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
53         ASSERT_NO_PENDING(env->conn);
54
55         ASSERT_RETURN(msg->items[0].type,==,(typeof(msg->items[0].type))KDBUS_ITEM_ID_ADD);
56         ASSERT_RETURN(msg->items[0].id_change.id,==,conn->id);
57
58         kdbus_conn_free(conn);
59
60         return TEST_OK;
61 }
62
63 wur int kdbus_test_match_id_remove(struct kdbus_test_env *env)
64 {
65         struct kdbus_conn *conn;
66         struct kdbus_msg *msg;
67         size_t id;
68
69         /* create 2nd connection */
70         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
71         id = conn->id;
72
73         /* register match on 1st connection */
74         ADD_ID_MATCH(env->conn, 0, REMOVE, id);
75
76         /* remove 2nd connection again */
77         kdbus_conn_free(conn);
78
79         /* 1st connection should have received a notification */
80         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
81
82         ASSERT_RETURN(msg->items[0].type,==,(typeof(msg->items[0].type))KDBUS_ITEM_ID_REMOVE);
83         ASSERT_RETURN(msg->items[0].id_change.id,==,id);
84
85         return TEST_OK;
86 }
87
88 wur int kdbus_test_match_replace(struct kdbus_test_env *env)
89 {
90         struct kdbus_conn *conn;
91         struct kdbus_msg *msg;
92         size_t id;
93
94         /* add a match to id_add */
95         ASSERT_RETURN(kdbus_test_match_id_add(env),==,TEST_OK);
96
97         /* do a replace of the match from id_add to id_remove */
98         ADD_ID_MATCH(env->conn, KDBUS_MATCH_REPLACE, REMOVE, KDBUS_MATCH_ID_ANY);
99
100         /* create 2nd connection */
101         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
102         id = conn->id;
103
104         /* 1st connection should _not_ have received a notification */
105         ASSERT_NONZERO(kdbus_msg_recv(env->conn, &msg, NULL));
106
107         /* remove 2nd connection */
108         kdbus_conn_free(conn);
109
110         /* 1st connection should _now_ have received a notification */
111         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
112
113         ASSERT_RETURN(msg->items[0].type,==,(typeof(msg->items[0].type))KDBUS_ITEM_ID_REMOVE);
114         ASSERT_RETURN(msg->items[0].id_change.id,==,id);
115
116         return TEST_OK;
117 }
118
119 #define UNMATCHED_NAME "this.will.never.match"
120
121 static wur int add_name_match_(struct kdbus_conn *conn, uint64_t flags, uint64_t old_id, uint64_t new_id, uint64_t notification_type, char const *name)
122 {
123         struct {
124                 struct kdbus_cmd_match cmd;
125                 struct {
126                         uint64_t size;
127                         uint64_t type;
128                         struct kdbus_notify_name_change chg;
129                 } item;
130                 char name[64];
131         } buf;
132         memset(&buf, 0, sizeof(buf));
133         buf.cmd.flags = flags;
134         buf.cmd.cookie = 0xdeaddeaddeafbeef;
135         buf.item.type = notification_type;
136         buf.item.chg.old_id.id = old_id;
137         buf.item.chg.new_id.id = new_id;
138         buf.item.size = sizeof(buf.item);
139         if (name) {
140                 __auto_type name_size = strlen(name)+1;
141                 memcpy(buf.name, name, name_size);
142                 buf.item.size += name_size;
143         }
144         buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
145         ASSERT_ZERO(kdbus_cmd_match_add(conn->fd, &buf.cmd));
146         return 0;
147 }
148 #define ADD_NAME_MATCH(CONN,FLAGS,OLD_ID,NEW_ID,NOTIFICATION_TYPE,NAME)\
149         ASSERT_ZERO(add_name_match_((CONN),(FLAGS),(OLD_ID),(NEW_ID),KDBUS_ITEM_NAME_##NOTIFICATION_TYPE,(NAME)))
150
151 static wur int assert_single_match_(struct kdbus_conn *conn, uint64_t old_id, uint64_t new_id, uint64_t notification_type, char const *name)
152 {
153         struct kdbus_msg *msg;
154         ASSERT_ZERO(kdbus_msg_recv(conn, &msg, NULL));
155         ASSERT_RETURN(msg->items[0].type,==,notification_type);
156         ASSERT_RETURN(msg->items[0].name_change.old_id.id,==,old_id);
157         ASSERT_RETURN(msg->items[0].name_change.new_id.id,==,new_id);
158         ASSERT_ZERO(strcmp(msg->items[0].name_change.name, name));
159         ASSERT_ZERO(kdbus_free_msg(conn, msg));
160         ASSERT_NO_PENDING(conn);
161         return 0;
162 }
163 #define ASSERT_SINGLE_MATCH(CONN,OLD_ID,NEW_ID,NOTIFICATION_TYPE,NAME)\
164         ASSERT_ZERO(assert_single_match_((CONN),(OLD_ID),(NEW_ID),KDBUS_ITEM_NAME_##NOTIFICATION_TYPE,(NAME)))
165
166 static wur int kdbus_test_match_name_add_(struct kdbus_test_env *env, char const *name, struct kdbus_conn *listener)
167 {
168         /* acquire the name */
169         ASSERT_ZERO(kdbus_name_acquire(env->conn, name, NULL));
170
171         #define CHECK(CONN) ASSERT_SINGLE_MATCH((CONN), 0, env->conn->id, ADD, name)
172                 CHECK(env->conn);
173                 if (listener)
174                         CHECK(listener);
175         #undef CHECK
176
177         ASSERT_ZERO(kdbus_name_release(env->conn, name));
178
179         return 0;
180 }
181
182 wur int kdbus_test_match_name_add(struct kdbus_test_env *env)
183 {
184         struct kdbus_conn *listener;
185         char const *name = "foo.bla.blaz";
186
187         ASSERT_NONZERO(listener = kdbus_hello(env->buspath, 0, NULL, 0));
188
189         /* install the match rule */
190         ADD_NAME_MATCH(env->conn, 0, KDBUS_MATCH_ID_ANY, KDBUS_MATCH_ID_ANY, ADD, name);
191
192         /* no accidental notifications when no match set up */
193         ASSERT_ZERO(kdbus_test_match_name_add_(env, name, NULL));
194         ASSERT_NO_PENDING(listener);
195
196         #define CHECK(ID,NAME,CONN_IF_WILL_MATCH) do {\
197                 ADD_NAME_MATCH(listener, KDBUS_MATCH_REPLACE, KDBUS_MATCH_ID_ANY, (ID), ADD, NAME);\
198                 ASSERT_ZERO(kdbus_test_match_name_add_(env, name, (CONN_IF_WILL_MATCH)));\
199                 ASSERT_NO_PENDING(listener);\
200         } while (0)
201                 CHECK(KDBUS_MATCH_ID_ANY, UNMATCHED_NAME, NULL); /* wrong name */
202                 CHECK(KDBUS_MATCH_ID_ANY, NULL, listener); /* wildcard name */
203                 CHECK(env->conn->id, NULL, listener); /* wildcard name + good id */
204                 CHECK(env->conn->id + 1, NULL, NULL); /* wildcard name + bad id */
205         #undef CHECK
206         kdbus_conn_free(listener);
207
208         return 0;
209 }
210
211 static wur int kdbus_test_match_name_remove_(struct kdbus_test_env *env, char const *name, struct kdbus_conn *listener)
212 {
213         /* acquire the name */
214         ASSERT_ZERO(kdbus_name_acquire(env->conn, name, NULL));
215
216         /* release the name again */
217         ASSERT_ZERO(kdbus_name_release(env->conn, name));
218
219         /* we should have received a notification */
220         #define CHECK(CONN) ASSERT_SINGLE_MATCH((CONN), env->conn->id, 0, REMOVE, name)
221                 CHECK(env->conn);
222                 if (listener)
223                         CHECK(listener);
224         #undef CHECK
225
226         return 0;
227 }
228
229 wur int kdbus_test_match_name_remove(struct kdbus_test_env *env)
230 {
231         struct kdbus_conn *listener;
232         char const *name = "foo.bla.blazz";
233
234         ASSERT_NONZERO(listener = kdbus_hello(env->buspath, 0, NULL, 0));
235
236         /* install the match rule */
237         ADD_NAME_MATCH(env->conn, 0, KDBUS_MATCH_ID_ANY, KDBUS_MATCH_ID_ANY, REMOVE, name);
238
239         /* no accidental notifications when no match set up */
240         ASSERT_ZERO(kdbus_test_match_name_remove_(env, name, NULL));
241         ASSERT_NO_PENDING(listener);
242
243         #define CHECK(ID,NAME,CONN_IF_WILL_MATCH) do {\
244                 ADD_NAME_MATCH(listener, KDBUS_MATCH_REPLACE, (ID), KDBUS_MATCH_ID_ANY, REMOVE, NAME);\
245                 ASSERT_ZERO(kdbus_test_match_name_remove_(env, name, (CONN_IF_WILL_MATCH)));\
246                 ASSERT_NO_PENDING(listener);\
247         } while (0)
248                 CHECK(KDBUS_MATCH_ID_ANY, UNMATCHED_NAME, NULL); /* wrong name */
249                 CHECK(KDBUS_MATCH_ID_ANY, NULL, listener); /* wildcard name */
250                 CHECK(env->conn->id, NULL, listener); /* wildcard name + good id */
251                 CHECK(env->conn->id + 1, NULL, NULL); /* wildcard name + bad id */
252         #undef CHECK
253         kdbus_conn_free(listener);
254
255         return 0;
256 }
257
258 static wur int kdbus_test_match_name_change_(struct kdbus_test_env *env, struct kdbus_conn *conn, char const *name, struct kdbus_conn *listener)
259 {
260         uint64_t flags;
261
262         /* acquire the name */
263         ASSERT_ZERO(kdbus_name_acquire(env->conn, name, NULL));
264
265         /* allow the new connection to own the same name */
266         /* queue the 2nd connection as waiting owner */
267         flags = KDBUS_NAME_QUEUE;
268         ASSERT_ZERO(kdbus_name_acquire(conn, name, &flags));
269         ASSERT_NONZERO(flags & KDBUS_NAME_IN_QUEUE);
270
271         /* release name from 1st connection */
272         ASSERT_ZERO(kdbus_name_release(env->conn, name));
273
274         /* we should have received a notification */
275         #define CHECK(CONN) ASSERT_SINGLE_MATCH((CONN), env->conn->id, conn->id, CHANGE, name)
276                 CHECK(env->conn);
277                 if (listener)
278                         CHECK(listener);
279         #undef CHECK
280
281         ASSERT_ZERO(kdbus_name_release(conn, name));
282
283         return 0;
284 }
285
286 wur int kdbus_test_match_name_change(struct kdbus_test_env *env)
287 {
288         struct kdbus_conn *listener, *conn;
289         char const *name = "foo.bla.baz";
290
291         /* create a 2nd connection */
292         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
293
294         ASSERT_NONZERO(listener = kdbus_hello(env->buspath, 0, NULL, 0));
295
296         ADD_NAME_MATCH(env->conn, 0, KDBUS_MATCH_ID_ANY, KDBUS_MATCH_ID_ANY, CHANGE, name);
297
298         /* no accidental notifications when no match set up */
299         ASSERT_ZERO(kdbus_test_match_name_change_(env, conn, name, NULL));
300         ASSERT_NO_PENDING(listener);
301
302         #define CHECK(OLD_ID,NEW_ID,NAME,CONN_IF_WILL_MATCH) do {\
303                 ADD_NAME_MATCH(listener, KDBUS_MATCH_REPLACE, (OLD_ID), (NEW_ID), CHANGE, NAME);\
304                 ASSERT_ZERO(kdbus_test_match_name_change_(env, conn, name, (CONN_IF_WILL_MATCH)));\
305                 ASSERT_NO_PENDING(listener);\
306         } while (0)
307                 CHECK(KDBUS_MATCH_ID_ANY, KDBUS_MATCH_ID_ANY, UNMATCHED_NAME, NULL); /* wrong name */
308                 CHECK(KDBUS_MATCH_ID_ANY, KDBUS_MATCH_ID_ANY, NULL, listener); /* wildcard name */
309
310                 CHECK(env->conn->id, KDBUS_MATCH_ID_ANY, NULL, listener); /* wildcard name + good id */
311                 CHECK(env->conn->id + 1, KDBUS_MATCH_ID_ANY, NULL, NULL); /* wildcard name + bad id */
312
313                 CHECK(KDBUS_MATCH_ID_ANY, conn->id, NULL, listener); /* good id */
314                 CHECK(KDBUS_MATCH_ID_ANY, conn->id + 1, NULL, NULL); /* bad id */
315
316                 CHECK(env->conn->id, conn->id, NULL, listener); /* wildcard name + good id */
317
318                 CHECK(env->conn->id + 1, conn->id, NULL, NULL); /* wildcard name + bad id */
319                 CHECK(env->conn->id, conn->id + 1, NULL, NULL); /* wildcard name + bad id */
320         #undef CHECK
321         kdbus_conn_free(listener);
322         ASSERT_NO_PENDING(conn);
323         kdbus_conn_free(conn);
324
325         return 0;
326 }
327
328 static wur int send_bloom_filter(const struct kdbus_conn *conn,
329                              uint64_t cookie,
330                              const uint8_t *filter,
331                              size_t filter_size,
332                              uint64_t filter_generation)
333 {
334         struct kdbus_cmd_send cmd = {};
335         struct kdbus_msg *msg;
336         struct kdbus_item *item;
337         uint64_t size;
338         int ret;
339
340         size = sizeof(struct kdbus_msg);
341         size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + filter_size;
342
343         msg = alloca(size);
344
345         memset(msg, 0, size);
346         msg->size = size;
347         msg->src_id = conn->id;
348         msg->dst_id = KDBUS_DST_ID_BROADCAST;
349         msg->flags = KDBUS_MSG_SIGNAL;
350         msg->payload_type = KDBUS_PAYLOAD_DBUS;
351         msg->cookie = cookie;
352
353         item = msg->items;
354         item->type = KDBUS_ITEM_BLOOM_FILTER;
355         item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) +
356                                 filter_size;
357
358         item->bloom_filter.generation = filter_generation;
359         memcpy(item->bloom_filter.data, filter, filter_size);
360
361         cmd.size = sizeof(cmd);
362         cmd.msg_address = (uintptr_t)msg;
363
364         ret = kdbus_cmd_send(conn->fd, &cmd);
365         if (ret < 0) {
366                 kdbus_printf("error sending message: %d (%m)\n", ret);
367                 return ret;
368         }
369
370         return 0;
371 }
372
373 wur int kdbus_test_match_bloom(struct kdbus_test_env *env)
374 {
375         struct {
376                 struct kdbus_cmd_match cmd;
377                 struct {
378                         uint64_t size;
379                         uint64_t type;
380                         uint8_t data_gen0[64];
381                         uint8_t data_gen1[64];
382                 } item;
383         } buf;
384         struct kdbus_conn *conn;
385         struct kdbus_msg *msg;
386         uint64_t cookie = 0xf000f00f;
387         uint8_t filter[64];
388
389         /* install the match rule */
390         memset(&buf, 0, sizeof(buf));
391         buf.cmd.size = sizeof(buf);
392
393         buf.item.size = sizeof(buf.item);
394         buf.item.type = KDBUS_ITEM_BLOOM_MASK;
395         buf.item.data_gen0[0] = 0x55;
396         buf.item.data_gen0[63] = 0x80;
397
398         buf.item.data_gen1[1] = 0xaa;
399         buf.item.data_gen1[9] = 0x02;
400
401         ASSERT_ZERO(kdbus_cmd_match_add(env->conn->fd, &buf.cmd));
402
403         /* create a 2nd connection */
404         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
405
406         /* a message with a 0'ed out filter must not reach the other peer */
407         memset(filter, 0, sizeof(filter));
408         ASSERT_ZERO(send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0));
409
410         ASSERT_RETURN(-EAGAIN,==,kdbus_msg_recv(env->conn, &msg, NULL));
411
412         /* now set the filter to the connection's mask and expect success */
413         filter[0] = 0x55;
414         filter[63] = 0x80;
415         ASSERT_ZERO(send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0));
416
417         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
418         ASSERT_RETURN(msg->cookie,==,cookie);
419
420         /* broaden the filter and try again. this should also succeed. */
421         filter[0] = 0xff;
422         filter[8] = 0xff;
423         filter[63] = 0xff;
424         ASSERT_ZERO(send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0));
425
426         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
427         ASSERT_RETURN(msg->cookie,==,cookie);
428
429         /* the same filter must not match against bloom generation 1 */
430         ASSERT_ZERO(send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1));
431
432         ASSERT_RETURN(-EAGAIN,==,kdbus_msg_recv(env->conn, &msg, NULL));
433
434         /* set a different filter and try again */
435         filter[1] = 0xaa;
436         filter[9] = 0x02;
437         ASSERT_ZERO(send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1));
438
439         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
440         ASSERT_RETURN(msg->cookie,==,cookie);
441
442         kdbus_conn_free(conn);
443
444         return TEST_OK;
445 }
446
447 static wur int has_all_names(struct kdbus_item *item, unsigned size)
448 {
449         char seen[256];
450         int left = sizeof(seen);
451         memset(seen, 0, sizeof(seen));
452
453         while (size && left) {
454                 uint64_t item_size = KDBUS_ALIGN8(item->size);
455                 if (item_size > size)
456                         return -1;
457                 if (KDBUS_ITEM_OWNED_NAME == item->type) {
458                         int i;
459                         ASSERT_RETURN(255u,==,strlen(item->name.name));
460                         ASSERT_RETURN(0,==,memcmp(item->name.name, "big.n", 5));
461                         for (i=5;i<252;++i)
462                                 ASSERT_RETURN('0',==,(int)item->name.name[i]);
463                         ASSERT_RETURN('0',<=,(int)item->name.name[252]);
464                         ASSERT_RETURN((int)item->name.name[252],<=,'9');
465                         ASSERT_RETURN('0',<=,(int)item->name.name[253]);
466                         ASSERT_RETURN((int)item->name.name[253],<=,'9');
467                         ASSERT_RETURN('0',<=,(int)item->name.name[254]);
468                         ASSERT_RETURN((int)item->name.name[254],<=,'9');
469                         i = item->name.name[254]-'0' + 10*(item->name.name[253]-'0') + 100*(item->name.name[252]-'0');
470                         ASSERT_RETURN(0,<=,i);
471                         ASSERT_RETURN(i,<,256);
472                         ASSERT_ZERO((int)seen[i]);
473                         seen[i] = 1;
474                         --left;
475                 }
476                 size -= (unsigned)item_size;
477                 item = (typeof(item))((uintptr_t)item + (unsigned)item_size);
478         }
479
480         return left;
481 }
482
483 wur int kdbus_test_big_metadata(struct kdbus_test_env *env)
484 {
485         uint64_t offset;
486         struct kdbus_conn *conn;
487         struct kdbus_msg *msg;
488         struct kdbus_info *info;
489         int i;
490         char buf[256];
491
492         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
493         for (i=256; --i>=0;) {
494                 sprintf(buf, "big.n%0250d", i);
495                 /*print("\nreg (%s)\n", buf);*/
496                 ASSERT_ZERO(kdbus_name_acquire(conn, buf, NULL));
497         }
498
499         /*print("\nreg done\n");*/
500
501         ASSERT_ZERO(kdbus_msg_send(conn, NULL, 1, 0, 0, 0, env->conn->id));
502         /*print("\nsend done\n");*/
503         /*print("\nfree done\n");*/
504
505         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
506         /*print("\nrecv done\n");*/
507
508         ASSERT_ZERO(has_all_names(msg->items, msg->size - offsetof(typeof(*msg), items)));
509
510         kdbus_msg_free(msg);
511
512         ASSERT_ZERO(kdbus_conn_info(env->conn, conn->id, NULL, _KDBUS_ATTACH_ALL, &offset));
513         info = (struct kdbus_info *)(env->conn->buf + offset);
514         ASSERT_RETURN(info->id,==,conn->id);
515         ASSERT_ZERO(has_all_names(info->items, info->size - offsetof(typeof(*info), items)));
516
517         kdbus_conn_free(conn);
518
519         /*print("\nfree done\n");*/
520
521         return TEST_OK;
522 }
523
524 wur int kdbus_test_match_itemless(struct kdbus_test_env *env)
525 {
526         struct kdbus_cmd_match cmd;
527         struct kdbus_conn *conn;
528         struct kdbus_msg *msg;
529         uint64_t cookie = 0xf000f00f;
530         uint8_t filter[64];
531
532         /* install the match rule */
533         memset(&cmd, 0, sizeof(cmd));
534         cmd.size = sizeof(cmd);
535
536         ASSERT_ZERO(kdbus_cmd_match_add(env->conn->fd, &cmd));
537
538         /* create a 2nd connection */
539         ASSERT_NONZERO(conn = kdbus_hello(env->buspath, 0, NULL, 0));
540
541         /* 1st connection should have received a notification */
542         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
543         ASSERT_NO_PENDING(env->conn);
544         ASSERT_RETURN(msg->items[0].type,==,(typeof(msg->items[0].type))KDBUS_ITEM_ID_ADD);
545         ASSERT_RETURN(msg->items[0].id_change.id,==,conn->id);
546
547         /* even a message with a 0'ed out filter must match */
548         memset(filter, 0, sizeof(filter));
549         ASSERT_ZERO(send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0));
550
551         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
552         ASSERT_NO_PENDING(env->conn);
553         ASSERT_RETURN(msg->cookie,==,cookie);
554
555         ASSERT_ZERO(kdbus_name_acquire(conn, "mein.volk", NULL));
556         /* 1st connection should have received a notification */
557         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
558         ASSERT_NO_PENDING(env->conn);
559         ASSERT_RETURN(msg->items[0].type,==,(typeof(msg->items[0].type))KDBUS_ITEM_NAME_ADD);
560         ASSERT_RETURN(msg->items[0].name_change.new_id.id,==,conn->id);
561
562         ASSERT_ZERO(kdbus_name_release(conn, "mein.volk"));
563         /* 1st connection should have received a notification */
564         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
565         ASSERT_NO_PENDING(env->conn);
566         ASSERT_RETURN(msg->items[0].type,==,(typeof(msg->items[0].type))KDBUS_ITEM_NAME_REMOVE);
567         ASSERT_RETURN(msg->items[0].name_change.old_id.id,==,conn->id);
568
569         kdbus_conn_free(conn);
570
571         /* 1st connection should have received a notification */
572         ASSERT_ZERO(kdbus_msg_recv(env->conn, &msg, NULL));
573         ASSERT_NO_PENDING(env->conn);
574         ASSERT_RETURN(msg->items[0].type,==,(typeof(msg->items[0].type))KDBUS_ITEM_ID_REMOVE);
575         ASSERT_RETURN(msg->items[0].id_change.id,==,conn->id);
576
577         ASSERT_NO_PENDING(env->conn);
578
579         return TEST_OK;
580 }