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