Imported Upstream version 1
[platform/upstream/buxton.git] / test / check_daemon.c
1 /*
2  * This file is part of buxton.
3  *
4  * Copyright (C) 2013 Intel Corporation
5  *
6  * buxton is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1
9  * of the License, or (at your option) any later version.
10  */
11
12 #ifdef HAVE_CONFIG_H
13         #include "config.h"
14 #endif
15
16 #include <check.h>
17 #include <fcntl.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 #include <sys/stat.h>
24 #include <errno.h>
25 #include <signal.h>
26 #include <unistd.h>
27 #include <time.h>
28
29 #include "buxton.h"
30 #include "buxtonresponse.h"
31 #include "configurator.h"
32 #include "check_utils.h"
33 #include "daemon.h"
34 #include "direct.h"
35 #include "hashmap.h"
36 #include "log.h"
37 #include "smack.h"
38 #include "util.h"
39
40 #ifdef NDEBUG
41 #error "re-run configure with --enable-debug"
42 #endif
43
44 #define BUXTON_ROOT_CHECK_ENV "BUXTON_ROOT_CHECK"
45
46 static pid_t daemon_pid;
47 int fuzz_time;
48
49 typedef struct _fuzz_context_t {
50         uint8_t buf[4096];
51         size_t size;
52         int iteration;
53 } FuzzContext;
54
55 static bool use_smack(void)
56 {
57         bool __attribute__((unused))dummy;
58
59         dummy = buxton_cache_smack_rules();
60
61         return buxton_smack_enabled();
62 }
63
64 static char* dump_fuzz(FuzzContext *fuzz)
65 {
66         char* buf;
67         size_t buff_size;
68         FILE* s;
69         int l = 0;
70         int c = 0;
71
72         s = open_memstream(&buf, &buff_size);
73
74         fprintf(s, "\n\n******************************************\n");
75         fprintf(s, "current time %ld\n", time(NULL));
76         fprintf(s, "iteration: %d\tsize: %llu\n", fuzz->iteration, (unsigned long long)fuzz->size);
77         for (int i = 0; i < fuzz->size; i++) {
78                 fprintf(s, "%02X ", fuzz->buf[i]);
79                 c+= 3;
80                 if (c > 80) {
81                         fprintf(s, "\n");
82                         c = 0;
83                         l++;
84                 }
85         }
86         fclose(s);
87
88         return buf;
89 }
90
91 static void check_did_not_crash(pid_t pid, FuzzContext *fuzz)
92 {
93         pid_t rpid;
94         int status;
95
96         rpid = waitpid(pid, &status, WNOHANG);
97         fail_if(rpid == -1, "couldn't wait for pid %m");
98         if (rpid == 0) {
99                 /* child is still running */
100                 return;
101         }
102         fail_if(WIFEXITED(status), "daemon exited with status %d%s",
103                 WEXITSTATUS(status), dump_fuzz(fuzz));
104         fail_if(WIFSIGNALED(status), "daemon was killed with signal %d%s",
105                 WTERMSIG(status), dump_fuzz(fuzz));
106 }
107
108 static void exec_daemon(void)
109 {
110         char path[PATH_MAX];
111
112         //FIXME: path is wrong for makedistcheck
113         snprintf(path, PATH_MAX, "%s/check_buxtond", get_current_dir_name());
114
115         if (execl(path, "check_buxtond", (const char*)NULL) < 0) {
116                 fail("couldn't exec: %m");
117         }
118         fail("should never reach here");
119 }
120
121 static void setup(void)
122 {
123         daemon_pid = 0;
124         sigset_t sigset;
125         pid_t pid;
126
127         unlink(buxton_socket());
128
129         sigemptyset(&sigset);
130         sigaddset(&sigset, SIGCHLD);
131         sigprocmask(SIG_BLOCK, &sigset, NULL);
132
133         pid = fork();
134         fail_if(pid < 0, "couldn't fork");
135         if (pid) {
136                 /* parent*/
137                 daemon_pid = pid;
138                 usleep(128*1000);
139         } else {
140                 /* child */
141                 exec_daemon();
142         }
143 }
144
145 static void teardown(void)
146 {
147         if (daemon_pid) {
148                 int status;
149                 pid_t pid;
150
151                 pid = waitpid(daemon_pid, &status, WNOHANG);
152                 fail_if(pid == -1, "waitpid error");
153                 if (pid) {
154                         fail("daemon crashed!");
155                 } else  {
156                         /* if the daemon is still running, kill it */
157                         kill(SIGTERM, daemon_pid);
158                         usleep(64*1000);
159                         kill(SIGKILL, daemon_pid);
160                 }
161         }
162 }
163
164 START_TEST(buxton_open_check)
165 {
166         BuxtonClient c = NULL;
167         fail_if(buxton_open(&c) == -1,
168                 "Connection failed to open with daemon.");
169 }
170 END_TEST
171
172 static void client_create_group_test(BuxtonResponse response, void *data)
173 {
174         char *k = (char *)data;
175         BuxtonKey key;
176         char *group;
177         uid_t uid = getuid();
178         char *root_check = getenv(BUXTON_ROOT_CHECK_ENV);
179         bool skip_check = (root_check && streq(root_check, "0"));
180
181         fail_if(buxton_response_type(response) != BUXTON_CONTROL_CREATE_GROUP,
182                 "Failed to get create group response type");
183
184         if (uid == 0) {
185                 fail_if(buxton_response_status(response) != 0,
186                         "Create group failed");
187                 key = buxton_response_key(response);
188                 fail_if(!key, "Failed to get create group key");
189                 group = buxton_key_get_group(key);
190                 fail_if(!group, "Failed to get group from key");
191                 fail_if(!streq(group, k),
192                         "Incorrect set key returned");
193                 free(group);
194                 buxton_key_free(key);
195         } else {
196                 fail_if(buxton_response_status(response) == 0  && !skip_check,
197                         "Create group succeeded, but the client is not root");
198         }
199 }
200 START_TEST(buxton_create_group_check)
201 {
202         BuxtonClient c;
203         BuxtonKey key = buxton_key_create("tgroup", NULL, "base", STRING);
204         fail_if(!key, "Failed to create key");
205         fail_if(buxton_open(&c) == -1,
206                 "Open failed with daemon.");
207         fail_if(buxton_create_group(c, key, client_create_group_test,
208                                     "tgroup", true),
209                 "Creating group in buxton failed.");
210         buxton_key_free(key);
211 }
212 END_TEST
213
214 static void client_remove_group_test(BuxtonResponse response, void *data)
215 {
216         char *k = (char *)data;
217         BuxtonKey key;
218         char *group;
219         uid_t uid = getuid();
220         char *root_check = getenv(BUXTON_ROOT_CHECK_ENV);
221         bool skip_check = (root_check && streq(root_check, "0"));
222
223         fail_if(buxton_response_type(response) != BUXTON_CONTROL_REMOVE_GROUP,
224                 "Failed to get remove group response type");
225
226         if (uid == 0) {
227                 fail_if(buxton_response_status(response) != 0,
228                         "Remove group failed");
229                 key = buxton_response_key(response);
230                 fail_if(!key, "Failed to get create group key");
231                 group = buxton_key_get_group(key);
232                 fail_if(!group, "Failed to get group from key");
233                 fail_if(!streq(group, k),
234                         "Incorrect set key returned");
235                 free(group);
236                 buxton_key_free(key);
237         } else {
238                 fail_if(buxton_response_status(response) == 0  && !skip_check,
239                         "Create group succeeded, but the client is not root");
240         }
241 }
242 START_TEST(buxton_remove_group_check)
243 {
244         BuxtonClient c;
245         BuxtonKey key = buxton_key_create("tgroup", NULL, "base", STRING);
246         fail_if(!key, "Failed to create key");
247         fail_if(buxton_open(&c) == -1,
248                 "Open failed with daemon.");
249         fail_if(buxton_remove_group(c, key, client_remove_group_test,
250                                     "tgroup", true),
251                 "Removing group in buxton failed.");
252         buxton_key_free(key);
253 }
254 END_TEST
255
256 static void client_set_value_test(BuxtonResponse response, void *data)
257 {
258         char *k = (char *)data;
259         BuxtonKey key;
260         char *group;
261
262         fail_if(buxton_response_type(response) != BUXTON_CONTROL_SET,
263                 "Failed to get set response type");
264         fail_if(buxton_response_status(response) != 0,
265                 "Set value failed");
266         key = buxton_response_key(response);
267         fail_if(!key, "Failed to get set key");
268         group = buxton_key_get_group(key);
269         fail_if(!group, "Failed to get group from key");
270         fail_if(!streq(group, k),
271                 "Incorrect set group returned");
272         free(group);
273         buxton_key_free(key);
274 }
275 START_TEST(buxton_set_value_check)
276 {
277         BuxtonClient c;
278         BuxtonKey group = buxton_key_create("group", NULL, "test-gdbm-user", STRING);
279         fail_if(!group, "Failed to create key for group");
280         BuxtonKey key = buxton_key_create("group", "name", "test-gdbm-user", STRING);
281         fail_if(!key, "Failed to create key");
282         fail_if(buxton_open(&c) == -1,
283                 "Open failed with daemon.");
284         fail_if(buxton_create_group(c, group, NULL, NULL, true),
285                 "Creating group in buxton failed.");
286         fail_if(buxton_set_label(c, group, "*", NULL, NULL, true),
287                 "Setting group in buxton failed.");
288         fail_if(buxton_set_value(c, key, "bxt_test_value",
289                                  client_set_value_test,
290                                  "group", true),
291                 "Setting value in buxton failed.");
292         buxton_key_free(group);
293         buxton_key_free(key);
294 }
295 END_TEST
296
297 static void client_set_label_test(BuxtonResponse response, void *data)
298 {
299         BuxtonKey user_key = (BuxtonKey)data;
300         BuxtonKey key;
301         char *user_group, *group;
302         char *user_name, *name;
303         uid_t uid = getuid();
304         char *root_check = getenv(BUXTON_ROOT_CHECK_ENV);
305         bool skip_check = (root_check && streq(root_check, "0"));
306
307         fail_if(buxton_response_type(response) != BUXTON_CONTROL_SET_LABEL,
308                 "Failed to get set label response type");
309
310         if (uid == 0) {
311                 fail_if(buxton_response_status(response) != 0,
312                         "Set label failed");
313                 key = buxton_response_key(response);
314                 fail_if(!key, "Failed to get set label key");
315                 user_group = buxton_key_get_group(user_key);
316                 fail_if(!user_group, "Failed to get group from user key");
317                 group = buxton_key_get_group(key);
318                 fail_if(!group, "Failed to get group from key");
319                 fail_if(!streq(group, user_group),
320                         "Incorrect set label group returned");
321                 free(user_group);
322                 free(group);
323
324                 user_name = buxton_key_get_name(user_key);
325                 if (user_name) {
326                         name = buxton_key_get_name(key);
327                         fail_if(!name, "Failed to get name from key");
328                         fail_if(!streq(name, user_name),
329                                 "Incorrect set label name returned");
330                         free(user_name);
331                         free(name);
332                 }
333                 buxton_key_free(key);
334         } else {
335                 if (skip_check) {
336                         fail_if(buxton_response_status(response) != 0,
337                         "Set label failed");
338                 } else {
339                         fail_if(buxton_response_status(response) == 0,
340                         "Set label succeeded, but the client is not root");
341                 }
342         }
343 }
344 START_TEST(buxton_set_label_check)
345 {
346         BuxtonClient c;
347         BuxtonKey group = buxton_key_create("bxt_group", NULL, "test-gdbm", STRING);
348         fail_if(!group, "Failed to create key for group");
349         fail_if(buxton_open(&c) == -1,
350                 "Open failed with daemon.");
351         fail_if(buxton_create_group(c, group, NULL, NULL, true),
352                 "Creating group in buxton failed.");
353         fail_if(buxton_set_label(c, group, "*",
354                                  client_set_label_test,
355                                  group, true),
356                 "Setting label for group in buxton failed.");
357
358         BuxtonKey name = buxton_key_create("bxt_group", "bxt_name", "test-gdbm", STRING);
359         fail_if(!name, "Failed to create key for name");
360         fail_if(buxton_set_value(c, name, "bxt_value", NULL, NULL, true),
361                 "Setting label for name in buxton failed.");
362         fail_if(buxton_set_label(c, name, "*",
363                                  client_set_label_test,
364                                  name, true),
365                 "Setting label for name in buxton failed.");
366
367         buxton_key_free(group);
368         buxton_key_free(name);
369 }
370 END_TEST
371
372 static void client_get_value_test(BuxtonResponse response, void *data)
373 {
374         BuxtonKey key;
375         char *group;
376         char *name;
377         char *v;
378         char *value = (char *)data;
379
380         fail_if(buxton_response_status(response) != 0,
381                 "Get value failed");
382
383         key = buxton_response_key(response);
384         fail_if(!key, "Failed to get key");
385         group = buxton_key_get_group(key);
386         fail_if(!group, "Failed to get group");
387         fail_if(!streq(group, "group"),
388                 "Failed to get correct group");
389         name = buxton_key_get_name(key);
390         fail_if(!name, "Failed to get name");
391         fail_if(!streq(name, "name"),
392                 "Failed to get correct name");
393         v = buxton_response_value(response);
394         printf("val=%s\n", v);
395         fail_if(!v, "Failed to get value");
396         fail_if(!streq(v, value),
397                 "Failed to get correct value");
398
399         free(v);
400         free(group);
401         free(name);
402         buxton_key_free(key);
403 }
404 START_TEST(buxton_get_value_for_layer_check)
405 {
406         BuxtonClient c = NULL;
407         BuxtonKey key = buxton_key_create("group", "name", "test-gdbm-user", STRING);
408
409         fail_if(buxton_open(&c) == -1,
410                 "Open failed with daemon.");
411         fail_if(buxton_get_value(c, key,
412                                  client_get_value_test,
413                                  "bxt_test_value", true),
414                 "Retrieving value from buxton gdbm backend failed.");
415 }
416 END_TEST
417
418 START_TEST(buxton_get_value_check)
419 {
420         BuxtonClient c = NULL;
421
422         BuxtonKey group = buxton_key_create("group", NULL, "test-gdbm", STRING);
423         fail_if(!group, "Failed to create key for group");
424         BuxtonKey key = buxton_key_create("group", "name", "test-gdbm", STRING);
425
426         fail_if(buxton_open(&c) == -1,
427                 "Open failed with daemon.");
428
429         fail_if(buxton_create_group(c, group, NULL, NULL, true),
430                 "Creating group in buxton failed.");
431         fail_if(buxton_set_label(c, group, "*", NULL, NULL, true),
432                 "Setting group in buxton failed.");
433         fail_if(buxton_set_value(c, key, "bxt_test_value2",
434                                  client_set_value_test, "group", true),
435                 "Failed to set second value.");
436         buxton_key_free(group);
437         buxton_key_free(key);
438         key = buxton_key_create("group", "name", NULL, STRING);
439         fail_if(buxton_get_value(c, key,
440                                  client_get_value_test,
441                                  "bxt_test_value2", true),
442                 "Retrieving value from buxton gdbm backend failed.");
443         buxton_key_free(key);
444 }
445 END_TEST
446
447 START_TEST(parse_list_check)
448 {
449         BuxtonData l3[2];
450         BuxtonData l2[4];
451         BuxtonData l1[3];
452         _BuxtonKey key;
453         BuxtonData *value = NULL;
454
455         fail_if(parse_list(BUXTON_CONTROL_NOTIFY, 2, l1, &key, &value),
456                 "Parsed bad notify argument count");
457         l1[0].type = INT32;
458         l1[1].type = STRING;
459         l1[2].type = UINT32;
460         fail_if(parse_list(BUXTON_CONTROL_NOTIFY, 3, l1, &key, &value),
461                 "Parsed bad notify type 1");
462         l1[0].type = STRING;
463         l1[1].type = FLOAT;
464         l1[2].type = UINT32;
465         fail_if(parse_list(BUXTON_CONTROL_NOTIFY, 3, l1, &key, &value),
466                 "Parsed bad notify type 3");
467         l1[0].type = STRING;
468         l1[1].type = STRING;
469         l1[2].type = STRING;
470         fail_if(parse_list(BUXTON_CONTROL_NOTIFY, 3, l1, &key, &value),
471                 "Parsed bad notify type 3");
472         l1[0].type = STRING;
473         l1[1].type = STRING;
474         l1[2].type = UINT32;
475         l1[0].store.d_string = buxton_string_pack("s1");
476         l1[1].store.d_string = buxton_string_pack("s2");
477         l1[2].store.d_uint32 = STRING;
478         fail_if(!parse_list(BUXTON_CONTROL_NOTIFY, 3, l1, &key, &value),
479                 "Unable to parse valid notify");
480         fail_if(!streq(key.group.value, l1[0].store.d_string.value),
481                 "Failed to set correct notify group");
482         fail_if(!streq(key.name.value, l1[1].store.d_string.value),
483                 "Failed to set correct notify name");
484         fail_if(key.type != l1[2].store.d_uint32,
485                 "Failed to set correct notify type");
486
487         fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 2, l1, &key, &value),
488                 "Parsed bad unnotify argument count");
489         l1[0].type = INT32;
490         l1[1].type = STRING;
491         l1[2].type = UINT32;
492         fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 1, l1, &key, &value),
493                 "Parsed bad unnotify type 1");
494         l1[0].type = STRING;
495         l1[1].type = FLOAT;
496         l1[2].type = UINT32;
497         fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 1, l1, &key, &value),
498                 "Parsed bad unnotify type 2");
499         l1[0].type = INT32;
500         l1[1].type = STRING;
501         l1[2].type = STRING;
502         fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 1, l1, &key, &value),
503                 "Parsed bad unnotify type 3");
504         l1[0].type = STRING;
505         l1[1].type = STRING;
506         l1[2].type = UINT32;
507         l1[0].store.d_string = buxton_string_pack("s3");
508         l1[1].store.d_string = buxton_string_pack("s4");
509         l1[2].store.d_uint32 = STRING;
510         fail_if(!parse_list(BUXTON_CONTROL_UNNOTIFY, 3, l1, &key, &value),
511                 "Unable to parse valid unnotify");
512         fail_if(!streq(key.group.value, l1[0].store.d_string.value),
513                 "Failed to set correct unnotify group");
514         fail_if(!streq(key.name.value, l1[1].store.d_string.value),
515                 "Failed to set correct unnotify name");
516         fail_if(key.type != l1[2].store.d_uint32,
517                 "Failed to set correct unnotify type");
518
519         fail_if(parse_list(BUXTON_CONTROL_GET, 5, l2, &key, &value),
520                 "Parsed bad get argument count");
521         l2[0].type = INT32;
522         l2[1].type = STRING;
523         l2[2].type = STRING;
524         l2[3].type = UINT32;
525         fail_if(parse_list(BUXTON_CONTROL_GET, 2, l2, &key, &value),
526                 "Parsed bad get type 1");
527         l2[0].type = STRING;
528         l2[1].type = FLOAT;
529         l2[2].type = STRING;
530         l2[3].type = UINT32;
531         fail_if(parse_list(BUXTON_CONTROL_GET, 2, l2, &key, &value),
532                 "Parsed bad get type 2");
533         l2[0].type = STRING;
534         l2[1].type = STRING;
535         l2[2].type = BOOLEAN;
536         l2[3].type = UINT32;
537         fail_if(parse_list(BUXTON_CONTROL_GET, 2, l2, &key, &value),
538                 "Parsed bad get type 3");
539         l2[0].type = STRING;
540         l2[1].type = STRING;
541         l2[2].type = STRING;
542         l2[3].type = STRING;
543         fail_if(parse_list(BUXTON_CONTROL_GET, 2, l2, &key, &value),
544                 "Parsed bad get type 4");
545         l2[0].type = STRING;
546         l2[1].type = STRING;
547         l2[2].type = STRING;
548         l2[3].type = UINT32;
549         l2[0].store.d_string = buxton_string_pack("s5");
550         l2[1].store.d_string = buxton_string_pack("s6");
551         l2[2].store.d_string = buxton_string_pack("s7");
552         l2[3].store.d_uint32 = STRING;
553         fail_if(!parse_list(BUXTON_CONTROL_GET, 4, l2, &key, &value),
554                 "Unable to parse valid get 1");
555         fail_if(!streq(key.layer.value, l2[0].store.d_string.value),
556                 "Failed to set correct get layer 1");
557         fail_if(!streq(key.group.value, l2[1].store.d_string.value),
558                 "Failed to set correct get group 1");
559         fail_if(!streq(key.name.value, l2[2].store.d_string.value),
560                 "Failed to set correct get name");
561         fail_if(key.type != l2[3].store.d_uint32,
562                 "Failed to set correct get type 1");
563         l2[0].store.d_string = buxton_string_pack("s6");
564         l2[1].store.d_string = buxton_string_pack("s6");
565         l2[2].type = UINT32;
566         l2[2].store.d_uint32 = STRING;
567         fail_if(!parse_list(BUXTON_CONTROL_GET, 3, l2, &key, &value),
568                 "Unable to parse valid get 2");
569         fail_if(!streq(key.group.value, l2[0].store.d_string.value),
570                 "Failed to set correct get group 2");
571         fail_if(!streq(key.name.value, l2[1].store.d_string.value),
572                 "Failed to set correct get name 2");
573         fail_if(key.type != l2[2].store.d_uint32,
574                 "Failed to set correct get type 2");
575
576         fail_if(parse_list(BUXTON_CONTROL_SET, 1, l2, &key, &value),
577                 "Parsed bad set argument count");
578         l2[0].type = INT32;
579         l2[1].type = STRING;
580         l2[2].type = STRING;
581         l2[3].type = FLOAT;
582         fail_if(parse_list(BUXTON_CONTROL_SET, 3, l2, &key, &value),
583                 "Parsed bad set type 1");
584         l2[0].type = STRING;
585         l2[1].type = FLOAT;
586         l2[2].type = STRING;
587         l2[3].type = FLOAT;
588         fail_if(parse_list(BUXTON_CONTROL_SET, 3, l2, &key, &value),
589                 "Parsed bad set type 2");
590         l2[0].type = STRING;
591         l2[1].type = STRING;
592         l2[2].type = BOOLEAN;
593         l2[3].type = FLOAT;
594         fail_if(parse_list(BUXTON_CONTROL_SET, 3, l2, &key, &value),
595                 "Parsed bad set type 3");
596         l2[0].type = STRING;
597         l2[1].type = STRING;
598         l2[2].type = STRING;
599         l2[3].type = FLOAT;
600         l2[0].store.d_string = buxton_string_pack("s8");
601         l2[1].store.d_string = buxton_string_pack("s9");
602         l2[2].store.d_string = buxton_string_pack("s10");
603         l2[3].store.d_float = 3.14F;
604         fail_if(!parse_list(BUXTON_CONTROL_SET, 4, l2, &key, &value),
605                 "Unable to parse valid set 1");
606         fail_if(!streq(key.layer.value, l2[0].store.d_string.value),
607                 "Failed to set correct set layer 1");
608         fail_if(!streq(key.group.value, l2[1].store.d_string.value),
609                 "Failed to set correct set group 1");
610         fail_if(!streq(key.name.value, l2[2].store.d_string.value),
611                 "Failed to set correct set name 1");
612         fail_if(value->store.d_float != l2[3].store.d_float,
613                 "Failed to set correct set value 1");
614
615         fail_if(parse_list(BUXTON_CONTROL_UNSET, 1, l2, &key, &value),
616                 "Parsed bad unset argument count");
617         l2[0].type = INT32;
618         l2[1].type = STRING;
619         l2[2].type = STRING;
620         l2[3].type = UINT32;
621         fail_if(parse_list(BUXTON_CONTROL_UNSET, 4, l2, &key, &value),
622                 "Parsed bad unset type 1");
623         l2[0].type = STRING;
624         l2[1].type = FLOAT;
625         l2[2].type = STRING;
626         l2[3].type = UINT32;
627         fail_if(parse_list(BUXTON_CONTROL_UNSET, 4, l2, &key, &value),
628                 "Parsed bad unset type 2");
629         l2[0].type = STRING;
630         l2[1].type = STRING;
631         l2[2].type = BOOLEAN;
632         l2[3].type = UINT32;
633         fail_if(parse_list(BUXTON_CONTROL_UNSET, 4, l2, &key, &value),
634                 "Parsed bad unset type 3");
635         l2[0].type = STRING;
636         l2[1].type = STRING;
637         l2[2].type = STRING;
638         l2[3].type = STRING;
639         fail_if(parse_list(BUXTON_CONTROL_UNSET, 4, l2, &key, &value),
640                 "Parsed bad unset type 4");
641         l2[0].type = STRING;
642         l2[1].type = STRING;
643         l2[2].type = STRING;
644         l2[3].type = UINT32;
645         l2[0].store.d_string = buxton_string_pack("s11");
646         l2[1].store.d_string = buxton_string_pack("s12");
647         l2[2].store.d_string = buxton_string_pack("s13");
648         l2[3].store.d_uint32 = STRING;
649         fail_if(!parse_list(BUXTON_CONTROL_UNSET, 4, l2, &key, &value),
650                 "Unable to parse valid unset 1");
651         fail_if(!streq(key.layer.value, l2[0].store.d_string.value),
652                 "Failed to set correct unset layer 1");
653         fail_if(!streq(key.group.value, l2[1].store.d_string.value),
654                 "Failed to set correct unset group 1");
655         fail_if(!streq(key.name.value, l2[2].store.d_string.value),
656                 "Failed to set correct unset name 1");
657         fail_if(key.type != l2[3].store.d_uint32,
658                 "Failed to set correct unset type 1");
659
660         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 1, l2, &key, &value),
661                 "Parsed bad set label argument count");
662         l1[0].type = INT32;
663         l1[1].type = STRING;
664         l1[2].type = STRING;
665         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 3, l1, &key, &value),
666                 "Parsed bad set label type 1");
667         l1[0].type = STRING;
668         l1[1].type = FLOAT;
669         l1[2].type = STRING;
670         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 3, l1, &key, &value),
671                 "Parsed bad set label type 2");
672         l1[0].type = STRING;
673         l1[1].type = STRING;
674         l1[2].type = BOOLEAN;
675         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 3, l1, &key, &value),
676                 "Parsed bad set label type 3");
677         l1[0].type = STRING;
678         l1[1].type = STRING;
679         l1[2].type = STRING;
680         l1[0].store.d_string = buxton_string_pack("s14");
681         l1[1].store.d_string = buxton_string_pack("s15");
682         l1[2].store.d_string = buxton_string_pack("*");
683         fail_if(!parse_list(BUXTON_CONTROL_SET_LABEL, 3, l1, &key, &value),
684                 "Unable to parse valid set label 1");
685         fail_if(!streq(key.layer.value, l1[0].store.d_string.value),
686                 "Failed to set correct set label layer 1");
687         fail_if(!streq(key.group.value, l1[1].store.d_string.value),
688                 "Failed to set correct set label group 1");
689         fail_if(!streq(value->store.d_string.value, l1[2].store.d_string.value),
690                 "Failed to set correct set label label 1");
691         fail_if(key.type != STRING, "Failed to key type in set label");
692
693         fail_if(parse_list(BUXTON_CONTROL_CREATE_GROUP, 1, l3, &key, &value),
694                 "Parsed bad create group argument count");
695         l3[0].type = INT32;
696         l3[1].type = STRING;
697         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 2, l3, &key, &value),
698                 "Parsed bad create group type 1");
699         l3[0].type = STRING;
700         l3[1].type = FLOAT;
701         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 2, l3, &key, &value),
702                 "Parsed bad create group type 2");
703         l3[0].type = STRING;
704         l3[1].type = STRING;
705         l3[0].store.d_string = buxton_string_pack("s16");
706         l3[1].store.d_string = buxton_string_pack("s17");
707         fail_if(!parse_list(BUXTON_CONTROL_CREATE_GROUP, 2, l3, &key, &value),
708                 "Unable to parse valid create group 1");
709         fail_if(!streq(key.layer.value, l3[0].store.d_string.value),
710                 "Failed to set correct create group layer 1");
711         fail_if(!streq(key.group.value, l3[1].store.d_string.value),
712                 "Failed to set correct create group group 1");
713         fail_if(key.type != STRING, "Failed to key type in create group");
714
715         fail_if(parse_list(BUXTON_CONTROL_REMOVE_GROUP, 1, l3, &key, &value),
716                 "Parsed bad remove group argument count");
717         l3[0].type = INT32;
718         l3[1].type = STRING;
719         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 2, l3, &key, &value),
720                 "Parsed bad remove group type 1");
721         l3[0].type = STRING;
722         l3[1].type = FLOAT;
723         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 2, l3, &key, &value),
724                 "Parsed bad remove group type 2");
725         l3[0].type = STRING;
726         l3[1].type = STRING;
727         l3[0].store.d_string = buxton_string_pack("s18");
728         l3[1].store.d_string = buxton_string_pack("s19");
729         fail_if(!parse_list(BUXTON_CONTROL_REMOVE_GROUP, 2, l3, &key, &value),
730                 "Unable to parse valid remove group 1");
731         fail_if(!streq(key.layer.value, l3[0].store.d_string.value),
732                 "Failed to set correct remove group layer 1");
733         fail_if(!streq(key.group.value, l3[1].store.d_string.value),
734                 "Failed to set correct remove group group 1");
735         fail_if(key.type != STRING, "Failed to key type in remove group");
736 }
737 END_TEST
738
739 START_TEST(create_group_check)
740 {
741         _BuxtonKey key = { {0}, {0}, {0}, 0};
742         client_list_item client;
743         int32_t status;
744         BuxtonDaemon server;
745         BuxtonString clabel = buxton_string_pack("_");
746
747         fail_if(!buxton_direct_open(&server.buxton),
748                 "Failed to open buxton direct connection");
749
750         client.cred.uid = getuid();
751         if (use_smack())
752                 client.smack_label = &clabel;
753         else
754                 client.smack_label = NULL;
755         server.buxton.client.uid = 0;
756
757         key.layer = buxton_string_pack("test-gdbm-user");
758         key.group = buxton_string_pack("daemon-check");
759         key.type = STRING;
760         create_group(&server, &client, &key, &status);
761         fail_if(status != 0, "Failed to create group");
762
763         key.layer = buxton_string_pack("test-gdbm");
764         create_group(&server, &client, &key, &status);
765         fail_if(status != 0, "Failed to create group");
766
767         key.layer = buxton_string_pack("base");
768         key.group = buxton_string_pack("tgroup");
769         create_group(&server, &client, &key, &status);
770         fail_if(status != 0, "Failed to create group");
771
772         buxton_direct_close(&server.buxton);
773 }
774 END_TEST
775
776 START_TEST(remove_group_check)
777 {
778         _BuxtonKey key = { {0}, {0}, {0}, 0};
779         client_list_item client;
780         int32_t status;
781         BuxtonDaemon server;
782         BuxtonString clabel = buxton_string_pack("_");
783
784         fail_if(!buxton_direct_open(&server.buxton),
785                 "Failed to open buxton direct connection");
786
787         client.cred.uid = getuid();
788         if (use_smack())
789                 client.smack_label = &clabel;
790         else
791                 client.smack_label = NULL;
792         server.buxton.client.uid = 0;
793
794         key.layer = buxton_string_pack("base");
795         key.group = buxton_string_pack("tgroup");
796         key.type = STRING;
797
798         remove_group(&server, &client, &key, &status);
799         fail_if(status != 0, "Failed to remove group");
800
801         buxton_direct_close(&server.buxton);
802 }
803 END_TEST
804
805 START_TEST(set_label_check)
806 {
807         _BuxtonKey key = { {0}, {0}, {0}, 0};
808         BuxtonData value;
809         client_list_item client;
810         int32_t status;
811         BuxtonDaemon server;
812         BuxtonString clabel = buxton_string_pack("_");
813
814         fail_if(!buxton_direct_open(&server.buxton),
815                 "Failed to open buxton direct connection");
816
817         client.cred.uid = getuid();
818         if (use_smack())
819                 client.smack_label = &clabel;
820         else
821                 client.smack_label = NULL;
822         server.buxton.client.uid = 0;
823         key.layer = buxton_string_pack("test-gdbm-user");
824         key.group = buxton_string_pack("daemon-check");
825         key.type = STRING;
826         value.type = STRING;
827         value.store.d_string = buxton_string_pack("*");
828
829         key.layer = buxton_string_pack("test-gdbm");
830         set_label(&server, &client, &key, &value, &status);
831         fail_if(status != 0, "Failed to set label 2");
832         buxton_direct_close(&server.buxton);
833 }
834 END_TEST
835
836 START_TEST(set_value_check)
837 {
838         _BuxtonKey key = { {0}, {0}, {0}, 0};
839         BuxtonData value;
840         client_list_item client;
841         int32_t status;
842         BuxtonDaemon server;
843         BuxtonString clabel = buxton_string_pack("_");
844
845         fail_if(!buxton_direct_open(&server.buxton),
846                 "Failed to open buxton direct connection");
847
848         client.cred.uid = getuid();
849         server.buxton.client.uid = 0;
850
851         if (use_smack())
852                 client.smack_label = &clabel;
853         else
854                 client.smack_label = NULL;
855
856         key.layer = buxton_string_pack("test-gdbm-user");
857         key.group = buxton_string_pack("daemon-check");
858         key.name = buxton_string_pack("name");
859         value.type = STRING;
860         value.store.d_string = buxton_string_pack("user-layer-value");
861
862         set_value(&server, &client, &key, &value, &status);
863         fail_if(status != 0, "Failed to set value");
864         fail_if(server.buxton.client.uid != client.cred.uid, "Failed to change buxton uid");
865
866         key.layer = buxton_string_pack("test-gdbm");
867         value.store.d_string = buxton_string_pack("system-layer-value");
868         set_value(&server, &client, &key, &value, &status);
869         fail_if(status != 0, "Failed to set value");
870
871         buxton_direct_close(&server.buxton);
872 }
873 END_TEST
874
875 START_TEST(get_value_check)
876 {
877         _BuxtonKey key = { {0}, {0}, {0}, 0};
878         BuxtonData *value;
879         client_list_item client;
880         int32_t status;
881         BuxtonDaemon server;
882         BuxtonString clabel = buxton_string_pack("_");
883
884         fail_if(!buxton_direct_open(&server.buxton),
885                 "Failed to open buxton direct connection");
886
887         fail_if(!buxton_cache_smack_rules(),
888                 "Failed to cache smack rules");
889         client.cred.uid = getuid();
890         if (use_smack())
891                 client.smack_label = &clabel;
892         else
893                 client.smack_label = NULL;
894         server.buxton.client.uid = 0;
895         key.layer = buxton_string_pack("test-gdbm-user");
896         key.group = buxton_string_pack("daemon-check");
897         key.name = buxton_string_pack("name");
898         key.type = STRING;
899
900         value = get_value(&server, &client, &key, &status);
901         fail_if(!value, "Failed to get value");
902         fail_if(status != 0, "Failed to get value");
903         fail_if(value->type != STRING, "Failed to get correct type");
904         fail_if(!streq(value->store.d_string.value, "user-layer-value"), "Failed to get correct value");
905         fail_if(server.buxton.client.uid != client.cred.uid, "Failed to change buxton uid");
906         free(value);
907
908         server.buxton.client.uid = 0;
909         key.layer.value = NULL;
910         key.layer.length = 0;
911         value = get_value(&server, &client, &key, &status);
912         fail_if(!value, "Failed to get value 2");
913         fail_if(status != 0, "Failed to get value 2");
914         fail_if(value->type != STRING, "Failed to get correct type 2");
915         fail_if(!streq(value->store.d_string.value, "system-layer-value"), "Failed to get correct value 2");
916         fail_if(server.buxton.client.uid != client.cred.uid, "Failed to change buxton uid 2");
917         free(value);
918
919         buxton_direct_close(&server.buxton);
920 }
921 END_TEST
922
923 START_TEST(register_notification_check)
924 {
925         _BuxtonKey key = { {0}, {0}, {0}, 0};
926         client_list_item client, no_client;
927         BuxtonString clabel = buxton_string_pack("_");
928         int32_t status;
929         BuxtonDaemon server;
930         uint32_t msgid;
931
932         fail_if(!buxton_cache_smack_rules(),
933                 "Failed to cache smack rules");
934         if (use_smack())
935                 client.smack_label = &clabel;
936         else
937                 client.smack_label = NULL;
938         client.cred.uid = 1002;
939         fail_if(!buxton_direct_open(&server.buxton),
940                 "Failed to open buxton direct connection");
941         server.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
942         fail_if(!server.notify_mapping, "Failed to allocate hashmap");
943
944         key.group = buxton_string_pack("group");
945         key.name = buxton_string_pack("name");
946         key.type = STRING;
947         register_notification(&server, &client, &key, 1, &status);
948         fail_if(status != 0, "Failed to register notification");
949         register_notification(&server, &client, &key, 1, &status);
950         fail_if(status != 0, "Failed to register notification");
951         //FIXME: Figure out what to do with duplicates
952         key.group = buxton_string_pack("no-key");
953         msgid = unregister_notification(&server, &client, &key, &status);
954         fail_if(status == 0,
955                 "Unregistered from notifications with invalid key");
956         fail_if(msgid != 0, "Got unexpected notify message id");
957         key.group = buxton_string_pack("group");
958         msgid = unregister_notification(&server, &no_client, &key, &status);
959         fail_if(status == 0,
960                 "Unregistered from notifications with invalid client");
961         fail_if(msgid != 0, "Got unexpected notify message id");
962         msgid = unregister_notification(&server, &client, &key, &status);
963         fail_if(status != 0,
964                 "Unable to unregister from notifications");
965         fail_if(msgid != 1, "Failed to get correct notify message id");
966         key.group = buxton_string_pack("key2");
967         register_notification(&server, &client, &key, 0, &status);
968         fail_if(status == 0, "Registered notification with key not in db");
969
970         hashmap_free(server.notify_mapping);
971         buxton_direct_close(&server.buxton);
972 }
973 END_TEST
974 START_TEST(buxtond_handle_message_error_check)
975 {
976         int client, server;
977         BuxtonDaemon daemon;
978         BuxtonString slabel;
979         size_t size;
980         BuxtonData data1;
981         client_list_item cl;
982         bool r;
983         BuxtonArray *list = NULL;
984         uint16_t control;
985
986         setup_socket_pair(&client, &server);
987         fail_if(fcntl(client, F_SETFL, O_NONBLOCK),
988                 "Failed to set socket to non blocking");
989         fail_if(fcntl(server, F_SETFL, O_NONBLOCK),
990                 "Failed to set socket to non blocking");
991         list = buxton_array_new();
992         fail_if(!list, "Failed to allocate list");
993
994         cl.fd = server;
995         slabel = buxton_string_pack("_");
996         cl.smack_label = &slabel;
997         daemon.buxton.client.uid = 1001;
998         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
999         fail_if(!buxton_direct_open(&daemon.buxton),
1000                 "Failed to open buxton direct connection");
1001
1002         cl.data = malloc(4);
1003         fail_if(!cl.data, "Couldn't allocate blank message");
1004         cl.data[0] = 0;
1005         cl.data[1]= 0;
1006         cl.data[2] = 0;
1007         cl.data[3] = 0;
1008         size = 100;
1009         r = buxtond_handle_message(&daemon, &cl, size);
1010         fail_if(r, "Failed to detect invalid message data");
1011         free(cl.data);
1012
1013         data1.type = STRING;
1014         data1.store.d_string = buxton_string_pack("group");
1015         r = buxton_array_add(list, &data1);
1016         fail_if(!r, "Failed to add element to array");
1017         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_NOTIFY, 0,
1018                                         list);
1019         fail_if(size == 0, "Failed to serialize message");
1020         control = BUXTON_CONTROL_MIN;
1021         memcpy(cl.data, &control, sizeof(uint16_t));
1022         r = buxtond_handle_message(&daemon, &cl, size);
1023         fail_if(r, "Failed to detect min control size");
1024         control = BUXTON_CONTROL_MAX;
1025         memcpy(cl.data, &control, sizeof(uint16_t));
1026         r = buxtond_handle_message(&daemon, &cl, size);
1027         free(cl.data);
1028         fail_if(r, "Failed to detect max control size");
1029
1030         close(client);
1031         buxton_direct_close(&daemon.buxton);
1032         buxton_array_free(&list, NULL);
1033 }
1034 END_TEST
1035
1036 START_TEST(buxtond_handle_message_create_group_check)
1037 {
1038         BuxtonDaemon daemon;
1039         BuxtonString slabel;
1040         size_t size;
1041         BuxtonData data1, data2;
1042         client_list_item cl;
1043         bool r;
1044         BuxtonData *list;
1045         BuxtonArray *out_list1, *out_list2;
1046         BuxtonControlMessage msg;
1047         ssize_t csize;
1048         int client, server;
1049         ssize_t s;
1050         uint8_t buf[4096];
1051         uint32_t msgid;
1052
1053         setup_socket_pair(&client, &server);
1054         fail_if(fcntl(client, F_SETFL, O_NONBLOCK),
1055                 "Failed to set socket to non blocking");
1056         fail_if(fcntl(server, F_SETFL, O_NONBLOCK),
1057                 "Failed to set socket to non blocking");
1058
1059         cl.fd = server;
1060         slabel = buxton_string_pack("_");
1061         if (use_smack())
1062                 cl.smack_label = &slabel;
1063         else
1064                 cl.smack_label = NULL;
1065         cl.cred.uid = 1002;
1066         daemon.buxton.client.uid = 1001;
1067         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1068         fail_if(!buxton_direct_open(&daemon.buxton),
1069                 "Failed to open buxton direct connection");
1070         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1071         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1072
1073         out_list1 = buxton_array_new();
1074         fail_if(!out_list1, "Failed to allocate list");
1075         data1.type = STRING;
1076         data1.store.d_string = buxton_string_pack("base");
1077         data2.type = STRING;
1078         data2.store.d_string = buxton_string_pack("tgroup");
1079         r = buxton_array_add(out_list1, &data1);
1080         fail_if(!r, "Failed to add element to array");
1081         r = buxton_array_add(out_list1, &data2);
1082         fail_if(!r, "Failed to add element to array");
1083
1084         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_CREATE_GROUP, 0,
1085                                         out_list1);
1086         fail_if(size == 0, "Failed to serialize message");
1087         r = buxtond_handle_message(&daemon, &cl, size);
1088         free(cl.data);
1089         fail_if(!r, "Failed to handle create group message");
1090
1091         s = read(client, buf, 4096);
1092         fail_if(s < 0, "Read from client failed");
1093         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1094         fail_if(csize != 1, "Failed to get correct response to create group");
1095         fail_if(msg != BUXTON_CONTROL_STATUS,
1096                 "Failed to get correct control type");
1097         fail_if(list[0].type != INT32,
1098                 "Failed to get correct indicator type");
1099         fail_if(list[0].store.d_int32 != 0,
1100                 "Failed to create group");
1101         fail_if(msgid != 0, "Failed to get correct message id");
1102         free(list);
1103
1104         out_list2 = buxton_array_new();
1105         fail_if(!out_list2, "Failed to allocate list");
1106         data1.store.d_string = buxton_string_pack("base");
1107         data2.store.d_string = buxton_string_pack("daemon-check");
1108         r = buxton_array_add(out_list2, &data1);
1109         fail_if(!r, "Failed to add element to array");
1110         r = buxton_array_add(out_list2, &data2);
1111         fail_if(!r, "Failed to add element to array");
1112
1113         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_CREATE_GROUP, 1,
1114                                         out_list2);
1115         fail_if(size == 0, "Failed to serialize message");
1116         r = buxtond_handle_message(&daemon, &cl, size);
1117         free(cl.data);
1118         fail_if(!r, "Failed to handle create group message");
1119
1120         s = read(client, buf, 4096);
1121         fail_if(s < 0, "Read from client failed");
1122         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1123         fail_if(csize != 1, "Failed to get correct response to create group");
1124         fail_if(msg != BUXTON_CONTROL_STATUS,
1125                 "Failed to get correct control type");
1126         fail_if(list[0].type != INT32,
1127                 "Failed to get correct indicator type");
1128         fail_if(list[0].store.d_int32 != 0,
1129                 "Failed to create group");
1130         fail_if(msgid != 1, "Failed to get correct message id");
1131
1132         free(list);
1133         cleanup_callbacks();
1134         close(client);
1135         hashmap_free(daemon.notify_mapping);
1136         buxton_direct_close(&daemon.buxton);
1137         buxton_array_free(&out_list1, NULL);
1138         buxton_array_free(&out_list2, NULL);
1139 }
1140 END_TEST
1141
1142 START_TEST(buxtond_handle_message_remove_group_check)
1143 {
1144         BuxtonDaemon daemon;
1145         BuxtonString slabel;
1146         size_t size;
1147         BuxtonData data1, data2;
1148         client_list_item cl;
1149         bool r;
1150         BuxtonData *list;
1151         BuxtonArray *out_list;
1152         BuxtonControlMessage msg;
1153         ssize_t csize;
1154         int client, server;
1155         ssize_t s;
1156         uint8_t buf[4096];
1157         uint32_t msgid;
1158
1159         setup_socket_pair(&client, &server);
1160         fail_if(fcntl(client, F_SETFL, O_NONBLOCK),
1161                 "Failed to set socket to non blocking");
1162         fail_if(fcntl(server, F_SETFL, O_NONBLOCK),
1163                 "Failed to set socket to non blocking");
1164
1165         out_list = buxton_array_new();
1166         fail_if(!out_list, "Failed to allocate list");
1167         cl.fd = server;
1168         slabel = buxton_string_pack("_");
1169         if (use_smack())
1170                 cl.smack_label = &slabel;
1171         else
1172                 cl.smack_label = NULL;
1173         cl.cred.uid = 1002;
1174         daemon.buxton.client.uid = 1001;
1175         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1176         fail_if(!buxton_direct_open(&daemon.buxton),
1177                 "Failed to open buxton direct connection");
1178         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1179         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1180
1181         data1.type = STRING;
1182         data1.store.d_string = buxton_string_pack("base");
1183         data2.type = STRING;
1184         data2.store.d_string = buxton_string_pack("tgroup");
1185         r = buxton_array_add(out_list, &data1);
1186         fail_if(!r, "Failed to add element to array");
1187         r = buxton_array_add(out_list, &data2);
1188         fail_if(!r, "Failed to add element to array");
1189
1190         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_REMOVE_GROUP, 0,
1191                                         out_list);
1192         fail_if(size == 0, "Failed to serialize message");
1193         r = buxtond_handle_message(&daemon, &cl, size);
1194         free(cl.data);
1195         fail_if(!r, "Failed to handle remove group message");
1196
1197         s = read(client, buf, 4096);
1198         fail_if(s < 0, "Read from client failed");
1199         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1200         fail_if(csize != 1, "Failed to get correct response to remove group");
1201         fail_if(msg != BUXTON_CONTROL_STATUS,
1202                 "Failed to get correct control type");
1203         fail_if(list[0].type != INT32,
1204                 "Failed to get correct indicator type");
1205         fail_if(list[0].store.d_int32 != 0,
1206                 "Failed to remove group");
1207         fail_if(msgid != 0, "Failed to get correct message id");
1208
1209         free(list);
1210         cleanup_callbacks();
1211         close(client);
1212         hashmap_free(daemon.notify_mapping);
1213         buxton_direct_close(&daemon.buxton);
1214         buxton_array_free(&out_list, NULL);
1215 }
1216 END_TEST
1217
1218 START_TEST(buxtond_handle_message_set_label_check)
1219 {
1220         BuxtonDaemon daemon;
1221         BuxtonString slabel;
1222         size_t size;
1223         BuxtonData data1, data2, data3;
1224         client_list_item cl;
1225         bool r;
1226         BuxtonData *list;
1227         BuxtonArray *out_list;
1228         BuxtonControlMessage msg;
1229         ssize_t csize;
1230         int client, server;
1231         ssize_t s;
1232         uint8_t buf[4096];
1233         uint32_t msgid;
1234
1235         setup_socket_pair(&client, &server);
1236         fail_if(fcntl(client, F_SETFL, O_NONBLOCK),
1237                 "Failed to set socket to non blocking");
1238         fail_if(fcntl(server, F_SETFL, O_NONBLOCK),
1239                 "Failed to set socket to non blocking");
1240
1241         out_list = buxton_array_new();
1242         fail_if(!out_list, "Failed to allocate list");
1243         cl.fd = server;
1244         slabel = buxton_string_pack("_");
1245         if (use_smack())
1246                 cl.smack_label = &slabel;
1247         else
1248                 cl.smack_label = NULL;
1249         cl.cred.uid = 1002;
1250         daemon.buxton.client.uid = 1001;
1251         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1252         fail_if(!buxton_direct_open(&daemon.buxton),
1253                 "Failed to open buxton direct connection");
1254         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1255         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1256
1257         data1.type = STRING;
1258         data1.store.d_string = buxton_string_pack("base");
1259         data2.type = STRING;
1260         data2.store.d_string = buxton_string_pack("daemon-check");
1261         data3.type = STRING;
1262         data3.store.d_string = buxton_string_pack("*");
1263         r = buxton_array_add(out_list, &data1);
1264         fail_if(!r, "Failed to add element to array");
1265         r = buxton_array_add(out_list, &data2);
1266         fail_if(!r, "Failed to add element to array");
1267         r = buxton_array_add(out_list, &data3);
1268         fail_if(!r, "Failed to add element to array");
1269
1270         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_SET_LABEL, 0,
1271                                         out_list);
1272         fail_if(size == 0, "Failed to serialize message");
1273         r = buxtond_handle_message(&daemon, &cl, size);
1274         free(cl.data);
1275         fail_if(!r, "Failed to handle set label message");
1276
1277         s = read(client, buf, 4096);
1278         fail_if(s < 0, "Read from client failed");
1279         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1280         fail_if(csize != 1, "Failed to get correct response to set label");
1281         fail_if(msg != BUXTON_CONTROL_STATUS,
1282                 "Failed to get correct control type");
1283         fail_if(list[0].type != INT32,
1284                 "Failed to get correct indicator type");
1285         fail_if(list[0].store.d_int32 != 0,
1286                 "Failed to set label");
1287         fail_if(msgid != 0, "Failed to get correct message id");
1288
1289         free(list);
1290         cleanup_callbacks();
1291         close(client);
1292         hashmap_free(daemon.notify_mapping);
1293         buxton_direct_close(&daemon.buxton);
1294         buxton_array_free(&out_list, NULL);
1295 }
1296 END_TEST
1297
1298 START_TEST(buxtond_handle_message_set_value_check)
1299 {
1300         BuxtonDaemon daemon;
1301         BuxtonString slabel;
1302         size_t size;
1303         BuxtonData data1, data2, data3, data4;
1304         client_list_item cl;
1305         bool r;
1306         BuxtonData *list;
1307         BuxtonArray *out_list;
1308         BuxtonControlMessage msg;
1309         ssize_t csize;
1310         int client, server;
1311         ssize_t s;
1312         uint8_t buf[4096];
1313         uint32_t msgid;
1314
1315         setup_socket_pair(&client, &server);
1316         fail_if(fcntl(client, F_SETFL, O_NONBLOCK),
1317                 "Failed to set socket to non blocking");
1318         fail_if(fcntl(server, F_SETFL, O_NONBLOCK),
1319                 "Failed to set socket to non blocking");
1320
1321         out_list = buxton_array_new();
1322         fail_if(!out_list, "Failed to allocate list");
1323         cl.fd = server;
1324         slabel = buxton_string_pack("_");
1325         if (use_smack())
1326                 cl.smack_label = &slabel;
1327         else
1328                 cl.smack_label = NULL;
1329         cl.cred.uid = 1002;
1330         daemon.buxton.client.uid = 1001;
1331         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1332         fail_if(!buxton_direct_open(&daemon.buxton),
1333                 "Failed to open buxton direct connection");
1334         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1335         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1336
1337         data1.type = STRING;
1338         data1.store.d_string = buxton_string_pack("base");
1339         data2.type = STRING;
1340         data2.store.d_string = buxton_string_pack("daemon-check");
1341         data3.type = STRING;
1342         data3.store.d_string = buxton_string_pack("name");
1343         data4.type = STRING;
1344         data4.store.d_string = buxton_string_pack("bxt_test_value3");
1345         r = buxton_array_add(out_list, &data1);
1346         fail_if(!r, "Failed to add element to array");
1347         r = buxton_array_add(out_list, &data2);
1348         fail_if(!r, "Failed to add element to array");
1349         r = buxton_array_add(out_list, &data3);
1350         fail_if(!r, "Failed to add element to array");
1351         r = buxton_array_add(out_list, &data4);
1352         fail_if(!r, "Failed to add element to array");
1353         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_NOTIFY, 0,
1354                                         out_list);
1355         fail_if(size == 0, "Failed to serialize message");
1356         r = buxtond_handle_message(&daemon, &cl, size);
1357         free(cl.data);
1358         fail_if(r, "Failed to detect parse_list failure");
1359
1360         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_SET, 0,
1361                                         out_list);
1362         fail_if(size == 0, "Failed to serialize message");
1363         r = buxtond_handle_message(&daemon, &cl, size);
1364         free(cl.data);
1365         fail_if(!r, "Failed to handle set message");
1366
1367         s = read(client, buf, 4096);
1368         fail_if(s < 0, "Read from client failed");
1369         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1370         fail_if(csize != 1, "Failed to get correct response to set");
1371         fail_if(msg != BUXTON_CONTROL_STATUS,
1372                 "Failed to get correct control type");
1373         fail_if(list[0].type != INT32,
1374                 "Failed to get correct indicator type");
1375         fail_if(list[0].store.d_int32 != 0,
1376                 "Failed to set");
1377         fail_if(msgid != 0, "Failed to get correct message id");
1378
1379         free(list);
1380         cleanup_callbacks();
1381         close(client);
1382         hashmap_free(daemon.notify_mapping);
1383         buxton_direct_close(&daemon.buxton);
1384         buxton_array_free(&out_list, NULL);
1385 }
1386 END_TEST
1387
1388 START_TEST(buxtond_handle_message_get_check)
1389 {
1390         int client, server;
1391         BuxtonDaemon daemon;
1392         BuxtonString slabel;
1393         size_t size;
1394         BuxtonData data1, data2, data3, data4;
1395         client_list_item cl;
1396         bool r;
1397         BuxtonData *list;
1398         BuxtonArray *out_list;
1399         BuxtonArray *out_list2;
1400         BuxtonControlMessage msg;
1401         ssize_t csize;
1402         ssize_t s;
1403         uint8_t buf[4096];
1404         uint32_t msgid;
1405
1406         setup_socket_pair(&client, &server);
1407         out_list = buxton_array_new();
1408         fail_if(!out_list, "Failed to allocate list");
1409
1410         cl.fd = server;
1411         slabel = buxton_string_pack("_");
1412         if (use_smack())
1413                 cl.smack_label = &slabel;
1414         else
1415                 cl.smack_label = NULL;
1416         cl.cred.uid = getuid();
1417         daemon.buxton.client.uid = 1001;
1418         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1419         fail_if(!buxton_direct_open(&daemon.buxton),
1420                 "Failed to open buxton direct connection");
1421
1422         data1.type = STRING;
1423         data1.store.d_string = buxton_string_pack("test-gdbm-user");
1424         data2.type = STRING;
1425         data2.store.d_string = buxton_string_pack("daemon-check");
1426         data3.type = STRING;
1427         data3.store.d_string = buxton_string_pack("name");
1428         data4.type = UINT32;
1429         data4.store.d_uint32 = STRING;
1430         r = buxton_array_add(out_list, &data1);
1431         fail_if(!r, "Failed to add element to array");
1432         r = buxton_array_add(out_list, &data2);
1433         fail_if(!r, "Failed to add element to array");
1434         r = buxton_array_add(out_list, &data3);
1435         fail_if(!r, "Failed to add element to array");
1436         r = buxton_array_add(out_list, &data4);
1437         fail_if(!r, "Failed to add element to array");
1438         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_GET, 0,
1439                                         out_list);
1440         fail_if(size == 0, "Failed to serialize message");
1441         r = buxtond_handle_message(&daemon, &cl, size);
1442         free(cl.data);
1443         fail_if(!r, "Failed to get message 1");
1444
1445         s = read(client, buf, 4096);
1446         fail_if(s < 0, "Read from client failed");
1447         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1448         fail_if(csize != 2, "Failed to get valid message from buffer");
1449         fail_if(msg != BUXTON_CONTROL_STATUS,
1450                 "Failed to get correct control type");
1451         fail_if(msgid != 0, "Failed to get correct message id");
1452         fail_if(list[0].type != INT32, "Failed to get correct response type");
1453         fail_if(list[0].store.d_int32 != 0,
1454                 "Failed to get value");
1455         fail_if(list[1].type != STRING, "Failed to get correct value type");
1456         fail_if(!streq(list[1].store.d_string.value, "user-layer-value"),
1457                 "Failed to get correct value");
1458
1459         free(list[1].store.d_string.value);
1460         free(list);
1461
1462         out_list2 = buxton_array_new();
1463         fail_if(!out_list2, "Failed to allocate list 2");
1464         r = buxton_array_add(out_list2, &data2);
1465         fail_if(!r, "Failed to add element to array 2");
1466         r = buxton_array_add(out_list2, &data3);
1467         fail_if(!r, "Failed to add element to array 2");
1468         r = buxton_array_add(out_list2, &data4);
1469         fail_if(!r, "Failed to add element to array 2");
1470         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_GET, 0,
1471                                         out_list2);
1472         fail_if(size == 0, "Failed to serialize message 2");
1473         r = buxtond_handle_message(&daemon, &cl, size);
1474         free(cl.data);
1475         fail_if(!r, "Failed to get message 2");
1476
1477         s = read(client, buf, 4096);
1478         fail_if(s < 0, "Read from client failed 2");
1479         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1480         fail_if(csize != 2, "Failed to get correct response to get 2");
1481         fail_if(msg != BUXTON_CONTROL_STATUS,
1482                 "Failed to get correct control type 2");
1483         fail_if(msgid != 0, "Failed to get correct message id 2");
1484         fail_if(list[0].type != INT32, "Failed to get correct response type 2");
1485         fail_if(list[0].store.d_int32 != 0,
1486                 "Failed to get value 2");
1487         fail_if(list[1].type != STRING, "Failed to get correct value type 2");
1488         fail_if(streq(list[1].store.d_string.value, "bxt_test_value2"),
1489                 "Failed to get correct value 2");
1490
1491         free(list[1].store.d_string.value);
1492         free(list);
1493         close(client);
1494         buxton_direct_close(&daemon.buxton);
1495         buxton_array_free(&out_list, NULL);
1496         buxton_array_free(&out_list2, NULL);
1497 }
1498 END_TEST
1499
1500 START_TEST(buxtond_handle_message_notify_check)
1501 {
1502         int client, server;
1503         BuxtonDaemon daemon;
1504         BuxtonString slabel;
1505         size_t size;
1506         BuxtonData data1, data2, data3;
1507         client_list_item cl;
1508         bool r;
1509         BuxtonData *list;
1510         BuxtonArray *out_list;
1511         BuxtonControlMessage msg;
1512         ssize_t csize;
1513         ssize_t s;
1514         uint8_t buf[4096];
1515         uint32_t msgid;
1516
1517         setup_socket_pair(&client, &server);
1518         out_list = buxton_array_new();
1519         fail_if(!out_list, "Failed to allocate list");
1520
1521         cl.fd = server;
1522         slabel = buxton_string_pack("_");
1523         if (use_smack())
1524                 cl.smack_label = &slabel;
1525         else
1526                 cl.smack_label = NULL;
1527         cl.cred.uid = 1002;
1528         daemon.buxton.client.uid = 1001;
1529         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1530         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1531         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1532         fail_if(!buxton_direct_open(&daemon.buxton),
1533                 "Failed to open buxton direct connection");
1534
1535         data1.type = STRING;
1536         data1.store.d_string = buxton_string_pack("group");
1537         data2.type = STRING;
1538         data2.store.d_string = buxton_string_pack("name");
1539         data3.type = UINT32;
1540         data3.store.d_uint32 = STRING;
1541         r = buxton_array_add(out_list, &data1);
1542         fail_if(!r, "Failed to add element to array");
1543         r = buxton_array_add(out_list, &data2);
1544         fail_if(!r, "Failed to add element to array");
1545         r = buxton_array_add(out_list, &data3);
1546         fail_if(!r, "Failed to add element to array");
1547         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_NOTIFY, 0,
1548                                         out_list);
1549         fail_if(size == 0, "Failed to serialize message");
1550         r = buxtond_handle_message(&daemon, &cl, size);
1551         free(cl.data);
1552         fail_if(!r, "Failed to register for notification");
1553
1554         s = read(client, buf, 4096);
1555         fail_if(s < 0, "Read from client failed");
1556         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1557         fail_if(csize != 1, "Failed to get correct response to notify");
1558         fail_if(msg != BUXTON_CONTROL_STATUS,
1559                 "Failed to get correct control type");
1560         fail_if(msgid != 0, "Failed to get correct notify message id");
1561         fail_if(list[0].type != INT32, "Failed to get correct response type");
1562         fail_if(list[0].store.d_int32 != 0,
1563                 "Failed to register notification");
1564
1565         free(list);
1566
1567         /* UNNOTIFY */
1568         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_UNNOTIFY, 0,
1569                                         out_list);
1570         fail_if(size == 0, "Failed to serialize message");
1571         r = buxtond_handle_message(&daemon, &cl, size);
1572         free(cl.data);
1573         fail_if(!r, "Failed to unregister from notification");
1574
1575         s = read(client, buf, 4096);
1576         fail_if(s < 0, "Read from client failed 2");
1577         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1578         fail_if(csize != 2, "Failed to get correct response to unnotify");
1579         fail_if(msg != BUXTON_CONTROL_STATUS,
1580                 "Failed to get correct control type 2");
1581         fail_if(list[0].type != INT32,
1582                 "Failed to get correct indicator type 2");
1583         fail_if(list[0].store.d_int32 != 0,
1584                 "Failed to unregister for notification");
1585         fail_if(list[1].type != UINT32,
1586                 "Failed to get correct unnotify message id type");
1587         fail_if(list[1].store.d_uint32 != 0,
1588                 "Failed to get correct unnotify message id");
1589         fail_if(msgid != 0, "Failed to get correct message id 2");
1590
1591         free(list);
1592         close(client);
1593         hashmap_free(daemon.notify_mapping);
1594         buxton_direct_close(&daemon.buxton);
1595         buxton_array_free(&out_list, NULL);
1596 }
1597 END_TEST
1598
1599 START_TEST(buxtond_handle_message_unset_check)
1600 {
1601         int client, server;
1602         BuxtonDaemon daemon;
1603         BuxtonString slabel;
1604         size_t size;
1605         BuxtonData data1, data2, data3, data4;
1606         client_list_item cl;
1607         bool r;
1608         BuxtonData *list;
1609         BuxtonArray *out_list;
1610         BuxtonControlMessage msg;
1611         ssize_t csize;
1612         ssize_t s;
1613         uint8_t buf[4096];
1614         uint32_t msgid;
1615
1616         setup_socket_pair(&client, &server);
1617         out_list = buxton_array_new();
1618         fail_if(!out_list, "Failed to allocate list");
1619
1620         cl.fd = server;
1621         slabel = buxton_string_pack("_");
1622         if (use_smack())
1623                 cl.smack_label = &slabel;
1624         else
1625                 cl.smack_label = NULL;
1626         cl.cred.uid = 1002;
1627         daemon.buxton.client.uid = 1001;
1628         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1629         fail_if(!buxton_direct_open(&daemon.buxton),
1630                 "Failed to open buxton direct connection");
1631         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1632         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1633
1634         data1.type = STRING;
1635         data1.store.d_string = buxton_string_pack("base");
1636         data2.type = STRING;
1637         data2.store.d_string = buxton_string_pack("daemon-check");
1638         data3.type = STRING;
1639         data3.store.d_string = buxton_string_pack("name");
1640         data4.type = UINT32;
1641         data4.store.d_uint32 = STRING;
1642         r = buxton_array_add(out_list, &data1);
1643         fail_if(!r, "Failed to add element to array");
1644         r = buxton_array_add(out_list, &data2);
1645         fail_if(!r, "Failed to add element to array");
1646         r = buxton_array_add(out_list, &data3);
1647         fail_if(!r, "Failed to add element to array");
1648         r = buxton_array_add(out_list, &data4);
1649         fail_if(!r, "Failed to add element to array");
1650         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_UNSET, 0,
1651                                         out_list);
1652         fail_if(size == 0, "Failed to serialize message");
1653         r = buxtond_handle_message(&daemon, &cl, size);
1654         free(cl.data);
1655         fail_if(!r, "Failed to unset message");
1656
1657         s = read(client, buf, 4096);
1658         fail_if(s < 0, "Read from client failed");
1659         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1660         fail_if(csize != 1, "Failed to get correct response to unset");
1661         fail_if(msg != BUXTON_CONTROL_STATUS,
1662                 "Failed to get correct control type");
1663         fail_if(list[0].type != INT32,
1664                 "Failed to get correct indicator type");
1665         fail_if(list[0].store.d_int32 != 0,
1666                 "Failed to unset");
1667         fail_if(msgid != 0, "Failed to get correct message id");
1668
1669         free(list);
1670         close(client);
1671         hashmap_free(daemon.notify_mapping);
1672         buxton_direct_close(&daemon.buxton);
1673         buxton_array_free(&out_list, NULL);
1674 }
1675 END_TEST
1676
1677 START_TEST(buxtond_notify_clients_check)
1678 {
1679         int client, server;
1680         BuxtonDaemon daemon;
1681         _BuxtonKey key;
1682         BuxtonString slabel;
1683         BuxtonData value1, value2;
1684         client_list_item cl;
1685         int32_t status;
1686         bool r;
1687         BuxtonData *list;
1688         BuxtonControlMessage msg;
1689         ssize_t csize;
1690         ssize_t s;
1691         uint8_t buf[4096];
1692         uint32_t msgid;
1693
1694         setup_socket_pair(&client, &server);
1695
1696         cl.fd = server;
1697         slabel = buxton_string_pack("_");
1698         if (use_smack())
1699                 cl.smack_label = &slabel;
1700         else
1701                 cl.smack_label = NULL;
1702         cl.cred.uid = 1002;
1703         daemon.notify_mapping = hashmap_new(string_hash_func,
1704                                             string_compare_func);
1705         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1706         fail_if(!buxton_cache_smack_rules(),
1707                 "Failed to cache Smack rules");
1708         fail_if(!buxton_direct_open(&daemon.buxton),
1709                 "Failed to open buxton direct connection");
1710
1711         value1.type = STRING;
1712         value1.store.d_string = buxton_string_pack("dummy value");
1713         key.group = buxton_string_pack("dummy");
1714         key.name = buxton_string_pack("name");
1715         buxtond_notify_clients(&daemon, &cl, &key, &value1);
1716
1717         value1.store.d_string = buxton_string_pack("real value");
1718         key.group = buxton_string_pack("daemon-check");
1719         key.name = buxton_string_pack("name");
1720         key.layer = buxton_string_pack("base");
1721         key.type = STRING;
1722         r = buxton_direct_set_value(&daemon.buxton, &key,
1723                                     &value1, NULL);
1724         fail_if(!r, "Failed to set value for notify");
1725         register_notification(&daemon, &cl, &key, 0, &status);
1726         fail_if(status != 0,
1727                 "Failed to register notification for notify");
1728         buxtond_notify_clients(&daemon, &cl, &key, &value1);
1729
1730         value2.type = STRING;
1731         value2.store.d_string = buxton_string_pack("new value");
1732         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1733
1734         s = read(client, buf, 4096);
1735         fail_if(s < 0, "Read from client failed");
1736         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1737         fail_if(csize != 1,
1738                 "Failed to get correct response to notify string");
1739         fail_if(msg != BUXTON_CONTROL_CHANGED,
1740                 "Failed to get correct control type");
1741         fail_if(msgid != 0, "Failed to get correct message id");
1742         fail_if(list[0].type != STRING,
1743                 "Failed to get correct notification value type string");
1744         fail_if(!streq(list[0].store.d_string.value, "new value"),
1745                 "Failed to get correct notification value data string");
1746
1747         free(list[0].store.d_string.value);
1748         free(list);
1749
1750         key.group = buxton_string_pack("group");
1751         key.name.value = NULL;
1752         key.name.length = 0;
1753         r = buxton_direct_create_group(&daemon.buxton, &key, NULL);
1754         fail_if(!r, "Unable to create group");
1755         r = buxton_direct_set_label(&daemon.buxton, &key, &slabel);
1756         fail_if(!r, "Unable set group label");
1757
1758         value1.type = INT32;
1759         value1.store.d_int32 = 1;
1760         value2.type = INT32;
1761         value2.store.d_int32 = 2;
1762         key.group = buxton_string_pack("group");
1763         key.name = buxton_string_pack("name32");
1764         key.type = INT32;
1765         r = buxton_direct_set_value(&daemon.buxton, &key,
1766                                     &value1, NULL);
1767         fail_if(!r, "Failed to set value for notify");
1768         register_notification(&daemon, &cl, &key, 0, &status);
1769         fail_if(status != 0,
1770                 "Failed to register notification for notify");
1771         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1772
1773         s = read(client, buf, 4096);
1774         fail_if(s < 0, "Read from client failed");
1775         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1776         fail_if(csize != 1,
1777                 "Failed to get correct response to notify int32");
1778         fail_if(msg != BUXTON_CONTROL_CHANGED,
1779                 "Failed to get correct control type");
1780         fail_if(msgid != 0, "Failed to get correct message id");
1781         fail_if(list[0].type != INT32,
1782                 "Failed to get correct notification value type int32");
1783         fail_if(list[0].store.d_int32 != 2,
1784                 "Failed to get correct notification value data int32");
1785
1786         free(list);
1787
1788         value1.type = UINT32;
1789         value1.store.d_uint32 = 1;
1790         value2.type = UINT32;
1791         value2.store.d_uint32 = 2;
1792         key.group = buxton_string_pack("group");
1793         key.name = buxton_string_pack("nameu32");
1794         key.type = UINT32;
1795         r = buxton_direct_set_value(&daemon.buxton, &key,
1796                                     &value1, NULL);
1797         fail_if(!r, "Failed to set value for notify");
1798         register_notification(&daemon, &cl, &key, 0, &status);
1799         fail_if(status != 0,
1800                 "Failed to register notification for notify");
1801         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1802
1803         s = read(client, buf, 4096);
1804         fail_if(s < 0, "Read from client failed");
1805         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1806         fail_if(csize != 1,
1807                 "Failed to get correct response to notify uint32");
1808         fail_if(msg != BUXTON_CONTROL_CHANGED,
1809                 "Failed to get correct control type");
1810         fail_if(msgid != 0, "Failed to get correct message id");
1811         fail_if(list[0].type != UINT32,
1812                 "Failed to get correct notification value type uint32");
1813         fail_if(list[0].store.d_uint32 != 2,
1814                 "Failed to get correct notification value data uint32");
1815
1816         free(list);
1817
1818         value1.type = INT64;
1819         value1.store.d_int64 = 2;
1820         value2.type = INT64;
1821         value2.store.d_int64 = 3;
1822         key.group = buxton_string_pack("group");
1823         key.name = buxton_string_pack("name64");
1824         key.type = INT64;
1825         r = buxton_direct_set_value(&daemon.buxton, &key,
1826                                     &value1, NULL);
1827         fail_if(!r, "Failed to set value for notify");
1828         register_notification(&daemon, &cl, &key, 0, &status);
1829         fail_if(status != 0,
1830                 "Failed to register notification for notify");
1831         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1832
1833         s = read(client, buf, 4096);
1834         fail_if(s < 0, "Read from client failed");
1835         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1836         fail_if(csize != 1,
1837                 "Failed to get correct response to notify int64");
1838         fail_if(msg != BUXTON_CONTROL_CHANGED,
1839                 "Failed to get correct control type");
1840         fail_if(msgid != 0, "Failed to get correct message id");
1841         fail_if(list[0].type != INT64,
1842                 "Failed to get correct notification value type int 64");
1843         fail_if(list[0].store.d_int64 != 3,
1844                 "Failed to get correct notification value data int64");
1845
1846         free(list);
1847
1848         value1.type = UINT64;
1849         value1.store.d_uint64 = 2;
1850         value2.type = UINT64;
1851         value2.store.d_uint64 = 3;
1852         key.group = buxton_string_pack("group");
1853         key.name = buxton_string_pack("nameu64");
1854         key.type = UINT64;
1855         r = buxton_direct_set_value(&daemon.buxton, &key,
1856                                     &value1, NULL);
1857         fail_if(!r, "Failed to set value for notify");
1858         register_notification(&daemon, &cl, &key, 0, &status);
1859         fail_if(status != 0,
1860                 "Failed to register notification for notify");
1861         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1862
1863         s = read(client, buf, 4096);
1864         fail_if(s < 0, "Read from client failed");
1865         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1866         fail_if(csize != 1,
1867                 "Failed to get correct response to notify uint64");
1868         fail_if(msg != BUXTON_CONTROL_CHANGED,
1869                 "Failed to get correct control type");
1870         fail_if(msgid != 0, "Failed to get correct message id");
1871         fail_if(list[0].type != UINT64,
1872                 "Failed to get correct notification value type uint64");
1873         fail_if(list[0].store.d_uint64 != 3,
1874                 "Failed to get correct notification value data uint64");
1875
1876         free(list);
1877
1878         value1.type = FLOAT;
1879         value1.store.d_float = 3.1F;
1880         value2.type = FLOAT;
1881         value2.store.d_float = 3.14F;
1882         key.group = buxton_string_pack("group");
1883         key.name = buxton_string_pack("namef");
1884         key.type = FLOAT;
1885         r = buxton_direct_set_value(&daemon.buxton, &key,
1886                                     &value1, NULL);
1887         fail_if(!r, "Failed to set value for notify");
1888         register_notification(&daemon, &cl, &key, 0, &status);
1889         fail_if(status != 0,
1890                 "Failed to register notification for notify");
1891         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1892
1893         s = read(client, buf, 4096);
1894         fail_if(s < 0, "Read from client failed");
1895         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1896         fail_if(csize != 1,
1897                 "Failed to get correct response to notify float");
1898         fail_if(msg != BUXTON_CONTROL_CHANGED,
1899                 "Failed to get correct control type");
1900         fail_if(msgid != 0, "Failed to get correct message id");
1901         fail_if(list[0].type != FLOAT,
1902                 "Failed to get correct notification value type float");
1903         fail_if(list[0].store.d_float != 3.14F,
1904                 "Failed to get correct notification value data float");
1905
1906         free(list);
1907
1908         value1.type = DOUBLE;
1909         value1.store.d_double = 3.141F;
1910         value2.type = DOUBLE;
1911         value2.store.d_double = 3.1415F;
1912         key.group = buxton_string_pack("group");
1913         key.name = buxton_string_pack("named");
1914         key.type = DOUBLE;
1915         r = buxton_direct_set_value(&daemon.buxton, &key,
1916                                     &value1, NULL);
1917         fail_if(!r, "Failed to set value for notify");
1918         register_notification(&daemon, &cl, &key, 0, &status);
1919         fail_if(status != 0,
1920                 "Failed to register notification for notify");
1921         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1922
1923         s = read(client, buf, 4096);
1924         fail_if(s < 0, "Read from client failed");
1925         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1926         fail_if(csize != 1,
1927                 "Failed to get correct response to notify double");
1928         fail_if(msg != BUXTON_CONTROL_CHANGED,
1929                 "Failed to get correct control type");
1930         fail_if(msgid != 0, "Failed to get correct message id");
1931         fail_if(list[0].type != DOUBLE,
1932                 "Failed to get correct notification value type double");
1933         fail_if(list[0].store.d_double != 3.1415F,
1934                 "Failed to get correct notification value data double");
1935
1936         free(list);
1937
1938         value1.type = BOOLEAN;
1939         value1.store.d_boolean = false;
1940         value2.type = BOOLEAN;
1941         value2.store.d_int32 = true;
1942         key.group = buxton_string_pack("group");
1943         key.name = buxton_string_pack("nameb");
1944         key.type = BOOLEAN;
1945         r = buxton_direct_set_value(&daemon.buxton, &key,
1946                                     &value1, NULL);
1947         fail_if(!r, "Failed to set value for notify");
1948         register_notification(&daemon, &cl, &key, 0, &status);
1949         fail_if(status != 0,
1950                 "Failed to register notification for notify");
1951         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1952
1953         s = read(client, buf, 4096);
1954         fail_if(s < 0, "Read from client failed");
1955         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1956         fail_if(csize != 1,
1957                 "Failed to get correct response to notify bool");
1958         fail_if(msg != BUXTON_CONTROL_CHANGED,
1959                 "Failed to get correct control type");
1960         fail_if(msgid != 0, "Failed to get correct message id");
1961         fail_if(list[0].type != BOOLEAN,
1962                 "Failed to get correct notification value type bool");
1963         fail_if(list[0].store.d_boolean != true,
1964                 "Failed to get correct notification value data bool");
1965
1966         free(list);
1967         close(client);
1968         buxton_direct_close(&daemon.buxton);
1969 }
1970 END_TEST
1971
1972 START_TEST(identify_client_check)
1973 {
1974         int sender;
1975         client_list_item client;
1976         bool r;
1977         int32_t msg = 5;
1978
1979         setup_socket_pair(&client.fd, &sender);
1980         r = identify_client(&client);
1981         fail_if(r, "Identified client without message");
1982
1983         write(sender, &msg, sizeof(int32_t));
1984         r = identify_client(&client);
1985         fail_if(!r, "Identify client failed");
1986
1987         close(client.fd);
1988         close(sender);
1989 }
1990 END_TEST
1991
1992 START_TEST(add_pollfd_check)
1993 {
1994         BuxtonDaemon daemon;
1995         int fd;
1996         short events;
1997         bool a;
1998
1999         fd = 3;
2000         daemon.nfds_alloc = 0;
2001         daemon.accepting_alloc = 0;
2002         daemon.nfds = 0;
2003         daemon.pollfds = NULL;
2004         daemon.accepting = NULL;
2005         events = 1;
2006         a = true;
2007         add_pollfd(&daemon, fd, events, a);
2008         fail_if(daemon.nfds != 1, "Failed to increase nfds");
2009         fail_if(daemon.pollfds[0].fd != fd, "Failed to set pollfd");
2010         fail_if(daemon.pollfds[0].events != events, "Failed to set events");
2011         fail_if(daemon.pollfds[0].revents != 0, "Failed to set revents");
2012         fail_if(daemon.accepting[0] != a, "Failed to set accepting status");
2013         free(daemon.pollfds);
2014         free(daemon.accepting);
2015 }
2016 END_TEST
2017
2018 START_TEST(del_pollfd_check)
2019 {
2020         BuxtonDaemon daemon;
2021         int fd;
2022         short events;
2023         bool a;
2024
2025         fd = 3;
2026         daemon.nfds_alloc = 0;
2027         daemon.accepting_alloc = 0;
2028         daemon.nfds = 0;
2029         daemon.pollfds = NULL;
2030         daemon.accepting = NULL;
2031         events = 1;
2032         a = true;
2033         add_pollfd(&daemon, fd, events, a);
2034         fail_if(daemon.nfds != 1, "Failed to add pollfd");
2035         del_pollfd(&daemon, 0);
2036         fail_if(daemon.nfds != 0, "Failed to decrease nfds 1");
2037
2038         fd = 4;
2039         events = 2;
2040         a = false;
2041         add_pollfd(&daemon, fd, events, a);
2042         fail_if(daemon.nfds != 1, "Failed to increase nfds after del");
2043         fail_if(daemon.pollfds[0].fd != fd, "Failed to set pollfd after del");
2044         fail_if(daemon.pollfds[0].events != events,
2045                 "Failed to set events after del");
2046         fail_if(daemon.pollfds[0].revents != 0,
2047                 "Failed to set revents after del");
2048         fail_if(daemon.accepting[0] != a,
2049                 "Failed to set accepting status after del");
2050         fd = 5;
2051         events = 3;
2052         a = true;
2053         add_pollfd(&daemon, fd, events, a);
2054         del_pollfd(&daemon, 0);
2055         fail_if(daemon.nfds != 1, "Failed to delete fd 2");
2056         fail_if(daemon.pollfds[0].fd != fd, "Failed to set pollfd after del2");
2057         fail_if(daemon.pollfds[0].events != events,
2058                 "Failed to set events after del2");
2059         fail_if(daemon.pollfds[0].revents != 0,
2060                 "Failed to set revents after del2");
2061         fail_if(daemon.accepting[0] != a,
2062                 "Failed to set accepting status after del2");
2063 }
2064 END_TEST
2065
2066 START_TEST(handle_client_check)
2067 {
2068 }
2069 END_TEST
2070
2071 START_TEST(buxtond_eat_garbage_check)
2072 {
2073         daemon_pid = 0;
2074         sigset_t sigset;
2075         pid_t pid;
2076
2077         unlink(buxton_socket());
2078
2079         sigemptyset(&sigset);
2080         sigaddset(&sigset, SIGCHLD);
2081         sigprocmask(SIG_BLOCK, &sigset, NULL);
2082
2083         pid = fork();
2084         fail_if(pid < 0, "couldn't fork");
2085         if (pid) {              /* parent*/
2086                 BuxtonClient c;
2087                 FuzzContext fuzz;
2088                 time_t start;
2089                 bool keep_going = true;
2090                 int fd;
2091
2092
2093                 srand(0);
2094                 bzero(&fuzz, sizeof(FuzzContext));
2095
2096                 daemon_pid = pid;
2097                 usleep(250*1000);
2098                 check_did_not_crash(daemon_pid, &fuzz);
2099
2100
2101                 fail_if(time(&start) == -1, "call to time() failed");
2102                 do {
2103                         pid_t client;
2104                         ssize_t bytes;
2105                         time_t now;
2106
2107                         fail_if(time(&now) == -1, "call to time() failed");
2108                         if (now - start >= fuzz_time) {
2109                                 keep_going = false;
2110                         }
2111
2112                         fuzz.size = (unsigned int)rand() % 4096;
2113                         for (int i=0; i < fuzz.size; i++) {
2114                                 fuzz.buf[i] = (uint8_t)(rand() % 255);
2115                         }
2116                         if ((fuzz.size >= 6) && (rand() % 4096)) {
2117                                 uint16_t control = (uint16_t)((rand() % (BUXTON_CONTROL_MAX-1)) + 1);
2118
2119                                 /* magic */
2120                                 fuzz.buf[0] = 0x06;
2121                                 fuzz.buf[1] = 0x72;
2122
2123                                 /* valid message type */
2124                                 memcpy((void*)(fuzz.buf + 2), (void*)(&control), sizeof(uint16_t));
2125
2126                                 /* valid size */
2127                                 memcpy((void *)(fuzz.buf + 4), (void *)(&fuzz.size), sizeof(uint32_t));
2128                         }
2129                         client = fork();
2130                         fail_if(client == -1, "couldn't fork");
2131                         if (client == 0) {
2132                                 fd = buxton_open(&c);
2133                                 fail_if(fd == -1,
2134                                         "Open failed with daemon%s", dump_fuzz(&fuzz));
2135
2136
2137                                 bytes = write(fd, (void*)(fuzz.buf), fuzz.size);
2138                                 fail_if(bytes == -1, "write failed: %m%s", dump_fuzz(&fuzz));
2139                                 fail_unless(bytes == fuzz.size, "write was %d instead of %d", bytes, fuzz.size);
2140
2141                                 buxton_close(c);
2142                                 usleep(1*1000);
2143
2144                                 check_did_not_crash(daemon_pid, &fuzz);
2145                                 exit(0);
2146                         } else {
2147                                 int status;
2148                                 pid_t wait = waitpid(client, &status, 0);
2149                                 fail_if(wait == -1, "waitpid failed");
2150                                 fail_unless(WIFEXITED(status), "client died");
2151                                 fuzz.iteration++;
2152                         }
2153                 } while (keep_going);
2154         } else {                /* child */
2155                 exec_daemon();
2156         }
2157 }
2158 END_TEST
2159
2160 static Suite *
2161 daemon_suite(void)
2162 {
2163         Suite *s;
2164         TCase *tc;
2165
2166         s = suite_create("daemon");
2167         tc = tcase_create("daemon test functions");
2168         tcase_add_checked_fixture(tc, setup, teardown);
2169         tcase_add_test(tc, buxton_open_check);
2170         tcase_add_test(tc, buxton_create_group_check);
2171         tcase_add_test(tc, buxton_remove_group_check);
2172         tcase_add_test(tc, buxton_set_value_check);
2173         tcase_add_test(tc, buxton_set_label_check);
2174         tcase_add_test(tc, buxton_get_value_for_layer_check);
2175         tcase_add_test(tc, buxton_get_value_check);
2176         suite_add_tcase(s, tc);
2177
2178         tc = tcase_create("buxton_daemon_functions");
2179         tcase_add_test(tc, parse_list_check);
2180         tcase_add_test(tc, create_group_check);
2181         tcase_add_test(tc, remove_group_check);
2182         tcase_add_test(tc, set_label_check);
2183         tcase_add_test(tc, set_value_check);
2184         tcase_add_test(tc, get_value_check);
2185         tcase_add_test(tc, register_notification_check);
2186         tcase_add_test(tc, buxtond_handle_message_error_check);
2187         tcase_add_test(tc, buxtond_handle_message_create_group_check);
2188         tcase_add_test(tc, buxtond_handle_message_remove_group_check);
2189         tcase_add_test(tc, buxtond_handle_message_set_label_check);
2190         tcase_add_test(tc, buxtond_handle_message_set_value_check);
2191         tcase_add_test(tc, buxtond_handle_message_get_check);
2192         tcase_add_test(tc, buxtond_handle_message_notify_check);
2193         tcase_add_test(tc, buxtond_handle_message_unset_check);
2194         tcase_add_test(tc, buxtond_notify_clients_check);
2195         tcase_add_test(tc, identify_client_check);
2196         tcase_add_test(tc, add_pollfd_check);
2197         tcase_add_test(tc, del_pollfd_check);
2198         tcase_add_test(tc, handle_client_check);
2199         suite_add_tcase(s, tc);
2200
2201         tc = tcase_create("buxton daemon evil tests");
2202         tcase_add_checked_fixture(tc, NULL, teardown);
2203         tcase_add_test(tc, buxtond_eat_garbage_check);
2204         tcase_set_timeout(tc, fuzz_time+2);
2205         suite_add_tcase(s, tc);
2206
2207         return s;
2208 }
2209
2210 int main(void)
2211 {
2212         int number_failed;
2213         Suite *s;
2214         SRunner *sr;
2215         char *fuzzenv;
2216
2217         putenv("BUXTON_CONF_FILE=" ABS_TOP_BUILDDIR "/test/test.conf");
2218         putenv("BUXTON_ROOT_CHECK=0");
2219         fuzzenv = getenv("BUXTON_FUZZ_TIME");
2220         if (fuzzenv)
2221                 fuzz_time = atoi(fuzzenv);
2222         else
2223                 fuzz_time = 2;
2224         s = daemon_suite();
2225         sr = srunner_create(s);
2226         srunner_run_all(sr, CK_VERBOSE);
2227         number_failed = srunner_ntests_failed(sr);
2228         srunner_free(sr);
2229
2230         return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
2231 }
2232
2233 /*
2234  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2235  *
2236  * Local variables:
2237  * c-basic-offset: 8
2238  * tab-width: 8
2239  * indent-tabs-mode: t
2240  * End:
2241  *
2242  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2243  * :indentSize=8:tabSize=8:noTabs=false:
2244  */