add meson support
[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_parse *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_NODE_ENDLIST;
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_node_parse_strvec(tk, vec);
73         if (p == NULL) {
74                 EC_LOG(EC_LOG_ERR, "parse is NULL\n");
75         }
76         if (ec_parse_matches(p))
77                 match = ec_parse_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_parse_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         unsigned int 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_NODE_ENDLIST;
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_node_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_NODE_ENDLIST;
131              s = va_arg(ap, const char *)) {
132                 struct ec_comp_iter *iter;
133                 const struct ec_comp_item *item;
134
135                 if (s == NULL) {
136                         ret = -1;
137                         goto out;
138                 }
139
140                 count++;
141
142                 /* only check matching completions */
143                 iter = ec_comp_iter(c, type);
144                 while ((item = ec_comp_iter_next(iter)) != NULL) {
145                         const char *str = ec_comp_item_get_str(item);
146                         if (str != NULL && strcmp(str, s) == 0)
147                                 break;
148                 }
149
150                 if (item == NULL) {
151                         EC_LOG(EC_LOG_ERR,
152                                 "completion <%s> not in list\n", s);
153                         ret = -1;
154                 }
155                 ec_comp_iter_free(iter);
156         }
157
158         /* check if we have more completions (or less) than expected */
159         if (count != ec_comp_count(c, type)) {
160                 EC_LOG(EC_LOG_ERR,
161                         "nb_completion (%d) does not match (%d)\n",
162                         count, ec_comp_count(c, type));
163                 ec_comp_dump(stdout, c);
164                 ret = -1;
165         }
166
167 out:
168         ec_strvec_free(vec);
169         ec_comp_free(c);
170         va_end(ap);
171         return ret;
172 }
173
174 static int launch_test(const char *name)
175 {
176         struct ec_test *test;
177         int ret = 0;
178         unsigned int count = 0;
179
180         TAILQ_FOREACH(test, &test_list, next) {
181                 if (name != NULL && strcmp(name, test->name))
182                         continue;
183
184                 EC_LOG(EC_LOG_INFO, "== starting test %-20s\n",
185                         test->name);
186
187                 count++;
188                 if (test->test() == 0) {
189                         EC_LOG(EC_LOG_INFO,
190                                 "== test %-20s success\n",
191                                 test->name);
192                 } else {
193                         EC_LOG(EC_LOG_INFO,
194                                 "== test %-20s failed\n",
195                                 test->name);
196                         ret = -1;
197                 }
198         }
199
200         if (name != NULL && count == 0) {
201                 EC_LOG(EC_LOG_WARNING,
202                         "== test %s not found\n", name);
203                 ret = -1;
204         }
205
206         return ret;
207 }
208
209 int ec_test_all(void)
210 {
211         return launch_test(NULL);
212 }
213
214 int ec_test_one(const char *name)
215 {
216         return launch_test(name);
217 }