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
31static char *
32test_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
52static void
53style_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
64static void
65load_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
112out:
113 g_free (mem: output);
114 g_free (mem: ui_file);
115}
116
117static void
118test_ui_file (GFile *file)
119{
120 load_ui_file (file, FALSE);
121}
122
123static void
124add_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
140static int
141compare_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
159static void
160add_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
197int
198main (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

source code of gtk/testsuite/css/nodes/test-css-nodes.c