1 | /* |
2 | * Copyright (C) 2015 Red Hat Inc. |
3 | * |
4 | * Author: |
5 | * Matthias Clasen <mclasen@redhat.com> |
6 | * |
7 | * This library is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Library General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2 of the License, or (at your option) any later version. |
11 | * |
12 | * This library is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Library General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Library General Public |
18 | * License along with this library. If not, see <http://www.gnu.org/licenses/>. |
19 | */ |
20 | |
21 | #include <string.h> |
22 | #include <glib/gstdio.h> |
23 | #include <gtk/gtk.h> |
24 | #include "testsuite/testutils.h" |
25 | |
26 | #ifdef G_OS_WIN32 |
27 | # include <io.h> |
28 | #endif |
29 | |
30 | |
31 | static char * |
32 | test_get_reference_file (const char *ui_file) |
33 | { |
34 | GString *file = g_string_new (NULL); |
35 | |
36 | if (g_str_has_suffix (str: ui_file, suffix: ".ui" )) |
37 | g_string_append_len (string: file, val: ui_file, len: strlen (s: ui_file) - 3); |
38 | else |
39 | g_string_append (string: file, val: ui_file); |
40 | |
41 | g_string_append (string: file, val: ".nodes" ); |
42 | |
43 | if (!g_file_test (filename: file->str, test: G_FILE_TEST_EXISTS)) |
44 | { |
45 | g_string_free (string: file, TRUE); |
46 | return g_strdup (str: ui_file); |
47 | } |
48 | |
49 | return g_string_free (string: file, FALSE); |
50 | } |
51 | |
52 | static void |
53 | style_context_changed (GtkWidget *window, const char **output) |
54 | { |
55 | GtkStyleContext *context; |
56 | |
57 | context = gtk_widget_get_style_context (widget: window); |
58 | |
59 | *output = gtk_style_context_to_string (context, flags: GTK_STYLE_CONTEXT_PRINT_RECURSE); |
60 | |
61 | g_main_context_wakeup (NULL); |
62 | } |
63 | |
64 | static void |
65 | load_ui_file (GFile *file, gboolean generate) |
66 | { |
67 | GtkBuilder *builder; |
68 | GtkWidget *window; |
69 | char *output, *diff; |
70 | char *ui_file, *reference_file; |
71 | GError *error = NULL; |
72 | |
73 | ui_file = g_file_get_path (file); |
74 | |
75 | if (g_str_has_suffix (str: ui_file, suffix: ".rtl.ui" )) |
76 | gtk_widget_set_default_direction (dir: GTK_TEXT_DIR_RTL); |
77 | else |
78 | gtk_widget_set_default_direction (dir: GTK_TEXT_DIR_LTR); |
79 | |
80 | builder = gtk_builder_new_from_file (filename: ui_file); |
81 | window = GTK_WIDGET (gtk_builder_get_object (builder, "window1" )); |
82 | |
83 | g_assert_nonnull (window); |
84 | |
85 | output = NULL; |
86 | g_signal_connect (window, "map" , G_CALLBACK (style_context_changed), &output); |
87 | |
88 | gtk_widget_show (widget: window); |
89 | |
90 | while (!output) |
91 | g_main_context_iteration (NULL, FALSE); |
92 | |
93 | if (generate) |
94 | { |
95 | g_print (format: "%s" , output); |
96 | goto out; |
97 | } |
98 | |
99 | reference_file = test_get_reference_file (ui_file); |
100 | |
101 | diff = diff_with_file (file1: reference_file, text: output, len: -1, error: &error); |
102 | g_assert_no_error (error); |
103 | |
104 | if (diff && diff[0]) |
105 | { |
106 | g_test_message (format: "Resulting output doesn't match reference:\n%s" , diff); |
107 | g_test_fail (); |
108 | } |
109 | g_free (mem: reference_file); |
110 | g_free (mem: diff); |
111 | |
112 | out: |
113 | g_free (mem: output); |
114 | g_free (mem: ui_file); |
115 | } |
116 | |
117 | static void |
118 | test_ui_file (GFile *file) |
119 | { |
120 | load_ui_file (file, FALSE); |
121 | } |
122 | |
123 | static void |
124 | add_test_for_file (GFile *file) |
125 | { |
126 | char *path; |
127 | |
128 | path = g_file_get_path (file); |
129 | |
130 | g_test_add_vtable (testpath: path, |
131 | data_size: 0, |
132 | g_object_ref (file), |
133 | NULL, |
134 | data_test: (GTestFixtureFunc) test_ui_file, |
135 | data_teardown: (GTestFixtureFunc) g_object_unref); |
136 | |
137 | g_free (mem: path); |
138 | } |
139 | |
140 | static int |
141 | compare_files (gconstpointer a, gconstpointer b) |
142 | { |
143 | GFile *file1 = G_FILE (a); |
144 | GFile *file2 = G_FILE (b); |
145 | char *path1, *path2; |
146 | int result; |
147 | |
148 | path1 = g_file_get_path (file: file1); |
149 | path2 = g_file_get_path (file: file2); |
150 | |
151 | result = strcmp (s1: path1, s2: path2); |
152 | |
153 | g_free (mem: path1); |
154 | g_free (mem: path2); |
155 | |
156 | return result; |
157 | } |
158 | |
159 | static void |
160 | add_tests_for_files_in_directory (GFile *dir) |
161 | { |
162 | GFileEnumerator *enumerator; |
163 | GFileInfo *info; |
164 | GList *files; |
165 | GError *error = NULL; |
166 | |
167 | enumerator = g_file_enumerate_children (file: dir, G_FILE_ATTRIBUTE_STANDARD_NAME, flags: 0, NULL, error: &error); |
168 | g_assert_no_error (error); |
169 | files = NULL; |
170 | |
171 | while ((info = g_file_enumerator_next_file (enumerator, NULL, error: &error))) |
172 | { |
173 | const char *filename; |
174 | |
175 | filename = g_file_info_get_name (info); |
176 | |
177 | if (!g_str_has_suffix (str: filename, suffix: ".ui" ) || |
178 | g_str_has_suffix (str: filename, suffix: ".nodes" )) |
179 | { |
180 | g_object_unref (object: info); |
181 | continue; |
182 | } |
183 | |
184 | files = g_list_prepend (list: files, data: g_file_get_child (file: dir, name: filename)); |
185 | |
186 | g_object_unref (object: info); |
187 | } |
188 | |
189 | g_assert_no_error (error); |
190 | g_object_unref (object: enumerator); |
191 | |
192 | files = g_list_sort (list: files, compare_func: compare_files); |
193 | g_list_foreach (list: files, func: (GFunc) add_test_for_file, NULL); |
194 | g_list_free_full (list: files, free_func: g_object_unref); |
195 | } |
196 | |
197 | int |
198 | main (int argc, char **argv) |
199 | { |
200 | g_setenv (variable: "GTK_CSS_DEBUG" , value: "1" , TRUE); |
201 | |
202 | if (argc >=3 && strcmp (s1: argv[1], s2: "--generate" ) == 0) |
203 | { |
204 | GFile *file = g_file_new_for_commandline_arg (arg: argv[2]); |
205 | |
206 | gtk_init (); |
207 | |
208 | load_ui_file (file, TRUE); |
209 | |
210 | g_object_unref (object: file); |
211 | |
212 | return 0; |
213 | } |
214 | |
215 | gtk_test_init (argcp: &argc, argvp: &argv); |
216 | |
217 | if (argc < 2) |
218 | { |
219 | const char *basedir; |
220 | GFile *dir; |
221 | |
222 | basedir = g_test_get_dir (file_type: G_TEST_DIST); |
223 | dir = g_file_new_for_path (path: basedir); |
224 | add_tests_for_files_in_directory (dir); |
225 | |
226 | g_object_unref (object: dir); |
227 | } |
228 | else |
229 | { |
230 | guint i; |
231 | |
232 | for (i = 1; i < argc; i++) |
233 | { |
234 | GFile *file = g_file_new_for_commandline_arg (arg: argv[i]); |
235 | |
236 | add_test_for_file (file); |
237 | |
238 | g_object_unref (object: file); |
239 | } |
240 | } |
241 | |
242 | return g_test_run (); |
243 | } |
244 | |
245 | |