1 | /* GIO default value tests |
2 | * Copyright (C) 2013 Red Hat, Inc. |
3 | * |
4 | * This library is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU Lesser General Public |
6 | * License as published by the Free Software Foundation; either |
7 | * version 2.1 of the License, or (at your option) any later version. |
8 | * |
9 | * This library is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | * Lesser General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU Lesser General Public License |
15 | * along with this library; if not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | |
18 | #include <string.h> |
19 | #include <gio/gio.h> |
20 | |
21 | static void |
22 | check_property (const char *output, |
23 | GParamSpec *pspec, |
24 | GValue *value) |
25 | { |
26 | GValue default_value = G_VALUE_INIT; |
27 | char *v, *dv, *msg; |
28 | |
29 | if (g_param_value_defaults (pspec, value)) |
30 | return; |
31 | |
32 | g_param_value_set_default (pspec, value: &default_value); |
33 | |
34 | v = g_strdup_value_contents (value); |
35 | dv = g_strdup_value_contents (value: &default_value); |
36 | |
37 | msg = g_strdup_printf (format: "%s %s.%s: %s != %s\n" , |
38 | output, |
39 | g_type_name (type: pspec->owner_type), |
40 | pspec->name, |
41 | dv, v); |
42 | g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, message: msg); |
43 | g_free (mem: msg); |
44 | |
45 | g_free (mem: v); |
46 | g_free (mem: dv); |
47 | g_value_unset (value: &default_value); |
48 | } |
49 | |
50 | static void |
51 | test_type (gconstpointer data) |
52 | { |
53 | GObjectClass *klass; |
54 | GObject *instance; |
55 | GParamSpec **pspecs; |
56 | guint n_pspecs, i; |
57 | GType type; |
58 | |
59 | type = * (GType *) data; |
60 | |
61 | if (g_type_is_a (type, G_TYPE_APP_INFO_MONITOR)) |
62 | { |
63 | g_test_skip (msg: "singleton" ); |
64 | return; |
65 | } |
66 | |
67 | if (g_type_is_a (type, G_TYPE_BINDING) || |
68 | g_type_is_a (type, G_TYPE_BUFFERED_INPUT_STREAM) || |
69 | g_type_is_a (type, G_TYPE_BUFFERED_OUTPUT_STREAM) || |
70 | g_type_is_a (type, G_TYPE_CHARSET_CONVERTER) || |
71 | g_type_is_a (type, G_TYPE_DBUS_ACTION_GROUP) || |
72 | g_type_is_a (type, G_TYPE_DBUS_CONNECTION) || |
73 | g_type_is_a (type, G_TYPE_DBUS_OBJECT_MANAGER_CLIENT) || |
74 | g_type_is_a (type, G_TYPE_DBUS_OBJECT_MANAGER_SERVER) || |
75 | g_type_is_a (type, G_TYPE_DBUS_PROXY) || |
76 | g_type_is_a (type, G_TYPE_DBUS_SERVER) || |
77 | g_type_is_a (type, G_TYPE_FILTER_OUTPUT_STREAM) || |
78 | g_type_is_a (type, G_TYPE_FILTER_INPUT_STREAM) || |
79 | g_type_is_a (type, G_TYPE_INET_ADDRESS) || |
80 | g_type_is_a (type, G_TYPE_INET_SOCKET_ADDRESS) || |
81 | g_type_is_a (type, G_TYPE_PROPERTY_ACTION) || |
82 | g_type_is_a (type, G_TYPE_SETTINGS) || |
83 | g_type_is_a (type, G_TYPE_SOCKET_CONNECTION) || |
84 | g_type_is_a (type, G_TYPE_SIMPLE_IO_STREAM) || |
85 | g_type_is_a (type, G_TYPE_THEMED_ICON) || |
86 | FALSE) |
87 | { |
88 | g_test_skip (msg: "mandatory construct params" ); |
89 | return; |
90 | } |
91 | |
92 | if (g_type_is_a (type, G_TYPE_DBUS_MENU_MODEL) || |
93 | g_type_is_a (type, G_TYPE_DBUS_METHOD_INVOCATION)) |
94 | { |
95 | g_test_skip (msg: "crash in finalize" ); |
96 | return; |
97 | } |
98 | |
99 | if (g_type_is_a (type, G_TYPE_FILE_ENUMERATOR) || |
100 | g_type_is_a (type, G_TYPE_FILE_IO_STREAM)) |
101 | { |
102 | g_test_skip (msg: "should be abstract" ); |
103 | return; |
104 | } |
105 | |
106 | klass = g_type_class_ref (type); |
107 | instance = g_object_new (object_type: type, NULL); |
108 | |
109 | if (G_IS_INITABLE (instance) && |
110 | !g_initable_init (G_INITABLE (instance), NULL, NULL)) |
111 | { |
112 | g_test_skip (msg: "initialization failed" ); |
113 | g_object_unref (object: instance); |
114 | g_type_class_unref (g_class: klass); |
115 | return; |
116 | } |
117 | |
118 | if (g_type_is_a (type, G_TYPE_INITIALLY_UNOWNED)) |
119 | g_object_ref_sink (instance); |
120 | |
121 | pspecs = g_object_class_list_properties (oclass: klass, n_properties: &n_pspecs); |
122 | for (i = 0; i < n_pspecs; ++i) |
123 | { |
124 | GParamSpec *pspec = pspecs[i]; |
125 | GValue value = G_VALUE_INIT; |
126 | |
127 | if (pspec->owner_type != type) |
128 | continue; |
129 | |
130 | if ((pspec->flags & G_PARAM_READABLE) == 0) |
131 | continue; |
132 | |
133 | if (g_type_is_a (type, G_TYPE_APPLICATION) && |
134 | (strcmp (s1: pspec->name, s2: "is-remote" ) == 0)) |
135 | { |
136 | g_test_message (format: "skipping GApplication:is-remote" ); |
137 | continue; |
138 | } |
139 | |
140 | if (g_type_is_a (type, G_TYPE_PROXY_ADDRESS_ENUMERATOR) && |
141 | (strcmp (s1: pspec->name, s2: "proxy-resolver" ) == 0)) |
142 | { |
143 | g_test_message (format: "skipping GProxyAddressEnumerator:proxy-resolver" ); |
144 | continue; |
145 | } |
146 | |
147 | if (g_type_is_a (type, G_TYPE_SOCKET_CLIENT) && |
148 | (strcmp (s1: pspec->name, s2: "proxy-resolver" ) == 0)) |
149 | { |
150 | g_test_message (format: "skipping GSocketClient:proxy-resolver" ); |
151 | continue; |
152 | } |
153 | |
154 | if (g_test_verbose ()) |
155 | g_printerr (format: "Property %s.%s\n" , g_type_name (type: pspec->owner_type), pspec->name); |
156 | g_value_init (value: &value, G_PARAM_SPEC_VALUE_TYPE (pspec)); |
157 | g_object_get_property (object: instance, property_name: pspec->name, value: &value); |
158 | check_property (output: "Property" , pspec, value: &value); |
159 | g_value_unset (value: &value); |
160 | } |
161 | g_free (mem: pspecs); |
162 | g_object_unref (object: instance); |
163 | g_type_class_unref (g_class: klass); |
164 | } |
165 | |
166 | static GType *all_registered_types; |
167 | |
168 | static const GType * |
169 | list_all_types (void) |
170 | { |
171 | if (!all_registered_types) |
172 | { |
173 | GType *tp; |
174 | all_registered_types = g_new0 (GType, 1000); |
175 | tp = all_registered_types; |
176 | #include "giotypefuncs.inc" |
177 | *tp = 0; |
178 | } |
179 | |
180 | return all_registered_types; |
181 | } |
182 | |
183 | int |
184 | main (int argc, char **argv) |
185 | { |
186 | const GType *otypes; |
187 | guint i; |
188 | GTestDBus *bus; |
189 | gint result; |
190 | |
191 | g_setenv (variable: "GIO_USE_VFS" , value: "local" , TRUE); |
192 | g_setenv (variable: "GSETTINGS_BACKEND" , value: "memory" , TRUE); |
193 | |
194 | g_test_init (argc: &argc, argv: &argv, NULL); |
195 | |
196 | /* Create one test bus for all tests, as we have a lot of very small |
197 | * and quick tests. |
198 | */ |
199 | bus = g_test_dbus_new (flags: G_TEST_DBUS_NONE); |
200 | g_test_dbus_up (self: bus); |
201 | |
202 | otypes = list_all_types (); |
203 | for (i = 0; otypes[i]; i++) |
204 | { |
205 | gchar *testname; |
206 | |
207 | if (!G_TYPE_IS_CLASSED (otypes[i])) |
208 | continue; |
209 | |
210 | if (G_TYPE_IS_ABSTRACT (otypes[i])) |
211 | continue; |
212 | |
213 | if (!g_type_is_a (type: otypes[i], G_TYPE_OBJECT)) |
214 | continue; |
215 | |
216 | testname = g_strdup_printf (format: "/Default Values/%s" , |
217 | g_type_name (type: otypes[i])); |
218 | g_test_add_data_func (testpath: testname, test_data: &otypes[i], test_func: test_type); |
219 | g_free (mem: testname); |
220 | } |
221 | |
222 | result = g_test_run (); |
223 | |
224 | g_test_dbus_down (self: bus); |
225 | g_object_unref (object: bus); |
226 | |
227 | return result; |
228 | } |
229 | |