hooks: Allow to remove hooking (and/or trace)
[src/app-framework-binder.git] / src / tests / apiset / test-apiset.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <errno.h>
5 #include <string.h>
6
7 #include <check.h>
8 #if !defined(ck_assert_ptr_null)
9 # define ck_assert_ptr_null(X)      ck_assert_ptr_eq(X, NULL)
10 # define ck_assert_ptr_nonnull(X)   ck_assert_ptr_ne(X, NULL)
11 #endif
12
13 #include "afb-api.h"
14 #include "afb-apiset.h"
15
16 const char *names[] = {
17         "Sadie",
18         "Milford",
19         "Yvette",
20         "Carma",
21         "Cory",
22         "Clarence",
23         "Jeffery",
24         "Molly",
25         "Sheba",
26         "Tasha",
27         "Corey",
28         "Gerry",
29         NULL
30 };
31
32 const char *aliases[] = {
33         "Rich",         "Molly",
34         "Alicia",       "Carma",
35         "Drema",        "YVETTE",
36         "Pablo",        "Sheba",
37         "Wendell",      "Sadie",
38         "Cathrine",     "CarMa",
39         "Allen",        "Corey",
40         "Tori",         "Drema",
41         NULL
42 };
43
44 const char *extras[] = {
45         "Meta",
46         "Delia",
47         "Pearlie",
48         "Hank",
49         "Vena",
50         "Terrance",
51         "Gloria",
52         "Tobi",
53         "Mack",
54         "Rosalee",
55         NULL
56 };
57
58 struct afb_api_itf api_itf_null = {
59         .call = NULL,
60         .service_start = NULL,
61 #if WITH_AFB_HOOK
62         .update_hooks = NULL,
63 #endif
64         .get_logmask = NULL,
65         .set_logmask = NULL,
66         .describe = NULL,
67         .unref = NULL
68 };
69
70
71 /*********************************************************************/
72 /* check the initialisation */
73 START_TEST (check_initialisation)
74 {
75         const char name[] = "name";
76         const char noname[] = "";
77         int to = 3600;
78         int noto = -1;
79         struct afb_apiset *a, *b;
80
81         a = afb_apiset_create(NULL, noto);
82         ck_assert_ptr_nonnull(a);
83         ck_assert_str_eq(noname, afb_apiset_name(a));
84         ck_assert_int_eq(noto, afb_apiset_timeout_get(a));
85         afb_apiset_timeout_set(a, to);
86         ck_assert_int_eq(to, afb_apiset_timeout_get(a));
87         b = afb_apiset_addref(a);
88         ck_assert_ptr_eq(a, b);
89         afb_apiset_unref(b);
90         afb_apiset_unref(a);
91
92         a = afb_apiset_create(name, to);
93         ck_assert_ptr_nonnull(a);
94         ck_assert_str_eq(name, afb_apiset_name(a));
95         ck_assert_int_eq(to, afb_apiset_timeout_get(a));
96         afb_apiset_timeout_set(a, noto);
97         ck_assert_int_eq(noto, afb_apiset_timeout_get(a));
98         b = afb_apiset_addref(a);
99         ck_assert_ptr_eq(a, b);
100         afb_apiset_unref(b);
101         afb_apiset_unref(a);
102 }
103 END_TEST
104
105 /*********************************************************************/
106 /* check that NULL is a valid value for addref/unref */
107 START_TEST (check_sanity)
108 {
109         struct afb_apiset *a;
110
111         a = afb_apiset_addref(NULL);
112         ck_assert_ptr_null(a);
113         afb_apiset_unref(NULL);
114         ck_assert(1);
115 }
116 END_TEST
117
118 /*********************************************************************/
119 /* check creation and retrieval of apis */
120
121 START_TEST (check_creation)
122 {
123         int i, j, nn, na;
124         struct afb_apiset *a;
125         struct afb_api_item sa;
126         const char *x, *y, **set;
127         const struct afb_api_item *pa;
128
129         /* create a apiset */
130         a = afb_apiset_create(NULL, 0);
131         ck_assert_ptr_nonnull(a);
132
133         /* add apis */
134         for (i = 0 ; names[i] != NULL ; i++) {
135                 sa.itf = &api_itf_null;
136                 sa.closure = (void*)names[i];
137                 sa.group = names[i];
138                 ck_assert_int_eq(0, afb_apiset_add(a, names[i], sa));
139                 pa = afb_apiset_lookup(a, names[i], 1);
140                 ck_assert_ptr_nonnull(pa);
141                 ck_assert_ptr_eq(sa.itf, pa->itf);
142                 ck_assert_ptr_eq(sa.closure, pa->closure);
143                 ck_assert_ptr_eq(sa.group, pa->group);
144                 ck_assert_int_eq(0, afb_apiset_is_alias(a, names[i]));
145                 ck_assert_str_eq(names[i], afb_apiset_unalias(a, names[i]));
146                 ck_assert_int_eq(-1, afb_apiset_add(a, names[i], sa));
147                 ck_assert_int_eq(errno, EEXIST);
148         }
149         nn = i;
150
151         /* add aliases */
152         for (i = 0 ; aliases[i] != NULL ; i += 2) {
153                 ck_assert_int_eq(-1, afb_apiset_add_alias(a, extras[0], aliases[i]));
154                 ck_assert_int_eq(errno, ENOENT);
155                 ck_assert_int_eq(0, afb_apiset_add_alias(a, aliases[i + 1], aliases[i]));
156                 ck_assert_ptr_nonnull(afb_apiset_lookup(a, aliases[i], 1));
157                 ck_assert_int_eq(1, afb_apiset_is_alias(a, aliases[i]));
158                 x = afb_apiset_unalias(a, aliases[i]);
159                 y = afb_apiset_unalias(a, aliases[i + 1]);
160                 ck_assert_int_eq(0, strcasecmp(x, y));
161                 ck_assert_int_eq(-1, afb_apiset_add_alias(a, aliases[i + 1], aliases[i]));
162                 ck_assert_int_eq(errno, EEXIST);
163         }
164         na = i / 2;
165
166         /* check extras */
167         for (i = 0 ; extras[i] != NULL ; i++) {
168                 pa = afb_apiset_lookup(a, extras[i], 1);
169                 ck_assert_ptr_null(pa);
170                 ck_assert_int_eq(errno, ENOENT);
171         }
172
173         /* get the names */
174         set = afb_apiset_get_names(a, 0, 1);
175         ck_assert_ptr_nonnull(set);
176         for (i = 0 ; set[i] != NULL ; i++) {
177                 ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[i], 0));
178                 ck_assert_int_eq(0, afb_apiset_is_alias(a, set[i]));
179                 if (i)
180                         ck_assert_int_gt(0, strcasecmp(set[i-1], set[i]));
181         }
182         ck_assert_int_eq(i, nn);
183         free(set);
184         set = afb_apiset_get_names(a, 0, 2);
185         ck_assert_ptr_nonnull(set);
186         for (i = 0 ; set[i] != NULL ; i++) {
187                 ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[i], 0));
188                 ck_assert_int_eq(1, afb_apiset_is_alias(a, set[i]));
189                 if (i)
190                         ck_assert_int_gt(0, strcasecmp(set[i-1], set[i]));
191         }
192         ck_assert_int_eq(i, na);
193         free(set);
194         set = afb_apiset_get_names(a, 0, 3);
195         ck_assert_ptr_nonnull(set);
196         for (i = 0 ; set[i] != NULL ; i++) {
197                 ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[i], 0));
198                 if (i)
199                         ck_assert_int_gt(0, strcasecmp(set[i-1], set[i]));
200         }
201         ck_assert_int_eq(i, nn + na);
202
203         /* removes the apis to check deletion */
204         for (i = 0 ; i < nn + na ; i++) {
205                 if (!set[i])
206                         continue;
207
208                 /* should be present */
209                 ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[i], 0));
210
211                 /* deleting a non aliased api removes the aliases! */
212                 if (!afb_apiset_is_alias(a, set[i])) {
213                         for (j = i + 1 ; j < nn + na ; j++) {
214                                 if (!set[j])
215                                         continue;
216                                 ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[j], 0));
217                                 if (afb_apiset_is_alias(a, set[j])
218                                  && afb_apiset_lookup(a, set[i], 0) == afb_apiset_lookup(a, set[j], 0)) {
219                                         ck_assert(set[j][0] > 0);
220                                         ((char*)set[j])[0] = (char)-set[j][0];
221                                 }
222                         }
223                 }
224
225                 /* delete now */
226                 ck_assert_int_eq(0, afb_apiset_del(a, set[i]));
227                 ck_assert_ptr_null(afb_apiset_lookup(a, set[i], 0));
228
229                 /* check other not removed except aliases */
230                 for (j = i + 1 ; j < nn + na ; j++) {
231                         if (!set[j])
232                                 continue;
233                         if (set[j][0] > 0)
234                                 ck_assert_ptr_nonnull(afb_apiset_lookup(a, set[j], 0));
235                         else {
236                                 ((char*)set[j])[0] = (char)-set[j][0];
237                                 ck_assert_ptr_null(afb_apiset_lookup(a, set[j], 0));
238                                 set[j] = NULL;
239                         }
240                 }
241         }
242         free(set);
243
244         afb_apiset_unref(a);
245 }
246 END_TEST
247
248 /*********************************************************************/
249 /* check onlack behaviour */
250
251 int onlackcount;
252
253 static void onlackcleanup(void *closure)
254 {
255         int *count = closure;
256         ck_assert_ptr_eq(count, &onlackcount);
257         *count = 0;
258 }
259 static int onlack(void *closure, struct afb_apiset *a, const char *name)
260 {
261         int *count = closure;
262         struct afb_api_item sa;
263
264         ck_assert_ptr_eq(count, &onlackcount);
265         (*count)++;
266
267         sa.itf = &api_itf_null;
268         sa.closure = (void*)name;
269         sa.group = name;
270
271         ck_assert_int_eq(0, afb_apiset_add(a, name, sa));
272         return 1;
273 }
274
275 START_TEST (check_onlack)
276 {
277         int i;
278         struct afb_apiset *a;
279         struct afb_api_item sa;
280         const char *x, *y;
281         const struct afb_api_item *pa;
282
283         /* create a apiset */
284         a = afb_apiset_create(NULL, 0);
285         ck_assert_ptr_nonnull(a);
286
287         /* add apis */
288         for (i = 0 ; names[i] != NULL ; i++) {
289                 sa.itf = &api_itf_null;
290                 sa.closure = (void*)names[i];
291                 sa.group = names[i];
292                 ck_assert_int_eq(0, afb_apiset_add(a, names[i], sa));
293                 pa = afb_apiset_lookup(a, names[i], 1);
294                 ck_assert_ptr_nonnull(pa);
295                 ck_assert_ptr_eq(sa.itf, pa->itf);
296                 ck_assert_ptr_eq(sa.closure, pa->closure);
297                 ck_assert_ptr_eq(sa.group, pa->group);
298                 ck_assert_int_eq(0, afb_apiset_is_alias(a, names[i]));
299                 ck_assert_str_eq(names[i], afb_apiset_unalias(a, names[i]));
300                 ck_assert_int_eq(-1, afb_apiset_add(a, names[i], sa));
301                 ck_assert_int_eq(errno, EEXIST);
302         }
303
304         /* add aliases */
305         for (i = 0 ; aliases[i] != NULL ; i += 2) {
306                 ck_assert_int_eq(-1, afb_apiset_add_alias(a, extras[0], aliases[i]));
307                 ck_assert_int_eq(errno, ENOENT);
308                 ck_assert_int_eq(0, afb_apiset_add_alias(a, aliases[i + 1], aliases[i]));
309                 ck_assert_ptr_nonnull(afb_apiset_lookup(a, aliases[i], 1));
310                 ck_assert_int_eq(1, afb_apiset_is_alias(a, aliases[i]));
311                 x = afb_apiset_unalias(a, aliases[i]);
312                 y = afb_apiset_unalias(a, aliases[i + 1]);
313                 ck_assert_int_eq(0, strcasecmp(x, y));
314                 ck_assert_int_eq(-1, afb_apiset_add_alias(a, aliases[i + 1], aliases[i]));
315                 ck_assert_int_eq(errno, EEXIST);
316         }
317
318         /* check extras */
319         for (i = 0 ; extras[i] != NULL ; i++) {
320                 pa = afb_apiset_lookup(a, extras[i], 1);
321                 ck_assert_ptr_null(pa);
322                 ck_assert_int_eq(errno, ENOENT);
323         }
324
325         /* put the onlack feature */
326         afb_apiset_onlack_set(a, onlack, &onlackcount, onlackcleanup);
327
328         /* check extras */
329         onlackcount = 0;
330         for (i = 0 ; extras[i] != NULL ; i++) {
331                 ck_assert_int_eq(onlackcount, i);
332                 pa = afb_apiset_lookup(a, extras[i], 1);
333                 ck_assert_int_eq(onlackcount, i + 1);
334                 ck_assert_ptr_nonnull(pa);
335                 ck_assert_ptr_eq(&api_itf_null, pa->itf);
336                 ck_assert_ptr_eq(extras[i], pa->closure);
337                 ck_assert_ptr_eq(extras[i], pa->group);
338         }
339
340         ck_assert_int_eq(onlackcount, i);
341         afb_apiset_unref(a);
342         ck_assert_int_eq(onlackcount, 0);
343 }
344 END_TEST
345
346 /*********************************************************************/
347
348 struct set_api {
349         const char *name;
350         int init;
351         int mask;
352 } set_apis[] = {
353         { "Sadie", 0, 0 },
354         { "Milford", 0, 0 },
355         { "Yvette", 0, 0 },
356         { "Carma", 0, 0 },
357         { "Cory", 0, 0 },
358         { "Clarence", 0, 0 },
359         { "Jeffery", 0, 0 },
360         { "Molly", 0, 0 },
361         { "Sheba", 0, 0 },
362         { "Tasha", 0, 0 },
363         { "Corey", 0, 0 },
364         { "Gerry", 0, 0 },
365         { NULL, 0, 0 }
366 };
367
368 int set_count;
369 struct set_api *set_last_api;
370
371 void set_cb0(void *closure)
372 {
373         set_last_api = closure;
374         set_count++;
375 }
376
377 void set_cb_setmask(void *closure, int mask)
378 {
379         set_cb0(closure);
380         set_last_api->mask = mask;
381 }
382
383 int set_cb_getmask(void *closure)
384 {
385         set_cb0(closure);
386         return set_last_api->mask;
387 }
388
389 int set_cb_start(void *closure)
390 {
391         set_cb0(closure);
392         ck_assert_int_eq(0, set_last_api->init);
393         set_last_api->init = 1;
394         return 0;
395 }
396
397 struct afb_api_itf set_api_itf = {
398         .call = NULL,
399         .service_start = set_cb_start,
400 #if WITH_AFB_HOOK
401         .update_hooks = set_cb0,
402 #endif
403         .get_logmask = set_cb_getmask,
404         .set_logmask = set_cb_setmask,
405         .describe = NULL,
406         .unref = set_cb0
407 };
408
409 START_TEST (check_settings)
410 {
411         int i, nn, mask;
412         struct afb_apiset *a;
413         struct afb_api_item sa;
414
415         /* create a apiset */
416         a = afb_apiset_create(NULL, 0);
417         ck_assert_ptr_nonnull(a);
418
419         /* add apis */
420         for (i = 0 ; set_apis[i].name != NULL ; i++) {
421                 sa.itf = &set_api_itf;
422                 sa.closure = &set_apis[i];
423                 sa.group = NULL;
424                 ck_assert_int_eq(0, afb_apiset_add(a, set_apis[i].name, sa));
425         }
426         nn = i;
427
428         set_count = 0;
429         afb_apiset_start_all_services(a);
430         ck_assert_int_eq(nn, set_count);
431
432         set_count = 0;
433 #if WITH_AFB_HOOK
434         afb_apiset_update_hooks(a, NULL);
435 #endif
436         ck_assert_int_eq(nn, set_count);
437
438         for (mask = 1 ; !(mask >> 10) ; mask <<= 1) {
439                 set_count = 0;
440                 afb_apiset_set_logmask(a, NULL, mask);
441                 ck_assert_int_eq(nn, set_count);
442                 set_count = 0;
443                 for (i = 0 ; set_apis[i].name != NULL ; i++) {
444                         ck_assert_int_eq(mask, afb_apiset_get_logmask(a, set_apis[i].name));
445                         ck_assert_ptr_eq(set_last_api, &set_apis[i]);
446                         ck_assert_int_eq(i + 1, set_count);
447                 }
448         }
449
450         set_count = 0;
451         afb_apiset_unref(a);
452         ck_assert_int_eq(nn, set_count);
453 }
454 END_TEST
455
456 /*********************************************************************/
457
458 struct clacl {
459         const char *name;
460         int count;
461 } clacl[] = {
462         { "Sadie", 0 },
463         { "Milford", 0 },
464         { "Yvette", 0 },
465 };
466
467 struct clapi {
468         const char *name;
469         const char *provides;
470         const char *requires;
471         const char *apireq;
472         int init;
473         int expect;
474 } clapi[] = {
475         { "Carma", "", "Sadie", "", 0, 9 },
476         { "Cory", "Milford", "", "Clarence", 0, 3 },
477         { "Clarence", "Milford", "", "Jeffery", 0, 2 },
478         { "Jeffery", "Milford", "", "", 0, 1 },
479         { "Molly", "Yvette", "", "Corey", 0, 6 },
480         { "Sheba", "Yvette", "Milford", "Molly", 0, 7 },
481         { "Tasha", "Sadie", "Yvette", "", 0, 8 },
482         { "Corey", "Sadie", "Milford", "Gerry", 0, 5 },
483         { "Gerry", "Sadie", "Milford", "", 0, 4 },
484         { NULL, NULL, NULL, NULL, 0, 0 }
485 };
486
487 int clorder;
488
489 int clacb_start(void *closure)
490 {
491         struct clapi *a = closure;
492         int i;
493
494         ck_assert_int_eq(0, a->init);
495
496         for (i = 0 ; clapi[i].name ; i++) {
497                 if (a->requires && a->requires[0]
498                 && clapi[i].provides && clapi[i].provides[0]
499                 && !strcmp(a->requires, clapi[i].provides))
500                         ck_assert_int_ne(0, clapi[i].init);
501                 if (a->apireq && a->apireq[0]
502                 && !strcmp(a->apireq, clapi[i].name))
503                         ck_assert_int_ne(0, clapi[i].init);
504         }
505         a->init = ++clorder;
506         ck_assert_int_eq(a->init, a->expect);
507
508         return 0;
509 }
510
511 struct afb_api_itf clitf = {
512         .call = NULL,
513         .service_start = clacb_start,
514 #if WITH_AFB_HOOK
515         .update_hooks = NULL,
516 #endif
517         .get_logmask = NULL,
518         .set_logmask = NULL,
519         .describe = NULL,
520         .unref = NULL
521 };
522
523 START_TEST (check_classes)
524 {
525         int i;
526         struct afb_apiset *a;
527         struct afb_api_item sa;
528
529         /* create a apiset */
530         a = afb_apiset_create(NULL, 0);
531         ck_assert_ptr_nonnull(a);
532
533         /* add apis */
534         for (i = 0 ; clapi[i].name != NULL ; i++) {
535                 sa.itf = &clitf;
536                 sa.closure = &clapi[i];
537                 sa.group = NULL;
538                 ck_assert_int_eq(0, afb_apiset_add(a, clapi[i].name, sa));
539         }
540
541         /* add constraints */
542         for (i = 0 ; clapi[i].name != NULL ; i++) {
543                 if (clapi[i].provides && clapi[i].provides[0])
544                         ck_assert_int_eq(0, afb_apiset_provide_class(a, clapi[i].name, clapi[i].provides));
545                 if (clapi[i].requires && clapi[i].requires[0])
546                         ck_assert_int_eq(0, afb_apiset_require_class(a, clapi[i].name, clapi[i].requires));
547                 if (clapi[i].apireq && clapi[i].apireq[0])
548                         ck_assert_int_eq(0, afb_apiset_require(a, clapi[i].name, clapi[i].apireq));
549         }
550
551         /* start all */
552         ck_assert_int_eq(0, afb_apiset_start_all_services(a));
553
554         afb_apiset_unref(a);
555 }
556 END_TEST
557
558 /*********************************************************************/
559
560 START_TEST (check_subset)
561 {
562         int rc;
563         struct afb_apiset *a, *b, *c, *d;
564
565         a = afb_apiset_create_subset_first(NULL, "a", 0);
566         ck_assert_ptr_nonnull(a);
567         ck_assert_str_eq("a", afb_apiset_name(a));
568         ck_assert_ptr_null(afb_apiset_subset_get(a));
569
570         b = afb_apiset_create_subset_first(a, "b", 0);
571         ck_assert_ptr_nonnull(b);
572         ck_assert_str_eq("b", afb_apiset_name(b));
573         ck_assert_ptr_eq(b, afb_apiset_subset_get(a));
574         ck_assert_ptr_null(afb_apiset_subset_get(b));
575
576         c = afb_apiset_create_subset_first(a, "c", 0);
577         ck_assert_ptr_nonnull(c);
578         ck_assert_str_eq("c", afb_apiset_name(c));
579         ck_assert_ptr_eq(c, afb_apiset_subset_get(a));
580         ck_assert_ptr_eq(b, afb_apiset_subset_get(c));
581         ck_assert_ptr_null(afb_apiset_subset_get(b));
582
583         d = afb_apiset_create_subset_last(a, "d", 0);
584         ck_assert_ptr_nonnull(d);
585         ck_assert_str_eq("d", afb_apiset_name(d));
586         ck_assert_ptr_eq(c, afb_apiset_subset_get(a));
587         ck_assert_ptr_eq(b, afb_apiset_subset_get(c));
588         ck_assert_ptr_eq(d, afb_apiset_subset_get(b));
589         ck_assert_ptr_null(afb_apiset_subset_get(d));
590
591         rc = afb_apiset_subset_set(a, b);
592         ck_assert(rc == 0);
593         ck_assert_ptr_eq(b, afb_apiset_subset_get(a));
594         ck_assert_ptr_eq(d, afb_apiset_subset_get(b));
595         ck_assert_ptr_null(afb_apiset_subset_get(d));
596
597         afb_apiset_unref(a);
598 }
599 END_TEST
600
601 /*********************************************************************/
602
603 static Suite *suite;
604 static TCase *tcase;
605
606 void mksuite(const char *name) { suite = suite_create(name); }
607 void addtcase(const char *name) { tcase = tcase_create(name); suite_add_tcase(suite, tcase); }
608 void addtest(TFun fun) { tcase_add_test(tcase, fun); }
609 int srun()
610 {
611         int nerr;
612         SRunner *srunner = srunner_create(suite);
613         srunner_run_all(srunner, CK_NORMAL);
614         nerr = srunner_ntests_failed(srunner);
615         srunner_free(srunner);
616         return nerr;
617 }
618
619 int main(int ac, char **av)
620 {
621         mksuite("apiset");
622                 addtcase("apiset");
623                         addtest(check_initialisation);
624                         addtest(check_sanity);
625                         addtest(check_creation);
626                         addtest(check_onlack);
627                         addtest(check_settings);
628                         addtest(check_classes);
629                         addtest(check_subset);
630         return !!srun();
631 }