2 * test-run.c: test the aug_srun API function
4 * Copyright (C) 2009-2016 David Lutterkort
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Author: David Lutterkort <lutter@redhat.com>
37 static const char *abs_top_srcdir;
40 #define KW_TEST "test"
41 #define KW_PRINTS "prints"
42 #define KW_SOMETHING "something"
45 /* This array needs to be kept in sync with aug_errcode_t, and
46 * the entries need to be in the same order as in that enum; used
49 static const char *const errtokens[] = {
50 "NOERROR", "ENOMEM", "EINTERNAL", "EPATHX", "ENOMATCH",
51 "EMMATCH", "ESYNTAX", "ENOLENS", "EMXFM", "ENOSPAN",
52 "EMVDESC", "ECMDRUN", "EBADARG", "ELABEL"
66 static void free_tests(struct test *test) {
69 free_tests(test->next);
79 fprintf(stderr, "%d: Fatal error: %s\n", __LINE__, msg); \
83 static char *skipws(char *s) {
84 while (isspace(*s)) s++;
88 static char *findws(char *s) {
89 while (*s && ! isspace(*s)) s++;
93 static char *token(char *s, char **tok) {
96 *tok = strndup(t, s - t);
100 static char *inttok(char *s, int *tok) {
103 *tok = strtol(t, NULL, 10);
107 static char *errtok(char *s, int *err) {
114 for (*err = 0; *err < ARRAY_CARDINALITY(errtokens); *err += 1) {
115 const char *e = errtokens[*err];
116 if (strlen(e) == s - t && STREQLEN(e, t, s - t))
119 fprintf(stderr, "errtok: '%s'\n", t);
120 die("unknown error code");
123 static bool looking_at(const char *s, const char *kw) {
124 return STREQLEN(s, kw, strlen(kw));
127 static struct test *read_tests(void) {
131 struct test *result = NULL, *t = NULL;
133 bool append_cmd = true;
135 if (asprintf(&fname, "%s/tests/run.tests", abs_top_srcdir) < 0)
136 die("asprintf fname");
138 if ((fp = fopen(fname, "r")) == NULL)
139 die("fopen run.tests");
141 while (fgets(line, BUFSIZ, fp) != NULL) {
143 char *s = skipws(line);
144 if (*s == '#' || *s == '\0')
148 char *eos = s + strlen(s) - 2;
149 if (eos >= s && *eos == ':') {
154 if (looking_at(s, KW_TEST)) {
157 list_append(result, t);
159 s = token(s + strlen(KW_TEST), &(t->name));
160 s = inttok(s, &t->result);
161 s = errtok(s, &t->errcode);
162 } else if (looking_at(s, KW_PRINTS)) {
163 s = skipws(s + strlen(KW_PRINTS));
164 t->out_present = looking_at(s, KW_SOMETHING);
166 } else if (looking_at(s, KW_USE)) {
167 if (t->module !=NULL)
168 die("Can use at most one module in a test");
169 s = token(s + strlen(KW_USE), &(t->module));
171 char **buf = append_cmd ? &(t->cmd) : &(t->out);
177 if (REALLOC_N(*buf, strlen(*buf) + strlen(s) + 1) < 0)
183 t->out_present = true;
189 #define fail(cond, msg ...) \
192 fprintf(stdout, ## msg); \
197 static int load_module(struct augeas *aug, struct test *test) {
201 if (test->module == NULL)
204 if (asprintf(&fname, "%s.aug", test->module) == -1)
205 fail(true, "asprintf test->module");
207 for (int i=0; i < strlen(fname); i++)
208 fname[i] = tolower(fname[i]);
210 if (asprintf(&fpath, "%s/%s", lensdir, fname) == -1)
211 fail(true, "asprintf lensdir");
213 r = __aug_load_module_file(aug, fpath);
214 fail(r < 0, "Could not load %s", fpath);
222 static int run_one_test(struct test *test) {
224 struct augeas *aug = NULL;
230 aug = aug_init("/dev/null", lensdir,
231 AUG_NO_STDINC|AUG_NO_MODL_AUTOLOAD|AUG_ENABLE_SPAN);
232 fail(aug == NULL, "aug_init");
233 fail(aug_error(aug) != AUG_NOERROR, "aug_init: errcode was %d",
236 printf("%-30s ... ", test->name);
238 r = load_module(aug, test);
242 r = init_memstream(&ms);
243 fail(r < 0, "init_memstream");
245 r = aug_srun(aug, ms.stream, test->cmd);
246 fail(r != test->result, "return value: expected %d, actual %d",
248 fail(aug_error(aug) != test->errcode, "errcode: expected %s, actual %s",
249 errtokens[test->errcode], errtokens[aug_error(aug)]);
251 r = close_memstream(&ms);
252 fail(r < 0, "close_memstream");
253 fail(ms.buf == NULL, "close_memstream left buf NULL");
255 if (test->out != NULL) {
256 fail(STRNEQ(ms.buf, test->out), "output: expected '%s', actual '%s'",
258 } else if (test->out_present) {
259 fail(strlen(ms.buf) == 0,
260 "output: expected some output");
262 fail(strlen(ms.buf) > 0,
263 "output: expected nothing, actual '%s'", ms.buf);
276 static int run_tests(struct test *tests, int argc, char **argv) {
277 int result = EXIT_SUCCESS;
279 list_for_each(t, tests) {
280 if (! should_run(t->name, argc, argv))
282 if (run_one_test(t) < 0)
283 result = EXIT_FAILURE;
288 int main(int argc, char **argv) {
291 abs_top_srcdir = getenv("abs_top_srcdir");
292 if (abs_top_srcdir == NULL)
293 die("env var abs_top_srcdir must be set");
295 if (asprintf(&lensdir, "%s/lenses", abs_top_srcdir) < 0)
296 die("out of memory setting lensdir");
298 tests = read_tests();
299 int result = run_tests(tests, argc - 1, argv + 1);
306 * indent-tabs-mode: nil