api documentation for ec_parse
[protos/libecoli.git] / src / ecoli_test.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
3  */
4
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <assert.h>
9 #include <errno.h>
10
11 #include <ecoli_log.h>
12 #include <ecoli_malloc.h>
13 #include <ecoli_test.h>
14 #include <ecoli_strvec.h>
15 #include <ecoli_node.h>
16 #include <ecoli_parse.h>
17 #include <ecoli_complete.h>
18 #include <ecoli_parse.h>
19
20 static struct ec_test_list test_list = TAILQ_HEAD_INITIALIZER(test_list);
21
22 EC_LOG_TYPE_REGISTER(test);
23
24 static struct ec_test *ec_test_lookup(const char *name)
25 {
26         struct ec_test *test;
27
28         TAILQ_FOREACH(test, &test_list, next) {
29                 if (!strcmp(name, test->name))
30                         return test;
31         }
32
33         errno = EEXIST;
34         return NULL;
35 }
36
37 int ec_test_register(struct ec_test *test)
38 {
39         if (ec_test_lookup(test->name) != NULL)
40                 return -1;
41
42         TAILQ_INSERT_TAIL(&test_list, test, next);
43
44         return 0;
45 }
46
47 int ec_test_check_parse(struct ec_node *tk, int expected, ...)
48 {
49         struct ec_pnode *p;
50         struct ec_strvec *vec = NULL;
51         const char *s;
52         int ret = -1, match;
53         va_list ap;
54
55         va_start(ap, expected);
56
57         /* build a string vector */
58         vec = ec_strvec();
59         if (vec == NULL)
60                 goto out;
61
62         for (s = va_arg(ap, const char *);
63              s != EC_VA_END;
64              s = va_arg(ap, const char *)) {
65                 if (s == NULL)
66                         goto out;
67
68                 if (ec_strvec_add(vec, s) < 0)
69                         goto out;
70         }
71
72         p = ec_parse_strvec(tk, vec);
73         if (p == NULL) {
74                 EC_LOG(EC_LOG_ERR, "parse is NULL\n");
75         }
76         if (ec_pnode_matches(p))
77                 match = ec_pnode_len(p);
78         else
79                 match = -1;
80         if (expected == match) {
81                 ret = 0;
82         } else {
83                 EC_LOG(EC_LOG_ERR,
84                         "parse len (%d) does not match expected (%d)\n",
85                         match, expected);
86         }
87
88         ec_pnode_free(p);
89
90 out:
91         ec_strvec_free(vec);
92         va_end(ap);
93         return ret;
94 }
95
96 int ec_test_check_complete(struct ec_node *tk, enum ec_comp_type type, ...)
97 {
98         struct ec_comp *c = NULL;
99         struct ec_strvec *vec = NULL;
100         const char *s;
101         int ret = 0;
102         size_t count = 0;
103         va_list ap;
104
105         va_start(ap, type);
106
107         /* build a string vector */
108         vec = ec_strvec();
109         if (vec == NULL)
110                 goto out;
111
112         for (s = va_arg(ap, const char *);
113              s != EC_VA_END;
114              s = va_arg(ap, const char *)) {
115                 if (s == NULL)
116                         goto out;
117
118                 if (ec_strvec_add(vec, s) < 0)
119                         goto out;
120         }
121
122         c = ec_complete_strvec(tk, vec);
123         if (c == NULL) {
124                 ret = -1;
125                 goto out;
126         }
127
128         /* for each expected completion, check it is there */
129         for (s = va_arg(ap, const char *);
130              s != EC_VA_END;
131              s = va_arg(ap, const char *)) {
132                 struct ec_comp_item *item;
133
134                 if (s == NULL) {
135                         ret = -1;
136                         goto out;
137                 }
138
139                 count++;
140
141                 /* only check matching completions */
142                 EC_COMP_FOREACH(item, c, type) {
143                         const char *str = ec_comp_item_get_str(item);
144                         if (str != NULL && strcmp(str, s) == 0)
145                                 break;
146                 }
147
148                 if (item == NULL) {
149                         EC_LOG(EC_LOG_ERR,
150                                 "completion <%s> not in list\n", s);
151                         ret = -1;
152                 }
153         }
154
155         /* check if we have more completions (or less) than expected */
156         if (count != ec_comp_count(c, type)) {
157                 EC_LOG(EC_LOG_ERR,
158                         "nb_completion (%zu) does not match (%zu)\n",
159                         count, ec_comp_count(c, type));
160                 ec_comp_dump(stdout, c);
161                 ret = -1;
162         }
163
164 out:
165         ec_strvec_free(vec);
166         ec_comp_free(c);
167         va_end(ap);
168         return ret;
169 }
170
171 static int launch_test(const char *name)
172 {
173         struct ec_test *test;
174         int ret = 0;
175         unsigned int count = 0;
176
177         TAILQ_FOREACH(test, &test_list, next) {
178                 if (name != NULL && strcmp(name, test->name))
179                         continue;
180
181                 EC_LOG(EC_LOG_INFO, "== starting test %-20s\n",
182                         test->name);
183
184                 count++;
185                 if (test->test() == 0) {
186                         EC_LOG(EC_LOG_INFO,
187                                 "== test %-20s success\n",
188                                 test->name);
189                 } else {
190                         EC_LOG(EC_LOG_INFO,
191                                 "== test %-20s failed\n",
192                                 test->name);
193                         ret = -1;
194                 }
195         }
196
197         if (name != NULL && count == 0) {
198                 EC_LOG(EC_LOG_WARNING,
199                         "== test %s not found\n", name);
200                 ret = -1;
201         }
202
203         return ret;
204 }
205
206 int ec_test_all(void)
207 {
208         return launch_test(NULL);
209 }
210
211 int ec_test_one(const char *name)
212 {
213         return launch_test(name);
214 }