2 * test-api.c: test public API functions for conformance
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>
33 #include <libxml/tree.h>
35 static const char *abs_top_srcdir;
37 static char *loadpath;
41 fprintf(stderr, "%d: Fatal error: %s\n", __LINE__, msg); \
45 static void testGet(CuTest *tc) {
51 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
52 CuAssertPtrNotNull(tc, aug);
53 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
55 /* Make sure we're looking at the right thing */
56 r = aug_match(aug, "/augeas/version/save/*", NULL);
57 CuAssertTrue(tc, r > 1);
58 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
60 /* aug_get returns 1 and the value if exactly one node matches */
61 r = aug_get(aug, "/augeas/version/save/*[1]", &value);
62 CuAssertIntEquals(tc, 1, r);
63 CuAssertPtrNotNull(tc, value);
64 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
66 /* aug_get returns 0 and no value when no node matches */
67 r = aug_get(aug, "/augeas/version/save/*[ last() + 1 ]", &value);
68 CuAssertIntEquals(tc, 0, r);
69 CuAssertPtrEquals(tc, NULL, value);
70 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
72 /* aug_get should return an error when multiple nodes match */
73 r = aug_get(aug, "/augeas/version/save/*", &value);
74 CuAssertIntEquals(tc, -1, r);
75 CuAssertPtrEquals(tc, NULL, value);
76 CuAssertIntEquals(tc, AUG_EMMATCH, aug_error(aug));
78 /* aug_label returns 1 and the label if exactly one node matches */
79 r = aug_label(aug, "/augeas/version/save/*[1]", &label);
80 CuAssertIntEquals(tc, 1, r);
81 CuAssertPtrNotNull(tc, label);
82 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
84 /* aug_label returns 0 and no label when no node matches */
85 r = aug_label(aug, "/augeas/version/save/*[ last() + 1 ]", &label);
86 CuAssertIntEquals(tc, 0, r);
87 CuAssertPtrEquals(tc, NULL, label);
88 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
90 /* aug_label should return an error when multiple nodes match */
91 r = aug_label(aug, "/augeas/version/save/*", &label);
92 CuAssertIntEquals(tc, -1, r);
93 CuAssertPtrEquals(tc, NULL, label);
94 CuAssertIntEquals(tc, AUG_EMMATCH, aug_error(aug));
96 /* augeas should prepend context if relative path given */
97 r = aug_set(aug, "/augeas/context", "/augeas/version");
98 r = aug_get(aug, "save/*[1]", &value);
99 CuAssertIntEquals(tc, 1, r);
100 CuAssertPtrNotNull(tc, value);
101 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
103 /* augeas should still work with an empty context */
104 r = aug_set(aug, "/augeas/context", "");
105 r = aug_get(aug, "/augeas/version", &value);
106 CuAssertIntEquals(tc, 1, r);
107 CuAssertPtrNotNull(tc, value);
108 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
110 /* augeas should ignore trailing slashes in context */
111 r = aug_set(aug, "/augeas/context", "/augeas/version/");
112 r = aug_get(aug, "save/*[1]", &value);
113 CuAssertIntEquals(tc, 1, r);
114 CuAssertPtrNotNull(tc, value);
115 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
117 /* augeas should create non-existent context path */
118 r = aug_set(aug, "/augeas/context", "/context/foo");
119 r = aug_set(aug, "bar", "value");
120 r = aug_get(aug, "/context/foo/bar", &value);
121 CuAssertIntEquals(tc, 1, r);
122 CuAssertPtrNotNull(tc, value);
123 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
125 /* aug_get should set VALUE to NULL even if the path expression is invalid
127 value = (const char *) 7;
128 r = aug_get(aug, "[invalid path]", &value);
129 CuAssertIntEquals(tc, -1, r);
130 CuAssertPtrEquals(tc, NULL, value);
135 static void testSet(CuTest *tc) {
140 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
141 CuAssertPtrNotNull(tc, aug);
142 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
144 /* aug_set returns 0 for a simple set */
145 r = aug_set(aug, "/augeas/testSet", "foo");
146 CuAssertIntEquals(tc, 0, r);
147 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
149 /* aug_set returns -1 when cannot set due to multiple nodes */
150 r = aug_set(aug, "/augeas/version/save/*", "foo");
151 CuAssertIntEquals(tc, -1, r);
152 CuAssertIntEquals(tc, AUG_EMMATCH, aug_error(aug));
154 /* aug_set is able to set the context, even when currently invalid */
155 r = aug_set(aug, "/augeas/context", "( /files | /augeas )");
156 CuAssertIntEquals(tc, 0, r);
157 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
158 r = aug_get(aug, "/augeas/version", &value);
159 CuAssertIntEquals(tc, -1, r);
160 CuAssertIntEquals(tc, AUG_EMMATCH, aug_error(aug));
161 r = aug_set(aug, "/augeas/context", "/files");
162 CuAssertIntEquals(tc, 0, r);
163 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
168 static void testSetM(CuTest *tc) {
172 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
173 CuAssertPtrNotNull(tc, aug);
174 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
176 /* Change base nodes when SUB is NULL */
177 r = aug_setm(aug, "/augeas/version/save/*", NULL, "changed");
178 CuAssertIntEquals(tc, 4, r);
180 r = aug_match(aug, "/augeas/version/save/*[. = 'changed']", NULL);
181 CuAssertIntEquals(tc, 4, r);
183 /* Only change existing nodes */
184 r = aug_setm(aug, "/augeas/version/save", "mode", "again");
185 CuAssertIntEquals(tc, 4, r);
187 r = aug_match(aug, "/augeas/version/save/*", NULL);
188 CuAssertIntEquals(tc, 4, r);
190 r = aug_match(aug, "/augeas/version/save/*[. = 'again']", NULL);
191 CuAssertIntEquals(tc, 4, r);
193 /* Create a new node */
194 r = aug_setm(aug, "/augeas/version/save", "mode[last() + 1]", "newmode");
195 CuAssertIntEquals(tc, 1, r);
197 r = aug_match(aug, "/augeas/version/save/*", NULL);
198 CuAssertIntEquals(tc, 5, r);
200 r = aug_match(aug, "/augeas/version/save/*[. = 'again']", NULL);
201 CuAssertIntEquals(tc, 4, r);
203 r = aug_match(aug, "/augeas/version/save/*[last()][. = 'newmode']", NULL);
204 CuAssertIntEquals(tc, 1, r);
206 /* Noexistent base */
207 r = aug_setm(aug, "/augeas/version/save[last()+1]", "mode", "newmode");
208 CuAssertIntEquals(tc, 0, r);
210 /* Invalid path expressions */
211 r = aug_setm(aug, "/augeas/version/save[]", "mode", "invalid");
212 CuAssertIntEquals(tc, -1, r);
214 r = aug_setm(aug, "/augeas/version/save/*", "mode[]", "invalid");
215 CuAssertIntEquals(tc, -1, r);
220 /* Check that defining a variable leads to a corresponding entry in
221 * /augeas/variables and that that entry disappears when the variable is
223 static void testDefVarMeta(CuTest *tc) {
226 static const char *const expr = "/augeas/version/save/mode";
229 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
230 CuAssertPtrNotNull(tc, aug);
231 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
233 r = aug_defvar(aug, "var", expr);
234 CuAssertIntEquals(tc, 4, r);
236 r = aug_match(aug, "/augeas/variables/*", NULL);
237 CuAssertIntEquals(tc, 1, r);
239 r = aug_get(aug, "/augeas/variables/var", &value);
240 CuAssertStrEquals(tc, expr, value);
242 r = aug_defvar(aug, "var", NULL);
243 CuAssertIntEquals(tc, 0, r);
245 r = aug_match(aug, "/augeas/variables/*", NULL);
246 CuAssertIntEquals(tc, 0, r);
251 /* Check that defining a variable with defnode leads to a corresponding
252 * entry in /augeas/variables and that that entry disappears when the
253 * variable is undefined
255 static void testDefNodeExistingMeta(CuTest *tc) {
258 static const char *const expr = "/augeas/version/save/mode";
261 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
262 CuAssertPtrNotNull(tc, aug);
263 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
265 r = aug_defnode(aug, "var", expr, "other", &created);
266 CuAssertIntEquals(tc, 4, r);
267 CuAssertIntEquals(tc, 0, created);
269 r = aug_match(aug, "/augeas/variables/*", NULL);
270 CuAssertIntEquals(tc, 1, r);
272 r = aug_get(aug, "/augeas/variables/var", &value);
273 CuAssertStrEquals(tc, expr, value);
275 r = aug_defvar(aug, "var", NULL);
276 CuAssertIntEquals(tc, 0, r);
278 r = aug_match(aug, "/augeas/variables/*", NULL);
279 CuAssertIntEquals(tc, 0, r);
284 /* Check that defining a variable with defnode leads to a corresponding
285 * entry in /augeas/variables and that that entry disappears when the
286 * variable is undefined
288 static void testDefNodeCreateMeta(CuTest *tc) {
291 static const char *const expr = "/augeas/version/save/mode[last()+1]";
292 static const char *const expr_can = "/augeas/version/save/mode[5]";
295 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
296 CuAssertPtrNotNull(tc, aug);
297 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
299 r = aug_defnode(aug, "var", expr, "other", &created);
300 CuAssertIntEquals(tc, 1, r);
301 CuAssertIntEquals(tc, 1, created);
303 r = aug_match(aug, "/augeas/variables/*", NULL);
304 CuAssertIntEquals(tc, 1, r);
306 r = aug_get(aug, "/augeas/variables/var", &value);
307 CuAssertStrEquals(tc, expr_can, value);
309 r = aug_defvar(aug, "var", NULL);
310 CuAssertIntEquals(tc, 0, r);
312 r = aug_match(aug, "/augeas/variables/*", NULL);
313 CuAssertIntEquals(tc, 0, r);
318 static void reset_indexes(uint *a, uint *b, uint *c, uint *d, uint *e, uint *f) {
319 *a = 0; *b = 0; *c = 0; *d = 0; *e = 0; *f = 0;
322 #define SPAN_TEST_DEF_LAST { .expr = NULL, .ls = 0, .le = 0, \
323 .vs = 0, .ve = 0, .ss = 0, .se = 0 }
325 struct span_test_def {
337 static const struct span_test_def span_test[] = {
338 { .expr = "/files/etc/hosts/1/ipaddr", .f = "hosts", .ret = 0, .ls = 0, .le = 0, .vs = 104, .ve = 113, .ss = 104, .se = 113 },
339 { .expr = "/files/etc/hosts/1", .f = "hosts", .ret = 0, .ls = 0, .le = 0, .vs = 0, .ve = 0, .ss = 104, .se = 171 },
340 { .expr = "/files/etc/hosts/*[last()]", .f = "hosts", .ret = 0, .ls = 0, .le = 0, .vs = 0, .ve = 0, .ss = 266, .se = 309 },
341 { .expr = "/files/etc/hosts/#comment[2]", .f = "hosts", .ret = 0, .ls = 0, .le = 0, .vs = 58, .ve = 103, .ss = 56, .se = 104 },
342 { .expr = "/files/etc/hosts", .f = "hosts", .ret = 0, .ls = 0, .le = 0, .vs = 0, .ve = 0, .ss = 0, .se = 309 },
343 { .expr = "/files", .f = NULL, .ret = -1, .ls = 0, .le = 0, .vs = 0, .ve = 0, .ss = 0, .se = 0 },
344 { .expr = "/random", .f = NULL, .ret = -1, .ls = 0, .le = 0, .vs = 0, .ve = 0, .ss = 0, .se = 0 },
348 static void testNodeInfo(CuTest *tc) {
352 struct span_test_def test;
355 static const char *const expr = "/files/etc/hosts/1/ipaddr";
358 uint label_start, label_end, value_start, value_end, span_start, span_end;
360 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD|AUG_ENABLE_SPAN);
362 CuAssertRetSuccess(tc, ret);
364 while(span_test[i].expr != NULL) {
367 ret = aug_span(aug, test.expr, &filename_ac, &label_start, &label_end,
368 &value_start, &value_end, &span_start, &span_end);
369 sprintf(msg, "span_test %d ret\n", i);
370 CuAssertIntEquals_Msg(tc, msg, test.ret, ret);
371 sprintf(msg, "span_test %d label_start\n", i);
372 CuAssertIntEquals_Msg(tc, msg, test.ls, label_start);
373 sprintf(msg, "span_test %d label_end\n", i);
374 CuAssertIntEquals_Msg(tc, msg, test.le, label_end);
375 sprintf(msg, "span_test %d value_start\n", i);
376 CuAssertIntEquals_Msg(tc, msg, test.vs, value_start);
377 sprintf(msg, "span_test %d value_end\n", i);
378 CuAssertIntEquals_Msg(tc, msg, test.ve, value_end);
379 sprintf(msg, "span_test %d span_start\n", i);
380 CuAssertIntEquals_Msg(tc, msg, test.ss, span_start);
381 sprintf(msg, "span_test %d span_end\n", i);
382 CuAssertIntEquals_Msg(tc, msg, test.se, span_end);
383 if (filename_ac != NULL) {
384 fbase = basename(filename_ac);
388 sprintf(msg, "span_test %d filename\n", i);
389 CuAssertStrEquals_Msg(tc, msg, test.f, fbase);
392 reset_indexes(&label_start, &label_end, &value_start, &value_end,
393 &span_start, &span_end);
396 /* aug_span returns -1 and when no node matches */
397 ret = aug_span(aug, "/files/etc/hosts/*[ last() + 1 ]", &filename_ac,
398 &label_start, &label_end, &value_start, &value_end,
399 &span_start, &span_end);
400 CuAssertIntEquals(tc, -1, ret);
401 CuAssertPtrEquals(tc, NULL, filename_ac);
402 CuAssertIntEquals(tc, AUG_ENOMATCH, aug_error(aug));
404 /* aug_span should return an error when multiple nodes match */
405 ret = aug_span(aug, "/files/etc/hosts/*", &filename_ac,
406 &label_start, &label_end, &value_start, &value_end,
407 &span_start, &span_end);
408 CuAssertIntEquals(tc, -1, ret);
409 CuAssertPtrEquals(tc, NULL, filename_ac);
410 CuAssertIntEquals(tc, AUG_EMMATCH, aug_error(aug));
412 /* aug_span returns -1 if nodes span are not loaded */
414 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
416 CuAssertRetSuccess(tc, ret);
417 ret = aug_span(aug, expr, &filename_ac, &label_start, &label_end,
418 &value_start, &value_end, &span_start, &span_end);
419 CuAssertIntEquals(tc, -1, ret);
420 CuAssertPtrEquals(tc, NULL, filename_ac);
421 CuAssertIntEquals(tc, AUG_ENOSPAN, aug_error(aug));
422 reset_indexes(&label_start, &label_end, &value_start, &value_end,
423 &span_start, &span_end);
428 static void testMv(CuTest *tc) {
432 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
433 CuAssertPtrNotNull(tc, aug);
435 r = aug_set(aug, "/a/b/c", "value");
436 CuAssertRetSuccess(tc, r);
438 r = aug_mv(aug, "/a/b/c", "/a/b/c/d");
439 CuAssertIntEquals(tc, -1, r);
440 CuAssertIntEquals(tc, AUG_EMVDESC, aug_error(aug));
445 static void testCp(CuTest *tc) {
450 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
451 CuAssertPtrNotNull(tc, aug);
453 CuAssertRetSuccess(tc, r);
455 r = aug_set(aug, "/a/b/c", "value");
456 CuAssertRetSuccess(tc, r);
458 r = aug_cp(aug, "/a/b/c", "/a/b/c/d");
459 CuAssertIntEquals(tc, -1, r);
460 CuAssertIntEquals(tc, AUG_ECPDESC, aug_error(aug));
462 // Copy recursive tree with empty label
463 r = aug_cp(aug, "/files/etc/logrotate.d/rpm/rule/create", "/files/etc/logrotate.d/acpid/rule/create");
464 CuAssertRetSuccess(tc, r);
467 r = aug_get(aug, "/files/etc/logrotate.d/rpm/rule/create", &value);
468 CuAssertIntEquals(tc, 1, r);
469 CuAssertStrEquals(tc, NULL, value);
471 // Check that copies are well separated
472 r = aug_set(aug, "/files/etc/logrotate.d/rpm/rule/create/mode", "1234");
473 CuAssertRetSuccess(tc, r);
474 r = aug_set(aug, "/files/etc/logrotate.d/acpid/rule/create/mode", "5678");
475 CuAssertRetSuccess(tc, r);
476 r = aug_get(aug, "/files/etc/logrotate.d/rpm/rule/create/mode", &value);
477 CuAssertIntEquals(tc, 1, r);
478 CuAssertStrEquals(tc, "1234", value);
479 r = aug_get(aug, "/files/etc/logrotate.d/acpid/rule/create/mode", &value);
480 CuAssertIntEquals(tc, 1, r);
481 CuAssertStrEquals(tc, "5678", value);
487 static void testRename(CuTest *tc) {
491 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
492 CuAssertPtrNotNull(tc, aug);
494 r = aug_set(aug, "/a/b/c", "value");
495 CuAssertRetSuccess(tc, r);
497 r = aug_rename(aug, "/a/b/c", "d");
498 CuAssertIntEquals(tc, 1, r);
500 r = aug_set(aug, "/a/e/d", "value2");
501 CuAssertRetSuccess(tc, r);
504 r = aug_rename(aug, "/a//d", "x");
505 CuAssertIntEquals(tc, 2, r);
508 r = aug_rename(aug, "/a/e/x", "a/b");
509 CuAssertIntEquals(tc, -1, r);
510 CuAssertIntEquals(tc, AUG_ELABEL, aug_error(aug));
515 static void testToXml(CuTest *tc) {
518 xmlNodePtr xmldoc, xmlnode;
521 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
523 CuAssertRetSuccess(tc, r);
525 r = aug_to_xml(aug, "/files/etc/passwd", &xmldoc, 0);
526 CuAssertRetSuccess(tc, r);
528 value = xmlGetProp(xmldoc, BAD_CAST "match");
529 CuAssertStrEquals(tc, "/files/etc/passwd", (const char *) value);
532 xmlnode = xmlFirstElementChild(xmldoc);
533 value = xmlGetProp(xmlnode, BAD_CAST "label");
534 CuAssertStrEquals(tc, "passwd", (const char *) value);
537 value = xmlGetProp(xmlnode, BAD_CAST "path");
538 CuAssertStrEquals(tc, "/files/etc/passwd", (const char *) value);
541 xmlnode = xmlFirstElementChild(xmlnode);
542 value = xmlGetProp(xmlnode, BAD_CAST "label");
543 CuAssertStrEquals(tc, "root", (const char *) value);
548 r = aug_set(aug, "/augeas/context", "/files/etc/passwd");
549 CuAssertRetSuccess(tc, r);
550 r = aug_to_xml(aug, ".", &xmldoc, 0);
551 CuAssertRetSuccess(tc, r);
552 xmlnode = xmlFirstElementChild(xmldoc);
553 value = xmlGetProp(xmlnode, BAD_CAST "label");
554 CuAssertStrEquals(tc, "passwd", (const char *) value);
561 static void testTextStore(CuTest *tc) {
562 static const char *const hosts = "192.168.0.1 rtr.example.com router\n";
563 /* Not acceptable for Hosts.lns - missing canonical and \n */
564 static const char *const hosts_bad = "192.168.0.1";
570 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
571 CuAssertPtrNotNull(tc, aug);
573 r = aug_set(aug, "/raw/hosts", hosts);
574 CuAssertRetSuccess(tc, r);
576 r = aug_text_store(aug, "Hosts.lns", "/raw/hosts", "/t1");
577 CuAssertRetSuccess(tc, r);
579 r = aug_match(aug, "/t1/*", NULL);
580 CuAssertIntEquals(tc, 1, r);
582 /* Test bad lens name */
583 r = aug_text_store(aug, "Notthere.lns", "/raw/hosts", "/t2");
584 CuAssertIntEquals(tc, -1, r);
585 CuAssertIntEquals(tc, AUG_ENOLENS, aug_error(aug));
587 r = aug_match(aug, "/t2", NULL);
588 CuAssertIntEquals(tc, 0, r);
590 /* Test parse error */
591 r = aug_set(aug, "/raw/hosts_bad", hosts_bad);
592 CuAssertRetSuccess(tc, r);
594 r = aug_text_store(aug, "Hosts.lns", "/raw/hosts_bad", "/t3");
595 CuAssertIntEquals(tc, -1, r);
597 r = aug_match(aug, "/t3", NULL);
598 CuAssertIntEquals(tc, 0, r);
600 r = aug_get(aug, "/augeas/text/t3/error", &v);
601 CuAssertIntEquals(tc, 1, r);
602 CuAssertStrEquals(tc, "parse_failed", v);
604 r = aug_text_store(aug, "Hosts.lns", "/raw/hosts", "/t3");
605 CuAssertRetSuccess(tc, r);
607 r = aug_match(aug, "/augeas/text/t3/error", NULL);
608 CuAssertIntEquals(tc, 0, r);
610 /* Test invalid PATH */
611 r = aug_text_store(aug, "Hosts.lns", "/raw/hosts", "[garbage]");
612 CuAssertIntEquals(tc, -1, r);
613 CuAssertIntEquals(tc, AUG_EPATHX, aug_error(aug));
615 r = aug_match(aug, "/t2", NULL);
616 CuAssertIntEquals(tc, 0, r);
621 static void testTextRetrieve(CuTest *tc) {
622 static const char *const hosts = "192.168.0.1 rtr.example.com router\n";
623 const char *hosts_out;
627 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
628 CuAssertPtrNotNull(tc, aug);
630 r = aug_set(aug, "/raw/hosts", hosts);
631 CuAssertRetSuccess(tc, r);
633 r = aug_text_store(aug, "Hosts.lns", "/raw/hosts", "/t1");
634 CuAssertRetSuccess(tc, r);
636 r = aug_text_retrieve(aug, "Hosts.lns", "/raw/hosts", "/t1", "/out/hosts");
637 CuAssertRetSuccess(tc, r);
639 r = aug_get(aug, "/out/hosts", &hosts_out);
640 CuAssertIntEquals(tc, 1, r);
642 CuAssertStrEquals(tc, hosts, hosts_out);
647 static void testAugEscape(CuTest *tc) {
648 static const char *const in = "a/[]b|=c()!, \td";
649 static const char *const exp = "a\\/\\[\\]b\\|\\=c\\(\\)\\!\\,\\ \\\td";
654 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
655 CuAssertPtrNotNull(tc, aug);
657 r = aug_escape_name(aug, in, &out);
658 CuAssertRetSuccess(tc, r);
660 CuAssertStrEquals(tc, out, exp);
666 static void testRm(CuTest *tc) {
670 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_MODL_AUTOLOAD);
671 CuAssertPtrNotNull(tc, aug);
673 r = aug_set(aug, "/files/1/2/3/4/5", "1");
674 CuAssertRetSuccess(tc, r);
676 r = aug_rm(aug, "/files//*");
677 CuAssertIntEquals(tc, 5, r);
682 static void testLoadFile(CuTest *tc) {
687 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
688 CuAssertPtrNotNull(tc, aug);
689 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
691 /* augeas should load a single file */
692 r = aug_load_file(aug, "/etc/fstab");
693 CuAssertRetSuccess(tc, r);
694 r = aug_get(aug, "/files/etc/fstab/1/vfstype", &value);
695 CuAssertIntEquals(tc, 1, r);
696 CuAssertPtrNotNull(tc, value);
698 /* Only one file should be loaded */
699 r = aug_match(aug, "/files/etc/*", NULL);
700 CuAssertIntEquals(tc, 1, r);
702 /* augeas should return an error when no lens can be found for a file */
703 r = aug_load_file(aug, "/etc/unknown.conf");
704 CuAssertIntEquals(tc, -1, r);
705 CuAssertIntEquals(tc, AUG_ENOLENS, aug_error(aug));
707 /* augeas should return without an error when trying to load a
708 nonexistent file that would be handled by a lens */
709 r = aug_load_file(aug, "/etc/mtab");
710 CuAssertRetSuccess(tc, r);
711 r = aug_match(aug, "/files/etc/mtab", NULL);
712 CuAssertIntEquals(tc, 0, r);
717 /* Make sure that if somebody erroneously creates a node
718 /augeas/files/path, we do not corrupt the tree. It used to be that
719 having such a node would free /augeas/files
721 static void testLoadBadPath(CuTest *tc) {
725 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
726 CuAssertPtrNotNull(tc, aug);
727 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
729 r = aug_set(aug, "/augeas/files/path", "/files");
730 CuAssertRetSuccess(tc, r);
733 CuAssertRetSuccess(tc, r);
738 /* If a lens is set to a partial path which happens to actually resolve to
739 a file when appended to the loadpath, we went into an infinite loop of
740 loading a module, but then not realizing that it had actually been
741 loaded, reloading it over and over again.
742 See https://github.com/hercules-team/augeas/issues/522
744 static void testLoadBadLens(CuTest *tc) {
749 // This setup depends on the fact that
750 // loadpath == abs_top_srcdir + "/lenses"
751 r = asprintf(&lp, "%s:%s", loadpath, abs_top_srcdir);
752 CuAssert(tc, "failed to allocate loadpath", (r >= 0));
754 aug = aug_init(root, lp, AUG_NO_STDINC|AUG_NO_LOAD);
755 CuAssertPtrNotNull(tc, aug);
756 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
758 r = aug_set(aug, "/augeas/load/Fstab/lens", "lenses/Fstab.lns");
759 CuAssertRetSuccess(tc, r);
762 CuAssertRetSuccess(tc, r);
764 // We used to record the error to load the lens above against every
765 // lens that we tried to load after it.
766 r = aug_match(aug, "/augeas//error", NULL);
767 CuAssertIntEquals(tc, 1, r);
772 /* Test the aug_ns_* functions */
773 static void testAugNs(CuTest *tc) {
779 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
780 CuAssertPtrNotNull(tc, aug);
781 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
783 r = aug_load_file(aug, "/etc/hosts");
784 CuAssertIntEquals(tc, 0, r);
786 r = aug_defvar(aug, "matches",
787 "/files/etc/hosts/*[label() != '#comment']/ipaddr");
788 CuAssertIntEquals(tc, 2, r);
790 r = aug_ns_attr(aug, "matches", 0, &v, &l, &s);
791 CuAssertIntEquals(tc, 1, r);
792 CuAssertStrEquals(tc, "127.0.0.1", v);
793 CuAssertStrEquals(tc, "ipaddr", l);
794 CuAssertStrEquals(tc, "/files/etc/hosts", s);
798 r = aug_ns_attr(aug, "matches", 0, NULL, NULL, NULL);
799 CuAssertIntEquals(tc, 1, r);
801 r = aug_ns_attr(aug, "matches", 1, &v, NULL, &s);
802 CuAssertIntEquals(tc, 1, r);
803 CuAssertStrEquals(tc, "172.31.122.14", v);
804 CuAssertStrEquals(tc, "/files/etc/hosts", s);
808 r = aug_ns_attr(aug, "matches", 2, &v, &l, &s);
809 CuAssertIntEquals(tc, -1, r);
810 CuAssertPtrEquals(tc, NULL, v);
811 CuAssertPtrEquals(tc, NULL, l);
812 CuAssertPtrEquals(tc, NULL, s);
819 /* Test aug_source */
820 static void testAugSource(CuTest *tc) {
825 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
826 CuAssertPtrNotNull(tc, aug);
827 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
829 r = aug_load_file(aug, "/etc/hosts");
830 CuAssertIntEquals(tc, 0, r);
832 r = aug_source(aug, "/files/etc/hosts/1", &s);
833 CuAssertIntEquals(tc, 0, r);
834 CuAssertStrEquals(tc, "/files/etc/hosts", s);
837 r = aug_source(aug, "/files/etc/fstab", &s);
838 CuAssertIntEquals(tc, -1, r);
839 CuAssertIntEquals(tc, AUG_ENOMATCH, aug_error(aug));
840 CuAssertPtrEquals(tc, NULL, s);
842 r = aug_source(aug, "/files[", &s);
843 CuAssertIntEquals(tc, -1, r);
844 CuAssertIntEquals(tc, AUG_EPATHX, aug_error(aug));
845 CuAssertPtrEquals(tc, NULL, s);
847 r = aug_source(aug, "/files/etc/hosts/*", &s);
848 CuAssertIntEquals(tc, -1, r);
849 CuAssertIntEquals(tc, AUG_EMMATCH, aug_error(aug));
850 CuAssertPtrEquals(tc, NULL, s);
854 static void testAugPreview(CuTest *tc) {
858 char *etc_hosts_fn = NULL;
859 FILE *hosts_fp = NULL;
860 char *hosts_txt = NULL;
863 /* Read the original contents of the etc/hosts file */
864 if (asprintf(&etc_hosts_fn,"%s/etc/hosts",root) >=0 ) {
865 hosts_fp = fopen(etc_hosts_fn,"r");
867 hosts_txt = calloc(sizeof(char),4096);
869 readsz = fread(hosts_txt,sizeof(char),4096,hosts_fp);
870 *(hosts_txt+readsz) = '\0';
877 aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
878 CuAssertPtrNotNull(tc, aug);
879 CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
881 r = aug_load_file(aug, "/etc/hosts");
882 CuAssertIntEquals(tc, 0, r);
884 r = aug_preview(aug, "/files/etc/hosts/1", &s);
885 CuAssertIntEquals(tc, 0, r);
886 CuAssertStrEquals(tc, hosts_txt, s);
895 CuSuite* suite = CuSuiteNew();
896 CuSuiteSetup(suite, NULL, NULL);
898 SUITE_ADD_TEST(suite, testGet);
899 SUITE_ADD_TEST(suite, testSet);
900 SUITE_ADD_TEST(suite, testSetM);
901 SUITE_ADD_TEST(suite, testDefVarMeta);
902 SUITE_ADD_TEST(suite, testDefNodeExistingMeta);
903 SUITE_ADD_TEST(suite, testDefNodeCreateMeta);
904 SUITE_ADD_TEST(suite, testNodeInfo);
905 SUITE_ADD_TEST(suite, testMv);
906 SUITE_ADD_TEST(suite, testCp);
907 SUITE_ADD_TEST(suite, testRename);
908 SUITE_ADD_TEST(suite, testToXml);
909 SUITE_ADD_TEST(suite, testTextStore);
910 SUITE_ADD_TEST(suite, testTextRetrieve);
911 SUITE_ADD_TEST(suite, testAugEscape);
912 SUITE_ADD_TEST(suite, testRm);
913 SUITE_ADD_TEST(suite, testLoadFile);
914 SUITE_ADD_TEST(suite, testLoadBadPath);
915 SUITE_ADD_TEST(suite, testLoadBadLens);
916 SUITE_ADD_TEST(suite, testAugNs);
917 SUITE_ADD_TEST(suite, testAugSource);
918 SUITE_ADD_TEST(suite, testAugPreview);
920 abs_top_srcdir = getenv("abs_top_srcdir");
921 if (abs_top_srcdir == NULL)
922 die("env var abs_top_srcdir must be set");
924 if (asprintf(&root, "%s/tests/root", abs_top_srcdir) < 0) {
925 die("failed to set root");
928 if (asprintf(&loadpath, "%s/lenses", abs_top_srcdir) < 0) {
929 die("failed to set loadpath");
933 CuSuiteSummary(suite, &output);
934 CuSuiteDetails(suite, &output);
935 printf("%s\n", output);
937 int result = suite->failCount;
944 * indent-tabs-mode: nil