tizen 2.3 release
[external/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 <errno.h>
18 #include <fcntl.h>
19 #include <semaphore.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <time.h>
29 #include <unistd.h>
30
31 #include "buxton.h"
32 #include "buxtonresponse.h"
33 #include "configurator.h"
34 #include "check_utils.h"
35 #include "daemon.h"
36 #include "direct.h"
37 #include "hashmap.h"
38 #include "log.h"
39 #include "smack.h"
40 #include "util.h"
41
42 #ifdef NDEBUG
43 #error "re-run configure with --enable-debug"
44 #endif
45
46 #define BUXTON_ROOT_CHECK_ENV "BUXTON_ROOT_CHECK"
47
48 static pid_t daemon_pid;
49 int fuzz_time;
50
51 typedef struct _fuzz_context_t {
52         uint8_t buf[4096];
53         size_t size;
54         int iteration;
55 } FuzzContext;
56
57 static bool use_smack(void)
58 {
59         bool __attribute__((unused))dummy;
60
61         dummy = buxton_cache_smack_rules();
62
63         return buxton_smack_enabled();
64 }
65
66 static char* dump_fuzz(FuzzContext *fuzz)
67 {
68         char* buf;
69         size_t buff_size;
70         FILE* s;
71         int l = 0;
72         int c = 0;
73
74         s = open_memstream(&buf, &buff_size);
75
76         fprintf(s, "\n\n******************************************\n");
77         fprintf(s, "current time %ld\n", time(NULL));
78         fprintf(s, "iteration: %d\tsize: %llu\n", fuzz->iteration, (unsigned long long)fuzz->size);
79         for (int i = 0; i < fuzz->size; i++) {
80                 fprintf(s, "%02X ", fuzz->buf[i]);
81                 c+= 3;
82                 if (c > 80) {
83                         fprintf(s, "\n");
84                         c = 0;
85                         l++;
86                 }
87         }
88         fclose(s);
89
90         return buf;
91 }
92
93 static void check_did_not_crash(pid_t pid, FuzzContext *fuzz)
94 {
95         pid_t rpid;
96         int status;
97
98         rpid = waitpid(pid, &status, WNOHANG);
99         fail_if(rpid == -1, "couldn't wait for pid %m");
100         if (rpid == 0) {
101                 /* child is still running */
102                 return;
103         }
104         fail_if(WIFEXITED(status), "daemon exited with status %d%s",
105                 WEXITSTATUS(status), dump_fuzz(fuzz));
106         fail_if(WIFSIGNALED(status), "daemon was killed with signal %d%s",
107                 WTERMSIG(status), dump_fuzz(fuzz));
108 }
109
110 static void exec_daemon(void)
111 {
112         char path[PATH_MAX];
113
114         //FIXME: path is wrong for makedistcheck
115         snprintf(path, PATH_MAX, "%s/check_buxtond", get_current_dir_name());
116
117         if (execl(path, "check_buxtond", (const char*)NULL) < 0) {
118                 fail("couldn't exec: %m");
119         }
120         fail("should never reach here");
121 }
122
123 static void setup(void)
124 {
125         daemon_pid = 0;
126         sigset_t sigset;
127         pid_t pid;
128
129         unlink(buxton_socket());
130
131         sigemptyset(&sigset);
132         sigaddset(&sigset, SIGCHLD);
133         sigprocmask(SIG_BLOCK, &sigset, NULL);
134
135         pid = fork();
136         fail_if(pid < 0, "couldn't fork");
137         if (pid) {
138                 /* parent*/
139                 daemon_pid = pid;
140                 usleep(128*1000);
141         } else {
142                 /* child */
143                 exec_daemon();
144         }
145 }
146
147 static void teardown(void)
148 {
149         if (daemon_pid) {
150                 int status;
151                 pid_t pid;
152
153                 pid = waitpid(daemon_pid, &status, WNOHANG);
154                 fail_if(pid == -1, "waitpid error");
155                 if (pid) {
156                         fail("daemon crashed!");
157                 } else  {
158                         /* if the daemon is still running, kill it */
159                         kill(SIGTERM, daemon_pid);
160                         usleep(64*1000);
161                         kill(SIGKILL, daemon_pid);
162                 }
163         }
164 }
165
166 START_TEST(buxton_open_check)
167 {
168         BuxtonClient c = NULL;
169         fail_if(buxton_open(&c) == -1,
170                 "Connection failed to open with daemon.");
171 }
172 END_TEST
173
174 static void client_create_group_test(BuxtonResponse response, void *data)
175 {
176         char *k = (char *)data;
177         BuxtonKey key;
178         char *group;
179         uid_t uid = getuid();
180         char *root_check = getenv(BUXTON_ROOT_CHECK_ENV);
181         bool skip_check = (root_check && streq(root_check, "0"));
182
183         fail_if(buxton_response_type(response) != BUXTON_CONTROL_CREATE_GROUP,
184                 "Failed to get create group response type");
185
186         if (uid == 0) {
187                 fail_if(buxton_response_status(response) != 0,
188                         "Create group failed");
189                 key = buxton_response_key(response);
190                 fail_if(!key, "Failed to get create group key");
191                 group = buxton_key_get_group(key);
192                 fail_if(!group, "Failed to get group from key");
193                 fail_if(!streq(group, k),
194                         "Incorrect set key returned");
195                 free(group);
196                 buxton_key_free(key);
197         } else {
198                 fail_if(buxton_response_status(response) == 0  && !skip_check,
199                         "Create group succeeded, but the client is not root");
200         }
201 }
202 START_TEST(buxton_create_group_check)
203 {
204         BuxtonClient c;
205         BuxtonKey key = buxton_key_create("tgroup", NULL, "base", STRING);
206         fail_if(!key, "Failed to create key");
207         fail_if(buxton_open(&c) == -1,
208                 "Open failed with daemon.");
209         fail_if(buxton_create_group(c, key, client_create_group_test,
210                                     "tgroup", true),
211                 "Creating group in buxton failed.");
212         buxton_key_free(key);
213 }
214 END_TEST
215
216 static void client_remove_group_test(BuxtonResponse response, void *data)
217 {
218         char *k = (char *)data;
219         BuxtonKey key;
220         char *group;
221         uid_t uid = getuid();
222         char *root_check = getenv(BUXTON_ROOT_CHECK_ENV);
223         bool skip_check = (root_check && streq(root_check, "0"));
224
225         fail_if(buxton_response_type(response) != BUXTON_CONTROL_REMOVE_GROUP,
226                 "Failed to get remove group response type");
227
228         if (uid == 0) {
229                 fail_if(buxton_response_status(response) != 0,
230                         "Remove group failed");
231                 key = buxton_response_key(response);
232                 fail_if(!key, "Failed to get create group key");
233                 group = buxton_key_get_group(key);
234                 fail_if(!group, "Failed to get group from key");
235                 fail_if(!streq(group, k),
236                         "Incorrect set key returned");
237                 free(group);
238                 buxton_key_free(key);
239         } else {
240                 fail_if(buxton_response_status(response) == 0  && !skip_check,
241                         "Create group succeeded, but the client is not root");
242         }
243 }
244 START_TEST(buxton_remove_group_check)
245 {
246         BuxtonClient c;
247         BuxtonKey key = buxton_key_create("tgroup", NULL, "base", STRING);
248         fail_if(!key, "Failed to create key");
249         fail_if(buxton_open(&c) == -1,
250                 "Open failed with daemon.");
251         fail_if(buxton_remove_group(c, key, client_remove_group_test,
252                                     "tgroup", true),
253                 "Removing group in buxton failed.");
254         buxton_key_free(key);
255 }
256 END_TEST
257
258 static void client_set_value_test(BuxtonResponse response, void *data)
259 {
260         char *k = (char *)data;
261         BuxtonKey key;
262         char *group;
263
264         fail_if(buxton_response_type(response) != BUXTON_CONTROL_SET,
265                 "Failed to get set response type");
266         fail_if(buxton_response_status(response) != 0,
267                 "Set value failed");
268         key = buxton_response_key(response);
269         fail_if(!key, "Failed to get set key");
270         group = buxton_key_get_group(key);
271         fail_if(!group, "Failed to get group from key");
272         fail_if(!streq(group, k),
273                 "Incorrect set group returned");
274         free(group);
275         buxton_key_free(key);
276 }
277 START_TEST(buxton_set_value_check)
278 {
279         BuxtonClient c;
280         BuxtonKey group = buxton_key_create("group", NULL, "test-gdbm-user", STRING);
281         fail_if(!group, "Failed to create key for group");
282         BuxtonKey key = buxton_key_create("group", "name", "test-gdbm-user", STRING);
283         fail_if(!key, "Failed to create key");
284         fail_if(buxton_open(&c) == -1,
285                 "Open failed with daemon.");
286         fail_if(buxton_create_group(c, group, NULL, NULL, true),
287                 "Creating group in buxton failed.");
288         fail_if(buxton_set_label(c, group, "*", NULL, NULL, true),
289                 "Setting group in buxton failed.");
290         fail_if(buxton_set_value(c, key, "bxt_test_value",
291                                  client_set_value_test,
292                                  "group", true),
293                 "Setting value in buxton failed.");
294         buxton_key_free(group);
295         buxton_key_free(key);
296 }
297 END_TEST
298
299 static void client_set_label_test(BuxtonResponse response, void *data)
300 {
301         BuxtonKey user_key = (BuxtonKey)data;
302         BuxtonKey key;
303         char *user_group, *group;
304         char *user_name, *name;
305         uid_t uid = getuid();
306         char *root_check = getenv(BUXTON_ROOT_CHECK_ENV);
307         bool skip_check = (root_check && streq(root_check, "0"));
308
309         fail_if(buxton_response_type(response) != BUXTON_CONTROL_SET_LABEL,
310                 "Failed to get set label response type");
311
312         if (uid == 0) {
313                 fail_if(buxton_response_status(response) != 0,
314                         "Set label failed");
315                 key = buxton_response_key(response);
316                 fail_if(!key, "Failed to get set label key");
317                 user_group = buxton_key_get_group(user_key);
318                 fail_if(!user_group, "Failed to get group from user key");
319                 group = buxton_key_get_group(key);
320                 fail_if(!group, "Failed to get group from key");
321                 fail_if(!streq(group, user_group),
322                         "Incorrect set label group returned");
323                 free(user_group);
324                 free(group);
325
326                 user_name = buxton_key_get_name(user_key);
327                 if (user_name) {
328                         name = buxton_key_get_name(key);
329                         fail_if(!name, "Failed to get name from key");
330                         fail_if(!streq(name, user_name),
331                                 "Incorrect set label name returned");
332                         free(user_name);
333                         free(name);
334                 }
335                 buxton_key_free(key);
336         } else {
337                 if (skip_check) {
338                         fail_if(buxton_response_status(response) != 0,
339                         "Set label failed");
340                 } else {
341                         fail_if(buxton_response_status(response) == 0,
342                         "Set label succeeded, but the client is not root");
343                 }
344         }
345 }
346 START_TEST(buxton_set_label_check)
347 {
348         BuxtonClient c;
349         BuxtonKey group = buxton_key_create("bxt_group", NULL, "test-gdbm", STRING);
350         fail_if(!group, "Failed to create key for group");
351         fail_if(buxton_open(&c) == -1,
352                 "Open failed with daemon.");
353         fail_if(buxton_create_group(c, group, NULL, NULL, true),
354                 "Creating group in buxton failed.");
355         fail_if(buxton_set_label(c, group, "*",
356                                  client_set_label_test,
357                                  group, true),
358                 "Setting label for group in buxton failed.");
359
360         BuxtonKey name = buxton_key_create("bxt_group", "bxt_name", "test-gdbm", STRING);
361         fail_if(!name, "Failed to create key for name");
362         fail_if(buxton_set_value(c, name, "bxt_value", NULL, NULL, true),
363                 "Setting label for name in buxton failed.");
364         fail_if(buxton_set_label(c, name, "*",
365                                  client_set_label_test,
366                                  name, true),
367                 "Setting label for name in buxton failed.");
368
369         buxton_key_free(group);
370         buxton_key_free(name);
371 }
372 END_TEST
373
374 static void client_get_value_test(BuxtonResponse response, void *data)
375 {
376         BuxtonKey key;
377         char *group;
378         char *name;
379         char *v;
380         char *value = (char *)data;
381
382         fail_if(buxton_response_status(response) != 0,
383                 "Get value failed");
384
385         key = buxton_response_key(response);
386         fail_if(!key, "Failed to get key");
387         group = buxton_key_get_group(key);
388         fail_if(!group, "Failed to get group");
389         fail_if(!streq(group, "group"),
390                 "Failed to get correct group");
391         name = buxton_key_get_name(key);
392         fail_if(!name, "Failed to get name");
393         fail_if(!streq(name, "name"),
394                 "Failed to get correct name");
395         v = buxton_response_value(response);
396         printf("val=%s\n", v);
397         fail_if(!v, "Failed to get value");
398         fail_if(!streq(v, value),
399                 "Failed to get correct value");
400
401         free(v);
402         free(group);
403         free(name);
404         buxton_key_free(key);
405 }
406 START_TEST(buxton_get_value_for_layer_check)
407 {
408         BuxtonClient c = NULL;
409         BuxtonKey key = buxton_key_create("group", "name", "test-gdbm-user", STRING);
410
411         fail_if(buxton_open(&c) == -1,
412                 "Open failed with daemon.");
413         fail_if(buxton_get_value(c, key,
414                                  client_get_value_test,
415                                  "bxt_test_value", true),
416                 "Retrieving value from buxton gdbm backend failed.");
417 }
418 END_TEST
419
420 START_TEST(buxton_get_value_check)
421 {
422         BuxtonClient c = NULL;
423
424         BuxtonKey group = buxton_key_create("group", NULL, "test-gdbm", STRING);
425         fail_if(!group, "Failed to create key for group");
426         BuxtonKey key = buxton_key_create("group", "name", "test-gdbm", STRING);
427
428         fail_if(buxton_open(&c) == -1,
429                 "Open failed with daemon.");
430
431         fail_if(buxton_create_group(c, group, NULL, NULL, true),
432                 "Creating group in buxton failed.");
433         fail_if(buxton_set_label(c, group, "*", NULL, NULL, true),
434                 "Setting group in buxton failed.");
435         fail_if(buxton_set_value(c, key, "bxt_test_value2",
436                                  client_set_value_test, "group", true),
437                 "Failed to set second value.");
438         buxton_key_free(group);
439         buxton_key_free(key);
440         key = buxton_key_create("group", "name", NULL, STRING);
441         fail_if(buxton_get_value(c, key,
442                                  client_get_value_test,
443                                  "bxt_test_value2", true),
444                 "Retrieving value from buxton gdbm backend failed.");
445         buxton_key_free(key);
446 }
447 END_TEST
448
449 START_TEST(parse_list_check)
450 {
451         BuxtonData l3[2];
452         BuxtonData l2[4];
453         BuxtonData l1[3];
454         _BuxtonKey key;
455         BuxtonData *value = NULL;
456
457         fail_if(parse_list(BUXTON_CONTROL_NOTIFY, 2, l1, &key, &value),
458                 "Parsed bad notify argument count");
459         l1[0].type = INT32;
460         l1[1].type = STRING;
461         l1[2].type = UINT32;
462         fail_if(parse_list(BUXTON_CONTROL_NOTIFY, 3, l1, &key, &value),
463                 "Parsed bad notify type 1");
464         l1[0].type = STRING;
465         l1[1].type = FLOAT;
466         l1[2].type = UINT32;
467         fail_if(parse_list(BUXTON_CONTROL_NOTIFY, 3, l1, &key, &value),
468                 "Parsed bad notify type 3");
469         l1[0].type = STRING;
470         l1[1].type = STRING;
471         l1[2].type = STRING;
472         fail_if(parse_list(BUXTON_CONTROL_NOTIFY, 3, l1, &key, &value),
473                 "Parsed bad notify type 3");
474         l1[0].type = STRING;
475         l1[1].type = STRING;
476         l1[2].type = UINT32;
477         l1[0].store.d_string = buxton_string_pack("s1");
478         l1[1].store.d_string = buxton_string_pack("s2");
479         l1[2].store.d_uint32 = STRING;
480         fail_if(!parse_list(BUXTON_CONTROL_NOTIFY, 3, l1, &key, &value),
481                 "Unable to parse valid notify");
482         fail_if(!streq(key.group.value, l1[0].store.d_string.value),
483                 "Failed to set correct notify group");
484         fail_if(!streq(key.name.value, l1[1].store.d_string.value),
485                 "Failed to set correct notify name");
486         fail_if(key.type != l1[2].store.d_uint32,
487                 "Failed to set correct notify type");
488
489         fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 2, l1, &key, &value),
490                 "Parsed bad unnotify argument count");
491         l1[0].type = INT32;
492         l1[1].type = STRING;
493         l1[2].type = UINT32;
494         fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 3, l1, &key, &value),
495                 "Parsed bad unnotify type 1");
496         l1[0].type = STRING;
497         l1[1].type = FLOAT;
498         l1[2].type = UINT32;
499         fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 3, l1, &key, &value),
500                 "Parsed bad unnotify type 2");
501         l1[0].type = INT32;
502         l1[1].type = STRING;
503         l1[2].type = STRING;
504         fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 3, l1, &key, &value),
505                 "Parsed bad unnotify type 3");
506         l1[0].type = STRING;
507         l1[1].type = STRING;
508         l1[2].type = UINT32;
509         l1[0].store.d_string = buxton_string_pack("s3");
510         l1[1].store.d_string = buxton_string_pack("s4");
511         l1[2].store.d_uint32 = STRING;
512         fail_if(!parse_list(BUXTON_CONTROL_UNNOTIFY, 3, l1, &key, &value),
513                 "Unable to parse valid unnotify");
514         fail_if(!streq(key.group.value, l1[0].store.d_string.value),
515                 "Failed to set correct unnotify group");
516         fail_if(!streq(key.name.value, l1[1].store.d_string.value),
517                 "Failed to set correct unnotify name");
518         fail_if(key.type != l1[2].store.d_uint32,
519                 "Failed to set correct unnotify type");
520
521         fail_if(parse_list(BUXTON_CONTROL_GET, 5, l2, &key, &value),
522                 "Parsed bad get argument count");
523         l2[0].type = INT32;
524         l2[1].type = STRING;
525         l2[2].type = STRING;
526         l2[3].type = UINT32;
527         fail_if(parse_list(BUXTON_CONTROL_GET, 4, l2, &key, &value),
528                 "Parsed bad get type 1");
529         l2[0].type = STRING;
530         l2[1].type = FLOAT;
531         l2[2].type = STRING;
532         l2[3].type = UINT32;
533         fail_if(parse_list(BUXTON_CONTROL_GET, 4, l2, &key, &value),
534                 "Parsed bad get type 2");
535         l2[0].type = STRING;
536         l2[1].type = STRING;
537         l2[2].type = BOOLEAN;
538         l2[3].type = UINT32;
539         fail_if(parse_list(BUXTON_CONTROL_GET, 4, l2, &key, &value),
540                 "Parsed bad get type 3");
541         l2[0].type = STRING;
542         l2[1].type = STRING;
543         l2[2].type = STRING;
544         l2[3].type = STRING;
545         fail_if(parse_list(BUXTON_CONTROL_GET, 4, l2, &key, &value),
546                 "Parsed bad get type 4");
547         l2[0].type = STRING;
548         l2[1].type = STRING;
549         l2[2].type = STRING;
550         l2[3].type = UINT32;
551         l2[0].store.d_string = buxton_string_pack("s5");
552         l2[1].store.d_string = buxton_string_pack("s6");
553         l2[2].store.d_string = buxton_string_pack("s7");
554         l2[3].store.d_uint32 = STRING;
555         fail_if(!parse_list(BUXTON_CONTROL_GET, 4, l2, &key, &value),
556                 "Unable to parse valid get 1");
557         fail_if(!streq(key.layer.value, l2[0].store.d_string.value),
558                 "Failed to set correct get layer 1");
559         fail_if(!streq(key.group.value, l2[1].store.d_string.value),
560                 "Failed to set correct get group 1");
561         fail_if(!streq(key.name.value, l2[2].store.d_string.value),
562                 "Failed to set correct get name");
563         fail_if(key.type != l2[3].store.d_uint32,
564                 "Failed to set correct get type 1");
565         l2[0].store.d_string = buxton_string_pack("s6");
566         l2[1].store.d_string = buxton_string_pack("s6");
567         l2[2].type = UINT32;
568         l2[2].store.d_uint32 = STRING;
569         fail_if(!parse_list(BUXTON_CONTROL_GET, 3, l2, &key, &value),
570                 "Unable to parse valid get 2");
571         fail_if(!streq(key.group.value, l2[0].store.d_string.value),
572                 "Failed to set correct get group 2");
573         fail_if(!streq(key.name.value, l2[1].store.d_string.value),
574                 "Failed to set correct get name 2");
575         fail_if(key.type != l2[2].store.d_uint32,
576                 "Failed to set correct get type 2");
577         l1[0].type = INT32;
578         l1[1].type = STRING;
579         l1[2].type = UINT32;
580         fail_if(parse_list(BUXTON_CONTROL_GET, 3, l1, &key, &value),
581                 "Parsed bad get type 5");
582         l1[0].type = STRING;
583         l1[1].type = FLOAT;
584         l1[2].type = UINT32;
585         fail_if(parse_list(BUXTON_CONTROL_GET, 3, l1, &key, &value),
586                 "Parsed bad get type 6");
587         l1[0].type = STRING;
588         l1[1].type = STRING;
589         l1[2].type = BOOLEAN;
590         fail_if(parse_list(BUXTON_CONTROL_GET, 3, l1, &key, &value),
591                 "Parsed bad get type 7");
592
593         fail_if(parse_list(BUXTON_CONTROL_SET, 1, l2, &key, &value),
594                 "Parsed bad set argument count");
595         l2[0].type = INT32;
596         l2[1].type = STRING;
597         l2[2].type = STRING;
598         l2[3].type = FLOAT;
599         fail_if(parse_list(BUXTON_CONTROL_SET, 4, l2, &key, &value),
600                 "Parsed bad set type 1");
601         l2[0].type = STRING;
602         l2[1].type = FLOAT;
603         l2[2].type = STRING;
604         l2[3].type = FLOAT;
605         fail_if(parse_list(BUXTON_CONTROL_SET, 4, l2, &key, &value),
606                 "Parsed bad set type 2");
607         l2[0].type = STRING;
608         l2[1].type = STRING;
609         l2[2].type = BOOLEAN;
610         l2[3].type = FLOAT;
611         fail_if(parse_list(BUXTON_CONTROL_SET, 4, l2, &key, &value),
612                 "Parsed bad set type 3");
613         l2[0].type = STRING;
614         l2[1].type = STRING;
615         l2[2].type = STRING;
616         l2[3].type = FLOAT;
617         l2[0].store.d_string = buxton_string_pack("s8");
618         l2[1].store.d_string = buxton_string_pack("s9");
619         l2[2].store.d_string = buxton_string_pack("s10");
620         l2[3].store.d_float = 3.14F;
621         fail_if(!parse_list(BUXTON_CONTROL_SET, 4, l2, &key, &value),
622                 "Unable to parse valid set 1");
623         fail_if(!streq(key.layer.value, l2[0].store.d_string.value),
624                 "Failed to set correct set layer 1");
625         fail_if(!streq(key.group.value, l2[1].store.d_string.value),
626                 "Failed to set correct set group 1");
627         fail_if(!streq(key.name.value, l2[2].store.d_string.value),
628                 "Failed to set correct set name 1");
629         fail_if(value->store.d_float != l2[3].store.d_float,
630                 "Failed to set correct set value 1");
631
632         fail_if(parse_list(BUXTON_CONTROL_UNSET, 1, l2, &key, &value),
633                 "Parsed bad unset argument count");
634         l2[0].type = INT32;
635         l2[1].type = STRING;
636         l2[2].type = STRING;
637         l2[3].type = UINT32;
638         fail_if(parse_list(BUXTON_CONTROL_UNSET, 4, l2, &key, &value),
639                 "Parsed bad unset type 1");
640         l2[0].type = STRING;
641         l2[1].type = FLOAT;
642         l2[2].type = STRING;
643         l2[3].type = UINT32;
644         fail_if(parse_list(BUXTON_CONTROL_UNSET, 4, l2, &key, &value),
645                 "Parsed bad unset type 2");
646         l2[0].type = STRING;
647         l2[1].type = STRING;
648         l2[2].type = BOOLEAN;
649         l2[3].type = UINT32;
650         fail_if(parse_list(BUXTON_CONTROL_UNSET, 4, l2, &key, &value),
651                 "Parsed bad unset type 3");
652         l2[0].type = STRING;
653         l2[1].type = STRING;
654         l2[2].type = STRING;
655         l2[3].type = STRING;
656         fail_if(parse_list(BUXTON_CONTROL_UNSET, 4, l2, &key, &value),
657                 "Parsed bad unset type 4");
658         l2[0].type = STRING;
659         l2[1].type = STRING;
660         l2[2].type = STRING;
661         l2[3].type = UINT32;
662         l2[0].store.d_string = buxton_string_pack("s11");
663         l2[1].store.d_string = buxton_string_pack("s12");
664         l2[2].store.d_string = buxton_string_pack("s13");
665         l2[3].store.d_uint32 = STRING;
666         fail_if(!parse_list(BUXTON_CONTROL_UNSET, 4, l2, &key, &value),
667                 "Unable to parse valid unset 1");
668         fail_if(!streq(key.layer.value, l2[0].store.d_string.value),
669                 "Failed to set correct unset layer 1");
670         fail_if(!streq(key.group.value, l2[1].store.d_string.value),
671                 "Failed to set correct unset group 1");
672         fail_if(!streq(key.name.value, l2[2].store.d_string.value),
673                 "Failed to set correct unset name 1");
674         fail_if(key.type != l2[3].store.d_uint32,
675                 "Failed to set correct unset type 1");
676
677         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 1, l2, &key, &value),
678                 "Parsed bad set label argument count");
679         l1[0].type = INT32;
680         l1[1].type = STRING;
681         l1[2].type = STRING;
682         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 3, l1, &key, &value),
683                 "Parsed bad set label type 1");
684         l1[0].type = STRING;
685         l1[1].type = FLOAT;
686         l1[2].type = STRING;
687         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 3, l1, &key, &value),
688                 "Parsed bad set label type 2");
689         l1[0].type = STRING;
690         l1[1].type = STRING;
691         l1[2].type = BOOLEAN;
692         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 3, l1, &key, &value),
693                 "Parsed bad set label type 3");
694         l1[0].type = STRING;
695         l1[1].type = STRING;
696         l1[2].type = STRING;
697         l1[0].store.d_string = buxton_string_pack("s14");
698         l1[1].store.d_string = buxton_string_pack("s15");
699         l1[2].store.d_string = buxton_string_pack("*");
700         fail_if(!parse_list(BUXTON_CONTROL_SET_LABEL, 3, l1, &key, &value),
701                 "Unable to parse valid set label 1");
702         fail_if(!streq(key.layer.value, l1[0].store.d_string.value),
703                 "Failed to set correct set label layer 1");
704         fail_if(!streq(key.group.value, l1[1].store.d_string.value),
705                 "Failed to set correct set label group 1");
706         fail_if(!streq(value->store.d_string.value, l1[2].store.d_string.value),
707                 "Failed to set correct set label label 1");
708         fail_if(key.type != STRING, "Failed to key type in set label");
709         l2[0].type = INT32;
710         l2[1].type = STRING;
711         l2[2].type = STRING;
712         l2[3].type = STRING;
713         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 4, l2, &key, &value),
714                 "Parsed bad set label type 4");
715         l2[0].type = STRING;
716         l2[1].type = FLOAT;
717         l2[2].type = STRING;
718         l2[3].type = STRING;
719         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 4, l2, &key, &value),
720                 "Parsed bad set label type 5");
721         l2[0].type = STRING;
722         l2[1].type = STRING;
723         l2[2].type = BOOLEAN;
724         l2[3].type = STRING;
725         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 4, l2, &key, &value),
726                 "Parsed bad set label type 6");
727         l2[0].type = STRING;
728         l2[1].type = STRING;
729         l2[2].type = STRING;
730         l2[3].type = UINT32;
731         fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 4, l2, &key, &value),
732                 "Parsed bad set label type 7");
733         l2[0].type = STRING;
734         l2[1].type = STRING;
735         l2[2].type = STRING;
736         l2[3].type = STRING;
737         l2[0].store.d_string = buxton_string_pack("x1");
738         l2[1].store.d_string = buxton_string_pack("x2");
739         l2[2].store.d_string = buxton_string_pack("x3");
740         l2[3].store.d_string = buxton_string_pack("x4");
741         fail_if(!parse_list(BUXTON_CONTROL_SET_LABEL, 4, l2, &key, &value),
742                 "Unable to parse valid set label 2");
743         fail_if(!streq(key.layer.value, l2[0].store.d_string.value),
744                 "Failed to set correct set label layer 2");
745         fail_if(!streq(key.group.value, l2[1].store.d_string.value),
746                 "Failed to set correct set label group 2");
747         fail_if(!streq(key.name.value, l2[2].store.d_string.value),
748                 "Failed to set correct set label name 2");
749         fail_if(!streq(value->store.d_string.value, l2[3].store.d_string.value),
750                 "Failed to set correct set label label 2");
751
752         fail_if(parse_list(BUXTON_CONTROL_CREATE_GROUP, 1, l3, &key, &value),
753                 "Parsed bad create group argument count");
754         l3[0].type = INT32;
755         l3[1].type = STRING;
756         fail_if(parse_list(BUXTON_CONTROL_CREATE_GROUP, 2, l3, &key, &value),
757                 "Parsed bad create group type 1");
758         l3[0].type = STRING;
759         l3[1].type = FLOAT;
760         fail_if(parse_list(BUXTON_CONTROL_CREATE_GROUP, 2, l3, &key, &value),
761                 "Parsed bad create group type 2");
762         l3[0].type = STRING;
763         l3[1].type = STRING;
764         l3[0].store.d_string = buxton_string_pack("s16");
765         l3[1].store.d_string = buxton_string_pack("s17");
766         fail_if(!parse_list(BUXTON_CONTROL_CREATE_GROUP, 2, l3, &key, &value),
767                 "Unable to parse valid create group 1");
768         fail_if(!streq(key.layer.value, l3[0].store.d_string.value),
769                 "Failed to set correct create group layer 1");
770         fail_if(!streq(key.group.value, l3[1].store.d_string.value),
771                 "Failed to set correct create group group 1");
772         fail_if(key.type != STRING, "Failed to key type in create group");
773
774         fail_if(parse_list(BUXTON_CONTROL_REMOVE_GROUP, 1, l3, &key, &value),
775                 "Parsed bad remove group argument count");
776         l3[0].type = INT32;
777         l3[1].type = STRING;
778         fail_if(parse_list(BUXTON_CONTROL_REMOVE_GROUP, 2, l3, &key, &value),
779                 "Parsed bad remove group type 1");
780         l3[0].type = STRING;
781         l3[1].type = FLOAT;
782         fail_if(parse_list(BUXTON_CONTROL_REMOVE_GROUP, 2, l3, &key, &value),
783                 "Parsed bad remove group type 2");
784         l3[0].type = STRING;
785         l3[1].type = STRING;
786         l3[0].store.d_string = buxton_string_pack("s18");
787         l3[1].store.d_string = buxton_string_pack("s19");
788         fail_if(!parse_list(BUXTON_CONTROL_REMOVE_GROUP, 2, l3, &key, &value),
789                 "Unable to parse valid remove group 1");
790         fail_if(!streq(key.layer.value, l3[0].store.d_string.value),
791                 "Failed to set correct remove group layer 1");
792         fail_if(!streq(key.group.value, l3[1].store.d_string.value),
793                 "Failed to set correct remove group group 1");
794         fail_if(key.type != STRING, "Failed to key type in remove group");
795
796         fail_if(parse_list(BUXTON_CONTROL_MIN, 2, l3, &key, &value),
797                 "Parsed bad control type 1");
798 }
799 END_TEST
800
801 START_TEST(create_group_check)
802 {
803         _BuxtonKey key = { {0}, {0}, {0}, 0};
804         client_list_item client;
805         int32_t status;
806         BuxtonDaemon server;
807         BuxtonString clabel = buxton_string_pack("_");
808
809         fail_if(!buxton_direct_open(&server.buxton),
810                 "Failed to open buxton direct connection");
811
812         client.cred.uid = getuid();
813         if (use_smack())
814                 client.smack_label = &clabel;
815         else
816                 client.smack_label = NULL;
817         server.buxton.client.uid = 0;
818
819         key.layer = buxton_string_pack("test-gdbm-user");
820         key.group = buxton_string_pack("daemon-check");
821         key.type = STRING;
822         create_group(&server, &client, &key, &status);
823         fail_if(status != 0, "Failed to create group");
824
825         key.layer = buxton_string_pack("test-gdbm");
826         create_group(&server, &client, &key, &status);
827         fail_if(status != 0, "Failed to create group");
828
829         key.layer = buxton_string_pack("base");
830         key.group = buxton_string_pack("tgroup");
831         create_group(&server, &client, &key, &status);
832         fail_if(status != 0, "Failed to create group");
833
834         buxton_direct_close(&server.buxton);
835 }
836 END_TEST
837
838 START_TEST(remove_group_check)
839 {
840         _BuxtonKey key = { {0}, {0}, {0}, 0};
841         client_list_item client;
842         int32_t status;
843         BuxtonDaemon server;
844         BuxtonString clabel = buxton_string_pack("_");
845
846         fail_if(!buxton_direct_open(&server.buxton),
847                 "Failed to open buxton direct connection");
848
849         client.cred.uid = getuid();
850         if (use_smack())
851                 client.smack_label = &clabel;
852         else
853                 client.smack_label = NULL;
854         server.buxton.client.uid = 0;
855
856         key.layer = buxton_string_pack("base");
857         key.group = buxton_string_pack("tgroup");
858         key.type = STRING;
859
860         remove_group(&server, &client, &key, &status);
861         fail_if(status != 0, "Failed to remove group");
862
863         buxton_direct_close(&server.buxton);
864 }
865 END_TEST
866
867 START_TEST(set_label_check)
868 {
869         _BuxtonKey key = { {0}, {0}, {0}, 0};
870         BuxtonData value;
871         client_list_item client;
872         int32_t status;
873         BuxtonDaemon server;
874         BuxtonString clabel = buxton_string_pack("_");
875
876         fail_if(!buxton_direct_open(&server.buxton),
877                 "Failed to open buxton direct connection");
878
879         client.cred.uid = getuid();
880         if (use_smack())
881                 client.smack_label = &clabel;
882         else
883                 client.smack_label = NULL;
884         server.buxton.client.uid = 0;
885         key.layer = buxton_string_pack("test-gdbm");
886         key.group = buxton_string_pack("daemon-check");
887         key.type = STRING;
888         value.type = STRING;
889         value.store.d_string = buxton_string_pack("*");
890
891         set_label(&server, &client, &key, &value, &status);
892         fail_if(status != 0, "Failed to set label");
893         buxton_direct_close(&server.buxton);
894 }
895 END_TEST
896
897 START_TEST(set_value_check)
898 {
899         _BuxtonKey key = { {0}, {0}, {0}, 0};
900         BuxtonData value;
901         client_list_item client;
902         int32_t status;
903         BuxtonDaemon server;
904         BuxtonString clabel = buxton_string_pack("_");
905
906         fail_if(!buxton_direct_open(&server.buxton),
907                 "Failed to open buxton direct connection");
908
909         client.cred.uid = getuid();
910         server.buxton.client.uid = 0;
911
912         if (use_smack())
913                 client.smack_label = &clabel;
914         else
915                 client.smack_label = NULL;
916
917         key.layer = buxton_string_pack("test-gdbm-user");
918         key.group = buxton_string_pack("daemon-check");
919         key.name = buxton_string_pack("name");
920         value.type = STRING;
921         value.store.d_string = buxton_string_pack("user-layer-value");
922
923         set_value(&server, &client, &key, &value, &status);
924         fail_if(status != 0, "Failed to set value");
925         fail_if(server.buxton.client.uid != client.cred.uid, "Failed to change buxton uid");
926
927         key.layer = buxton_string_pack("test-gdbm");
928         value.store.d_string = buxton_string_pack("system-layer-value");
929         set_value(&server, &client, &key, &value, &status);
930         fail_if(status != 0, "Failed to set value");
931
932         buxton_direct_close(&server.buxton);
933 }
934 END_TEST
935
936 START_TEST(get_value_check)
937 {
938         _BuxtonKey key = { {0}, {0}, {0}, 0};
939         BuxtonData *value;
940         client_list_item client;
941         int32_t status;
942         BuxtonDaemon server;
943         BuxtonString clabel = buxton_string_pack("_");
944
945         fail_if(!buxton_direct_open(&server.buxton),
946                 "Failed to open buxton direct connection");
947
948         fail_if(!buxton_cache_smack_rules(),
949                 "Failed to cache smack rules");
950         client.cred.uid = getuid();
951         if (use_smack())
952                 client.smack_label = &clabel;
953         else
954                 client.smack_label = NULL;
955         server.buxton.client.uid = 0;
956         key.layer = buxton_string_pack("test-gdbm-user");
957         key.group = buxton_string_pack("daemon-check");
958         key.name = buxton_string_pack("name");
959         key.type = STRING;
960
961         value = get_value(&server, &client, &key, &status);
962         fail_if(!value, "Failed to get value");
963         fail_if(status != 0, "Failed to get value");
964         fail_if(value->type != STRING, "Failed to get correct type");
965         fail_if(!streq(value->store.d_string.value, "user-layer-value"), "Failed to get correct value");
966         fail_if(server.buxton.client.uid != client.cred.uid, "Failed to change buxton uid");
967         free(value);
968
969         server.buxton.client.uid = 0;
970         key.layer.value = NULL;
971         key.layer.length = 0;
972         value = get_value(&server, &client, &key, &status);
973         fail_if(!value, "Failed to get value 2");
974         fail_if(status != 0, "Failed to get value 2");
975         fail_if(value->type != STRING, "Failed to get correct type 2");
976         fail_if(!streq(value->store.d_string.value, "system-layer-value"), "Failed to get correct value 2");
977         fail_if(server.buxton.client.uid != client.cred.uid, "Failed to change buxton uid 2");
978         free(value);
979
980         buxton_direct_close(&server.buxton);
981 }
982 END_TEST
983
984 START_TEST(register_notification_check)
985 {
986         _BuxtonKey key = { {0}, {0}, {0}, 0};
987         client_list_item client, no_client;
988         BuxtonString clabel = buxton_string_pack("_");
989         int32_t status;
990         BuxtonDaemon server;
991         uint32_t msgid;
992
993         fail_if(!buxton_cache_smack_rules(),
994                 "Failed to cache smack rules");
995         if (use_smack())
996                 client.smack_label = &clabel;
997         else
998                 client.smack_label = NULL;
999         client.cred.uid = 1002;
1000         fail_if(!buxton_direct_open(&server.buxton),
1001                 "Failed to open buxton direct connection");
1002         server.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1003         fail_if(!server.notify_mapping, "Failed to allocate hashmap");
1004
1005         key.group = buxton_string_pack("group");
1006         key.name = buxton_string_pack("name");
1007         key.type = STRING;
1008         register_notification(&server, &client, &key, 1, &status);
1009         fail_if(status != 0, "Failed to register notification");
1010         register_notification(&server, &client, &key, 1, &status);
1011         fail_if(status != 0, "Failed to register notification");
1012         //FIXME: Figure out what to do with duplicates
1013         key.group = buxton_string_pack("no-key");
1014         msgid = unregister_notification(&server, &client, &key, &status);
1015         fail_if(status == 0,
1016                 "Unregistered from notifications with invalid key");
1017         fail_if(msgid != 0, "Got unexpected notify message id");
1018         key.group = buxton_string_pack("group");
1019         msgid = unregister_notification(&server, &no_client, &key, &status);
1020         fail_if(status == 0,
1021                 "Unregistered from notifications with invalid client");
1022         fail_if(msgid != 0, "Got unexpected notify message id");
1023         msgid = unregister_notification(&server, &client, &key, &status);
1024         fail_if(status != 0,
1025                 "Unable to unregister from notifications");
1026         fail_if(msgid != 1, "Failed to get correct notify message id");
1027         key.group = buxton_string_pack("key2");
1028         register_notification(&server, &client, &key, 0, &status);
1029         fail_if(status == 0, "Registered notification with key not in db");
1030
1031         hashmap_free(server.notify_mapping);
1032         buxton_direct_close(&server.buxton);
1033 }
1034 END_TEST
1035 START_TEST(buxtond_handle_message_error_check)
1036 {
1037         int client, server;
1038         BuxtonDaemon daemon;
1039         BuxtonString slabel;
1040         size_t size;
1041         BuxtonData data1;
1042         client_list_item cl;
1043         bool r;
1044         BuxtonArray *list = NULL;
1045         uint16_t control;
1046
1047         setup_socket_pair(&client, &server);
1048         fail_if(fcntl(client, F_SETFL, O_NONBLOCK),
1049                 "Failed to set socket to non blocking");
1050         fail_if(fcntl(server, F_SETFL, O_NONBLOCK),
1051                 "Failed to set socket to non blocking");
1052         list = buxton_array_new();
1053         fail_if(!list, "Failed to allocate list");
1054
1055         cl.fd = server;
1056         slabel = buxton_string_pack("_");
1057         cl.smack_label = &slabel;
1058         daemon.buxton.client.uid = 1001;
1059         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1060         fail_if(!buxton_direct_open(&daemon.buxton),
1061                 "Failed to open buxton direct connection");
1062
1063         cl.data = malloc(4);
1064         fail_if(!cl.data, "Couldn't allocate blank message");
1065         cl.data[0] = 0;
1066         cl.data[1]= 0;
1067         cl.data[2] = 0;
1068         cl.data[3] = 0;
1069         size = 100;
1070         r = buxtond_handle_message(&daemon, &cl, size);
1071         fail_if(r, "Failed to detect invalid message data");
1072         free(cl.data);
1073
1074         data1.type = STRING;
1075         data1.store.d_string = buxton_string_pack("group");
1076         r = buxton_array_add(list, &data1);
1077         fail_if(!r, "Failed to add element to array");
1078         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_NOTIFY, 0,
1079                                         list);
1080         fail_if(size == 0, "Failed to serialize message");
1081         control = BUXTON_CONTROL_MIN;
1082         memcpy(cl.data, &control, sizeof(uint16_t));
1083         r = buxtond_handle_message(&daemon, &cl, size);
1084         fail_if(r, "Failed to detect min control size");
1085         control = BUXTON_CONTROL_MAX;
1086         memcpy(cl.data, &control, sizeof(uint16_t));
1087         r = buxtond_handle_message(&daemon, &cl, size);
1088         free(cl.data);
1089         fail_if(r, "Failed to detect max control size");
1090
1091         close(client);
1092         buxton_direct_close(&daemon.buxton);
1093         buxton_array_free(&list, NULL);
1094 }
1095 END_TEST
1096
1097 START_TEST(buxtond_handle_message_create_group_check)
1098 {
1099         BuxtonDaemon daemon;
1100         BuxtonString slabel;
1101         size_t size;
1102         BuxtonData data1, data2;
1103         client_list_item cl;
1104         bool r;
1105         BuxtonData *list;
1106         BuxtonArray *out_list1, *out_list2;
1107         BuxtonControlMessage msg;
1108         ssize_t csize;
1109         int client, server;
1110         ssize_t s;
1111         uint8_t buf[4096];
1112         uint32_t msgid;
1113
1114         setup_socket_pair(&client, &server);
1115         fail_if(fcntl(client, F_SETFL, O_NONBLOCK),
1116                 "Failed to set socket to non blocking");
1117         fail_if(fcntl(server, F_SETFL, O_NONBLOCK),
1118                 "Failed to set socket to non blocking");
1119
1120         cl.fd = server;
1121         slabel = buxton_string_pack("_");
1122         if (use_smack())
1123                 cl.smack_label = &slabel;
1124         else
1125                 cl.smack_label = NULL;
1126         cl.cred.uid = 1002;
1127         daemon.buxton.client.uid = 1001;
1128         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1129         fail_if(!buxton_direct_open(&daemon.buxton),
1130                 "Failed to open buxton direct connection");
1131         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1132         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1133
1134         out_list1 = buxton_array_new();
1135         fail_if(!out_list1, "Failed to allocate list");
1136         data1.type = STRING;
1137         data1.store.d_string = buxton_string_pack("base");
1138         data2.type = STRING;
1139         data2.store.d_string = buxton_string_pack("tgroup");
1140         r = buxton_array_add(out_list1, &data1);
1141         fail_if(!r, "Failed to add element to array");
1142         r = buxton_array_add(out_list1, &data2);
1143         fail_if(!r, "Failed to add element to array");
1144
1145         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_CREATE_GROUP, 0,
1146                                         out_list1);
1147         fail_if(size == 0, "Failed to serialize message");
1148         r = buxtond_handle_message(&daemon, &cl, size);
1149         free(cl.data);
1150         fail_if(!r, "Failed to handle create group message");
1151
1152         s = read(client, buf, 4096);
1153         fail_if(s < 0, "Read from client failed");
1154         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1155         fail_if(csize != 1, "Failed to get correct response to create group");
1156         fail_if(msg != BUXTON_CONTROL_STATUS,
1157                 "Failed to get correct control type");
1158         fail_if(list[0].type != INT32,
1159                 "Failed to get correct indicator type");
1160         fail_if(list[0].store.d_int32 != 0,
1161                 "Failed to create group");
1162         fail_if(msgid != 0, "Failed to get correct message id");
1163         free(list);
1164
1165         out_list2 = buxton_array_new();
1166         fail_if(!out_list2, "Failed to allocate list");
1167         data1.store.d_string = buxton_string_pack("base");
1168         data2.store.d_string = buxton_string_pack("daemon-check");
1169         r = buxton_array_add(out_list2, &data1);
1170         fail_if(!r, "Failed to add element to array");
1171         r = buxton_array_add(out_list2, &data2);
1172         fail_if(!r, "Failed to add element to array");
1173
1174         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_CREATE_GROUP, 1,
1175                                         out_list2);
1176         fail_if(size == 0, "Failed to serialize message");
1177         r = buxtond_handle_message(&daemon, &cl, size);
1178         free(cl.data);
1179         fail_if(!r, "Failed to handle create group message");
1180
1181         s = read(client, buf, 4096);
1182         fail_if(s < 0, "Read from client failed");
1183         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1184         fail_if(csize != 1, "Failed to get correct response to create group");
1185         fail_if(msg != BUXTON_CONTROL_STATUS,
1186                 "Failed to get correct control type");
1187         fail_if(list[0].type != INT32,
1188                 "Failed to get correct indicator type");
1189         fail_if(list[0].store.d_int32 != 0,
1190                 "Failed to create group");
1191         fail_if(msgid != 1, "Failed to get correct message id");
1192
1193         free(list);
1194         cleanup_callbacks();
1195         close(client);
1196         hashmap_free(daemon.notify_mapping);
1197         buxton_direct_close(&daemon.buxton);
1198         buxton_array_free(&out_list1, NULL);
1199         buxton_array_free(&out_list2, NULL);
1200 }
1201 END_TEST
1202
1203 START_TEST(buxtond_handle_message_remove_group_check)
1204 {
1205         BuxtonDaemon daemon;
1206         BuxtonString slabel;
1207         size_t size;
1208         BuxtonData data1, data2;
1209         client_list_item cl;
1210         bool r;
1211         BuxtonData *list;
1212         BuxtonArray *out_list;
1213         BuxtonControlMessage msg;
1214         ssize_t csize;
1215         int client, server;
1216         ssize_t s;
1217         uint8_t buf[4096];
1218         uint32_t msgid;
1219
1220         setup_socket_pair(&client, &server);
1221         fail_if(fcntl(client, F_SETFL, O_NONBLOCK),
1222                 "Failed to set socket to non blocking");
1223         fail_if(fcntl(server, F_SETFL, O_NONBLOCK),
1224                 "Failed to set socket to non blocking");
1225
1226         out_list = buxton_array_new();
1227         fail_if(!out_list, "Failed to allocate list");
1228         cl.fd = server;
1229         slabel = buxton_string_pack("_");
1230         if (use_smack())
1231                 cl.smack_label = &slabel;
1232         else
1233                 cl.smack_label = NULL;
1234         cl.cred.uid = 1002;
1235         daemon.buxton.client.uid = 1001;
1236         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1237         fail_if(!buxton_direct_open(&daemon.buxton),
1238                 "Failed to open buxton direct connection");
1239         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1240         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1241
1242         data1.type = STRING;
1243         data1.store.d_string = buxton_string_pack("base");
1244         data2.type = STRING;
1245         data2.store.d_string = buxton_string_pack("tgroup");
1246         r = buxton_array_add(out_list, &data1);
1247         fail_if(!r, "Failed to add element to array");
1248         r = buxton_array_add(out_list, &data2);
1249         fail_if(!r, "Failed to add element to array");
1250
1251         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_REMOVE_GROUP, 0,
1252                                         out_list);
1253         fail_if(size == 0, "Failed to serialize message");
1254         r = buxtond_handle_message(&daemon, &cl, size);
1255         free(cl.data);
1256         fail_if(!r, "Failed to handle remove group message");
1257
1258         s = read(client, buf, 4096);
1259         fail_if(s < 0, "Read from client failed");
1260         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1261         fail_if(csize != 1, "Failed to get correct response to remove group");
1262         fail_if(msg != BUXTON_CONTROL_STATUS,
1263                 "Failed to get correct control type");
1264         fail_if(list[0].type != INT32,
1265                 "Failed to get correct indicator type");
1266         fail_if(list[0].store.d_int32 != 0,
1267                 "Failed to remove group");
1268         fail_if(msgid != 0, "Failed to get correct message id");
1269
1270         free(list);
1271         cleanup_callbacks();
1272         close(client);
1273         hashmap_free(daemon.notify_mapping);
1274         buxton_direct_close(&daemon.buxton);
1275         buxton_array_free(&out_list, NULL);
1276 }
1277 END_TEST
1278
1279 START_TEST(buxtond_handle_message_set_label_check)
1280 {
1281         BuxtonDaemon daemon;
1282         BuxtonString slabel;
1283         size_t size;
1284         BuxtonData data1, data2, data3;
1285         client_list_item cl;
1286         bool r;
1287         BuxtonData *list;
1288         BuxtonArray *out_list;
1289         BuxtonControlMessage msg;
1290         ssize_t csize;
1291         int client, server;
1292         ssize_t s;
1293         uint8_t buf[4096];
1294         uint32_t msgid;
1295
1296         setup_socket_pair(&client, &server);
1297         fail_if(fcntl(client, F_SETFL, O_NONBLOCK),
1298                 "Failed to set socket to non blocking");
1299         fail_if(fcntl(server, F_SETFL, O_NONBLOCK),
1300                 "Failed to set socket to non blocking");
1301
1302         out_list = buxton_array_new();
1303         fail_if(!out_list, "Failed to allocate list");
1304         cl.fd = server;
1305         slabel = buxton_string_pack("_");
1306         if (use_smack())
1307                 cl.smack_label = &slabel;
1308         else
1309                 cl.smack_label = NULL;
1310         cl.cred.uid = 1002;
1311         daemon.buxton.client.uid = 1001;
1312         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1313         fail_if(!buxton_direct_open(&daemon.buxton),
1314                 "Failed to open buxton direct connection");
1315         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1316         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1317
1318         data1.type = STRING;
1319         data1.store.d_string = buxton_string_pack("base");
1320         data2.type = STRING;
1321         data2.store.d_string = buxton_string_pack("daemon-check");
1322         data3.type = STRING;
1323         data3.store.d_string = buxton_string_pack("*");
1324         r = buxton_array_add(out_list, &data1);
1325         fail_if(!r, "Failed to add element to array");
1326         r = buxton_array_add(out_list, &data2);
1327         fail_if(!r, "Failed to add element to array");
1328         r = buxton_array_add(out_list, &data3);
1329         fail_if(!r, "Failed to add element to array");
1330
1331         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_SET_LABEL, 0,
1332                                         out_list);
1333         fail_if(size == 0, "Failed to serialize message");
1334         r = buxtond_handle_message(&daemon, &cl, size);
1335         free(cl.data);
1336         fail_if(!r, "Failed to handle set label message");
1337
1338         s = read(client, buf, 4096);
1339         fail_if(s < 0, "Read from client failed");
1340         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1341         fail_if(csize != 1, "Failed to get correct response to set label");
1342         fail_if(msg != BUXTON_CONTROL_STATUS,
1343                 "Failed to get correct control type");
1344         fail_if(list[0].type != INT32,
1345                 "Failed to get correct indicator type");
1346         fail_if(list[0].store.d_int32 != 0,
1347                 "Failed to set label");
1348         fail_if(msgid != 0, "Failed to get correct message id");
1349
1350         free(list);
1351         cleanup_callbacks();
1352         close(client);
1353         hashmap_free(daemon.notify_mapping);
1354         buxton_direct_close(&daemon.buxton);
1355         buxton_array_free(&out_list, NULL);
1356 }
1357 END_TEST
1358
1359 START_TEST(buxtond_handle_message_set_value_check)
1360 {
1361         BuxtonDaemon daemon;
1362         BuxtonString slabel;
1363         size_t size;
1364         BuxtonData data1, data2, data3, data4;
1365         client_list_item cl;
1366         bool r;
1367         BuxtonData *list;
1368         BuxtonArray *out_list;
1369         BuxtonControlMessage msg;
1370         ssize_t csize;
1371         int client, server;
1372         ssize_t s;
1373         uint8_t buf[4096];
1374         uint32_t msgid;
1375
1376         setup_socket_pair(&client, &server);
1377         fail_if(fcntl(client, F_SETFL, O_NONBLOCK),
1378                 "Failed to set socket to non blocking");
1379         fail_if(fcntl(server, F_SETFL, O_NONBLOCK),
1380                 "Failed to set socket to non blocking");
1381
1382         out_list = buxton_array_new();
1383         fail_if(!out_list, "Failed to allocate list");
1384         cl.fd = server;
1385         slabel = buxton_string_pack("_");
1386         if (use_smack())
1387                 cl.smack_label = &slabel;
1388         else
1389                 cl.smack_label = NULL;
1390         cl.cred.uid = 1002;
1391         daemon.buxton.client.uid = 1001;
1392         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1393         fail_if(!buxton_direct_open(&daemon.buxton),
1394                 "Failed to open buxton direct connection");
1395         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1396         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1397
1398         data1.type = STRING;
1399         data1.store.d_string = buxton_string_pack("base");
1400         data2.type = STRING;
1401         data2.store.d_string = buxton_string_pack("daemon-check");
1402         data3.type = STRING;
1403         data3.store.d_string = buxton_string_pack("name");
1404         data4.type = STRING;
1405         data4.store.d_string = buxton_string_pack("bxt_test_value3");
1406         r = buxton_array_add(out_list, &data1);
1407         fail_if(!r, "Failed to add element to array");
1408         r = buxton_array_add(out_list, &data2);
1409         fail_if(!r, "Failed to add element to array");
1410         r = buxton_array_add(out_list, &data3);
1411         fail_if(!r, "Failed to add element to array");
1412         r = buxton_array_add(out_list, &data4);
1413         fail_if(!r, "Failed to add element to array");
1414         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_NOTIFY, 0,
1415                                         out_list);
1416         fail_if(size == 0, "Failed to serialize message");
1417         r = buxtond_handle_message(&daemon, &cl, size);
1418         free(cl.data);
1419         fail_if(r, "Failed to detect parse_list failure");
1420
1421         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_SET, 0,
1422                                         out_list);
1423         fail_if(size == 0, "Failed to serialize message");
1424         r = buxtond_handle_message(&daemon, &cl, size);
1425         free(cl.data);
1426         fail_if(!r, "Failed to handle set message");
1427
1428         s = read(client, buf, 4096);
1429         fail_if(s < 0, "Read from client failed");
1430         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1431         fail_if(csize != 1, "Failed to get correct response to set");
1432         fail_if(msg != BUXTON_CONTROL_STATUS,
1433                 "Failed to get correct control type");
1434         fail_if(list[0].type != INT32,
1435                 "Failed to get correct indicator type");
1436         fail_if(list[0].store.d_int32 != 0,
1437                 "Failed to set");
1438         fail_if(msgid != 0, "Failed to get correct message id");
1439
1440         free(list);
1441         cleanup_callbacks();
1442         close(client);
1443         hashmap_free(daemon.notify_mapping);
1444         buxton_direct_close(&daemon.buxton);
1445         buxton_array_free(&out_list, NULL);
1446 }
1447 END_TEST
1448
1449 START_TEST(buxtond_handle_message_get_check)
1450 {
1451         int client, server;
1452         BuxtonDaemon daemon;
1453         BuxtonString slabel;
1454         size_t size;
1455         BuxtonData data1, data2, data3, data4;
1456         client_list_item cl;
1457         bool r;
1458         BuxtonData *list;
1459         BuxtonArray *out_list;
1460         BuxtonArray *out_list2;
1461         BuxtonControlMessage msg;
1462         ssize_t csize;
1463         ssize_t s;
1464         uint8_t buf[4096];
1465         uint32_t msgid;
1466
1467         setup_socket_pair(&client, &server);
1468         out_list = buxton_array_new();
1469         fail_if(!out_list, "Failed to allocate list");
1470
1471         cl.fd = server;
1472         slabel = buxton_string_pack("_");
1473         if (use_smack())
1474                 cl.smack_label = &slabel;
1475         else
1476                 cl.smack_label = NULL;
1477         cl.cred.uid = getuid();
1478         daemon.buxton.client.uid = 1001;
1479         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1480         fail_if(!buxton_direct_open(&daemon.buxton),
1481                 "Failed to open buxton direct connection");
1482
1483         data1.type = STRING;
1484         data1.store.d_string = buxton_string_pack("test-gdbm-user");
1485         data2.type = STRING;
1486         data2.store.d_string = buxton_string_pack("daemon-check");
1487         data3.type = STRING;
1488         data3.store.d_string = buxton_string_pack("name");
1489         data4.type = UINT32;
1490         data4.store.d_uint32 = STRING;
1491         r = buxton_array_add(out_list, &data1);
1492         fail_if(!r, "Failed to add element to array");
1493         r = buxton_array_add(out_list, &data2);
1494         fail_if(!r, "Failed to add element to array");
1495         r = buxton_array_add(out_list, &data3);
1496         fail_if(!r, "Failed to add element to array");
1497         r = buxton_array_add(out_list, &data4);
1498         fail_if(!r, "Failed to add element to array");
1499         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_GET, 0,
1500                                         out_list);
1501         fail_if(size == 0, "Failed to serialize message");
1502         r = buxtond_handle_message(&daemon, &cl, size);
1503         free(cl.data);
1504         fail_if(!r, "Failed to get message 1");
1505
1506         s = read(client, buf, 4096);
1507         fail_if(s < 0, "Read from client failed");
1508         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1509         fail_if(csize != 2, "Failed to get valid message from buffer");
1510         fail_if(msg != BUXTON_CONTROL_STATUS,
1511                 "Failed to get correct control type");
1512         fail_if(msgid != 0, "Failed to get correct message id");
1513         fail_if(list[0].type != INT32, "Failed to get correct response type");
1514         fail_if(list[0].store.d_int32 != 0,
1515                 "Failed to get value");
1516         fail_if(list[1].type != STRING, "Failed to get correct value type");
1517         fail_if(!streq(list[1].store.d_string.value, "user-layer-value"),
1518                 "Failed to get correct value");
1519
1520         free(list[1].store.d_string.value);
1521         free(list);
1522
1523         out_list2 = buxton_array_new();
1524         fail_if(!out_list2, "Failed to allocate list 2");
1525         r = buxton_array_add(out_list2, &data2);
1526         fail_if(!r, "Failed to add element to array 2");
1527         r = buxton_array_add(out_list2, &data3);
1528         fail_if(!r, "Failed to add element to array 2");
1529         r = buxton_array_add(out_list2, &data4);
1530         fail_if(!r, "Failed to add element to array 2");
1531         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_GET, 0,
1532                                         out_list2);
1533         fail_if(size == 0, "Failed to serialize message 2");
1534         r = buxtond_handle_message(&daemon, &cl, size);
1535         free(cl.data);
1536         fail_if(!r, "Failed to get message 2");
1537
1538         s = read(client, buf, 4096);
1539         fail_if(s < 0, "Read from client failed 2");
1540         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1541         fail_if(csize != 2, "Failed to get correct response to get 2");
1542         fail_if(msg != BUXTON_CONTROL_STATUS,
1543                 "Failed to get correct control type 2");
1544         fail_if(msgid != 0, "Failed to get correct message id 2");
1545         fail_if(list[0].type != INT32, "Failed to get correct response type 2");
1546         fail_if(list[0].store.d_int32 != 0,
1547                 "Failed to get value 2");
1548         fail_if(list[1].type != STRING, "Failed to get correct value type 2");
1549         fail_if(streq(list[1].store.d_string.value, "bxt_test_value2"),
1550                 "Failed to get correct value 2");
1551
1552         free(list[1].store.d_string.value);
1553         free(list);
1554         close(client);
1555         buxton_direct_close(&daemon.buxton);
1556         buxton_array_free(&out_list, NULL);
1557         buxton_array_free(&out_list2, NULL);
1558 }
1559 END_TEST
1560
1561 START_TEST(buxtond_handle_message_notify_check)
1562 {
1563         int client, server;
1564         BuxtonDaemon daemon;
1565         BuxtonString slabel;
1566         size_t size;
1567         BuxtonData data1, data2, data3;
1568         client_list_item cl;
1569         bool r;
1570         BuxtonData *list;
1571         BuxtonArray *out_list;
1572         BuxtonControlMessage msg;
1573         ssize_t csize;
1574         ssize_t s;
1575         uint8_t buf[4096];
1576         uint32_t msgid;
1577
1578         setup_socket_pair(&client, &server);
1579         out_list = buxton_array_new();
1580         fail_if(!out_list, "Failed to allocate list");
1581
1582         cl.fd = server;
1583         slabel = buxton_string_pack("_");
1584         if (use_smack())
1585                 cl.smack_label = &slabel;
1586         else
1587                 cl.smack_label = NULL;
1588         cl.cred.uid = 1002;
1589         daemon.buxton.client.uid = 1001;
1590         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1591         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1592         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1593         fail_if(!buxton_direct_open(&daemon.buxton),
1594                 "Failed to open buxton direct connection");
1595
1596         data1.type = STRING;
1597         data1.store.d_string = buxton_string_pack("group");
1598         data2.type = STRING;
1599         data2.store.d_string = buxton_string_pack("name");
1600         data3.type = UINT32;
1601         data3.store.d_uint32 = STRING;
1602         r = buxton_array_add(out_list, &data1);
1603         fail_if(!r, "Failed to add element to array");
1604         r = buxton_array_add(out_list, &data2);
1605         fail_if(!r, "Failed to add element to array");
1606         r = buxton_array_add(out_list, &data3);
1607         fail_if(!r, "Failed to add element to array");
1608         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_NOTIFY, 0,
1609                                         out_list);
1610         fail_if(size == 0, "Failed to serialize message");
1611         r = buxtond_handle_message(&daemon, &cl, size);
1612         free(cl.data);
1613         fail_if(!r, "Failed to register for notification");
1614
1615         s = read(client, buf, 4096);
1616         fail_if(s < 0, "Read from client failed");
1617         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1618         fail_if(csize != 1, "Failed to get correct response to notify");
1619         fail_if(msg != BUXTON_CONTROL_STATUS,
1620                 "Failed to get correct control type");
1621         fail_if(msgid != 0, "Failed to get correct notify message id");
1622         fail_if(list[0].type != INT32, "Failed to get correct response type");
1623         fail_if(list[0].store.d_int32 != 0,
1624                 "Failed to register notification");
1625
1626         free(list);
1627
1628         /* UNNOTIFY */
1629         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_UNNOTIFY, 0,
1630                                         out_list);
1631         fail_if(size == 0, "Failed to serialize message");
1632         r = buxtond_handle_message(&daemon, &cl, size);
1633         free(cl.data);
1634         fail_if(!r, "Failed to unregister from notification");
1635
1636         s = read(client, buf, 4096);
1637         fail_if(s < 0, "Read from client failed 2");
1638         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1639         fail_if(csize != 2, "Failed to get correct response to unnotify");
1640         fail_if(msg != BUXTON_CONTROL_STATUS,
1641                 "Failed to get correct control type 2");
1642         fail_if(list[0].type != INT32,
1643                 "Failed to get correct indicator type 2");
1644         fail_if(list[0].store.d_int32 != 0,
1645                 "Failed to unregister for notification");
1646         fail_if(list[1].type != UINT32,
1647                 "Failed to get correct unnotify message id type");
1648         fail_if(list[1].store.d_uint32 != 0,
1649                 "Failed to get correct unnotify message id");
1650         fail_if(msgid != 0, "Failed to get correct message id 2");
1651
1652         free(list);
1653         close(client);
1654         hashmap_free(daemon.notify_mapping);
1655         buxton_direct_close(&daemon.buxton);
1656         buxton_array_free(&out_list, NULL);
1657 }
1658 END_TEST
1659
1660 START_TEST(buxtond_handle_message_unset_check)
1661 {
1662         int client, server;
1663         BuxtonDaemon daemon;
1664         BuxtonString slabel;
1665         size_t size;
1666         BuxtonData data1, data2, data3, data4;
1667         client_list_item cl;
1668         bool r;
1669         BuxtonData *list;
1670         BuxtonArray *out_list;
1671         BuxtonControlMessage msg;
1672         ssize_t csize;
1673         ssize_t s;
1674         uint8_t buf[4096];
1675         uint32_t msgid;
1676
1677         setup_socket_pair(&client, &server);
1678         out_list = buxton_array_new();
1679         fail_if(!out_list, "Failed to allocate list");
1680
1681         cl.fd = server;
1682         slabel = buxton_string_pack("_");
1683         if (use_smack())
1684                 cl.smack_label = &slabel;
1685         else
1686                 cl.smack_label = NULL;
1687         cl.cred.uid = 1002;
1688         daemon.buxton.client.uid = 1001;
1689         fail_if(!buxton_cache_smack_rules(), "Failed to cache Smack rules");
1690         fail_if(!buxton_direct_open(&daemon.buxton),
1691                 "Failed to open buxton direct connection");
1692         daemon.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
1693         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1694
1695         data1.type = STRING;
1696         data1.store.d_string = buxton_string_pack("base");
1697         data2.type = STRING;
1698         data2.store.d_string = buxton_string_pack("daemon-check");
1699         data3.type = STRING;
1700         data3.store.d_string = buxton_string_pack("name");
1701         data4.type = UINT32;
1702         data4.store.d_uint32 = STRING;
1703         r = buxton_array_add(out_list, &data1);
1704         fail_if(!r, "Failed to add element to array");
1705         r = buxton_array_add(out_list, &data2);
1706         fail_if(!r, "Failed to add element to array");
1707         r = buxton_array_add(out_list, &data3);
1708         fail_if(!r, "Failed to add element to array");
1709         r = buxton_array_add(out_list, &data4);
1710         fail_if(!r, "Failed to add element to array");
1711         size = buxton_serialize_message(&cl.data, BUXTON_CONTROL_UNSET, 0,
1712                                         out_list);
1713         fail_if(size == 0, "Failed to serialize message");
1714         r = buxtond_handle_message(&daemon, &cl, size);
1715         free(cl.data);
1716         fail_if(!r, "Failed to unset message");
1717
1718         s = read(client, buf, 4096);
1719         fail_if(s < 0, "Read from client failed");
1720         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1721         fail_if(csize != 1, "Failed to get correct response to unset");
1722         fail_if(msg != BUXTON_CONTROL_STATUS,
1723                 "Failed to get correct control type");
1724         fail_if(list[0].type != INT32,
1725                 "Failed to get correct indicator type");
1726         fail_if(list[0].store.d_int32 != 0,
1727                 "Failed to unset");
1728         fail_if(msgid != 0, "Failed to get correct message id");
1729
1730         free(list);
1731         close(client);
1732         hashmap_free(daemon.notify_mapping);
1733         buxton_direct_close(&daemon.buxton);
1734         buxton_array_free(&out_list, NULL);
1735 }
1736 END_TEST
1737
1738 START_TEST(buxtond_notify_clients_check)
1739 {
1740         int client, server;
1741         BuxtonDaemon daemon;
1742         _BuxtonKey key;
1743         BuxtonString slabel;
1744         BuxtonData value1, value2;
1745         client_list_item cl;
1746         int32_t status;
1747         bool r;
1748         BuxtonData *list;
1749         BuxtonControlMessage msg;
1750         ssize_t csize;
1751         ssize_t s;
1752         uint8_t buf[4096];
1753         uint32_t msgid;
1754
1755         setup_socket_pair(&client, &server);
1756
1757         cl.fd = server;
1758         slabel = buxton_string_pack("_");
1759         if (use_smack())
1760                 cl.smack_label = &slabel;
1761         else
1762                 cl.smack_label = NULL;
1763         cl.cred.uid = 1002;
1764         daemon.notify_mapping = hashmap_new(string_hash_func,
1765                                             string_compare_func);
1766         fail_if(!daemon.notify_mapping, "Failed to allocate hashmap");
1767         fail_if(!buxton_cache_smack_rules(),
1768                 "Failed to cache Smack rules");
1769         fail_if(!buxton_direct_open(&daemon.buxton),
1770                 "Failed to open buxton direct connection");
1771
1772         value1.type = STRING;
1773         value1.store.d_string = buxton_string_pack("dummy value");
1774         key.group = buxton_string_pack("dummy");
1775         key.name = buxton_string_pack("name");
1776         buxtond_notify_clients(&daemon, &cl, &key, &value1);
1777
1778         value1.store.d_string = buxton_string_pack("real value");
1779         key.group = buxton_string_pack("daemon-check");
1780         key.name = buxton_string_pack("name");
1781         key.layer = buxton_string_pack("base");
1782         key.type = STRING;
1783         r = buxton_direct_set_value(&daemon.buxton, &key,
1784                                     &value1, NULL);
1785         fail_if(!r, "Failed to set value for notify");
1786         register_notification(&daemon, &cl, &key, 0, &status);
1787         fail_if(status != 0,
1788                 "Failed to register notification for notify");
1789         buxtond_notify_clients(&daemon, &cl, &key, &value1);
1790
1791         value2.type = STRING;
1792         value2.store.d_string = buxton_string_pack("new value");
1793         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1794
1795         s = read(client, buf, 4096);
1796         fail_if(s < 0, "Read from client failed");
1797         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1798         fail_if(csize != 1,
1799                 "Failed to get correct response to notify string");
1800         fail_if(msg != BUXTON_CONTROL_CHANGED,
1801                 "Failed to get correct control type");
1802         fail_if(msgid != 0, "Failed to get correct message id");
1803         fail_if(list[0].type != STRING,
1804                 "Failed to get correct notification value type string");
1805         fail_if(!streq(list[0].store.d_string.value, "new value"),
1806                 "Failed to get correct notification value data string");
1807
1808         free(list[0].store.d_string.value);
1809         free(list);
1810
1811         key.group = buxton_string_pack("group");
1812         key.name.value = NULL;
1813         key.name.length = 0;
1814         r = buxton_direct_create_group(&daemon.buxton, &key, NULL);
1815         fail_if(!r, "Unable to create group");
1816         r = buxton_direct_set_label(&daemon.buxton, &key, &slabel);
1817         fail_if(!r, "Unable set group label");
1818
1819         value1.type = INT32;
1820         value1.store.d_int32 = 1;
1821         value2.type = INT32;
1822         value2.store.d_int32 = 2;
1823         key.group = buxton_string_pack("group");
1824         key.name = buxton_string_pack("name32");
1825         key.type = INT32;
1826         r = buxton_direct_set_value(&daemon.buxton, &key,
1827                                     &value1, NULL);
1828         fail_if(!r, "Failed to set value for notify");
1829         register_notification(&daemon, &cl, &key, 0, &status);
1830         fail_if(status != 0,
1831                 "Failed to register notification for notify");
1832         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1833
1834         s = read(client, buf, 4096);
1835         fail_if(s < 0, "Read from client failed");
1836         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1837         fail_if(csize != 1,
1838                 "Failed to get correct response to notify int32");
1839         fail_if(msg != BUXTON_CONTROL_CHANGED,
1840                 "Failed to get correct control type");
1841         fail_if(msgid != 0, "Failed to get correct message id");
1842         fail_if(list[0].type != INT32,
1843                 "Failed to get correct notification value type int32");
1844         fail_if(list[0].store.d_int32 != 2,
1845                 "Failed to get correct notification value data int32");
1846
1847         free(list);
1848
1849         value1.type = UINT32;
1850         value1.store.d_uint32 = 1;
1851         value2.type = UINT32;
1852         value2.store.d_uint32 = 2;
1853         key.group = buxton_string_pack("group");
1854         key.name = buxton_string_pack("nameu32");
1855         key.type = UINT32;
1856         r = buxton_direct_set_value(&daemon.buxton, &key,
1857                                     &value1, NULL);
1858         fail_if(!r, "Failed to set value for notify");
1859         register_notification(&daemon, &cl, &key, 0, &status);
1860         fail_if(status != 0,
1861                 "Failed to register notification for notify");
1862         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1863
1864         s = read(client, buf, 4096);
1865         fail_if(s < 0, "Read from client failed");
1866         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1867         fail_if(csize != 1,
1868                 "Failed to get correct response to notify uint32");
1869         fail_if(msg != BUXTON_CONTROL_CHANGED,
1870                 "Failed to get correct control type");
1871         fail_if(msgid != 0, "Failed to get correct message id");
1872         fail_if(list[0].type != UINT32,
1873                 "Failed to get correct notification value type uint32");
1874         fail_if(list[0].store.d_uint32 != 2,
1875                 "Failed to get correct notification value data uint32");
1876
1877         free(list);
1878
1879         value1.type = INT64;
1880         value1.store.d_int64 = 2;
1881         value2.type = INT64;
1882         value2.store.d_int64 = 3;
1883         key.group = buxton_string_pack("group");
1884         key.name = buxton_string_pack("name64");
1885         key.type = INT64;
1886         r = buxton_direct_set_value(&daemon.buxton, &key,
1887                                     &value1, NULL);
1888         fail_if(!r, "Failed to set value for notify");
1889         register_notification(&daemon, &cl, &key, 0, &status);
1890         fail_if(status != 0,
1891                 "Failed to register notification for notify");
1892         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1893
1894         s = read(client, buf, 4096);
1895         fail_if(s < 0, "Read from client failed");
1896         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1897         fail_if(csize != 1,
1898                 "Failed to get correct response to notify int64");
1899         fail_if(msg != BUXTON_CONTROL_CHANGED,
1900                 "Failed to get correct control type");
1901         fail_if(msgid != 0, "Failed to get correct message id");
1902         fail_if(list[0].type != INT64,
1903                 "Failed to get correct notification value type int 64");
1904         fail_if(list[0].store.d_int64 != 3,
1905                 "Failed to get correct notification value data int64");
1906
1907         free(list);
1908
1909         value1.type = UINT64;
1910         value1.store.d_uint64 = 2;
1911         value2.type = UINT64;
1912         value2.store.d_uint64 = 3;
1913         key.group = buxton_string_pack("group");
1914         key.name = buxton_string_pack("nameu64");
1915         key.type = UINT64;
1916         r = buxton_direct_set_value(&daemon.buxton, &key,
1917                                     &value1, NULL);
1918         fail_if(!r, "Failed to set value for notify");
1919         register_notification(&daemon, &cl, &key, 0, &status);
1920         fail_if(status != 0,
1921                 "Failed to register notification for notify");
1922         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1923
1924         s = read(client, buf, 4096);
1925         fail_if(s < 0, "Read from client failed");
1926         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1927         fail_if(csize != 1,
1928                 "Failed to get correct response to notify uint64");
1929         fail_if(msg != BUXTON_CONTROL_CHANGED,
1930                 "Failed to get correct control type");
1931         fail_if(msgid != 0, "Failed to get correct message id");
1932         fail_if(list[0].type != UINT64,
1933                 "Failed to get correct notification value type uint64");
1934         fail_if(list[0].store.d_uint64 != 3,
1935                 "Failed to get correct notification value data uint64");
1936
1937         free(list);
1938
1939         value1.type = FLOAT;
1940         value1.store.d_float = 3.1F;
1941         value2.type = FLOAT;
1942         value2.store.d_float = 3.14F;
1943         key.group = buxton_string_pack("group");
1944         key.name = buxton_string_pack("namef");
1945         key.type = FLOAT;
1946         r = buxton_direct_set_value(&daemon.buxton, &key,
1947                                     &value1, NULL);
1948         fail_if(!r, "Failed to set value for notify");
1949         register_notification(&daemon, &cl, &key, 0, &status);
1950         fail_if(status != 0,
1951                 "Failed to register notification for notify");
1952         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1953
1954         s = read(client, buf, 4096);
1955         fail_if(s < 0, "Read from client failed");
1956         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1957         fail_if(csize != 1,
1958                 "Failed to get correct response to notify float");
1959         fail_if(msg != BUXTON_CONTROL_CHANGED,
1960                 "Failed to get correct control type");
1961         fail_if(msgid != 0, "Failed to get correct message id");
1962         fail_if(list[0].type != FLOAT,
1963                 "Failed to get correct notification value type float");
1964         fail_if(list[0].store.d_float != 3.14F,
1965                 "Failed to get correct notification value data float");
1966
1967         free(list);
1968
1969         value1.type = DOUBLE;
1970         value1.store.d_double = 3.141F;
1971         value2.type = DOUBLE;
1972         value2.store.d_double = 3.1415F;
1973         key.group = buxton_string_pack("group");
1974         key.name = buxton_string_pack("named");
1975         key.type = DOUBLE;
1976         r = buxton_direct_set_value(&daemon.buxton, &key,
1977                                     &value1, NULL);
1978         fail_if(!r, "Failed to set value for notify");
1979         register_notification(&daemon, &cl, &key, 0, &status);
1980         fail_if(status != 0,
1981                 "Failed to register notification for notify");
1982         buxtond_notify_clients(&daemon, &cl, &key, &value2);
1983
1984         s = read(client, buf, 4096);
1985         fail_if(s < 0, "Read from client failed");
1986         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
1987         fail_if(csize != 1,
1988                 "Failed to get correct response to notify double");
1989         fail_if(msg != BUXTON_CONTROL_CHANGED,
1990                 "Failed to get correct control type");
1991         fail_if(msgid != 0, "Failed to get correct message id");
1992         fail_if(list[0].type != DOUBLE,
1993                 "Failed to get correct notification value type double");
1994         fail_if(list[0].store.d_double != 3.1415F,
1995                 "Failed to get correct notification value data double");
1996
1997         free(list);
1998
1999         value1.type = BOOLEAN;
2000         value1.store.d_boolean = false;
2001         value2.type = BOOLEAN;
2002         value2.store.d_int32 = true;
2003         key.group = buxton_string_pack("group");
2004         key.name = buxton_string_pack("nameb");
2005         key.type = BOOLEAN;
2006         r = buxton_direct_set_value(&daemon.buxton, &key,
2007                                     &value1, NULL);
2008         fail_if(!r, "Failed to set value for notify");
2009         register_notification(&daemon, &cl, &key, 0, &status);
2010         fail_if(status != 0,
2011                 "Failed to register notification for notify");
2012         buxtond_notify_clients(&daemon, &cl, &key, &value2);
2013
2014         s = read(client, buf, 4096);
2015         fail_if(s < 0, "Read from client failed");
2016         csize = buxton_deserialize_message(buf, &msg, (size_t)s, &msgid, &list);
2017         fail_if(csize != 1,
2018                 "Failed to get correct response to notify bool");
2019         fail_if(msg != BUXTON_CONTROL_CHANGED,
2020                 "Failed to get correct control type");
2021         fail_if(msgid != 0, "Failed to get correct message id");
2022         fail_if(list[0].type != BOOLEAN,
2023                 "Failed to get correct notification value type bool");
2024         fail_if(list[0].store.d_boolean != true,
2025                 "Failed to get correct notification value data bool");
2026
2027         free(list);
2028         close(client);
2029         buxton_direct_close(&daemon.buxton);
2030 }
2031 END_TEST
2032
2033 START_TEST(identify_client_check)
2034 {
2035         int sender;
2036         client_list_item client;
2037         bool r;
2038         int32_t msg = 5;
2039
2040         setup_socket_pair(&client.fd, &sender);
2041         r = identify_client(&client);
2042         fail_if(r, "Identified client without message");
2043
2044         write(sender, &msg, sizeof(int32_t));
2045         r = identify_client(&client);
2046         fail_if(!r, "Identify client failed");
2047
2048         close(client.fd);
2049         close(sender);
2050 }
2051 END_TEST
2052
2053 START_TEST(add_pollfd_check)
2054 {
2055         BuxtonDaemon daemon;
2056         int fd;
2057         short events;
2058         bool a;
2059
2060         fd = 3;
2061         daemon.nfds_alloc = 0;
2062         daemon.accepting_alloc = 0;
2063         daemon.nfds = 0;
2064         daemon.pollfds = NULL;
2065         daemon.accepting = NULL;
2066         events = 1;
2067         a = true;
2068         add_pollfd(&daemon, fd, events, a);
2069         fail_if(daemon.nfds != 1, "Failed to increase nfds");
2070         fail_if(daemon.pollfds[0].fd != fd, "Failed to set pollfd");
2071         fail_if(daemon.pollfds[0].events != events, "Failed to set events");
2072         fail_if(daemon.pollfds[0].revents != 0, "Failed to set revents");
2073         fail_if(daemon.accepting[0] != a, "Failed to set accepting status");
2074         free(daemon.pollfds);
2075         free(daemon.accepting);
2076 }
2077 END_TEST
2078
2079 START_TEST(del_pollfd_check)
2080 {
2081         BuxtonDaemon daemon;
2082         int fd;
2083         short events;
2084         bool a;
2085
2086         fd = 3;
2087         daemon.nfds_alloc = 0;
2088         daemon.accepting_alloc = 0;
2089         daemon.nfds = 0;
2090         daemon.pollfds = NULL;
2091         daemon.accepting = NULL;
2092         events = 1;
2093         a = true;
2094         add_pollfd(&daemon, fd, events, a);
2095         fail_if(daemon.nfds != 1, "Failed to add pollfd");
2096         del_pollfd(&daemon, 0);
2097         fail_if(daemon.nfds != 0, "Failed to decrease nfds 1");
2098
2099         fd = 4;
2100         events = 2;
2101         a = false;
2102         add_pollfd(&daemon, fd, events, a);
2103         fail_if(daemon.nfds != 1, "Failed to increase nfds after del");
2104         fail_if(daemon.pollfds[0].fd != fd, "Failed to set pollfd after del");
2105         fail_if(daemon.pollfds[0].events != events,
2106                 "Failed to set events after del");
2107         fail_if(daemon.pollfds[0].revents != 0,
2108                 "Failed to set revents after del");
2109         fail_if(daemon.accepting[0] != a,
2110                 "Failed to set accepting status after del");
2111         fd = 5;
2112         events = 3;
2113         a = true;
2114         add_pollfd(&daemon, fd, events, a);
2115         del_pollfd(&daemon, 0);
2116         fail_if(daemon.nfds != 1, "Failed to delete fd 2");
2117         fail_if(daemon.pollfds[0].fd != fd, "Failed to set pollfd after del2");
2118         fail_if(daemon.pollfds[0].events != events,
2119                 "Failed to set events after del2");
2120         fail_if(daemon.pollfds[0].revents != 0,
2121                 "Failed to set revents after del2");
2122         fail_if(daemon.accepting[0] != a,
2123                 "Failed to set accepting status after del2");
2124 }
2125 END_TEST
2126
2127 START_TEST(handle_smack_label_check)
2128 {
2129         client_list_item client;
2130         int server;
2131
2132         setup_socket_pair(&client.fd, &server);
2133         handle_smack_label(&client);
2134
2135         close(client.fd);
2136         close(server);
2137 }
2138 END_TEST
2139
2140 START_TEST(terminate_client_check)
2141 {
2142         client_list_item *client;
2143         BuxtonDaemon daemon;
2144         int dummy;
2145
2146         client = malloc0(sizeof(client_list_item));
2147         fail_if(!client, "client malloc failed");
2148         client->smack_label = malloc0(sizeof(BuxtonString));
2149         fail_if(!client->smack_label, "smack label malloc failed");
2150         daemon.client_list = client;
2151         setup_socket_pair(&client->fd, &dummy);
2152         daemon.nfds_alloc = 0;
2153         daemon.accepting_alloc = 0;
2154         daemon.nfds = 0;
2155         daemon.pollfds = NULL;
2156         daemon.accepting = NULL;
2157         add_pollfd(&daemon, client->fd, 2, false);
2158         fail_if(daemon.nfds != 1, "Failed to add pollfd");
2159         client->smack_label->value = strdup("dummy");
2160         client->smack_label->length = 6;
2161         fail_if(!client->smack_label->value, "label strdup failed");
2162
2163         terminate_client(&daemon, client, 0);
2164         fail_if(daemon.client_list, "Failed to set client list item to NULL");
2165         close(dummy);
2166 }
2167 END_TEST
2168
2169 START_TEST(handle_client_check)
2170 {
2171         BuxtonDaemon daemon;
2172         int dummy;
2173         uint8_t buf[4096];
2174         uint8_t *message = NULL;
2175         BuxtonData data1, data2, data3, data4;
2176         BuxtonArray *list = NULL;
2177         bool r;
2178         size_t ret;
2179         uint32_t bsize;
2180
2181         list = buxton_array_new();
2182         data1.type = STRING;
2183         data1.store.d_string = buxton_string_pack("test-gdbm-user");
2184         data2.type = STRING;
2185         data2.store.d_string = buxton_string_pack("daemon-check");
2186         data3.type = STRING;
2187         data3.store.d_string = buxton_string_pack("name");
2188         data4.type = UINT32;
2189         data4.store.d_uint32 = STRING;
2190         r = buxton_array_add(list, &data1);
2191         fail_if(!r, "Failed to add data to array");
2192         r = buxton_array_add(list, &data2);
2193         fail_if(!r, "Failed to add data to array");
2194         r = buxton_array_add(list, &data3);
2195         fail_if(!r, "Failed to add data to array");
2196         r = buxton_array_add(list, &data4);
2197         fail_if(!r, "Failed to add data to array");
2198         ret = buxton_serialize_message(&message, BUXTON_CONTROL_GET, 0, list);
2199         fail_if(ret == 0, "Failed to serialize string data");
2200         daemon.client_list = malloc0(sizeof(client_list_item));
2201         fail_if(!daemon.client_list, "client malloc failed");
2202         setup_socket_pair(&daemon.client_list->fd, &dummy);
2203         fcntl(daemon.client_list->fd, F_SETFL, O_NONBLOCK);
2204         daemon.nfds_alloc = 0;
2205         daemon.accepting_alloc = 0;
2206         daemon.nfds = 0;
2207         daemon.pollfds = NULL;
2208         daemon.accepting = NULL;
2209         add_pollfd(&daemon, daemon.client_list->fd, 2, false);
2210         fail_if(daemon.nfds != 1, "Failed to add pollfd 1");
2211         fail_if(handle_client(&daemon, daemon.client_list, 0), "More data available 1");
2212         fail_if(daemon.client_list, "Failed to terminate client with no data");
2213         close(dummy);
2214
2215         daemon.client_list = malloc0(sizeof(client_list_item));
2216         fail_if(!daemon.client_list, "client malloc failed");
2217         setup_socket_pair(&daemon.client_list->fd, &dummy);
2218         fcntl(daemon.client_list->fd, F_SETFL, O_NONBLOCK);
2219         add_pollfd(&daemon, daemon.client_list->fd, 2, false);
2220         fail_if(daemon.nfds != 1, "Failed to add pollfd 2");
2221         write(dummy, buf, 1);
2222         fail_if(handle_client(&daemon, daemon.client_list, 0), "More data available 2");
2223         fail_if(!daemon.client_list, "Terminated client with insufficient data");
2224         fail_if(daemon.client_list->data, "Didn't clean up left over client data 1");
2225
2226         bsize = 0;
2227         memcpy(message + BUXTON_LENGTH_OFFSET, &bsize, sizeof(uint32_t));
2228         write(dummy, message, BUXTON_MESSAGE_HEADER_LENGTH);
2229         fail_if(handle_client(&daemon, daemon.client_list, 0), "More data available 3");
2230         fail_if(daemon.client_list, "Failed to terminate client with bad size 1");
2231         close(dummy);
2232
2233         daemon.client_list = malloc0(sizeof(client_list_item));
2234         fail_if(!daemon.client_list, "client malloc failed");
2235         setup_socket_pair(&daemon.client_list->fd, &dummy);
2236         fcntl(daemon.client_list->fd, F_SETFL, O_NONBLOCK);
2237         add_pollfd(&daemon, daemon.client_list->fd, 2, false);
2238         fail_if(daemon.nfds != 1, "Failed to add pollfd 3");
2239         bsize = BUXTON_MESSAGE_MAX_LENGTH + 1;
2240         memcpy(message + BUXTON_LENGTH_OFFSET, &bsize, sizeof(uint32_t));
2241         write(dummy, message, BUXTON_MESSAGE_HEADER_LENGTH);
2242         fail_if(handle_client(&daemon, daemon.client_list, 0), "More data available 4");
2243         fail_if(daemon.client_list, "Failed to terminate client with bad size 2");
2244         close(dummy);
2245
2246         daemon.client_list = malloc0(sizeof(client_list_item));
2247         fail_if(!daemon.client_list, "client malloc failed");
2248         setup_socket_pair(&daemon.client_list->fd, &dummy);
2249         fcntl(daemon.client_list->fd, F_SETFL, O_NONBLOCK);
2250         add_pollfd(&daemon, daemon.client_list->fd, 2, false);
2251         fail_if(daemon.nfds != 1, "Failed to add pollfd 4");
2252         bsize = (uint32_t)ret;
2253         memcpy(message + BUXTON_LENGTH_OFFSET, &bsize, sizeof(uint32_t));
2254         write(dummy, message, ret);
2255         fail_if(handle_client(&daemon, daemon.client_list, 0), "More data available 5");
2256         fail_if(!daemon.client_list, "Terminated client with correct data length");
2257
2258         for (int i = 0; i < 33; i++) {
2259                 write(dummy, message, ret);
2260         }
2261         fail_if(!handle_client(&daemon, daemon.client_list, 0), "No more data available");
2262         fail_if(!daemon.client_list, "Terminated client with correct data length");
2263         terminate_client(&daemon, daemon.client_list, 0);
2264         fail_if(daemon.client_list, "Failed to remove client 1");
2265         close(dummy);
2266
2267         //FIXME add SIGPIPE handler
2268         /* daemon.client_list = malloc0(sizeof(client_list_item)); */
2269         /* fail_if(!daemon.client_list, "client malloc failed"); */
2270         /* setup_socket_pair(&daemon.client_list->fd, &dummy); */
2271         /* fcntl(daemon.client_list->fd, F_SETFL, O_NONBLOCK); */
2272         /* add_pollfd(&daemon, daemon.client_list->fd, 2, false); */
2273         /* fail_if(daemon.nfds != 1, "Failed to add pollfd 5"); */
2274         /* write(dummy, message, ret); */
2275         /* close(dummy); */
2276         /* fail_if(handle_client(&daemon, daemon.client_list, 0), "More data available 6"); */
2277         /* fail_if(daemon.client_list, "Failed to terminate client"); */
2278 }
2279 END_TEST
2280
2281 START_TEST(buxtond_eat_garbage_check)
2282 {
2283         daemon_pid = 0;
2284         sigset_t sigset;
2285         pid_t pid;
2286
2287         unlink(buxton_socket());
2288
2289         sigemptyset(&sigset);
2290         sigaddset(&sigset, SIGCHLD);
2291         sigprocmask(SIG_BLOCK, &sigset, NULL);
2292
2293         pid = fork();
2294         fail_if(pid < 0, "couldn't fork");
2295         if (pid) {              /* parent*/
2296                 BuxtonClient c;
2297                 FuzzContext fuzz;
2298                 time_t start;
2299                 bool keep_going = true;
2300                 int fd;
2301
2302
2303                 srand(0);
2304                 bzero(&fuzz, sizeof(FuzzContext));
2305
2306                 daemon_pid = pid;
2307                 usleep(250*1000);
2308                 check_did_not_crash(daemon_pid, &fuzz);
2309
2310
2311                 fail_if(time(&start) == -1, "call to time() failed");
2312                 do {
2313                         pid_t client;
2314                         ssize_t bytes;
2315                         time_t now;
2316
2317                         fail_if(time(&now) == -1, "call to time() failed");
2318                         if (now - start >= fuzz_time) {
2319                                 keep_going = false;
2320                         }
2321
2322                         fuzz.size = (unsigned int)rand() % 4096;
2323                         for (int i=0; i < fuzz.size; i++) {
2324                                 fuzz.buf[i] = (uint8_t)(rand() % 255);
2325                         }
2326                         if ((fuzz.size >= 6) && (rand() % 4096)) {
2327                                 uint16_t control = (uint16_t)((rand() % (BUXTON_CONTROL_MAX-1)) + 1);
2328
2329                                 /* magic */
2330                                 fuzz.buf[0] = 0x06;
2331                                 fuzz.buf[1] = 0x72;
2332
2333                                 /* valid message type */
2334                                 memcpy((void*)(fuzz.buf + 2), (void*)(&control), sizeof(uint16_t));
2335
2336                                 /* valid size */
2337                                 memcpy((void *)(fuzz.buf + 4), (void *)(&fuzz.size), sizeof(uint32_t));
2338                         }
2339                         client = fork();
2340                         fail_if(client == -1, "couldn't fork");
2341                         if (client == 0) {
2342                                 fd = buxton_open(&c);
2343                                 fail_if(fd == -1,
2344                                         "Open failed with daemon%s", dump_fuzz(&fuzz));
2345
2346
2347                                 bytes = write(fd, (void*)(fuzz.buf), fuzz.size);
2348                                 fail_if(bytes == -1, "write failed: %m%s", dump_fuzz(&fuzz));
2349                                 fail_unless(bytes == fuzz.size, "write was %d instead of %d", bytes, fuzz.size);
2350
2351                                 buxton_close(c);
2352                                 usleep(1*1000);
2353
2354                                 check_did_not_crash(daemon_pid, &fuzz);
2355                                 exit(0);
2356                         } else {
2357                                 int status;
2358                                 pid_t wait = waitpid(client, &status, 0);
2359                                 fail_if(wait == -1, "waitpid failed");
2360                                 fail_unless(WIFEXITED(status), "client died");
2361                                 fuzz.iteration++;
2362                         }
2363                 } while (keep_going);
2364         } else {                /* child */
2365                 exec_daemon();
2366         }
2367 }
2368 END_TEST
2369
2370 BuxtonClient c;
2371
2372 void cleanup(void)
2373 {
2374         //used to cleanup the helper groups, values, names that are needed by other fuzzed values/labels
2375
2376         fail_if(buxton_open(&c) == -1, "Cleanup: Open failed with daemon.");
2377
2378         BuxtonKey key = buxton_key_create("tempgroup", NULL, "base", STRING);
2379         fail_if(buxton_remove_group(c, key, NULL, "tempgroup", true), "Cleanup: Error at removing");
2380         buxton_key_free(key);
2381         buxton_close(c);
2382
2383 }
2384
2385 char *random_string(int str_size)
2386 {
2387         //generates random strings of maximum str_size characters
2388         //ignore this for now, it will be replaced by something more intelligent
2389
2390         int size;
2391         char *str;
2392
2393         size = rand() % str_size;
2394         str = calloc((size_t)(size + 1), sizeof(char));
2395
2396         for (int i = 0; i < size ; i++) {
2397                 str[i] = (char)(rand() % 255 + 1); //1-255, use % 25+97 to use lower-case alpha chars
2398         }
2399
2400         return str;
2401 }
2402
2403 static void SIGPIPE_handler(int signo)
2404 {
2405         buxton_close(c);
2406
2407         //reconnect
2408         fail_if(buxton_open(&c) == -1,"SIGPIPE: Open failed with daemon.");
2409 }
2410
2411 START_TEST(buxtond_fuzz_commands)
2412 {
2413 /*      Previous fuzzer had correct MAGIC, CONTROL code, Message SIZE and randomized everything else.
2414  *      This only randomizes the Data Value.
2415  *
2416  *      If you want to fuzz the protocol, use the above fuzzer.
2417  *      If you want to fuzz the daemon, use this one. Use export BUXTON_FUZZER=NEW
2418  */
2419
2420         daemon_pid = 0;
2421         pid_t pid;
2422         sigset_t sigset;
2423         struct sigaction sa;
2424         char *random_group, *random_layer, *random_label, *random_value, *random_name;
2425         int max_length = 32768;
2426         unlink(buxton_socket());
2427
2428         sigemptyset(&sigset);
2429         sigaddset(&sigset, SIGCHLD);
2430         sigprocmask(SIG_BLOCK, &sigset, NULL);
2431
2432         // since the daemon will close the connection with the client if it receives a "weird" command
2433         // we have to treat SIGPIPE
2434         memset(&sa, 0, sizeof(sa));
2435         sa.sa_handler = SIGPIPE_handler;
2436         sigaction(SIGPIPE, &sa, NULL);
2437
2438         printf("============== CAUTION!!! Fuzzer at work =================\n");
2439         FILE *f = fopen("debug_check_daemon.txt", "w");
2440         fclose(f);
2441
2442         pid = fork();
2443         fail_if(pid < 0, "couldn't fork");
2444         if (pid) {              /* parent*/
2445                 FuzzContext fuzz;
2446                 time_t start;
2447                 bool keep_going = true;
2448
2449                 srand((unsigned int) time(NULL));
2450                 bzero(&fuzz, sizeof(FuzzContext));
2451
2452                 usleep(250*1000); //wait for daemon to start
2453
2454                 fail_if(time(&start) == -1, "call to time() failed");
2455                 do {
2456                         BuxtonKey key = NULL;
2457                         time_t now;
2458
2459                         fail_if(time(&now) == -1, "call to time() failed");
2460                         if (now - start >= fuzz_time) {
2461                                 keep_going = false;
2462                         }
2463
2464                         cleanup();
2465
2466                         /* create a random group and layer */
2467                         random_group = random_string(max_length);
2468                         random_layer = random_string(max_length);
2469
2470                         key = buxton_key_create(random_group, NULL, random_layer, STRING);
2471                         fail_if(!key, "Failed to create key");
2472                         fail_if(buxton_open(&c) == -1, "Open failed with daemon.");
2473
2474                         f = fopen("debug_check_daemon.txt", "w");
2475                         fail_if(!f, "Unable to open file\n");
2476                         fprintf(f, "Create group: Group: %s\t Layer: %s\n", random_group, random_layer);
2477                         fflush(f);
2478
2479                         if (buxton_create_group(c, key, NULL, random_group, true)) {
2480                                 fprintf(f, "1: Group created!\n");
2481                         } else {
2482                                 fprintf(f, "1: Group was NOT created.\n");
2483                         }
2484                         fflush(f);
2485                         buxton_key_free(key);
2486
2487                         /* create a random group in an existing layer */
2488                         key = buxton_key_create(random_group, NULL, "base", STRING);
2489                         fail_if(!key, "Failed to create key");
2490                         fprintf(f, "Create group: Group: %s\t Layer: base\n", random_group);
2491                         fflush(f);
2492
2493                         if (buxton_create_group(c, key, NULL, random_group, true)) {
2494                                 fprintf(f, "1: Group created!\n");
2495                         } else {
2496                                 fprintf(f, "1: Group was NOT created.\n");
2497                         }
2498                         fflush(f);
2499                         buxton_key_free(key);
2500
2501                         // create a random name on random group on a random layer
2502                         random_name = random_string(max_length);
2503                         key = buxton_key_create(random_group, random_name, random_layer, STRING);
2504                         fail_if(!key, "Failed to create key");
2505
2506                         fprintf(f, "Create name: Group: %s\t Layer: %s\t Name:%s\n", random_group, random_layer, random_name);
2507                         fflush(f);
2508
2509                         if (buxton_create_group(c, key, NULL, random_group, true)) {
2510                                 fprintf(f, "2: Name created!\n");
2511                         } else {
2512                                 fprintf(f, "2: Name was NOT created.\n");
2513                         }
2514                         fflush(f);
2515                         buxton_key_free(key);
2516
2517                         // create a random name on existing group
2518                         // create group
2519                         key = buxton_key_create("tempgroup", NULL, "base", STRING);
2520                         fail_if(!key, "Failed to create key");
2521                         fail_if(buxton_create_group(c, key, NULL,"tempgroup", true), "Creating group in buxton failed.");
2522                         buxton_key_free(key);
2523
2524                         // put name on group
2525                         key = buxton_key_create("tempgroup", random_name, "base", STRING);
2526                         fail_if(!key, "Failed to create key");
2527                         fprintf(f, "Create name: Group: tempgroup\t Layer: base\t Name: %s\n", random_name);
2528
2529                         if (buxton_create_group(c, key, NULL, "tempgroup", true)) {
2530                                 fprintf(f, "2: Name created!\n");
2531                         } else {
2532                                 fprintf(f, "2: Name was NOT created.\n");
2533                         }
2534                         fflush(f);
2535                         buxton_key_free(key);
2536
2537                         // create a random value on a existing labeled group
2538                         //create the "existing" group, plus the name
2539                         random_value = random_string(max_length);
2540                         BuxtonKey group = buxton_key_create("tempgroup", NULL, "base", STRING);
2541                         fail_if(!group, "Failed to create key for group");
2542                         key = buxton_key_create("tempgroup", "name", "base", STRING);
2543                         fail_if(!key, "Failed to create key");
2544
2545                         // set the a correct label and randomized value
2546                         fprintf(f, "Set label: Group: tgroup\t Layer: base\t Value: %s\n", random_value);
2547                         fflush(f);
2548                         fail_if(buxton_set_label(c, group, "*", NULL, NULL, true), "Setting label in buxton failed.");
2549
2550                         if (buxton_set_value(c, key, random_value, NULL, "tgroup", true)) {
2551                                 fprintf(f, "3: Value was set!\n");
2552                         } else {
2553                                 fprintf(f, "3: Value was NOT set.\n");
2554                         }
2555                         fflush(f);
2556                         buxton_key_free(group);
2557                         buxton_key_free(key);
2558
2559                         //set a random label on an existing group
2560                         random_label = random_string(3);
2561                         group = buxton_key_create("tempgroup", NULL, "base", STRING);
2562                         fail_if(!group, "Failed to create key for group");
2563
2564                         fprintf(f, "Set label: Group: tempgroup\t Layer: base\t Label: %s\n", random_label);
2565                         if (buxton_set_label(c, group, random_label, NULL, group, true)) {
2566                                 fprintf(f, "3: Label was set!\n");
2567                         } else {
2568                                 fprintf(f, "3: Label was NOT set.\n");
2569                         }
2570                         fflush(f);
2571
2572                         //set random value/label on name
2573                         BuxtonKey name = buxton_key_create("tempgroup", "name", "base", STRING);
2574                         fail_if(!name, "Failed to create key for name");
2575
2576                         fprintf(f, "Set label and value: Group: tempgroup\t Layer: base\t Name: name\t Value: %s\t Label: %s \n", random_value, random_label);
2577                         if (buxton_set_value(c, name, random_value, NULL, NULL, true)) {
2578                                 fprintf(f, "4: Value on name was set!\n");
2579                         } else {
2580                                 fprintf(f, "4: Value on name  was NOT set.\n");
2581                         }
2582                         free(random_value);
2583                         fflush(f);
2584
2585                         if (buxton_set_label(c, name, random_label, NULL, name, true)) {
2586                                 fprintf(f, "4: Label on name was set!\n");
2587                         } else {
2588                                 fprintf(f, "4: Label on name was NOT set.\n");
2589                         }
2590                         fflush(f);
2591                         buxton_key_free(group);
2592                         buxton_key_free(name);
2593                         free(random_label);
2594
2595                         // remove name from group
2596                         key = buxton_key_create(random_group, random_name, random_layer, STRING);
2597                         fprintf(f, "Remove group: Group: %s\t Layer: %s\t Name:%s\n", random_group, random_layer, random_name);
2598                         if (buxton_remove_group(c, key, NULL, random_group, true)) {
2599                                 fprintf(f, "5: Name from group was removed!\n");
2600                         } else {
2601                                 fprintf(f, "5: Name from group was NOT removed.\n");
2602                         }
2603                         fflush(f);
2604                         buxton_key_free(key);
2605
2606                         // remove name from existing group
2607                         key = buxton_key_create("tempgroup", random_name, "base", STRING);
2608                         fprintf(f, "Remove group: Group: tempgroup\t Layer: base\t Name:%s\n", random_name);
2609                         if (buxton_remove_group(c, key, NULL, "tempgroup", true)) {
2610                                 fprintf(f, "5: Name from group was removed!\n");
2611                         } else {
2612                                 fprintf(f, "5: Name from group was NOT removed.\n");
2613                         }
2614                         fflush(f);
2615                         free(random_name);
2616                         buxton_key_free(key);
2617
2618                         /* remove group from existing layer*/
2619                         key = buxton_key_create(random_group, NULL, "base", STRING);
2620                         fail_if(!key, "Failed to create key");
2621                         fprintf(f, "Remove group: Group: %s\t Layer: base\n", random_group);
2622                         if (buxton_remove_group(c, key, NULL, random_group, true)) {
2623                                 fprintf(f, "5: Group was removed!\n");
2624                         } else {
2625                                 fprintf(f, "5: Group was NOT removed.\n");
2626                         }
2627                         fflush(f);
2628                         buxton_key_free(key);
2629
2630                         /* remove group */
2631                         key = buxton_key_create(random_group, NULL, random_layer, STRING);
2632                         fail_if(!key, "Failed to create key");
2633                         fprintf(f, "Remove group: Group: %s\t Layer: %s\n", random_group, random_layer);
2634                         if (buxton_remove_group(c, key, NULL, random_group, true)) {
2635                                 fprintf(f, "5: Group was removed!\n");
2636                         } else {
2637                                 fprintf(f, "5: Group was NOT removed.\n");
2638                         }
2639                         buxton_key_free(key);
2640                         fflush(f);
2641
2642                         buxton_close(c);
2643                         usleep(1*1000);
2644
2645                         fprintf(f, "5: Closed comm.\n");
2646                         fclose(f);
2647                         free(random_layer);
2648                         free(random_group);
2649
2650                         reap_callbacks();
2651                 } while (keep_going);
2652         } else {                /* child */
2653                 exec_daemon();
2654         }
2655
2656         usleep(3 * 1000);
2657         reap_callbacks();
2658 }
2659 END_TEST
2660
2661 static Suite *
2662 daemon_suite(void)
2663 {
2664         Suite *s;
2665         TCase *tc;
2666         char *fuzzer_engine;
2667
2668         s = suite_create("daemon");
2669         tc = tcase_create("daemon test functions");
2670         tcase_add_checked_fixture(tc, setup, teardown);
2671         tcase_add_test(tc, buxton_open_check);
2672         tcase_add_test(tc, buxton_create_group_check);
2673         tcase_add_test(tc, buxton_remove_group_check);
2674         tcase_add_test(tc, buxton_set_value_check);
2675         tcase_add_test(tc, buxton_set_label_check);
2676         tcase_add_test(tc, buxton_get_value_for_layer_check);
2677         tcase_add_test(tc, buxton_get_value_check);
2678         suite_add_tcase(s, tc);
2679
2680         tc = tcase_create("buxton_daemon_functions");
2681         tcase_add_test(tc, parse_list_check);
2682         tcase_add_test(tc, create_group_check);
2683         tcase_add_test(tc, remove_group_check);
2684         tcase_add_test(tc, set_label_check);
2685
2686         tcase_add_test(tc, set_value_check);
2687         tcase_add_test(tc, get_value_check);
2688         tcase_add_test(tc, register_notification_check);
2689         tcase_add_test(tc, buxtond_handle_message_error_check);
2690         tcase_add_test(tc, buxtond_handle_message_create_group_check);
2691         tcase_add_test(tc, buxtond_handle_message_remove_group_check);
2692         tcase_add_test(tc, buxtond_handle_message_set_label_check);
2693         tcase_add_test(tc, buxtond_handle_message_set_value_check);
2694         tcase_add_test(tc, buxtond_handle_message_get_check);
2695         tcase_add_test(tc, buxtond_handle_message_notify_check);
2696         tcase_add_test(tc, buxtond_handle_message_unset_check);
2697         tcase_add_test(tc, buxtond_notify_clients_check);
2698         tcase_add_test(tc, identify_client_check);
2699         tcase_add_test(tc, add_pollfd_check);
2700         tcase_add_test(tc, del_pollfd_check);
2701         tcase_add_test(tc, handle_smack_label_check);
2702         tcase_add_test(tc, terminate_client_check);
2703         tcase_add_test(tc, handle_client_check);
2704         suite_add_tcase(s, tc);
2705
2706         tc = tcase_create("buxton daemon evil tests");
2707         tcase_add_checked_fixture(tc, NULL, teardown);
2708         fuzzer_engine = getenv("BUXTON_FUZZER");
2709         if (fuzzer_engine) {
2710                 if (strcmp(fuzzer_engine,"NEW") == 0) {
2711                         tcase_add_test(tc, buxtond_fuzz_commands);
2712                 } else {
2713                         tcase_add_test(tc, buxtond_eat_garbage_check);
2714                 }
2715         } else {
2716                 tcase_add_test(tc, buxtond_eat_garbage_check);
2717         }
2718         tcase_set_timeout(tc, fuzz_time+2);
2719         suite_add_tcase(s, tc);
2720
2721         return s;
2722 }
2723
2724 int main(void)
2725 {
2726         int number_failed;
2727         Suite *s;
2728         SRunner *sr;
2729         char *fuzzenv;
2730
2731         putenv("BUXTON_CONF_FILE=" ABS_TOP_BUILDDIR "/test/test.conf");
2732         putenv("BUXTON_ROOT_CHECK=0");
2733         fuzzenv = getenv("BUXTON_FUZZ_TIME");
2734         if (fuzzenv) {
2735                 fuzz_time = atoi(fuzzenv);
2736         } else {
2737                 fuzz_time = 2;
2738         }
2739         s = daemon_suite();
2740         sr = srunner_create(s);
2741         srunner_run_all(sr, CK_VERBOSE);
2742         number_failed = srunner_ntests_failed(sr);
2743         srunner_free(sr);
2744
2745         return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
2746 }
2747
2748 /*
2749  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
2750  *
2751  * Local variables:
2752  * c-basic-offset: 8
2753  * tab-width: 8
2754  * indent-tabs-mode: t
2755  * End:
2756  *
2757  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2758  * :indentSize=8:tabSize=8:noTabs=false:
2759  */