1/* Pango
2 * markup-parse.c: Test Pango markup
3 *
4 * Copyright (C) 2014 Red Hat, Inc
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
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 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22#include <glib.h>
23#include <string.h>
24
25#ifdef G_OS_WIN32
26# include <io.h>
27#else
28# include <unistd.h>
29#endif
30
31#include <locale.h>
32
33#include <pango/pangocairo.h>
34#include "test-common.h"
35
36static void
37test_file (const gchar *filename, GString *string)
38{
39 gchar *contents;
40 gsize length;
41 GError *error = NULL;
42 gchar *text;
43 PangoAttrList *attrs;
44 PangoAttrIterator *iter;
45 PangoFontDescription *desc;
46 PangoLanguage *lang;
47 gboolean ret;
48 char *str;
49 int start, end;
50 gunichar accel = 0;
51
52 g_file_get_contents (filename, contents: &contents, length: &length, error: &error);
53 g_assert_no_error (error);
54
55 ret = pango_parse_markup (markup_text: contents, length, accel_marker: '_', attr_list: &attrs, text: &text, accel_char: &accel, error: &error);
56
57 if (ret)
58 {
59 g_assert_no_error (error);
60 g_string_append (string, val: text);
61 g_string_append (string, val: "\n\n---\n\n");
62 print_attr_list (attrs, string);
63 g_string_append (string, val: "\n\n---\n\n");
64 desc = pango_font_description_new ();
65 iter = pango_attr_list_get_iterator (list: attrs);
66 do {
67 pango_attr_iterator_range (iterator: iter, start: &start, end: &end);
68 pango_attr_iterator_get_font (iterator: iter, desc, language: &lang, NULL);
69 str = pango_font_description_to_string (desc);
70 g_string_append_printf (string, format: "[%d:%d] %s %s\n", start, end, (char *)lang, str);
71 g_free (mem: str);
72 } while (pango_attr_iterator_next (iterator: iter));
73 pango_attr_iterator_destroy (iterator: iter);
74 pango_attr_list_unref (list: attrs);
75 pango_font_description_free (desc);
76 g_free (mem: text);
77
78 if (accel)
79 {
80 g_string_append (string, val: "\n\n---\n\n");
81 g_string_append_unichar (string, wc: accel);
82 }
83
84 /* Check that all optional arguments can be NULL */
85 ret = pango_parse_markup (markup_text: contents, length, accel_marker: '_', NULL, NULL, NULL, NULL);
86 g_assert_true (ret);
87 }
88 else
89 {
90 g_string_append_printf (string, format: "ERROR: %s", error->message);
91 g_error_free (error);
92 }
93
94 g_free (mem: contents);
95}
96
97static gchar *
98get_expected_filename (const gchar *filename)
99{
100 gchar *f, *p, *expected;
101
102 f = g_strdup (str: filename);
103 p = strstr (haystack: f, needle: ".markup");
104 if (p)
105 *p = 0;
106 expected = g_strconcat (string1: f, ".expected", NULL);
107
108 g_free (mem: f);
109
110 return expected;
111}
112
113static void
114test_parse (gconstpointer d)
115{
116 const gchar *filename = d;
117 gchar *expected_file;
118 GError *error = NULL;
119 GString *string;
120 char *diff;
121
122 expected_file = get_expected_filename (filename);
123
124 string = g_string_sized_new (dfl_size: 0);
125
126 test_file (filename, string);
127
128 diff = diff_with_file (file: expected_file, text: string->str, len: string->len, error: &error);
129 g_assert_no_error (error);
130
131 if (diff && diff[0])
132 {
133 g_test_message (format: "Resulting output doesn't match reference:\n%s", diff);
134 g_test_fail ();
135 }
136 g_free (mem: diff);
137
138 g_string_free (string, TRUE);
139
140 g_free (mem: expected_file);
141}
142
143static void
144test_file_incrementally (const gchar *filename, GString *string)
145{
146 gchar *contents;
147 gsize length;
148 GError *error = NULL;
149 gchar *text;
150 PangoAttrList *attrs;
151 PangoAttrIterator *iter;
152 PangoFontDescription *desc;
153 PangoLanguage *lang;
154 gboolean ret;
155 char *str;
156 int start, end;
157 gunichar accel = 0;
158 GMarkupParseContext *ctx;
159
160 g_file_get_contents (filename, contents: &contents, length: &length, error: &error);
161 g_assert_no_error (error);
162
163 ctx = pango_markup_parser_new (accel_marker: '_');
164
165 ret = TRUE;
166 for (int i = 0; i < length; i++)
167 {
168 ret = g_markup_parse_context_parse (context: ctx, text: &contents[i], text_len: 1, error: &error);
169 if (!ret)
170 break;
171 }
172
173 g_free (mem: contents);
174
175 if (ret)
176 {
177 pango_markup_parser_finish (context: ctx, attr_list: &attrs, text: &text, accel_char: &accel, error: &error);
178
179 g_assert_no_error (error);
180 g_string_append (string, val: text);
181 g_string_append (string, val: "\n\n---\n\n");
182 print_attr_list (attrs, string);
183 g_string_append (string, val: "\n\n---\n\n");
184 desc = pango_font_description_new ();
185 iter = pango_attr_list_get_iterator (list: attrs);
186 do {
187 pango_attr_iterator_range (iterator: iter, start: &start, end: &end);
188 pango_attr_iterator_get_font (iterator: iter, desc, language: &lang, NULL);
189 str = pango_font_description_to_string (desc);
190 g_string_append_printf (string, format: "[%d:%d] %s %s\n", start, end, (char *)lang, str);
191 g_free (mem: str);
192 } while (pango_attr_iterator_next (iterator: iter));
193 pango_attr_iterator_destroy (iterator: iter);
194 pango_attr_list_unref (list: attrs);
195 pango_font_description_free (desc);
196 g_free (mem: text);
197
198 if (accel)
199 {
200 g_string_append (string, val: "\n\n---\n\n");
201 g_string_append_unichar (string, wc: accel);
202 }
203 }
204 else
205 {
206 g_string_append_printf (string, format: "ERROR: %s", error->message);
207 g_error_free (error);
208 }
209
210 g_markup_parse_context_free (context: ctx);
211}
212
213static void
214test_parse_incrementally (gconstpointer d)
215{
216 const gchar *filename = d;
217 gchar *expected_file;
218 GError *error = NULL;
219 GString *string;
220 char *diff;
221 gboolean ret;
222
223 expected_file = get_expected_filename (filename);
224
225 string = g_string_sized_new (dfl_size: 0);
226
227 test_file_incrementally (filename, string);
228
229 /* incremental parsing can affect line numbers,
230 * so avoid comparing the exact error strings
231 */
232 if (g_str_has_prefix (str: string->str, prefix: "ERROR:"))
233 {
234 ret = file_has_prefix (file: expected_file, str: "ERROR:", error: &error);
235 g_assert_no_error (error);
236 g_assert_true (ret);
237 }
238 else
239 {
240 diff = diff_with_file (file: expected_file, text: string->str, len: string->len, error: &error);
241 g_assert_no_error (error);
242
243 if (diff && diff[0])
244 {
245 g_test_message (format: "Resulting output doesn't match reference:\n%s", diff);
246 g_test_fail ();
247 }
248 g_free (mem: diff);
249 }
250
251 g_string_free (string, TRUE);
252
253 g_free (mem: expected_file);
254}
255
256int
257main (int argc, char *argv[])
258{
259 GDir *dir;
260 GError *error = NULL;
261 const gchar *name;
262 gchar *path;
263
264 g_setenv (variable: "LC_ALL", value: "en_US.UTF8", TRUE);
265 setlocale (LC_ALL, locale: "");
266
267 /* allow to easily generate expected output for new test cases */
268 if (argc > 1 && argv[1][0] != '-')
269 {
270 GString *string;
271
272 string = g_string_sized_new (dfl_size: 0);
273 test_file (filename: argv[1], string);
274 g_print (format: "%s", string->str);
275
276 return 0;
277 }
278
279 g_test_init (argc: &argc, argv: &argv, NULL);
280
281 path = g_test_build_filename (file_type: G_TEST_DIST, first_path: "markups", NULL);
282 dir = g_dir_open (path, flags: 0, error: &error);
283 g_free (mem: path);
284 g_assert_no_error (error);
285 while ((name = g_dir_read_name (dir)) != NULL)
286 {
287 if (!strstr (haystack: name, needle: "markup"))
288 continue;
289
290 path = g_strdup_printf (format: "/markup/parse/%s", name);
291 g_test_add_data_func_full (testpath: path, test_data: g_test_build_filename (file_type: G_TEST_DIST, first_path: "markups", name, NULL),
292 test_func: test_parse, data_free_func: g_free);
293 g_free (mem: path);
294
295 path = g_strdup_printf (format: "/markup/parse-incrementally/%s", name);
296 g_test_add_data_func_full (testpath: path, test_data: g_test_build_filename (file_type: G_TEST_DIST, first_path: "markups", name, NULL),
297 test_func: test_parse_incrementally, data_free_func: g_free);
298 g_free (mem: path);
299 }
300 g_dir_close (dir);
301
302 return g_test_run ();
303}
304

source code of gtk/subprojects/pango/tests/markup-parse.c