1/* Simple sanity-check for D-Bus syntax validation.
2 *
3 * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
4 * Copyright �� 2010-2011 Nokia Corporation
5 *
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction,
9 * including without limitation the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27#include <config.h>
28
29#include <glib.h>
30
31#include <dbus/dbus.h>
32
33typedef struct {
34    DBusError e;
35} Fixture;
36
37typedef struct {
38    dbus_bool_t (*function) (const char *, DBusError *);
39    const char * const * valid;
40    const char * const * invalid;
41} Test;
42
43Test paths, interfaces, members, errors, bus_names, signatures,
44     single_signatures, strings;
45
46const char * const valid_paths[] = {
47    "/",
48    "/a",
49    "/_",
50    "/a/b/c",
51    "/com/example/123",
52    "/org/freedesktop/DBus",
53    "/org/freedesktop/Telepathy/AccountManager",
54    NULL
55};
56
57const char * const invalid_paths[] = {
58    "",
59    ".",
60    "//",
61    "/a/",
62    "/-",
63    "/com//example/MyApp",
64    "/$",
65    "/\xa9",      /* �� in latin-1 */
66    "/\xc2\xa9",  /* �� in UTF-8 */
67    NULL
68};
69
70const char * const valid_interfaces[] = {
71    "com.example",
72    "com.example.a0",
73    "org.freedesktop.DBus",
74    NULL
75};
76
77const char * const invalid_interfaces[] = {
78   "",
79    "com",
80    "com.example.",
81    "com.example..a0",
82    "com.example.0a",
83    "com.example.a$",
84    "com.example.a\xa9",
85    "com.example.a\xc2\xa9",
86    NULL
87};
88
89const char * const valid_members[] = {
90    "_",
91    "a",
92    "a0",
93    "GetAll",
94    "BadgerMushroomSnake",
95    NULL
96};
97
98const char * const invalid_members[] = {
99    "",
100    "-",
101    "a-",
102    "0",
103    "0_",
104    "Badger.Mushroom",
105    "a$",
106    "a\xa9",
107    "a\xc2\xa9",
108    NULL
109};
110
111const char * const valid_errors[] = {
112    "com.example",
113    "com.example.a0",
114    "org.freedesktop.DBus.NameHasNoOwner",
115    NULL
116};
117
118const char * const invalid_errors[] = {
119   "",
120    "com",
121    "com.example.",
122    "com.example..a0",
123    "com.example.0a",
124    "com.example.a$",
125    "com.example.a\xa9",
126    "com.example.a\xc2\xa9",
127    NULL
128};
129
130const char * const valid_bus_names[] = {
131    "com.example",
132    "com.example.a0",
133    "com.example._",
134    ":1.42",
135    ":1.2.3.4.5",
136    ":com.example",
137    "org.freedesktop.DBus",
138    NULL
139};
140
141const char * const invalid_bus_names[] = {
142   "",
143    "com",
144    "com.example.",
145    "com.example..a0",
146    "com.example.0a",
147    "com.example.a:b",
148    "com.example.a\xa9",
149    "com.example.a\xc2\xa9",
150    NULL
151};
152
153const char * const valid_signatures[] = {
154    "",
155    "a{sv}",
156    NULL
157};
158
159const char * const invalid_signatures[] = {
160    "a",
161    "a{s_}",
162    NULL
163};
164
165const char * const valid_single_signatures[] = {
166    "s",
167    "a{sv}",
168    NULL
169};
170
171const char * const invalid_single_signatures[] = {
172    "",
173    "a",
174    "sv",
175    "a{sv}as",
176    NULL
177};
178
179const char * const valid_strings[] = {
180    "",
181    "\xc2\xa9",
182    NULL
183};
184
185const char * const invalid_strings[] = {
186    "\xa9",
187    NULL
188};
189
190static void
191setup (Fixture *f,
192    gconstpointer arg G_GNUC_UNUSED)
193{
194  dbus_error_init (&f->e);
195
196#define FILL_TEST(name, func) \
197  do { \
198    (name).function = (func); \
199    (name).valid = valid_ ## name; \
200    (name).invalid = invalid_ ## name; \
201  } while (0)
202
203  FILL_TEST (paths, dbus_validate_path);
204  FILL_TEST (interfaces, dbus_validate_interface);
205  FILL_TEST (members, dbus_validate_member);
206  FILL_TEST (errors, dbus_validate_error_name);
207  FILL_TEST (bus_names, dbus_validate_bus_name);
208  FILL_TEST (signatures, dbus_signature_validate);
209  FILL_TEST (single_signatures, dbus_signature_validate_single);
210  FILL_TEST (strings, dbus_validate_utf8);
211}
212
213static void
214test_syntax (Fixture *f,
215    gconstpointer arg)
216{
217  const Test *test = arg;
218  int i;
219
220  g_assert (test != NULL);
221  g_assert (test->function != NULL);
222  g_assert (test->valid != NULL);
223  g_assert (test->invalid != NULL);
224
225  for (i = 0; test->valid[i] != NULL; i++)
226    {
227      dbus_bool_t ok = test->function (test->valid[i], &f->e);
228
229      if (dbus_error_is_set (&f->e))
230        g_error ("%s was considered invalid: %s: %s", test->valid[i],
231            f->e.name, f->e.message);
232
233      if (!ok)
234        g_error ("%s was considered invalid without an error", test->valid[i]);
235    }
236
237  for (i = 0; test->invalid[i] != NULL; i++)
238    {
239      dbus_bool_t ok = test->function (test->invalid[i], &f->e);
240
241      if (ok)
242        g_error ("%s should have been considered invalid", test->invalid[i]);
243
244      if (!dbus_error_is_set (&f->e))
245        g_error ("%s should have an error set", test->invalid[i]);
246
247      if (!dbus_validate_error_name (f->e.name, NULL))
248        g_error ("%s produced an invalid error name: %s",
249            test->invalid[i], f->e.name);
250
251      if (!dbus_validate_utf8 (f->e.message, NULL))
252        g_error ("%s produced an invalid error message: %s",
253            test->invalid[i], f->e.message);
254
255      dbus_error_free (&f->e);
256    }
257}
258
259static void
260teardown (Fixture *f,
261    gconstpointer arg G_GNUC_UNUSED)
262{
263  dbus_error_free (&f->e);
264}
265
266int
267main (int argc,
268    char **argv)
269{
270  g_test_init (&argc, &argv, NULL);
271
272  g_test_add ("/syntax/path", Fixture, &paths, setup, test_syntax, teardown);
273  g_test_add ("/syntax/interface", Fixture, &interfaces,
274      setup, test_syntax, teardown);
275  g_test_add ("/syntax/error", Fixture, &errors,
276      setup, test_syntax, teardown);
277  g_test_add ("/syntax/member", Fixture, &members,
278      setup, test_syntax, teardown);
279  g_test_add ("/syntax/bus-name", Fixture, &bus_names,
280      setup, test_syntax, teardown);
281  g_test_add ("/syntax/signature", Fixture, &signatures,
282      setup, test_syntax, teardown);
283  g_test_add ("/syntax/single-signature", Fixture, &single_signatures,
284      setup, test_syntax, teardown);
285  g_test_add ("/syntax/utf8", Fixture, &strings,
286      setup, test_syntax, teardown);
287
288  return g_test_run ();
289}
290