Skip to content

Commit be320f1

Browse files
committed
Add tests/t1000-add-xpath-node.c
This unit-test shows that duplicate entries are incorrectly added when xpath expressions with different capitalisation are passed to xml_add_node()
1 parent 32e27ba commit be320f1

File tree

7 files changed

+244
-0
lines changed

7 files changed

+244
-0
lines changed

meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ executable(
1717
install : true,
1818
)
1919

20+
subdir('tests')
2021
subdir('data')

tests/meson.build

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
test_lib = static_library(
2+
'tests',
3+
sources: files(
4+
'../xml.c',
5+
),
6+
dependencies: [dependency('libxml-2.0'), dependency('glib-2.0')],
7+
)
8+
9+
tests = [
10+
't1000-add-xpath-node.c',
11+
]
12+
13+
foreach t : tests
14+
testname = t.split('.')[0].underscorify()
15+
exe = executable(
16+
testname,
17+
sources: [t, 'tap.c'],
18+
dependencies: [dependency('glib-2.0')],
19+
link_with: [test_lib],
20+
)
21+
test(testname, exe)
22+
endforeach
23+

tests/t1000-add-xpath-node.c

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#define _POSIX_C_SOURCE 200809L
2+
#include <glib.h>
3+
#include <stdbool.h>
4+
#include <stdio.h>
5+
#include <unistd.h>
6+
#include "tap.h"
7+
#include "../xml.h"
8+
9+
static char template[] =
10+
"<?xml version=\"1.0\"?>\n"
11+
"<labwc_config>\n"
12+
" <core>\n"
13+
" <gap/>\n"
14+
" </core>\n"
15+
"</labwc_config>\n";
16+
17+
void show_diff(const char *filename, const char *buf, size_t size)
18+
{
19+
char cmd[1000];
20+
snprintf(cmd, sizeof(cmd), "diff -u - %s >&2", filename);
21+
FILE *f = popen(cmd, "w");
22+
fwrite(buf, size, 1, f);
23+
pclose(f);
24+
}
25+
26+
void test(const char *filename, const char *expect)
27+
{
28+
gsize length; gchar *actual;
29+
g_file_get_contents(filename, &actual, &length, NULL);
30+
bool is_equal = strcmp(actual, expect) == 0;
31+
ok1(is_equal);
32+
if (!is_equal)
33+
show_diff(filename, expect, strlen(expect));
34+
g_free(actual);
35+
}
36+
37+
int main(int argc, char **argv)
38+
{
39+
char in[] = "/tmp/t1000-expect_XXXXXX";
40+
char out[] = "/tmp/t1000-actual";
41+
42+
plan(4);
43+
44+
int fd = mkstemp(in);
45+
if (fd < 0)
46+
exit(EXIT_FAILURE);
47+
write(fd, template, sizeof(template) - 1);
48+
49+
/* test 1 */
50+
diag("add node <theme><cornerradius> using xpath (lowercase)");
51+
xml_init(in);
52+
xml_add_node("/labwc_config/theme/cornerradius");
53+
xml_save_as(out);
54+
xml_finish();
55+
test(out,
56+
"<?xml version=\"1.0\"?>\n"
57+
"<labwc_config>\n"
58+
" <core>\n"
59+
" <gap/>\n"
60+
" </core>\n"
61+
" <theme>\n"
62+
" <cornerradius/>\n"
63+
" </theme>\n"
64+
"</labwc_config>\n");
65+
66+
/* test 2 */
67+
diag("add node <theme><cornerRadius> using xpath (camelCase)");
68+
xml_init(in);
69+
xml_add_node("/labwc_config/theme/cornerRadius");
70+
xml_save_as(out);
71+
xml_finish();
72+
test(out,
73+
"<?xml version=\"1.0\"?>\n"
74+
"<labwc_config>\n"
75+
" <core>\n"
76+
" <gap/>\n"
77+
" </core>\n"
78+
" <theme>\n"
79+
" <cornerRadius/>\n"
80+
" </theme>\n"
81+
"</labwc_config>\n");
82+
83+
/* test 3 */
84+
diag("check xpath does not add duplicate entries - when identical");
85+
xml_init(in);
86+
xml_add_node("/labwc_config/theme/cornerradius");
87+
xml_add_node("/labwc_config/theme/cornerradius");
88+
xml_save_as(out);
89+
xml_finish();
90+
test(out,
91+
"<?xml version=\"1.0\"?>\n"
92+
"<labwc_config>\n"
93+
" <core>\n"
94+
" <gap/>\n"
95+
" </core>\n"
96+
" <theme>\n"
97+
" <cornerradius/>\n"
98+
" </theme>\n"
99+
"</labwc_config>\n");
100+
101+
/* test 4 */
102+
diag("check xpath does not add duplicate entries - even if they have differing capitalisation");
103+
xml_init(in);
104+
xml_add_node("/labwc_config/theme/cornerradius");
105+
xml_add_node("/labwc_config/theme/Cornerradius");
106+
xml_save_as(out);
107+
xml_finish();
108+
test(out,
109+
"<?xml version=\"1.0\"?>\n"
110+
"<labwc_config>\n"
111+
" <core>\n"
112+
" <gap/>\n"
113+
" </core>\n"
114+
" <theme>\n"
115+
" <cornerradius/>\n"
116+
" </theme>\n"
117+
"</labwc_config>\n");
118+
119+
unlink(in);
120+
unlink(out);
121+
return exit_status();
122+
}
123+

tests/tap.c

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <stdarg.h>
4+
#include <ctype.h>
5+
#include <unistd.h>
6+
#include <stdbool.h>
7+
8+
#include "tap.h"
9+
10+
static int nr_tests_run;
11+
static int nr_tests_expected;
12+
static int nr_tests_failed;
13+
14+
void plan(int nr_tests)
15+
{
16+
static bool run_once;
17+
18+
if (run_once)
19+
return;
20+
run_once = true;
21+
printf("1..%d\n", nr_tests);
22+
nr_tests_expected = nr_tests;
23+
}
24+
25+
void diag(const char *fmt, ...)
26+
{
27+
va_list params;
28+
29+
fprintf(stdout, "# ");
30+
va_start(params, fmt);
31+
vfprintf(stdout, fmt, params);
32+
va_end(params);
33+
fprintf(stdout, "\n");
34+
}
35+
36+
int ok(int result, const char *testname, ...)
37+
{
38+
va_list params;
39+
40+
++nr_tests_run;
41+
if (!result) {
42+
printf("not ");
43+
nr_tests_failed++;
44+
}
45+
printf("ok %d", nr_tests_run);
46+
if (testname) {
47+
printf(" - ");
48+
va_start(params, testname);
49+
vfprintf(stdout, testname, params);
50+
va_end(params);
51+
}
52+
printf("\n");
53+
if (!result)
54+
diag(" Failed test");
55+
return result ? 1 : 0;
56+
}
57+
58+
int exit_status(void)
59+
{
60+
int ret;
61+
62+
if (nr_tests_expected != nr_tests_run) {
63+
diag("expected=%d; run=%d; failed=%d", nr_tests_expected,
64+
nr_tests_run, nr_tests_failed);
65+
}
66+
if (nr_tests_expected < nr_tests_run)
67+
ret = nr_tests_run - nr_tests_expected;
68+
else
69+
ret = nr_tests_failed + nr_tests_expected - nr_tests_run;
70+
if (ret > 255)
71+
ret = 255;
72+
return ret;
73+
}

tests/tap.h

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Minimalist, partial TAP implementation
3+
*
4+
* Copyright Johan Malm 2020
5+
*/
6+
7+
#ifndef TAP_H
8+
#define TAP_H
9+
10+
#define ok1(__x__) (ok(__x__, "%s", #__x__))
11+
12+
void plan(int nr_tests);
13+
void diag(const char *fmt, ...);
14+
int ok(int result, const char *test_name, ...);
15+
int exit_status(void);
16+
17+
#endif /* TAP_H */

xml.c

+6
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ xml_save(void)
162162
xmlSaveFormatFile(ctx.filename, ctx.doc, 1);
163163
}
164164

165+
void
166+
xml_save_as(const char *filename)
167+
{
168+
xmlSaveFormatFile(filename, ctx.doc, 1);
169+
}
170+
165171
void
166172
xml_finish(void)
167173
{

xml.h

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
void xml_init(const char *filename);
55
void xml_save(void);
6+
void xml_save_as(const char *filename);
67
void xml_finish(void);
78
void xml_set(char *nodename, char *value);
89
void xml_set_num(char *nodename, double value);

0 commit comments

Comments
 (0)