1 /* Simple sanity-check for loopback through TCP and Unix sockets.
3 * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
4 * Copyright © 2010-2012 Nokia Corporation
5 * Copyright © 2015 Collabora Ltd.
7 * Permission is hereby granted, free of charge, to any person
8 * obtaining a copy of this software and associated documentation files
9 * (the "Software"), to deal in the Software without restriction,
10 * including without limitation the rights to use, copy, modify, merge,
11 * publish, distribute, sublicense, and/or sell copies of the Software,
12 * and to permit persons to whom the Software is furnished to do so,
13 * subject to the following conditions:
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 #include <glib/gstdio.h>
33 #include <dbus/dbus.h>
38 #include "test-utils-glib.h"
45 DBusConnection *server_conn;
46 /* queue of DBusMessage */
47 GQueue server_messages;
49 DBusConnection *client_conn;
51 gchar *tmp_runtime_dir;
52 gchar *saved_runtime_dir;
56 assert_no_error (const DBusError *e)
58 if (G_UNLIKELY (dbus_error_is_set (e)))
59 g_error ("expected success but got error: %s: %s", e->name, e->message);
62 static DBusHandlerResult
63 server_message_cb (DBusConnection *server_conn,
69 g_assert (server_conn == f->server_conn);
70 g_queue_push_tail (&f->server_messages, dbus_message_ref (message));
72 return DBUS_HANDLER_RESULT_HANDLED;
76 new_conn_cb (DBusServer *server,
77 DBusConnection *server_conn,
83 g_assert (f->server_conn == NULL);
84 f->server_conn = dbus_connection_ref (server_conn);
85 test_connection_setup (f->ctx, server_conn);
87 have_mem = dbus_connection_add_filter (server_conn,
88 server_message_cb, f, NULL);
96 f->ctx = test_main_context_get ();
97 dbus_error_init (&f->e);
98 g_queue_init (&f->server_messages);
100 f->server = dbus_server_listen (addr, &f->e);
101 assert_no_error (&f->e);
102 g_assert (f->server != NULL);
104 dbus_server_set_new_connection_function (f->server,
105 new_conn_cb, f, NULL);
106 test_server_setup (f->ctx, f->server);
111 setup_runtime (Fixture *f,
115 GError *error = NULL;
117 /* this is chosen to be something needing escaping */
118 f->tmp_runtime_dir = g_dir_make_tmp ("dbus=daemon=test.XXXXXX", &error);
119 g_assert_no_error (error);
121 /* we're relying on being single-threaded for this to be safe */
122 f->saved_runtime_dir = g_strdup (g_getenv ("XDG_RUNTIME_DIR"));
123 g_setenv ("XDG_RUNTIME_DIR", f->tmp_runtime_dir, TRUE);
127 listening_at = dbus_server_get_address (f->server);
128 g_test_message ("listening at %s", listening_at);
129 g_assert (g_str_has_prefix (listening_at, "unix:path="));
130 g_assert (strstr (listening_at, "dbus%3ddaemon%3dtest.") != NULL);
131 g_assert (strstr (listening_at, "/bus,") != NULL ||
132 g_str_has_suffix (listening_at, "/bus"));
134 dbus_free (listening_at);
138 setup_no_runtime (Fixture *f,
143 /* we're relying on being single-threaded for this to be safe */
144 f->saved_runtime_dir = g_strdup (g_getenv ("XDG_RUNTIME_DIR"));
145 g_unsetenv ("XDG_RUNTIME_DIR");
149 listening_at = dbus_server_get_address (f->server);
150 g_test_message ("listening at %s", listening_at);
151 /* we have fallen back to something in /tmp, either abstract or not */
152 g_assert (g_str_has_prefix (listening_at, "unix:"));
153 g_assert (strstr (listening_at, "=/tmp/") != NULL);
155 dbus_free (listening_at);
160 test_connect (Fixture *f,
161 gconstpointer addr G_GNUC_UNUSED)
163 g_assert (f->server_conn == NULL);
165 f->client_conn = dbus_connection_open_private (
166 dbus_server_get_address (f->server), &f->e);
167 assert_no_error (&f->e);
168 g_assert (f->client_conn != NULL);
169 test_connection_setup (f->ctx, f->client_conn);
171 while (f->server_conn == NULL)
174 test_main_context_iterate (f->ctx, TRUE);
179 test_bad_guid (Fixture *f,
180 gconstpointer addr G_GNUC_UNUSED)
182 DBusMessage *incoming;
183 gchar *address = g_strdup (dbus_server_get_address (f->server));
186 g_test_bug ("39720");
188 g_assert (f->server_conn == NULL);
190 g_assert (strstr (address, "guid=") != NULL);
191 guid = strstr (address, "guid=");
192 g_assert_cmpuint (strlen (guid), >=, 5 + 32);
194 /* Change the first char of the guid to something different */
200 f->client_conn = dbus_connection_open_private (address, &f->e);
201 assert_no_error (&f->e);
202 g_assert (f->client_conn != NULL);
203 test_connection_setup (f->ctx, f->client_conn);
205 while (f->server_conn == NULL)
208 test_main_context_iterate (f->ctx, TRUE);
211 /* We get disconnected */
213 while (g_queue_is_empty (&f->server_messages))
216 test_main_context_iterate (f->ctx, TRUE);
219 g_assert_cmpuint (g_queue_get_length (&f->server_messages), ==, 1);
221 incoming = g_queue_pop_head (&f->server_messages);
223 g_assert (!dbus_message_contains_unix_fds (incoming));
224 g_assert_cmpstr (dbus_message_get_destination (incoming), ==, NULL);
225 g_assert_cmpstr (dbus_message_get_error_name (incoming), ==, NULL);
226 g_assert_cmpstr (dbus_message_get_interface (incoming), ==,
227 DBUS_INTERFACE_LOCAL);
228 g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Disconnected");
229 g_assert_cmpstr (dbus_message_get_sender (incoming), ==, NULL);
230 g_assert_cmpstr (dbus_message_get_signature (incoming), ==, "");
231 g_assert_cmpstr (dbus_message_get_path (incoming), ==, DBUS_PATH_LOCAL);
233 dbus_message_unref (incoming);
239 test_message (Fixture *f,
242 dbus_bool_t have_mem;
243 dbus_uint32_t serial;
244 DBusMessage *outgoing, *incoming;
246 test_connect (f, addr);
248 outgoing = dbus_message_new_signal ("/com/example/Hello",
249 "com.example.Hello", "Greeting");
250 g_assert (outgoing != NULL);
252 have_mem = dbus_connection_send (f->client_conn, outgoing, &serial);
254 g_assert (serial != 0);
256 while (g_queue_is_empty (&f->server_messages))
259 test_main_context_iterate (f->ctx, TRUE);
262 g_assert_cmpuint (g_queue_get_length (&f->server_messages), ==, 1);
264 incoming = g_queue_pop_head (&f->server_messages);
266 g_assert (!dbus_message_contains_unix_fds (incoming));
267 g_assert_cmpstr (dbus_message_get_destination (incoming), ==, NULL);
268 g_assert_cmpstr (dbus_message_get_error_name (incoming), ==, NULL);
269 g_assert_cmpstr (dbus_message_get_interface (incoming), ==,
270 "com.example.Hello");
271 g_assert_cmpstr (dbus_message_get_member (incoming), ==, "Greeting");
272 g_assert_cmpstr (dbus_message_get_sender (incoming), ==, NULL);
273 g_assert_cmpstr (dbus_message_get_signature (incoming), ==, "");
274 g_assert_cmpstr (dbus_message_get_path (incoming), ==, "/com/example/Hello");
275 g_assert_cmpuint (dbus_message_get_serial (incoming), ==, serial);
277 dbus_message_unref (incoming);
279 dbus_message_unref (outgoing);
283 teardown (Fixture *f,
284 gconstpointer addr G_GNUC_UNUSED)
286 if (f->client_conn != NULL)
288 dbus_connection_close (f->client_conn);
289 dbus_connection_unref (f->client_conn);
290 f->client_conn = NULL;
293 if (f->server_conn != NULL)
295 dbus_connection_close (f->server_conn);
296 dbus_connection_unref (f->server_conn);
297 f->server_conn = NULL;
300 if (f->server != NULL)
302 dbus_server_disconnect (f->server);
303 dbus_server_unref (f->server);
307 test_main_context_unref (f->ctx);
312 teardown_no_runtime (Fixture *f,
317 /* we're relying on being single-threaded for this to be safe */
318 if (f->saved_runtime_dir != NULL)
319 g_setenv ("XDG_RUNTIME_DIR", f->saved_runtime_dir, TRUE);
321 g_unsetenv ("XDG_RUNTIME_DIR");
322 g_free (f->saved_runtime_dir);
326 teardown_runtime (Fixture *f,
333 /* the socket may exist */
334 path = g_strdup_printf ("%s/bus", f->tmp_runtime_dir);
335 g_assert (g_remove (path) == 0 || errno == ENOENT);
337 /* there shouldn't be anything else in there */
338 g_assert_cmpint (g_rmdir (f->tmp_runtime_dir), ==, 0);
340 /* we're relying on being single-threaded for this to be safe */
341 if (f->saved_runtime_dir != NULL)
342 g_setenv ("XDG_RUNTIME_DIR", f->saved_runtime_dir, TRUE);
344 g_unsetenv ("XDG_RUNTIME_DIR");
345 g_free (f->saved_runtime_dir);
346 g_free (f->tmp_runtime_dir);
354 test_init (&argc, &argv);
356 g_test_add ("/connect/tcp", Fixture, "tcp:host=127.0.0.1", setup,
357 test_connect, teardown);
358 g_test_add ("/message/tcp", Fixture, "tcp:host=127.0.0.1", setup,
359 test_message, teardown);
361 g_test_add ("/connect/nonce-tcp", Fixture, "nonce-tcp:host=127.0.0.1", setup,
362 test_connect, teardown);
363 g_test_add ("/message/nonce-tcp", Fixture, "nonce-tcp:host=127.0.0.1", setup,
364 test_message, teardown);
367 g_test_add ("/connect/unix", Fixture, "unix:tmpdir=/tmp", setup,
368 test_connect, teardown);
369 g_test_add ("/message/unix", Fixture, "unix:tmpdir=/tmp", setup,
370 test_message, teardown);
372 g_test_add ("/connect/unix/runtime", Fixture,
373 "unix:runtime=yes;unix:tmpdir=/tmp", setup_runtime, test_connect,
375 g_test_add ("/connect/unix/no-runtime", Fixture,
376 "unix:runtime=yes;unix:tmpdir=/tmp", setup_no_runtime, test_connect,
377 teardown_no_runtime);
380 g_test_add ("/message/bad-guid", Fixture, "tcp:host=127.0.0.1", setup,
381 test_bad_guid, teardown);
383 return g_test_run ();