Branch data Line data Source code
1 : : /*
2 : : * Copyright © 2007 Ryan Lortie
3 : : *
4 : : * SPDX-License-Identifier: LGPL-2.1-or-later
5 : : *
6 : : * This program 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.
10 : : *
11 : : * See the included COPYING file for more information.
12 : : */
13 : :
14 : : #include <stdlib.h>
15 : : #include <string.h>
16 : : #include <glib.h>
17 : :
18 : : static void
19 : 20 : start (GMarkupParseContext *context,
20 : : const char *element_name,
21 : : const char **attribute_names,
22 : : const char **attribute_values,
23 : : gpointer user_data,
24 : : GError **error)
25 : : {
26 : 20 : GString *string = user_data;
27 : : gboolean result;
28 : :
29 : : #define collect(...) \
30 : : g_markup_collect_attributes (element_name, attribute_names, \
31 : : attribute_values, error, __VA_ARGS__, \
32 : : G_MARKUP_COLLECT_INVALID)
33 : : #define BOOL G_MARKUP_COLLECT_BOOLEAN
34 : : #define OPTBOOL G_MARKUP_COLLECT_BOOLEAN | G_MARKUP_COLLECT_OPTIONAL
35 : : #define TRI G_MARKUP_COLLECT_TRISTATE
36 : : #define STR G_MARKUP_COLLECT_STRING
37 : : #define STRDUP G_MARKUP_COLLECT_STRDUP
38 : : #define OPTSTR G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL
39 : : #define OPTDUP G_MARKUP_COLLECT_STRDUP | G_MARKUP_COLLECT_OPTIONAL
40 : : #define n(x) ((x)?(x):"(null)")
41 : :
42 [ + + ]: 20 : if (strcmp (element_name, "bool") == 0)
43 : : {
44 : 12 : gboolean mb = 2, ob = 2, tri = 2;
45 : :
46 : 12 : result = collect (BOOL, "mb", &mb,
47 : : OPTBOOL, "ob", &ob,
48 : : TRI, "tri", &tri);
49 : :
50 : 12 : g_assert (result ||
51 : : (mb == FALSE && ob == FALSE && tri != TRUE && tri != FALSE));
52 : :
53 [ + + + + ]: 12 : if (tri != FALSE && tri != TRUE)
54 : 10 : tri = -1;
55 : :
56 : 12 : g_string_append_printf (string, "<bool(%d) %d %d %d>",
57 : : result, mb, ob, tri);
58 : : }
59 : :
60 [ + - ]: 8 : else if (strcmp (element_name, "str") == 0)
61 : : {
62 : : const char *cm, *co;
63 : : char *am, *ao;
64 : :
65 : 8 : result = collect (STR, "cm", &cm,
66 : : STRDUP, "am", &am,
67 : : OPTDUP, "ao", &ao,
68 : : OPTSTR, "co", &co);
69 : :
70 : 8 : g_assert (result ||
71 : : (cm == NULL && am == NULL && ao == NULL && co == NULL));
72 : :
73 : 32 : g_string_append_printf (string, "<str(%d) %s %s %s %s>",
74 [ - + - + : 32 : result, n (cm), n (am), n (ao), n (co));
+ + + + ]
75 : :
76 : 8 : g_free (am);
77 : 8 : g_free (ao);
78 : : }
79 : 20 : }
80 : :
81 : : static GMarkupParser parser = { start, NULL, NULL, NULL, NULL };
82 : :
83 : : struct test
84 : : {
85 : : const char *document;
86 : : const char *result;
87 : : GMarkupError error_code;
88 : : const char *error_info;
89 : : };
90 : :
91 : : static struct test tests[] =
92 : : {
93 : : { "<bool mb='y'>", "<bool(1) 1 0 -1>",
94 : : G_MARKUP_ERROR_PARSE, "'bool'" },
95 : :
96 : : { "<bool mb='false'/>", "<bool(1) 0 0 -1>", 0, NULL },
97 : : { "<bool mb='true'/>", "<bool(1) 1 0 -1>", 0, NULL },
98 : : { "<bool mb='t' ob='f' tri='1'/>", "<bool(1) 1 0 1>", 0, NULL },
99 : : { "<bool mb='y' ob='n' tri='0'/>", "<bool(1) 1 0 0>", 0, NULL },
100 : :
101 : : { "<bool mb='y' my:attr='q'><my:tag/></bool>", "<bool(1) 1 0 -1>", 0, NULL },
102 : : { "<bool mb='y' my:attr='q'><my:tag>some <b>text</b> is in here</my:tag></bool>",
103 : : "<bool(1) 1 0 -1>", 0, NULL },
104 : :
105 : : { "<bool ob='y'/>", "<bool(0) 0 0 -1>",
106 : : G_MARKUP_ERROR_MISSING_ATTRIBUTE, "'mb'" },
107 : :
108 : : { "<bool mb='y' mb='y'/>", "<bool(0) 0 0 -1>",
109 : : G_MARKUP_ERROR_INVALID_CONTENT, "'mb'" },
110 : :
111 : : { "<bool mb='y' tri='y' tri='n'/>", "<bool(0) 0 0 -1>",
112 : : G_MARKUP_ERROR_INVALID_CONTENT, "'tri'" },
113 : :
114 : : { "<str cm='x' am='y'/>", "<str(1) x y (null) (null)>", 0, NULL },
115 : :
116 : : { "<str am='x' co='y'/>", "<str(0) (null) (null) (null) (null)>",
117 : : G_MARKUP_ERROR_MISSING_ATTRIBUTE, "'cm'" },
118 : :
119 : : { "<str am='x'/>", "<str(0) (null) (null) (null) (null)>",
120 : : G_MARKUP_ERROR_MISSING_ATTRIBUTE, "'cm'" },
121 : :
122 : : { "<str am='x' cm='x' am='y'/>", "<str(0) (null) (null) (null) (null)>",
123 : : G_MARKUP_ERROR_INVALID_CONTENT, "'am'" },
124 : :
125 : : { "<str am='x' qm='y' cm='x'/>", "<str(0) (null) (null) (null) (null)>",
126 : : G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, "'qm'" },
127 : :
128 : : { "<str am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' cm='x'/>", "<str(0) (null) (null) (null) (null)>",
129 : : G_MARKUP_ERROR_INVALID_CONTENT, "'am'" },
130 : :
131 : : { "<str cm='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x' am='x'/>", "<str(0) (null) (null) (null) (null)>",
132 : : G_MARKUP_ERROR_INVALID_CONTENT, "'am'" },
133 : :
134 : : { "<str a='x' b='x' c='x' d='x' e='x' f='x' g='x' h='x' i='x' j='x' k='x' l='x' m='x' n='x' o='x' p='x' q='x' r='x' s='x' t='x' u='x' v='x' w='x' x='x' y='x' z='x' aa='x' bb='x' cc='x' dd='x' ee='x' ff='x' gg='x' hh='x' ii='x' jj='x' kk='x' ll='x' mm='x' nn='x' oo='x' pp='x' qq='x' rr='x' ss='x' tt='x' uu='x' vv='x' ww='x' xx='x' yy='x' zz='x' am='x' cm='x'/>",
135 : : "<str(0) (null) (null) (null) (null)>",
136 : : G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, "'a'" },
137 : :
138 : : { "<bool mb='ja'/>", "<bool(0) 0 0 -1>",
139 : : G_MARKUP_ERROR_INVALID_CONTENT, "'mb'" },
140 : :
141 : : { "<bool mb='nein'/>", "<bool(0) 0 0 -1>",
142 : : G_MARKUP_ERROR_INVALID_CONTENT, "'mb'" }
143 : : };
144 : :
145 : : static void
146 : 20 : test_collect (gconstpointer d)
147 : : {
148 : 20 : const struct test *test = d;
149 : :
150 : : GMarkupParseContext *ctx;
151 : 20 : GError *error = NULL;
152 : : GString *string;
153 : : gboolean result;
154 : :
155 : 20 : string = g_string_new ("");
156 : 20 : ctx = g_markup_parse_context_new (&parser, G_MARKUP_IGNORE_QUALIFIED, string, NULL);
157 : 20 : result = g_markup_parse_context_parse (ctx,
158 : 20 : test->document,
159 : : -1, &error);
160 [ + + ]: 20 : if (result)
161 : 8 : result = g_markup_parse_context_end_parse (ctx, &error);
162 : :
163 [ + + ]: 20 : if (result)
164 : : {
165 : 7 : g_assert_no_error (error);
166 : 7 : g_assert_cmpint (test->error_code, ==, 0);
167 : 7 : g_assert_cmpstr (test->result, ==, string->str);
168 : : }
169 : : else
170 : : {
171 : 13 : g_assert_error (error, G_MARKUP_ERROR, (gint) test->error_code);
172 : : }
173 : :
174 : 20 : g_markup_parse_context_free (ctx);
175 : 20 : g_string_free (string, TRUE);
176 : 20 : g_clear_error (&error);
177 : 20 : }
178 : :
179 : : #define XML "<element a='1' b='2' c='3'/>"
180 : :
181 : : static void
182 : 1 : start_element (GMarkupParseContext *context,
183 : : const gchar *element_name,
184 : : const gchar **attribute_names,
185 : : const gchar **attribute_values,
186 : : gpointer user_data,
187 : : GError **error)
188 : : {
189 : : /* Omitting "c" attribute intentionally to trigger crash. */
190 : 1 : g_markup_collect_attributes (element_name,
191 : : attribute_names,
192 : : attribute_values,
193 : : error,
194 : : G_MARKUP_COLLECT_STRING, "a", NULL,
195 : : G_MARKUP_COLLECT_STRING, "b", NULL,
196 : : G_MARKUP_COLLECT_INVALID);
197 : 1 : }
198 : :
199 : : static GMarkupParser cleanup_parser = {
200 : : start_element, NULL, NULL, NULL, NULL
201 : : };
202 : :
203 : : static void
204 : 1 : test_cleanup (void)
205 : : {
206 : : GMarkupParseContext *context;
207 : :
208 [ - + ]: 1 : if (!g_test_undefined ())
209 : 0 : return;
210 : :
211 : 1 : context = g_markup_parse_context_new (&cleanup_parser,
212 : : G_MARKUP_DEFAULT_FLAGS, NULL,
213 : : NULL);
214 : 1 : g_markup_parse_context_parse (context, XML, -1, NULL);
215 : :
216 : 1 : g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
217 : : "g_markup_parse_context_end_parse: assertion 'context->state != STATE_ERROR' failed");
218 : 1 : g_markup_parse_context_end_parse (context, NULL);
219 : 1 : g_test_assert_expected_messages ();
220 : :
221 : 1 : g_markup_parse_context_free (context);
222 : : }
223 : :
224 : : int
225 : 1 : main (int argc, char **argv)
226 : : {
227 : : gsize i;
228 : : gchar *path;
229 : :
230 : 1 : g_test_init (&argc, &argv, NULL);
231 : :
232 [ + + ]: 21 : for (i = 0; i < G_N_ELEMENTS (tests); i++)
233 : : {
234 : 20 : path = g_strdup_printf ("/markup/collect/%" G_GSIZE_FORMAT, i);
235 : 20 : g_test_add_data_func (path, &tests[i], test_collect);
236 : 20 : g_free (path);
237 : : }
238 : :
239 : 1 : g_test_add_func ("/markup/collect/cleanup", test_cleanup);
240 : :
241 : 1 : return g_test_run ();
242 : : }
|