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 | |
36 | static void |
37 | test_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 | |
97 | static gchar * |
98 | get_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 | |
113 | static void |
114 | test_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 | |
143 | static void |
144 | test_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 | |
213 | static void |
214 | test_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 | |
256 | int |
257 | main (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 | |