bus: Assign a serial number for messages from the driver
[platform/upstream/dbus.git] / test / dbus-daemon.c
1 /* Integration tests for the dbus-daemon
2  *
3  * Author: Simon McVittie <simon.mcvittie@collabora.co.uk>
4  * Copyright © 2010-2011 Nokia Corporation
5  * Copyright © 2015 Collabora Ltd.
6  *
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:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
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
25  * SOFTWARE.
26  */
27
28 #include <config.h>
29
30 #include <errno.h>
31 #include <string.h>
32
33 #include <dbus/dbus.h>
34
35 #include <glib.h>
36 #include <glib/gstdio.h>
37 #include <gio/gio.h>
38
39 #include "bus/stats.h"
40 #include "test-utils-glib.h"
41
42 #include <string.h>
43
44 #ifdef DBUS_UNIX
45 # include <pwd.h>
46 # include <unistd.h>
47 # include <sys/types.h>
48
49 # ifdef HAVE_GIO_UNIX
50     /* The CMake build system doesn't know how to check for this yet */
51 #   include <gio/gunixfdmessage.h>
52 # endif
53
54 # ifdef HAVE_SYS_RESOURCE_H
55 #   include <sys/resource.h>
56 # endif
57
58 # ifdef HAVE_SYS_TIME_H
59 #   include <sys/time.h>
60 # endif
61 #endif
62
63 /* Platforms where we know that credentials-passing passes both the
64  * uid and the pid. Please keep these in alphabetical order.
65  *
66  * These platforms should #error in _dbus_read_credentials_socket()
67  * if we didn't detect their flavour of credentials-passing, since that
68  * would be a regression.
69  */
70 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
71   defined(__linux__) || \
72   defined(__NetBSD__) || \
73   defined(__OpenBSD__)
74 # define UNIX_USER_SHOULD_WORK
75 # define PID_SHOULD_WORK
76 #endif
77
78 /* Platforms where we know that credentials-passing passes the
79  * uid, but not necessarily the pid. Again, alphabetical order please.
80  *
81  * These platforms should also #error in _dbus_read_credentials_socket()
82  * if we didn't detect their flavour of credentials-passing.
83  */
84 #if 0 /* defined(__your_platform_here__) */
85 # define UNIX_USER_SHOULD_WORK
86 #endif
87
88 typedef struct {
89     gboolean skip;
90
91     TestMainContext *ctx;
92
93     DBusError e;
94     GError *ge;
95
96     GPid daemon_pid;
97     gchar *address;
98
99     DBusConnection *left_conn;
100
101     DBusConnection *right_conn;
102     GQueue held_messages;
103     gboolean right_conn_echo;
104     gboolean right_conn_hold;
105     gboolean wait_forever_called;
106
107     gchar *tmp_runtime_dir;
108     gchar *saved_runtime_dir;
109 } Fixture;
110
111 static DBusHandlerResult
112 echo_filter (DBusConnection *connection,
113     DBusMessage *message,
114     void *user_data)
115 {
116   Fixture *f = user_data;
117   DBusMessage *reply;
118
119   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
120     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
121
122   /* WaitForever() never replies, emulating a service that has got stuck */
123   if (dbus_message_is_method_call (message, "com.example", "WaitForever"))
124     {
125       f->wait_forever_called = TRUE;
126       return DBUS_HANDLER_RESULT_HANDLED;
127     }
128
129   reply = dbus_message_new_method_return (message);
130
131   if (reply == NULL)
132     g_error ("OOM");
133
134   if (!dbus_connection_send (connection, reply, NULL))
135     g_error ("OOM");
136
137   dbus_clear_message (&reply);
138
139   return DBUS_HANDLER_RESULT_HANDLED;
140 }
141
142 static DBusHandlerResult
143 hold_filter (DBusConnection *connection,
144     DBusMessage *message,
145     void *user_data)
146 {
147   Fixture *f = user_data;
148
149   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
150     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
151
152   g_queue_push_tail (&f->held_messages, dbus_message_ref (message));
153
154   return DBUS_HANDLER_RESULT_HANDLED;
155 }
156
157 typedef struct {
158     const char *bug_ref;
159     guint min_messages;
160     const char *config_file;
161     TestUser user;
162     enum { SPECIFY_ADDRESS = 0, RELY_ON_DEFAULT } connect_mode;
163 } Config;
164
165 static void
166 setup (Fixture *f,
167     gconstpointer context)
168 {
169   const Config *config = context;
170
171   /* Some tests are fairly slow, so make the test timeout per-test */
172   test_timeout_reset (1);
173
174   f->ctx = test_main_context_get ();
175   f->ge = NULL;
176   dbus_error_init (&f->e);
177
178   if (config != NULL && config->connect_mode == RELY_ON_DEFAULT)
179     {
180       /* this is chosen to be something needing escaping */
181       f->tmp_runtime_dir = g_dir_make_tmp ("dbus=daemon=test.XXXXXX", &f->ge);
182       g_assert_no_error (f->ge);
183
184       /* we're relying on being single-threaded for this to be safe */
185       f->saved_runtime_dir = g_strdup (g_getenv ("XDG_RUNTIME_DIR"));
186       g_setenv ("XDG_RUNTIME_DIR", f->tmp_runtime_dir, TRUE);
187       g_unsetenv ("DBUS_SESSION_BUS_ADDRESS");
188     }
189
190   f->address = test_get_dbus_daemon (config ? config->config_file : NULL,
191                                      config ? config->user : TEST_USER_ME,
192                                      NULL, &f->daemon_pid);
193
194   if (f->address == NULL)
195     {
196       f->skip = TRUE;
197       return;
198     }
199
200   f->left_conn = test_connect_to_bus (f->ctx, f->address);
201
202   if (config != NULL && config->connect_mode == RELY_ON_DEFAULT)
203     {
204       /* use the default bus for the echo service ("right"), to check that
205        * it ends up on the same bus as the client ("left") */
206       f->right_conn = dbus_bus_get_private (DBUS_BUS_SESSION, &f->e);
207       test_assert_no_error (&f->e);
208
209       if (!test_connection_setup (f->ctx, f->right_conn))
210         g_error ("OOM");
211     }
212   else
213     {
214       f->right_conn = test_connect_to_bus (f->ctx, f->address);
215     }
216 }
217
218 static void
219 add_echo_filter (Fixture *f)
220 {
221   if (!dbus_connection_add_filter (f->right_conn, echo_filter, f, NULL))
222     g_error ("OOM");
223
224   f->right_conn_echo = TRUE;
225 }
226
227 static void
228 add_hold_filter (Fixture *f)
229 {
230   if (!dbus_connection_add_filter (f->right_conn, hold_filter, f, NULL))
231     g_error ("OOM");
232
233   f->right_conn_hold = TRUE;
234 }
235
236 static void
237 pc_count (DBusPendingCall *pc,
238     void *data)
239 {
240   guint *received_p = data;
241
242   (*received_p)++;
243 }
244
245 static void
246 pc_enqueue (DBusPendingCall *pc,
247             void *data)
248 {
249   GQueue *q = data;
250   DBusMessage *m = dbus_pending_call_steal_reply (pc);
251
252   g_test_message ("message of type %d", dbus_message_get_type (m));
253   g_queue_push_tail (q, m);
254 }
255
256 static void
257 test_echo (Fixture *f,
258     gconstpointer context)
259 {
260   const Config *config = context;
261   guint count = 2000;
262   guint sent;
263   guint received = 0;
264   double elapsed;
265
266   if (f->skip)
267     return;
268
269   if (config != NULL && config->bug_ref != NULL)
270     g_test_bug (config->bug_ref);
271
272   if (g_test_perf ())
273     count = 100000;
274
275   if (config != NULL)
276     count = MAX (config->min_messages, count);
277
278   add_echo_filter (f);
279
280   g_test_timer_start ();
281
282   for (sent = 0; sent < count; sent++)
283     {
284       DBusMessage *m = dbus_message_new_method_call (
285           dbus_bus_get_unique_name (f->right_conn), "/",
286           "com.example", "Spam");
287       DBusPendingCall *pc;
288
289       if (m == NULL)
290         g_error ("OOM");
291
292       if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
293                                             DBUS_TIMEOUT_INFINITE) ||
294           pc == NULL)
295         g_error ("OOM");
296
297       if (dbus_pending_call_get_completed (pc))
298         pc_count (pc, &received);
299       else if (!dbus_pending_call_set_notify (pc, pc_count, &received,
300             NULL))
301         g_error ("OOM");
302
303       dbus_clear_pending_call (&pc);
304       dbus_clear_message (&m);
305     }
306
307   while (received < count)
308     test_main_context_iterate (f->ctx, TRUE);
309
310   elapsed = g_test_timer_elapsed ();
311
312   g_test_maximized_result (count / elapsed, "%u messages / %f seconds",
313       count, elapsed);
314 }
315
316 static void
317 test_no_reply (Fixture *f,
318     gconstpointer context)
319 {
320   const Config *config = context;
321   DBusMessage *m;
322   DBusPendingCall *pc;
323   DBusMessage *reply = NULL;
324   enum { TIMEOUT, DISCONNECT } mode;
325   gboolean ok;
326
327   if (f->skip)
328     return;
329
330   g_test_bug ("76112");
331
332   if (config != NULL && config->config_file != NULL)
333     mode = TIMEOUT;
334   else
335     mode = DISCONNECT;
336
337   m = dbus_message_new_method_call (
338       dbus_bus_get_unique_name (f->right_conn), "/",
339       "com.example", "WaitForever");
340
341   add_echo_filter (f);
342
343   if (m == NULL)
344     g_error ("OOM");
345
346   if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
347                                         DBUS_TIMEOUT_INFINITE) ||
348       pc == NULL)
349     g_error ("OOM");
350
351   if (dbus_pending_call_get_completed (pc))
352     test_pending_call_store_reply (pc, &reply);
353   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
354         &reply, NULL))
355     g_error ("OOM");
356
357   dbus_clear_pending_call (&pc);
358   dbus_clear_message (&m);
359
360   if (mode == DISCONNECT)
361     {
362       while (!f->wait_forever_called)
363         test_main_context_iterate (f->ctx, TRUE);
364
365       dbus_connection_remove_filter (f->right_conn, echo_filter, f);
366       dbus_connection_close (f->right_conn);
367       dbus_clear_connection (&f->right_conn);
368     }
369
370   while (reply == NULL)
371     test_main_context_iterate (f->ctx, TRUE);
372
373   /* using inefficient string comparison for better assertion message */
374   g_assert_cmpstr (
375       dbus_message_type_to_string (dbus_message_get_type (reply)), ==,
376       dbus_message_type_to_string (DBUS_MESSAGE_TYPE_ERROR));
377   ok = dbus_set_error_from_message (&f->e, reply);
378   g_assert (ok);
379   g_assert_cmpstr (f->e.name, ==, DBUS_ERROR_NO_REPLY);
380
381   if (mode == DISCONNECT)
382     g_assert_cmpstr (f->e.message, ==,
383         "Message recipient disconnected from message bus without replying");
384   else
385     g_assert_cmpstr (f->e.message, ==,
386         "Message did not receive a reply (timeout by message bus)");
387
388   dbus_clear_message (&reply);
389 }
390
391 static void
392 test_creds (Fixture *f,
393     gconstpointer context)
394 {
395   const char *unique = dbus_bus_get_unique_name (f->left_conn);
396   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
397       DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetConnectionCredentials");
398   DBusPendingCall *pc;
399   DBusMessageIter args_iter;
400   DBusMessageIter arr_iter;
401   DBusMessageIter pair_iter;
402   DBusMessageIter var_iter;
403   enum {
404       SEEN_UNIX_USER = 1,
405       SEEN_PID = 2,
406       SEEN_WINDOWS_SID = 4,
407       SEEN_LINUX_SECURITY_LABEL = 8
408   } seen = 0;
409
410   if (m == NULL)
411     g_error ("OOM");
412
413   if (!dbus_message_append_args (m,
414         DBUS_TYPE_STRING, &unique,
415         DBUS_TYPE_INVALID))
416     g_error ("OOM");
417
418   if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
419                                         DBUS_TIMEOUT_USE_DEFAULT) ||
420       pc == NULL)
421     g_error ("OOM");
422
423   dbus_clear_message (&m);
424
425   if (dbus_pending_call_get_completed (pc))
426     test_pending_call_store_reply (pc, &m);
427   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
428                                           &m, NULL))
429     g_error ("OOM");
430
431   while (m == NULL)
432     test_main_context_iterate (f->ctx, TRUE);
433
434   g_assert_cmpstr (dbus_message_get_signature (m), ==, "a{sv}");
435
436   dbus_message_iter_init (m, &args_iter);
437   g_assert_cmpuint (dbus_message_iter_get_arg_type (&args_iter), ==,
438       DBUS_TYPE_ARRAY);
439   g_assert_cmpuint (dbus_message_iter_get_element_type (&args_iter), ==,
440       DBUS_TYPE_DICT_ENTRY);
441   dbus_message_iter_recurse (&args_iter, &arr_iter);
442
443   while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
444     {
445       const char *name;
446
447       dbus_message_iter_recurse (&arr_iter, &pair_iter);
448       g_assert_cmpuint (dbus_message_iter_get_arg_type (&pair_iter), ==,
449           DBUS_TYPE_STRING);
450       dbus_message_iter_get_basic (&pair_iter, &name);
451       dbus_message_iter_next (&pair_iter);
452       g_assert_cmpuint (dbus_message_iter_get_arg_type (&pair_iter), ==,
453           DBUS_TYPE_VARIANT);
454       dbus_message_iter_recurse (&pair_iter, &var_iter);
455
456       if (g_strcmp0 (name, "UnixUserID") == 0)
457         {
458 #ifdef G_OS_UNIX
459           guint32 u32;
460
461           g_assert (!(seen & SEEN_UNIX_USER));
462           g_assert_cmpuint (dbus_message_iter_get_arg_type (&var_iter), ==,
463               DBUS_TYPE_UINT32);
464           dbus_message_iter_get_basic (&var_iter, &u32);
465           g_test_message ("%s of this process is %u", name, u32);
466           g_assert_cmpuint (u32, ==, geteuid ());
467           seen |= SEEN_UNIX_USER;
468 #else
469           g_assert_not_reached ();
470 #endif
471         }
472       else if (g_strcmp0 (name, "WindowsSID") == 0)
473         {
474 #ifdef G_OS_WIN32
475           gchar *sid;
476           char *self_sid;
477
478           g_assert (!(seen & SEEN_WINDOWS_SID));
479           g_assert_cmpuint (dbus_message_iter_get_arg_type (&var_iter), ==,
480               DBUS_TYPE_STRING);
481           dbus_message_iter_get_basic (&var_iter, &sid);
482           g_test_message ("%s of this process is %s", name, sid);
483           if (_dbus_getsid (&self_sid, 0))
484             {
485               g_assert_cmpstr (self_sid, ==, sid);
486               LocalFree(self_sid);
487             }
488           seen |= SEEN_WINDOWS_SID;
489 #else
490           g_assert_not_reached ();
491 #endif
492         }
493       else if (g_strcmp0 (name, "ProcessID") == 0)
494         {
495           guint32 u32;
496
497           g_assert (!(seen & SEEN_PID));
498           g_assert_cmpuint (dbus_message_iter_get_arg_type (&var_iter), ==,
499               DBUS_TYPE_UINT32);
500           dbus_message_iter_get_basic (&var_iter, &u32);
501           g_test_message ("%s of this process is %u", name, u32);
502 #ifdef G_OS_UNIX
503           g_assert_cmpuint (u32, ==, getpid ());
504 #elif defined(G_OS_WIN32)
505           g_assert_cmpuint (u32, ==, GetCurrentProcessId ());
506 #else
507           g_assert_not_reached ();
508 #endif
509           seen |= SEEN_PID;
510         }
511       else if (g_strcmp0 (name, "LinuxSecurityLabel") == 0)
512         {
513 #ifdef __linux__
514           gchar *label;
515           int len;
516           DBusMessageIter ay_iter;
517
518           g_assert (!(seen & SEEN_LINUX_SECURITY_LABEL));
519           g_assert_cmpuint (dbus_message_iter_get_arg_type (&var_iter), ==,
520               DBUS_TYPE_ARRAY);
521           dbus_message_iter_recurse (&var_iter, &ay_iter);
522           g_assert_cmpuint (dbus_message_iter_get_arg_type (&ay_iter), ==,
523               DBUS_TYPE_BYTE);
524           dbus_message_iter_get_fixed_array (&ay_iter, &label, &len);
525           g_test_message ("%s of this process is %s", name, label);
526           g_assert_cmpuint (strlen (label) + 1, ==, len);
527           seen |= SEEN_LINUX_SECURITY_LABEL;
528 #else
529           g_assert_not_reached ();
530 #endif
531         }
532
533       dbus_message_iter_next (&arr_iter);
534     }
535
536 #ifdef UNIX_USER_SHOULD_WORK
537   g_assert (seen & SEEN_UNIX_USER);
538 #endif
539
540 #ifdef PID_SHOULD_WORK
541   g_assert (seen & SEEN_PID);
542 #endif
543
544 #ifdef G_OS_WIN32
545   g_assert (seen & SEEN_WINDOWS_SID);
546 #endif
547
548   dbus_clear_message (&m);
549   dbus_clear_pending_call (&pc);
550 }
551
552 static void
553 test_processid (Fixture *f,
554     gconstpointer context)
555 {
556   const char *unique = dbus_bus_get_unique_name (f->left_conn);
557   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
558       DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "GetConnectionUnixProcessID");
559   DBusPendingCall *pc;
560   DBusError error = DBUS_ERROR_INIT;
561   guint32 pid;
562
563   if (m == NULL)
564     g_error ("OOM");
565
566   if (!dbus_message_append_args (m,
567         DBUS_TYPE_STRING, &unique,
568         DBUS_TYPE_INVALID))
569     g_error ("OOM");
570
571   if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
572                                         DBUS_TIMEOUT_USE_DEFAULT) ||
573       pc == NULL)
574     g_error ("OOM");
575
576   dbus_clear_message (&m);
577
578   if (dbus_pending_call_get_completed (pc))
579     test_pending_call_store_reply (pc, &m);
580   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
581                                           &m, NULL))
582     g_error ("OOM");
583
584   while (m == NULL)
585     test_main_context_iterate (f->ctx, TRUE);
586
587   if (dbus_set_error_from_message (&error, m))
588     {
589       g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN);
590
591 #ifdef PID_SHOULD_WORK
592       g_error ("Expected pid to be passed, but got %s: %s",
593           error.name, error.message);
594 #endif
595
596       dbus_error_free (&error);
597     }
598   else if (dbus_message_get_args (m, &error,
599         DBUS_TYPE_UINT32, &pid,
600         DBUS_TYPE_INVALID))
601     {
602       g_assert_cmpstr (dbus_message_get_signature (m), ==, "u");
603       test_assert_no_error (&error);
604
605       g_test_message ("GetConnectionUnixProcessID returned %u", pid);
606
607 #ifdef G_OS_UNIX
608       g_assert_cmpuint (pid, ==, getpid ());
609 #elif defined(G_OS_WIN32)
610       g_assert_cmpuint (pid, ==, GetCurrentProcessId ());
611 #else
612       g_assert_not_reached ();
613 #endif
614     }
615   else
616     {
617       g_error ("Unexpected error: %s: %s", error.name, error.message);
618     }
619
620   dbus_clear_message (&m);
621   dbus_clear_pending_call (&pc);
622 }
623
624 static void
625 test_canonical_path_uae (Fixture *f,
626     gconstpointer context)
627 {
628   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
629       DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "UpdateActivationEnvironment");
630   DBusPendingCall *pc;
631   DBusMessageIter args_iter;
632   DBusMessageIter arr_iter;
633
634   if (m == NULL)
635     g_error ("OOM");
636
637   dbus_message_iter_init_append (m, &args_iter);
638
639   /* Append an empty a{ss} (string => string dictionary). */
640   if (!dbus_message_iter_open_container (&args_iter, DBUS_TYPE_ARRAY,
641         "{ss}", &arr_iter) ||
642       !dbus_message_iter_close_container (&args_iter, &arr_iter))
643     g_error ("OOM");
644
645   if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
646                                         DBUS_TIMEOUT_USE_DEFAULT) ||
647       pc == NULL)
648     g_error ("OOM");
649
650   dbus_clear_message (&m);
651
652   if (dbus_pending_call_get_completed (pc))
653     test_pending_call_store_reply (pc, &m);
654   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
655                                           &m, NULL))
656     g_error ("OOM");
657
658   while (m == NULL)
659     test_main_context_iterate (f->ctx, TRUE);
660
661   /* it succeeds */
662   g_assert_cmpint (dbus_message_get_type (m), ==,
663       DBUS_MESSAGE_TYPE_METHOD_RETURN);
664
665   dbus_clear_message (&m);
666   dbus_clear_pending_call (&pc);
667
668   /* Now try with the wrong object path */
669   m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
670       "/com/example/Wrong", DBUS_INTERFACE_DBUS, "UpdateActivationEnvironment");
671
672   if (m == NULL)
673     g_error ("OOM");
674
675   dbus_message_iter_init_append (m, &args_iter);
676
677   /* Append an empty a{ss} (string => string dictionary). */
678   if (!dbus_message_iter_open_container (&args_iter, DBUS_TYPE_ARRAY,
679         "{ss}", &arr_iter) ||
680       !dbus_message_iter_close_container (&args_iter, &arr_iter))
681     g_error ("OOM");
682
683   if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
684                                         DBUS_TIMEOUT_USE_DEFAULT) ||
685       pc == NULL)
686     g_error ("OOM");
687
688   dbus_clear_message (&m);
689
690   if (dbus_pending_call_get_completed (pc))
691     test_pending_call_store_reply (pc, &m);
692   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
693                                           &m, NULL))
694     g_error ("OOM");
695
696   while (m == NULL)
697     test_main_context_iterate (f->ctx, TRUE);
698
699   /* it fails, yielding an error message with one string argument */
700   g_assert_cmpint (dbus_message_get_type (m), ==, DBUS_MESSAGE_TYPE_ERROR);
701   g_assert_cmpstr (dbus_message_get_error_name (m), ==,
702       DBUS_ERROR_ACCESS_DENIED);
703   g_assert_cmpstr (dbus_message_get_signature (m), ==, "s");
704
705   dbus_clear_message (&m);
706   dbus_clear_pending_call (&pc);
707 }
708
709 static void
710 test_max_connections (Fixture *f,
711     gconstpointer context)
712 {
713   DBusError error = DBUS_ERROR_INIT;
714   DBusConnection *third_conn;
715   DBusConnection *failing_conn;
716
717   if (f->skip)
718     return;
719
720   /* We have two connections already */
721   g_assert (f->left_conn != NULL);
722   g_assert (f->right_conn != NULL);
723
724   /* Our configuration file sets the limit to 3 connections, either globally
725    * or per uid, so this one is the last that will work */
726   third_conn = test_connect_to_bus (f->ctx, f->address);
727
728   /* This one is going to fail. We don't guarantee whether it will fail
729    * now, or while registering (implementation detail: it's the latter). */
730   failing_conn = dbus_connection_open_private (f->address, &error);
731
732   if (failing_conn != NULL)
733     {
734       gboolean ok = dbus_bus_register (failing_conn, &error);
735
736       g_assert (!ok);
737     }
738
739   g_assert (dbus_error_is_set (&error));
740   g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
741
742   if (failing_conn != NULL)
743     dbus_connection_close (failing_conn);
744
745   dbus_clear_connection (&failing_conn);
746   dbus_connection_close (third_conn);
747   dbus_clear_connection (&third_conn);
748 }
749
750 static void
751 test_max_replies_per_connection (Fixture *f,
752     gconstpointer context)
753 {
754   GQueue received = G_QUEUE_INIT;
755   GQueue errors = G_QUEUE_INIT;
756   DBusMessage *m;
757   DBusPendingCall *pc;
758   guint i;
759   DBusError error = DBUS_ERROR_INIT;
760
761   if (f->skip)
762     return;
763
764   add_hold_filter (f);
765
766   /* The configured limit is 3 replies per connection. */
767   for (i = 0; i < 3; i++)
768     {
769       m = dbus_message_new_method_call (
770           dbus_bus_get_unique_name (f->right_conn), "/",
771           "com.example", "Spam");
772
773       if (m == NULL)
774         g_error ("OOM");
775
776       if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
777                                             DBUS_TIMEOUT_INFINITE) ||
778           pc == NULL)
779         g_error ("OOM");
780
781       if (dbus_pending_call_get_completed (pc))
782         pc_enqueue (pc, &received);
783       else if (!dbus_pending_call_set_notify (pc, pc_enqueue, &received,
784             NULL))
785         g_error ("OOM");
786
787       dbus_pending_call_unref (pc);
788       dbus_message_unref (m);
789     }
790
791   while (g_queue_get_length (&f->held_messages) < 3)
792     test_main_context_iterate (f->ctx, TRUE);
793
794   g_assert_cmpuint (g_queue_get_length (&received), ==, 0);
795   g_assert_cmpuint (g_queue_get_length (&errors), ==, 0);
796
797   /* Go a couple of messages over the limit. */
798   for (i = 0; i < 2; i++)
799     {
800       m = dbus_message_new_method_call (
801           dbus_bus_get_unique_name (f->right_conn), "/",
802           "com.example", "Spam");
803
804       if (m == NULL)
805         g_error ("OOM");
806
807       if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
808                                             DBUS_TIMEOUT_INFINITE) ||
809           pc == NULL)
810         g_error ("OOM");
811
812       if (dbus_pending_call_get_completed (pc))
813         pc_enqueue (pc, &errors);
814       else if (!dbus_pending_call_set_notify (pc, pc_enqueue, &errors,
815             NULL))
816         g_error ("OOM");
817
818       dbus_pending_call_unref (pc);
819       dbus_message_unref (m);
820     }
821
822   /* Reply to the held messages. */
823   for (m = g_queue_pop_head (&f->held_messages);
824        m != NULL;
825        m = g_queue_pop_head (&f->held_messages))
826     {
827       DBusMessage *reply = dbus_message_new_method_return (m);
828
829       if (reply == NULL)
830         g_error ("OOM");
831
832       if (!dbus_connection_send (f->right_conn, reply, NULL))
833         g_error ("OOM");
834
835       dbus_clear_message (&m);
836       dbus_clear_message (&reply);
837     }
838
839   /* Wait for all 5 replies to come in. */
840   while (g_queue_get_length (&received) + g_queue_get_length (&errors) < 5)
841     test_main_context_iterate (f->ctx, TRUE);
842
843   /* The first three succeeded. */
844   for (i = 0; i < 3; i++)
845     {
846       m = g_queue_pop_head (&received);
847       g_assert (m != NULL);
848
849       if (dbus_set_error_from_message (&error, m))
850         g_error ("Unexpected error: %s: %s", error.name, error.message);
851
852       dbus_clear_message (&m);
853     }
854
855   /* The last two failed. */
856   for (i = 0; i < 2; i++)
857     {
858       m = g_queue_pop_head (&errors);
859       g_assert (m != NULL);
860
861       if (!dbus_set_error_from_message (&error, m))
862         g_error ("Unexpected success");
863
864       g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
865       dbus_error_free (&error);
866       dbus_clear_message (&m);
867     }
868
869   g_assert_cmpuint (g_queue_get_length (&received), ==, 0);
870   g_assert_cmpuint (g_queue_get_length (&errors), ==, 0);
871   g_queue_clear (&received);
872   g_queue_clear (&errors);
873 }
874
875 static void
876 test_max_match_rules_per_connection (Fixture *f,
877     gconstpointer context)
878 {
879   DBusError error = DBUS_ERROR_INIT;
880
881   if (f->skip)
882     return;
883
884   dbus_bus_add_match (f->left_conn, "sender='com.example.C1'", &error);
885   test_assert_no_error (&error);
886   dbus_bus_add_match (f->left_conn, "sender='com.example.C2'", &error);
887   test_assert_no_error (&error);
888   dbus_bus_add_match (f->left_conn, "sender='com.example.C3'", &error);
889   test_assert_no_error (&error);
890
891   dbus_bus_add_match (f->left_conn, "sender='com.example.C4'", &error);
892   g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
893   dbus_error_free (&error);
894
895   dbus_bus_remove_match (f->left_conn, "sender='com.example.C3'", &error);
896   test_assert_no_error (&error);
897
898   dbus_bus_add_match (f->left_conn, "sender='com.example.C4'", &error);
899   test_assert_no_error (&error);
900 }
901
902 static void
903 test_max_names_per_connection (Fixture *f,
904     gconstpointer context)
905 {
906   DBusError error = DBUS_ERROR_INIT;
907   int ret;
908
909   if (f->skip)
910     return;
911
912   /* The limit in the configuration file is set to 4, but we only own 3
913    * names here - remember that the unique name is a name too. */
914
915   ret = dbus_bus_request_name (f->left_conn, "com.example.C1", 0, &error);
916   test_assert_no_error (&error);
917   g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
918
919   ret = dbus_bus_request_name (f->left_conn, "com.example.C2", 0, &error);
920   test_assert_no_error (&error);
921   g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
922
923   ret = dbus_bus_request_name (f->left_conn, "com.example.C3", 0, &error);
924   test_assert_no_error (&error);
925   g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
926
927   ret = dbus_bus_request_name (f->left_conn, "com.example.C4", 0, &error);
928   g_assert_cmpstr (error.name, ==, DBUS_ERROR_LIMITS_EXCEEDED);
929   dbus_error_free (&error);
930   g_assert_cmpint (ret, ==, -1);
931
932   ret = dbus_bus_release_name (f->left_conn, "com.example.C3", &error);
933   test_assert_no_error (&error);
934   g_assert_cmpint (ret, ==, DBUS_RELEASE_NAME_REPLY_RELEASED);
935
936   ret = dbus_bus_request_name (f->left_conn, "com.example.C4", 0, &error);
937   test_assert_no_error (&error);
938   g_assert_cmpint (ret, ==, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
939 }
940
941 #if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) && defined(HAVE_GIO_UNIX)
942
943 static DBusHandlerResult
944 wait_for_disconnected_cb (DBusConnection *client_conn,
945     DBusMessage *message,
946     void *data)
947 {
948   gboolean *disconnected = data;
949
950   if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected"))
951     {
952       *disconnected = TRUE;
953       return DBUS_HANDLER_RESULT_HANDLED;
954     }
955
956   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
957 }
958
959 static const guchar partial_message[] =
960 {
961   DBUS_LITTLE_ENDIAN,
962   DBUS_MESSAGE_TYPE_METHOD_CALL,
963   0, /* flags */
964   1, /* version */
965   0xff, 0xff, 0, 0, /* length of body = 65535 bytes */
966   1, 2, 3, 4, /* cookie */
967   0xff, 0xff, 0, 0, /* length of header fields array = 65535 bytes */
968   42 /* pretending to be the beginning of the header fields array */
969 };
970
971 static void
972 send_all_with_fd (GSocket *socket,
973                   const guchar *local_partial_message,
974                   gsize len,
975                   int fd)
976 {
977   GSocketControlMessage *fdm = g_unix_fd_message_new ();
978   GError *error = NULL;
979   gssize sent;
980   GOutputVector vector = { local_partial_message, len };
981
982   g_unix_fd_message_append_fd (G_UNIX_FD_MESSAGE (fdm), fd, &error);
983   g_assert_no_error (error);
984
985   sent = g_socket_send_message (socket, NULL, &vector, 1, &fdm, 1,
986       G_SOCKET_MSG_NONE, NULL, &error);
987   g_assert_no_error (error);
988   g_assert_cmpint (sent, >=, 1);
989   g_assert_cmpint (sent, <=, vector.size);
990
991   while (((gsize) sent) < vector.size)
992     {
993       vector.size -= sent;
994       vector.buffer = ((const guchar *) vector.buffer) + sent;
995       sent = g_socket_send_message (socket, NULL, &vector, 1, NULL, 0,
996           G_SOCKET_MSG_NONE, NULL, &error);
997       g_assert_no_error (error);
998       g_assert_cmpint (sent, >=, 1);
999       g_assert_cmpint (sent, <=, vector.size);
1000     }
1001
1002   g_object_unref (fdm);
1003 }
1004
1005 static void
1006 test_pending_fd_timeout (Fixture *f,
1007     gconstpointer context)
1008 {
1009   GError *error = NULL;
1010   gint64 start;
1011   int fd;
1012   GSocket *socket;
1013   gboolean have_mem;
1014   gboolean disconnected = FALSE;
1015
1016   if (f->skip)
1017     return;
1018
1019   if (getuid () == 0)
1020     {
1021       g_test_skip ("Cannot test, uid 0 is immune to this limit");
1022       return;
1023     }
1024
1025   have_mem = dbus_connection_add_filter (f->left_conn, wait_for_disconnected_cb,
1026       &disconnected, NULL);
1027   g_assert (have_mem);
1028
1029   /* This is not API. Never do this. */
1030
1031   if (!dbus_connection_get_socket (f->left_conn, &fd))
1032     g_error ("failed to steal fd from left connection");
1033
1034   socket = g_socket_new_from_fd (fd, &error);
1035   g_assert_no_error (error);
1036   g_assert (socket != NULL);
1037
1038   /* We send part of a message that contains a fd, then stop. */
1039   start = g_get_monotonic_time ();
1040   send_all_with_fd (socket, partial_message, G_N_ELEMENTS (partial_message),
1041                     fd);
1042
1043   while (!disconnected)
1044     {
1045       test_progress ('.');
1046       test_main_context_iterate (f->ctx, TRUE);
1047
1048       /* It should take 0.5s to get disconnected, as configured in
1049        * valid-config-files/pending-fd-timeout.conf; but this test
1050        * might get starved by other processes running in parallel
1051        * (particularly on shared CI systems), so we have to be a lot
1052        * more generous. Allow up to 10 seconds. */
1053       g_assert_cmpint (g_get_monotonic_time (), <=,
1054                        start + (10 * G_USEC_PER_SEC));
1055     }
1056
1057   g_object_unref (socket);
1058 }
1059
1060 typedef struct
1061 {
1062   const gchar *path;
1063   guint n_fds;
1064   gboolean should_work;
1065 } CountFdsVector;
1066
1067 static const CountFdsVector count_fds_vectors[] =
1068 {
1069   /* Deny sending if number of fds <= 2 */
1070   { "/test/DenySendMax2", 1, FALSE },
1071   { "/test/DenySendMax2", 2, FALSE },
1072   { "/test/DenySendMax2", 3, TRUE },
1073   { "/test/DenySendMax2", 4, TRUE },
1074
1075   /* Deny receiving if number of fds <= 3 */
1076   { "/test/DenyReceiveMax3", 2, FALSE },
1077   { "/test/DenyReceiveMax3", 3, FALSE },
1078   { "/test/DenyReceiveMax3", 4, TRUE },
1079   { "/test/DenyReceiveMax3", 5, TRUE },
1080
1081   /* Deny sending if number of fds >= 4 */
1082   { "/test/DenySendMin4", 2, TRUE },
1083   { "/test/DenySendMin4", 3, TRUE },
1084   { "/test/DenySendMin4", 4, FALSE },
1085   { "/test/DenySendMin4", 5, FALSE },
1086
1087   /* Deny receiving if number of fds >= 5 */
1088   { "/test/DenyReceiveMin5", 3, TRUE },
1089   { "/test/DenyReceiveMin5", 4, TRUE },
1090   { "/test/DenyReceiveMin5", 5, FALSE },
1091   { "/test/DenyReceiveMin5", 6, FALSE },
1092 };
1093
1094 static void
1095 test_count_fds (Fixture *f,
1096     gconstpointer context)
1097 {
1098   GQueue received = G_QUEUE_INIT;
1099   DBusMessage *m;
1100   DBusPendingCall *pc;
1101   guint i;
1102   DBusError error = DBUS_ERROR_INIT;
1103   const int stdin_fd = 0;
1104
1105   if (f->skip)
1106     return;
1107
1108   add_hold_filter (f);
1109
1110   for (i = 0; i < G_N_ELEMENTS (count_fds_vectors); i++)
1111     {
1112       const CountFdsVector *vector = &count_fds_vectors[i];
1113       guint j;
1114
1115       m = dbus_message_new_method_call (
1116           dbus_bus_get_unique_name (f->right_conn), vector->path,
1117           "com.example", "Spam");
1118
1119       if (m == NULL)
1120         g_error ("OOM");
1121
1122       for (j = 0; j < vector->n_fds; j++)
1123         {
1124           if (!dbus_message_append_args (m,
1125                                          DBUS_TYPE_UNIX_FD, &stdin_fd,
1126                                          DBUS_TYPE_INVALID))
1127             g_error ("OOM");
1128         }
1129
1130       if (!dbus_connection_send_with_reply (f->left_conn, m, &pc,
1131                                             DBUS_TIMEOUT_INFINITE) ||
1132           pc == NULL)
1133         g_error ("OOM");
1134
1135       if (dbus_pending_call_get_completed (pc))
1136         pc_enqueue (pc, &received);
1137       else if (!dbus_pending_call_set_notify (pc, pc_enqueue, &received,
1138             NULL))
1139         g_error ("OOM");
1140
1141       dbus_pending_call_unref (pc);
1142       dbus_message_unref (m);
1143
1144       if (vector->should_work)
1145         {
1146           DBusMessage *reply;
1147
1148           while (g_queue_get_length (&f->held_messages) < 1)
1149             test_main_context_iterate (f->ctx, TRUE);
1150
1151           g_assert_cmpint (g_queue_get_length (&f->held_messages), ==, 1);
1152
1153           m = g_queue_pop_head (&f->held_messages);
1154
1155           g_assert_cmpint (g_queue_get_length (&f->held_messages), ==, 0);
1156
1157           reply = dbus_message_new_method_return (m);
1158
1159           if (reply == NULL)
1160             g_error ("OOM");
1161
1162           if (!dbus_connection_send (f->right_conn, reply, NULL))
1163             g_error ("OOM");
1164
1165           dbus_message_unref (reply);
1166           dbus_message_unref (m);
1167         }
1168
1169       while (g_queue_get_length (&received) < 1)
1170         test_main_context_iterate (f->ctx, TRUE);
1171
1172       g_assert_cmpint (g_queue_get_length (&received), ==, 1);
1173       m = g_queue_pop_head (&received);
1174       g_assert (m != NULL);
1175       g_assert_cmpint (g_queue_get_length (&received), ==, 0);
1176
1177       if (vector->should_work)
1178         {
1179           if (dbus_set_error_from_message (&error, m))
1180             g_error ("Unexpected error: %s: %s", error.name, error.message);
1181
1182           g_test_message ("Sending %u fds to %s was not denied, as expected",
1183                           vector->n_fds, vector->path);
1184         }
1185       else if (!dbus_set_error_from_message (&error, m))
1186         {
1187           g_error ("Unexpected success");
1188         }
1189       else
1190         {
1191           g_assert_cmpstr (error.name, ==, DBUS_ERROR_ACCESS_DENIED);
1192           dbus_error_free (&error);
1193           g_test_message ("Sending %u fds to %s was denied, as expected",
1194                           vector->n_fds, vector->path);
1195         }
1196
1197       dbus_message_unref (m);
1198     }
1199 }
1200
1201 #endif
1202
1203 static void
1204 test_peer_get_machine_id (Fixture *f,
1205                           gconstpointer context)
1206 {
1207   char *what_i_think;
1208   const char *what_daemon_thinks;
1209   DBusMessage *m = NULL;
1210   DBusPendingCall *pc = NULL;
1211   DBusError error = DBUS_ERROR_INIT;
1212
1213   if (f->skip)
1214     return;
1215
1216   what_i_think = dbus_try_get_local_machine_id (&error);
1217
1218   if (what_i_think == NULL)
1219     {
1220       if (g_getenv ("DBUS_TEST_UNINSTALLED") != NULL)
1221         {
1222           /* When running unit tests during make check or make installcheck,
1223            * tolerate this */
1224           g_test_skip ("Machine UUID not available");
1225           return;
1226         }
1227       else
1228         {
1229           /* When running integration tests, don't tolerate it */
1230           g_error ("%s", error.message);
1231         }
1232     }
1233
1234   /* Check that the dbus-daemon agrees with us. */
1235   m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1236                                     DBUS_PATH_DBUS,
1237                                     DBUS_INTERFACE_PEER,
1238                                     "GetMachineId");
1239
1240   if (m == NULL ||
1241       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1242                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1243       pc == NULL)
1244     g_error ("OOM");
1245
1246   dbus_clear_message (&m);
1247
1248   if (dbus_pending_call_get_completed (pc))
1249     test_pending_call_store_reply (pc, &m);
1250   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1251                                           &m, NULL))
1252     g_error ("OOM");
1253
1254   while (m == NULL)
1255     test_main_context_iterate (f->ctx, TRUE);
1256
1257   if (!dbus_message_get_args (m, &error,
1258         DBUS_TYPE_STRING, &what_daemon_thinks,
1259         DBUS_TYPE_INVALID))
1260     g_error ("%s: %s", error.name, error.message);
1261
1262   g_assert_cmpstr (what_i_think, ==, what_daemon_thinks);
1263   g_assert_nonnull (what_daemon_thinks);
1264   g_assert_cmpuint (strlen (what_daemon_thinks), ==, 32);
1265
1266   dbus_clear_message (&m);
1267   dbus_clear_pending_call (&pc);
1268   dbus_free (what_i_think);
1269 }
1270
1271 static void
1272 test_peer_ping (Fixture *f,
1273                 gconstpointer context)
1274 {
1275   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1276       DBUS_PATH_DBUS, DBUS_INTERFACE_PEER, "Ping");
1277   DBusPendingCall *pc = NULL;
1278   DBusError error = DBUS_ERROR_INIT;
1279
1280   if (f->skip)
1281     return;
1282
1283   m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1284       DBUS_PATH_DBUS, DBUS_INTERFACE_PEER, "Ping");
1285
1286   if (m == NULL ||
1287       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1288                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1289       pc == NULL)
1290     g_error ("OOM");
1291
1292   dbus_clear_message (&m);
1293
1294   if (dbus_pending_call_get_completed (pc))
1295     test_pending_call_store_reply (pc, &m);
1296   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1297                                           &m, NULL))
1298     g_error ("OOM");
1299
1300   while (m == NULL)
1301     test_main_context_iterate (f->ctx, TRUE);
1302
1303   if (!dbus_message_get_args (m, &error, DBUS_TYPE_INVALID))
1304     g_error ("%s: %s", error.name, error.message);
1305
1306   dbus_clear_message (&m);
1307   dbus_clear_pending_call (&pc);
1308 }
1309
1310 static void
1311 test_get_invalid_path (Fixture *f,
1312                        gconstpointer context)
1313 {
1314   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1315       "/", DBUS_INTERFACE_PROPERTIES, "Get");
1316   DBusPendingCall *pc = NULL;
1317   DBusError error = DBUS_ERROR_INIT;
1318   const char *iface = DBUS_INTERFACE_DBUS;
1319   const char *property = "Interfaces";
1320
1321   if (f->skip)
1322     return;
1323
1324   if (m == NULL ||
1325       !dbus_message_append_args (m,
1326         DBUS_TYPE_STRING, &iface,
1327         DBUS_TYPE_STRING, &property,
1328         DBUS_TYPE_INVALID) ||
1329       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1330                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1331       pc == NULL)
1332     g_error ("OOM");
1333
1334   dbus_clear_message (&m);
1335
1336   if (dbus_pending_call_get_completed (pc))
1337     test_pending_call_store_reply (pc, &m);
1338   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1339                                           &m, NULL))
1340     g_error ("OOM");
1341
1342   while (m == NULL)
1343     test_main_context_iterate (f->ctx, TRUE);
1344
1345   if (!dbus_set_error_from_message (&error, m))
1346     g_error ("Unexpected success");
1347
1348   /* That object path does not have that interface */
1349   g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
1350   dbus_error_free (&error);
1351
1352   dbus_clear_message (&m);
1353   dbus_clear_pending_call (&pc);
1354 }
1355
1356 static void
1357 test_get_invalid_iface (Fixture *f,
1358                         gconstpointer context)
1359 {
1360   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1361       DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
1362   DBusPendingCall *pc = NULL;
1363   DBusError error = DBUS_ERROR_INIT;
1364   const char *iface = "com.example.Nope";
1365   const char *property = "Whatever";
1366
1367   if (f->skip)
1368     return;
1369
1370   if (m == NULL ||
1371       !dbus_message_append_args (m,
1372         DBUS_TYPE_STRING, &iface,
1373         DBUS_TYPE_STRING, &property,
1374         DBUS_TYPE_INVALID) ||
1375       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1376                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1377       pc == NULL)
1378     g_error ("OOM");
1379
1380   dbus_clear_message (&m);
1381
1382   if (dbus_pending_call_get_completed (pc))
1383     test_pending_call_store_reply (pc, &m);
1384   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1385                                           &m, NULL))
1386     g_error ("OOM");
1387
1388   while (m == NULL)
1389     test_main_context_iterate (f->ctx, TRUE);
1390
1391   if (!dbus_set_error_from_message (&error, m))
1392     g_error ("Unexpected success");
1393
1394   g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
1395   dbus_error_free (&error);
1396
1397   dbus_clear_message (&m);
1398   dbus_clear_pending_call (&pc);
1399 }
1400
1401 static void
1402 test_get_invalid (Fixture *f,
1403                   gconstpointer context)
1404 {
1405   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1406       DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
1407   DBusPendingCall *pc = NULL;
1408   DBusError error = DBUS_ERROR_INIT;
1409   const char *iface = DBUS_INTERFACE_DBUS;
1410   const char *property = "Whatever";
1411
1412   if (f->skip)
1413     return;
1414
1415   if (m == NULL ||
1416       !dbus_message_append_args (m,
1417         DBUS_TYPE_STRING, &iface,
1418         DBUS_TYPE_STRING, &property,
1419         DBUS_TYPE_INVALID) ||
1420       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1421                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1422       pc == NULL)
1423     g_error ("OOM");
1424
1425   dbus_clear_message (&m);
1426
1427   if (dbus_pending_call_get_completed (pc))
1428     test_pending_call_store_reply (pc, &m);
1429   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1430                                           &m, NULL))
1431     g_error ("OOM");
1432
1433   while (m == NULL)
1434     test_main_context_iterate (f->ctx, TRUE);
1435
1436   if (!dbus_set_error_from_message (&error, m))
1437     g_error ("Unexpected success");
1438
1439   g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_PROPERTY);
1440   dbus_error_free (&error);
1441
1442   dbus_clear_message (&m);
1443   dbus_clear_pending_call (&pc);
1444 }
1445
1446 static void
1447 test_get_all_invalid_iface (Fixture *f,
1448                             gconstpointer context)
1449 {
1450   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1451       DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "GetAll");
1452   DBusPendingCall *pc = NULL;
1453   DBusError error = DBUS_ERROR_INIT;
1454   const char *iface = "com.example.Nope";
1455
1456   if (f->skip)
1457     return;
1458
1459   if (m == NULL ||
1460       !dbus_message_append_args (m,
1461         DBUS_TYPE_STRING, &iface,
1462         DBUS_TYPE_INVALID) ||
1463       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1464                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1465       pc == NULL)
1466     g_error ("OOM");
1467
1468   dbus_clear_message (&m);
1469
1470   if (dbus_pending_call_get_completed (pc))
1471     test_pending_call_store_reply (pc, &m);
1472   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1473                                           &m, NULL))
1474     g_error ("OOM");
1475
1476   while (m == NULL)
1477     test_main_context_iterate (f->ctx, TRUE);
1478
1479   if (!dbus_set_error_from_message (&error, m))
1480     g_error ("Unexpected success");
1481
1482   g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
1483   dbus_error_free (&error);
1484
1485   dbus_clear_message (&m);
1486   dbus_clear_pending_call (&pc);
1487 }
1488
1489 static void
1490 test_get_all_invalid_path (Fixture *f,
1491                            gconstpointer context)
1492 {
1493   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1494       "/", DBUS_INTERFACE_PROPERTIES, "GetAll");
1495   DBusPendingCall *pc = NULL;
1496   DBusError error = DBUS_ERROR_INIT;
1497   const char *iface = DBUS_INTERFACE_DBUS;
1498
1499   if (f->skip)
1500     return;
1501
1502   if (m == NULL ||
1503       !dbus_message_append_args (m,
1504         DBUS_TYPE_STRING, &iface,
1505         DBUS_TYPE_INVALID) ||
1506       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1507                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1508       pc == NULL)
1509     g_error ("OOM");
1510
1511   dbus_clear_message (&m);
1512
1513   if (dbus_pending_call_get_completed (pc))
1514     test_pending_call_store_reply (pc, &m);
1515   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1516                                           &m, NULL))
1517     g_error ("OOM");
1518
1519   while (m == NULL)
1520     test_main_context_iterate (f->ctx, TRUE);
1521
1522   if (!dbus_set_error_from_message (&error, m))
1523     g_error ("Unexpected success");
1524
1525   /* That object path does not have that interface */
1526   g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
1527   dbus_error_free (&error);
1528
1529   dbus_clear_message (&m);
1530   dbus_clear_pending_call (&pc);
1531 }
1532
1533 static void
1534 test_set_invalid_iface (Fixture *f,
1535                         gconstpointer context)
1536 {
1537   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1538       DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Set");
1539   DBusPendingCall *pc = NULL;
1540   DBusError error = DBUS_ERROR_INIT;
1541   const char *iface = "com.example.Nope";
1542   const char *property = "Whatever";
1543   DBusMessageIter args_iter;
1544   DBusMessageIter var_iter;
1545   dbus_bool_t b = FALSE;
1546
1547   if (f->skip)
1548     return;
1549
1550   if (m == NULL ||
1551       !dbus_message_append_args (m,
1552         DBUS_TYPE_STRING, &iface,
1553         DBUS_TYPE_STRING, &property,
1554         DBUS_TYPE_INVALID))
1555     g_error ("OOM");
1556
1557   dbus_message_iter_init_append (m, &args_iter);
1558
1559   if (!dbus_message_iter_open_container (&args_iter,
1560         DBUS_TYPE_VARIANT, "b", &var_iter) ||
1561       !dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
1562       !dbus_message_iter_close_container (&args_iter, &var_iter) ||
1563       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1564                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1565       pc == NULL)
1566     g_error ("OOM");
1567
1568   dbus_clear_message (&m);
1569
1570   if (dbus_pending_call_get_completed (pc))
1571     test_pending_call_store_reply (pc, &m);
1572   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1573                                           &m, NULL))
1574     g_error ("OOM");
1575
1576   while (m == NULL)
1577     test_main_context_iterate (f->ctx, TRUE);
1578
1579   if (!dbus_set_error_from_message (&error, m))
1580     g_error ("Unexpected success");
1581
1582   g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
1583   dbus_error_free (&error);
1584
1585   dbus_clear_message (&m);
1586   dbus_clear_pending_call (&pc);
1587 }
1588
1589 static void
1590 test_set_invalid_path (Fixture *f,
1591                        gconstpointer context)
1592 {
1593   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1594       "/", DBUS_INTERFACE_PROPERTIES, "Set");
1595   DBusPendingCall *pc = NULL;
1596   DBusError error = DBUS_ERROR_INIT;
1597   const char *iface = DBUS_INTERFACE_DBUS;
1598   const char *property = "Interfaces";
1599   DBusMessageIter args_iter;
1600   DBusMessageIter var_iter;
1601   dbus_bool_t b = FALSE;
1602
1603   if (f->skip)
1604     return;
1605
1606   if (m == NULL ||
1607       !dbus_message_append_args (m,
1608         DBUS_TYPE_STRING, &iface,
1609         DBUS_TYPE_STRING, &property,
1610         DBUS_TYPE_INVALID))
1611     g_error ("OOM");
1612
1613   dbus_message_iter_init_append (m, &args_iter);
1614
1615   if (!dbus_message_iter_open_container (&args_iter,
1616         DBUS_TYPE_VARIANT, "b", &var_iter) ||
1617       !dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
1618       !dbus_message_iter_close_container (&args_iter, &var_iter) ||
1619       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1620                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1621       pc == NULL)
1622     g_error ("OOM");
1623
1624   dbus_clear_message (&m);
1625
1626   if (dbus_pending_call_get_completed (pc))
1627     test_pending_call_store_reply (pc, &m);
1628   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1629                                           &m, NULL))
1630     g_error ("OOM");
1631
1632   while (m == NULL)
1633     test_main_context_iterate (f->ctx, TRUE);
1634
1635   if (!dbus_set_error_from_message (&error, m))
1636     g_error ("Unexpected success");
1637
1638   g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_INTERFACE);
1639   dbus_error_free (&error);
1640
1641   dbus_clear_message (&m);
1642   dbus_clear_pending_call (&pc);
1643 }
1644
1645 static void
1646 test_set_invalid (Fixture *f,
1647                   gconstpointer context)
1648 {
1649   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1650       DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Set");
1651   DBusPendingCall *pc = NULL;
1652   DBusError error = DBUS_ERROR_INIT;
1653   const char *iface = DBUS_INTERFACE_DBUS;
1654   const char *property = "Whatever";
1655   DBusMessageIter args_iter;
1656   DBusMessageIter var_iter;
1657   dbus_bool_t b = FALSE;
1658
1659   if (f->skip)
1660     return;
1661
1662   if (m == NULL ||
1663       !dbus_message_append_args (m,
1664         DBUS_TYPE_STRING, &iface,
1665         DBUS_TYPE_STRING, &property,
1666         DBUS_TYPE_INVALID))
1667     g_error ("OOM");
1668
1669   dbus_message_iter_init_append (m, &args_iter);
1670
1671   if (!dbus_message_iter_open_container (&args_iter,
1672         DBUS_TYPE_VARIANT, "b", &var_iter) ||
1673       !dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
1674       !dbus_message_iter_close_container (&args_iter, &var_iter) ||
1675       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1676                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1677       pc == NULL)
1678     g_error ("OOM");
1679
1680   dbus_clear_message (&m);
1681
1682   if (dbus_pending_call_get_completed (pc))
1683     test_pending_call_store_reply (pc, &m);
1684   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1685                                           &m, NULL))
1686     g_error ("OOM");
1687
1688   while (m == NULL)
1689     test_main_context_iterate (f->ctx, TRUE);
1690
1691   if (!dbus_set_error_from_message (&error, m))
1692     g_error ("Unexpected success");
1693
1694   g_assert_cmpstr (error.name, ==, DBUS_ERROR_UNKNOWN_PROPERTY);
1695   dbus_error_free (&error);
1696
1697   dbus_clear_message (&m);
1698   dbus_clear_pending_call (&pc);
1699 }
1700
1701 static void
1702 test_set (Fixture *f,
1703           gconstpointer context)
1704 {
1705   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1706       DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Set");
1707   DBusPendingCall *pc = NULL;
1708   DBusError error = DBUS_ERROR_INIT;
1709   const char *iface = DBUS_INTERFACE_DBUS;
1710   const char *property = "Features";
1711   DBusMessageIter args_iter;
1712   DBusMessageIter var_iter;
1713   dbus_bool_t b = FALSE;
1714
1715   if (f->skip)
1716     return;
1717
1718   if (m == NULL ||
1719       !dbus_message_append_args (m,
1720         DBUS_TYPE_STRING, &iface,
1721         DBUS_TYPE_STRING, &property,
1722         DBUS_TYPE_INVALID))
1723     g_error ("OOM");
1724
1725   dbus_message_iter_init_append (m, &args_iter);
1726
1727   if (!dbus_message_iter_open_container (&args_iter,
1728         DBUS_TYPE_VARIANT, "b", &var_iter) ||
1729       !dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_BOOLEAN, &b) ||
1730       !dbus_message_iter_close_container (&args_iter, &var_iter) ||
1731       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1732                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1733       pc == NULL)
1734     g_error ("OOM");
1735
1736   dbus_clear_message (&m);
1737
1738   if (dbus_pending_call_get_completed (pc))
1739     test_pending_call_store_reply (pc, &m);
1740   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1741                                           &m, NULL))
1742     g_error ("OOM");
1743
1744   while (m == NULL)
1745     test_main_context_iterate (f->ctx, TRUE);
1746
1747   if (!dbus_set_error_from_message (&error, m))
1748     g_error ("Unexpected success");
1749
1750   g_assert_cmpstr (error.name, ==, DBUS_ERROR_PROPERTY_READ_ONLY);
1751   dbus_error_free (&error);
1752
1753   dbus_clear_message (&m);
1754   dbus_clear_pending_call (&pc);
1755 }
1756
1757 static void
1758 check_features (DBusMessageIter *var_iter)
1759 {
1760   DBusMessageIter arr_iter;
1761   gboolean have_systemd_activation = FALSE;
1762
1763   g_assert_cmpint (dbus_message_iter_get_arg_type (var_iter), ==,
1764       DBUS_TYPE_ARRAY);
1765   g_assert_cmpint (dbus_message_iter_get_element_type (var_iter), ==,
1766       DBUS_TYPE_STRING);
1767   dbus_message_iter_recurse (var_iter, &arr_iter);
1768
1769   while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
1770     {
1771       const char *feature;
1772
1773       g_assert_cmpint (dbus_message_iter_get_arg_type (&arr_iter), ==,
1774           DBUS_TYPE_STRING);
1775       dbus_message_iter_get_basic (&arr_iter, &feature);
1776
1777       g_test_message ("Feature: %s", feature);
1778
1779       if (g_strcmp0 (feature, "SystemdActivation") == 0)
1780         have_systemd_activation = TRUE;
1781
1782       dbus_message_iter_next (&arr_iter);
1783     }
1784
1785   /* We pass --systemd-activation to the daemon for this unit test on Unix
1786    * (it can only work in practice on Linux, but there's nothing
1787    * inherently Linux-specific about the protocol). */
1788 #ifdef DBUS_UNIX
1789   g_assert_true (have_systemd_activation);
1790 #else
1791   g_assert_false (have_systemd_activation);
1792 #endif
1793 }
1794
1795 static void
1796 test_features (Fixture *f,
1797                gconstpointer context)
1798 {
1799   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1800       DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
1801   DBusPendingCall *pc = NULL;
1802   DBusMessageIter args_iter;
1803   DBusMessageIter var_iter;
1804   const char *iface = DBUS_INTERFACE_DBUS;
1805   const char *features = "Features";
1806
1807   if (f->skip)
1808     return;
1809
1810   if (m == NULL ||
1811       !dbus_message_append_args (m,
1812         DBUS_TYPE_STRING, &iface,
1813         DBUS_TYPE_STRING, &features,
1814         DBUS_TYPE_INVALID) ||
1815       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1816                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1817       pc == NULL)
1818     g_error ("OOM");
1819
1820   dbus_clear_message (&m);
1821
1822   if (dbus_pending_call_get_completed (pc))
1823     test_pending_call_store_reply (pc, &m);
1824   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1825                                           &m, NULL))
1826     g_error ("OOM");
1827
1828   while (m == NULL)
1829     test_main_context_iterate (f->ctx, TRUE);
1830
1831   if (!dbus_message_iter_init (m, &args_iter))
1832     g_error ("Reply has no arguments");
1833
1834   g_assert_cmpint (dbus_message_iter_get_arg_type (&args_iter), ==,
1835       DBUS_TYPE_VARIANT);
1836
1837   dbus_message_iter_recurse (&args_iter, &var_iter);
1838   check_features (&var_iter);
1839
1840   if (dbus_message_iter_next (&args_iter))
1841     g_error ("Reply has too many arguments");
1842
1843   dbus_clear_message (&m);
1844   dbus_clear_pending_call (&pc);
1845 }
1846
1847 static void
1848 check_interfaces (DBusMessageIter *var_iter)
1849 {
1850   DBusMessageIter arr_iter;
1851   gboolean have_monitoring = FALSE;
1852   gboolean have_stats = FALSE;
1853   gboolean have_verbose = FALSE;
1854
1855   g_assert_cmpint (dbus_message_iter_get_arg_type (var_iter), ==,
1856       DBUS_TYPE_ARRAY);
1857   g_assert_cmpint (dbus_message_iter_get_element_type (var_iter), ==,
1858       DBUS_TYPE_STRING);
1859   dbus_message_iter_recurse (var_iter, &arr_iter);
1860
1861   while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
1862     {
1863       const char *iface;
1864
1865       g_assert_cmpint (dbus_message_iter_get_arg_type (&arr_iter), ==,
1866           DBUS_TYPE_STRING);
1867       dbus_message_iter_get_basic (&arr_iter, &iface);
1868       g_test_message ("Interface: %s", iface);
1869
1870       g_assert_cmpstr (iface, !=, DBUS_INTERFACE_DBUS);
1871       g_assert_cmpstr (iface, !=, DBUS_INTERFACE_PROPERTIES);
1872       g_assert_cmpstr (iface, !=, DBUS_INTERFACE_INTROSPECTABLE);
1873       g_assert_cmpstr (iface, !=, DBUS_INTERFACE_PEER);
1874
1875       if (g_strcmp0 (iface, DBUS_INTERFACE_MONITORING) == 0)
1876         have_monitoring = TRUE;
1877       else if (g_strcmp0 (iface, BUS_INTERFACE_STATS) == 0)
1878         have_stats = TRUE;
1879       else if (g_strcmp0 (iface, DBUS_INTERFACE_VERBOSE) == 0)
1880         have_verbose = TRUE;
1881
1882       dbus_message_iter_next (&arr_iter);
1883     }
1884
1885   g_assert_true (have_monitoring);
1886
1887 #ifdef DBUS_ENABLE_STATS
1888   g_assert_true (have_stats);
1889 #else
1890   g_assert_false (have_stats);
1891 #endif
1892
1893 #ifdef DBUS_ENABLE_VERBOSE_MODE
1894   g_assert_true (have_verbose);
1895 #else
1896   g_assert_false (have_verbose);
1897 #endif
1898 }
1899
1900 static void
1901 test_interfaces (Fixture *f,
1902                  gconstpointer context)
1903 {
1904   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1905       DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "Get");
1906   DBusPendingCall *pc = NULL;
1907   DBusMessageIter args_iter;
1908   DBusMessageIter var_iter;
1909   const char *iface = DBUS_INTERFACE_DBUS;
1910   const char *ifaces = "Interfaces";
1911
1912   if (f->skip)
1913     return;
1914
1915   if (m == NULL ||
1916       !dbus_message_append_args (m,
1917         DBUS_TYPE_STRING, &iface,
1918         DBUS_TYPE_STRING, &ifaces,
1919         DBUS_TYPE_INVALID) ||
1920       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1921                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1922       pc == NULL)
1923     g_error ("OOM");
1924
1925   dbus_clear_message (&m);
1926
1927   if (dbus_pending_call_get_completed (pc))
1928     test_pending_call_store_reply (pc, &m);
1929   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1930                                           &m, NULL))
1931     g_error ("OOM");
1932
1933   while (m == NULL)
1934     test_main_context_iterate (f->ctx, TRUE);
1935
1936   if (!dbus_message_iter_init (m, &args_iter))
1937     g_error ("Reply has no arguments");
1938
1939   if (dbus_message_iter_get_arg_type (&args_iter) != DBUS_TYPE_VARIANT)
1940     g_error ("Reply does not have a variant argument");
1941
1942   dbus_message_iter_recurse (&args_iter, &var_iter);
1943   check_interfaces (&var_iter);
1944
1945   if (dbus_message_iter_next (&args_iter))
1946     g_error ("Reply has too many arguments");
1947
1948   dbus_clear_message (&m);
1949   dbus_clear_pending_call (&pc);
1950 }
1951
1952 static void
1953 test_get_all (Fixture *f,
1954               gconstpointer context)
1955 {
1956   DBusMessage *m = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1957       DBUS_PATH_DBUS, DBUS_INTERFACE_PROPERTIES, "GetAll");
1958   DBusPendingCall *pc = NULL;
1959   DBusMessageIter args_iter;
1960   DBusMessageIter arr_iter;
1961   DBusMessageIter pair_iter;
1962   DBusMessageIter var_iter;
1963   const char *iface = DBUS_INTERFACE_DBUS;
1964   gboolean have_features = FALSE;
1965   gboolean have_interfaces = FALSE;
1966
1967   if (f->skip)
1968     return;
1969
1970   if (m == NULL ||
1971       !dbus_message_append_args (m,
1972         DBUS_TYPE_STRING, &iface,
1973         DBUS_TYPE_INVALID) ||
1974       !dbus_connection_send_with_reply (f->left_conn, m, &pc,
1975                                         DBUS_TIMEOUT_USE_DEFAULT) ||
1976       pc == NULL)
1977     g_error ("OOM");
1978
1979   dbus_clear_message (&m);
1980
1981   if (dbus_pending_call_get_completed (pc))
1982     test_pending_call_store_reply (pc, &m);
1983   else if (!dbus_pending_call_set_notify (pc, test_pending_call_store_reply,
1984                                           &m, NULL))
1985     g_error ("OOM");
1986
1987   while (m == NULL)
1988     test_main_context_iterate (f->ctx, TRUE);
1989
1990   dbus_message_iter_init (m, &args_iter);
1991   g_assert_cmpuint (dbus_message_iter_get_arg_type (&args_iter), ==,
1992       DBUS_TYPE_ARRAY);
1993   g_assert_cmpuint (dbus_message_iter_get_element_type (&args_iter), ==,
1994       DBUS_TYPE_DICT_ENTRY);
1995   dbus_message_iter_recurse (&args_iter, &arr_iter);
1996
1997   while (dbus_message_iter_get_arg_type (&arr_iter) != DBUS_TYPE_INVALID)
1998     {
1999       const char *name;
2000
2001       dbus_message_iter_recurse (&arr_iter, &pair_iter);
2002       g_assert_cmpuint (dbus_message_iter_get_arg_type (&pair_iter), ==,
2003           DBUS_TYPE_STRING);
2004       dbus_message_iter_get_basic (&pair_iter, &name);
2005       dbus_message_iter_next (&pair_iter);
2006       g_assert_cmpuint (dbus_message_iter_get_arg_type (&pair_iter), ==,
2007           DBUS_TYPE_VARIANT);
2008       dbus_message_iter_recurse (&pair_iter, &var_iter);
2009
2010       if (g_strcmp0 (name, "Features") == 0)
2011         {
2012           check_features (&var_iter);
2013           have_features = TRUE;
2014         }
2015       else if (g_strcmp0 (name, "Interfaces") == 0)
2016         {
2017           check_interfaces (&var_iter);
2018           have_interfaces = TRUE;
2019         }
2020
2021       dbus_message_iter_next (&arr_iter);
2022     }
2023
2024   g_assert_true (have_features);
2025   g_assert_true (have_interfaces);
2026
2027   if (dbus_message_iter_next (&args_iter))
2028     g_error ("Reply has too many arguments");
2029
2030   dbus_clear_message (&m);
2031   dbus_clear_pending_call (&pc);
2032 }
2033
2034 #define DESIRED_RLIMIT 65536
2035
2036 #ifdef DBUS_UNIX
2037 static void
2038 test_fd_limit (Fixture *f,
2039                gconstpointer context)
2040 {
2041 #ifdef HAVE_PRLIMIT
2042   struct rlimit lim;
2043   struct rlimit new_limit;
2044   const struct passwd *pwd = NULL;
2045 #endif
2046
2047   if (f->skip)
2048     return;
2049
2050 #ifdef HAVE_PRLIMIT
2051
2052   if (getuid () != 0)
2053     {
2054       g_test_skip ("Cannot test, only uid 0 is expected to raise fd limit");
2055       return;
2056     }
2057
2058   pwd = getpwnam (DBUS_USER);
2059
2060   if (pwd == NULL)
2061     {
2062       gchar *message = g_strdup_printf ("user '%s' does not exist",
2063           DBUS_USER);
2064
2065       g_test_skip (message);
2066       g_free (message);
2067       return;
2068     }
2069
2070   if (prlimit (getpid (), RLIMIT_NOFILE, NULL, &lim) < 0)
2071     g_error ("get prlimit (self): %s", g_strerror (errno));
2072
2073   g_test_message ("our RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld",
2074                   (long) lim.rlim_cur, (long) lim.rlim_max);
2075
2076   if (lim.rlim_cur == RLIM_INFINITY || lim.rlim_cur >= DESIRED_RLIMIT)
2077     {
2078       /* The dbus-daemon will have inherited our large rlimit */
2079       g_test_skip ("Cannot test, our own fd limit was already large");
2080       return;
2081     }
2082
2083   new_limit = lim;
2084   new_limit.rlim_cur = DESIRED_RLIMIT;
2085   new_limit.rlim_max = DESIRED_RLIMIT;
2086
2087   /* Try to increase the rlimit ourselves. If we're root in an
2088    * unprivileged Linux container, then we won't have CAP_SYS_RESOURCE
2089    * and this will fail with EPERM. If so, the dbus-daemon wouldn't be
2090    * able to increase its rlimit either. */
2091   if (prlimit (getpid (), RLIMIT_NOFILE, &new_limit, NULL) < 0)
2092     {
2093       gchar *message;
2094
2095       message = g_strdup_printf ("Cannot test, we cannot change the rlimit so "
2096                                  "presumably neither can the dbus-daemon: %s",
2097                                  g_strerror (errno));
2098       g_test_skip (message);
2099       g_free (message);
2100       return;
2101     }
2102
2103   /* Immediately put our original limit back so it won't interfere with
2104    * subsequent tests. This should always succeed. */
2105   if (prlimit (getpid (), RLIMIT_NOFILE, &lim, NULL) < 0)
2106     g_error ("Cannot restore our original limits: %s", g_strerror (errno));
2107
2108   if (prlimit (f->daemon_pid, RLIMIT_NOFILE, NULL, &lim) < 0)
2109     g_error ("get prlimit (dbus-daemon): %s", g_strerror (errno));
2110
2111   g_test_message ("dbus-daemon's RLIMIT_NOFILE: rlim_cur: %ld, rlim_max: %ld",
2112                   (long) lim.rlim_cur, (long) lim.rlim_max);
2113
2114   if (lim.rlim_cur != RLIM_INFINITY)
2115     g_assert_cmpint (lim.rlim_cur, >=, DESIRED_RLIMIT);
2116
2117 #else /* !HAVE_PRLIMIT */
2118
2119   g_test_skip ("prlimit() not supported on this platform");
2120
2121 #endif /* !HAVE_PRLIMIT */
2122 }
2123 #endif
2124
2125 static void
2126 teardown (Fixture *f,
2127     gconstpointer context G_GNUC_UNUSED)
2128 {
2129   dbus_error_free (&f->e);
2130   g_clear_error (&f->ge);
2131
2132   if (f->left_conn != NULL)
2133     dbus_connection_close (f->left_conn);
2134
2135   if (f->right_conn != NULL)
2136     {
2137       if (f->right_conn_echo)
2138         {
2139           dbus_connection_remove_filter (f->right_conn, echo_filter, f);
2140           f->right_conn_echo = FALSE;
2141         }
2142
2143       if (f->right_conn_hold)
2144         {
2145           dbus_connection_remove_filter (f->right_conn, hold_filter, f);
2146           f->right_conn_hold = FALSE;
2147         }
2148
2149       g_queue_foreach (&f->held_messages, (GFunc) dbus_message_unref, NULL);
2150       g_queue_clear (&f->held_messages);
2151
2152       dbus_connection_close (f->right_conn);
2153     }
2154
2155   dbus_clear_connection (&f->left_conn);
2156   dbus_clear_connection (&f->right_conn);
2157
2158   if (f->daemon_pid != 0)
2159     {
2160       test_kill_pid (f->daemon_pid);
2161       g_spawn_close_pid (f->daemon_pid);
2162       f->daemon_pid = 0;
2163     }
2164
2165   if (f->tmp_runtime_dir != NULL)
2166     {
2167       gchar *path;
2168
2169       /* the socket may exist */
2170       path = g_strdup_printf ("%s/bus", f->tmp_runtime_dir);
2171
2172       test_remove_if_exists (path);
2173       g_free (path);
2174       /* there shouldn't be anything else in there */
2175       test_rmdir_must_exist (f->tmp_runtime_dir);
2176
2177       /* we're relying on being single-threaded for this to be safe */
2178       if (f->saved_runtime_dir != NULL)
2179         g_setenv ("XDG_RUNTIME_DIR", f->saved_runtime_dir, TRUE);
2180       else
2181         g_unsetenv ("XDG_RUNTIME_DIR");
2182       g_free (f->saved_runtime_dir);
2183       g_free (f->tmp_runtime_dir);
2184     }
2185
2186   test_main_context_unref (f->ctx);
2187   g_free (f->address);
2188 }
2189
2190 static Config limited_config = {
2191     "34393", 10000, "valid-config-files/incoming-limit.conf",
2192     TEST_USER_ME, SPECIFY_ADDRESS
2193 };
2194
2195 static Config finite_timeout_config = {
2196     NULL, 1, "valid-config-files/finite-timeout.conf",
2197     TEST_USER_ME, SPECIFY_ADDRESS
2198 };
2199
2200 #ifdef DBUS_UNIX
2201 static Config listen_unix_runtime_config = {
2202     "61303", 1, "valid-config-files/listen-unix-runtime.conf",
2203     TEST_USER_ME, RELY_ON_DEFAULT
2204 };
2205 #endif
2206
2207 static Config max_completed_connections_config = {
2208     NULL, 1, "valid-config-files/max-completed-connections.conf",
2209     TEST_USER_ME, SPECIFY_ADDRESS
2210 };
2211
2212 static Config max_connections_per_user_config = {
2213     NULL, 1, "valid-config-files/max-connections-per-user.conf",
2214     TEST_USER_ME, SPECIFY_ADDRESS
2215 };
2216
2217 static Config max_replies_per_connection_config = {
2218     NULL, 1, "valid-config-files/max-replies-per-connection.conf",
2219     TEST_USER_ME, SPECIFY_ADDRESS
2220 };
2221
2222 static Config max_match_rules_per_connection_config = {
2223     NULL, 1, "valid-config-files/max-match-rules-per-connection.conf",
2224     TEST_USER_ME, SPECIFY_ADDRESS
2225 };
2226
2227 static Config max_names_per_connection_config = {
2228     NULL, 1, "valid-config-files/max-names-per-connection.conf",
2229     TEST_USER_ME, SPECIFY_ADDRESS
2230 };
2231
2232 #if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) && defined(HAVE_GIO_UNIX)
2233 static Config pending_fd_timeout_config = {
2234     NULL, 1, "valid-config-files/pending-fd-timeout.conf",
2235     TEST_USER_ME, SPECIFY_ADDRESS
2236 };
2237
2238 static Config count_fds_config = {
2239     NULL, 1, "valid-config-files/count-fds.conf",
2240     TEST_USER_ME, SPECIFY_ADDRESS
2241 };
2242 #endif
2243
2244 #if defined(DBUS_UNIX)
2245 static Config as_another_user_config = {
2246     NULL, 1, "valid-config-files/as-another-user.conf",
2247     /* We start the dbus-daemon as root and drop privileges, like the
2248      * real system bus does */
2249     TEST_USER_ROOT, SPECIFY_ADDRESS
2250 };
2251 #endif
2252
2253 int
2254 main (int argc,
2255     char **argv)
2256 {
2257   test_init (&argc, &argv);
2258
2259   g_test_add ("/echo/session", Fixture, NULL, setup, test_echo, teardown);
2260   g_test_add ("/echo/limited", Fixture, &limited_config,
2261       setup, test_echo, teardown);
2262   g_test_add ("/no-reply/disconnect", Fixture, NULL,
2263       setup, test_no_reply, teardown);
2264   g_test_add ("/no-reply/timeout", Fixture, &finite_timeout_config,
2265       setup, test_no_reply, teardown);
2266   g_test_add ("/creds", Fixture, NULL, setup, test_creds, teardown);
2267   g_test_add ("/processid", Fixture, NULL, setup, test_processid, teardown);
2268   g_test_add ("/canonical-path/uae", Fixture, NULL,
2269       setup, test_canonical_path_uae, teardown);
2270   g_test_add ("/limits/max-completed-connections", Fixture,
2271       &max_completed_connections_config,
2272       setup, test_max_connections, teardown);
2273   g_test_add ("/limits/max-connections-per-user", Fixture,
2274       &max_connections_per_user_config,
2275       setup, test_max_connections, teardown);
2276   g_test_add ("/limits/max-replies-per-connection", Fixture,
2277       &max_replies_per_connection_config,
2278       setup, test_max_replies_per_connection, teardown);
2279   g_test_add ("/limits/max-match-rules-per-connection", Fixture,
2280       &max_match_rules_per_connection_config,
2281       setup, test_max_match_rules_per_connection, teardown);
2282   g_test_add ("/limits/max-names-per-connection", Fixture,
2283       &max_names_per_connection_config,
2284       setup, test_max_names_per_connection, teardown);
2285   g_test_add ("/peer/ping", Fixture, NULL, setup, test_peer_ping, teardown);
2286   g_test_add ("/peer/get-machine-id", Fixture, NULL,
2287       setup, test_peer_get_machine_id, teardown);
2288   g_test_add ("/properties/get-invalid-iface", Fixture, NULL,
2289       setup, test_get_invalid_iface, teardown);
2290   g_test_add ("/properties/get-invalid-path", Fixture, NULL,
2291       setup, test_get_invalid_path, teardown);
2292   g_test_add ("/properties/get-invalid", Fixture, NULL,
2293       setup, test_get_invalid, teardown);
2294   g_test_add ("/properties/get-all-invalid-iface", Fixture, NULL, setup,
2295       test_get_all_invalid_iface, teardown);
2296   g_test_add ("/properties/get-all-invalid-path", Fixture, NULL, setup,
2297       test_get_all_invalid_path, teardown);
2298   g_test_add ("/properties/set-invalid-iface", Fixture, NULL,
2299       setup, test_set_invalid_iface, teardown);
2300   g_test_add ("/properties/set-invalid-path", Fixture, NULL,
2301       setup, test_set_invalid_path, teardown);
2302   g_test_add ("/properties/set-invalid", Fixture, NULL,
2303       setup, test_set_invalid, teardown);
2304   g_test_add ("/properties/set", Fixture, NULL,
2305       setup, test_set, teardown);
2306   g_test_add ("/properties/features", Fixture, NULL,
2307       setup, test_features, teardown);
2308   g_test_add ("/properties/interfaces", Fixture, NULL, setup,
2309       test_interfaces, teardown);
2310   g_test_add ("/properties/get-all", Fixture, NULL, setup,
2311       test_get_all, teardown);
2312
2313 #if defined(DBUS_UNIX) && defined(HAVE_UNIX_FD_PASSING) && defined(HAVE_GIO_UNIX)
2314   g_test_add ("/limits/pending-fd-timeout", Fixture,
2315       &pending_fd_timeout_config,
2316       setup, test_pending_fd_timeout, teardown);
2317   g_test_add ("/policy/count-fds", Fixture, &count_fds_config,
2318       setup, test_count_fds, teardown);
2319 #endif
2320
2321 #ifdef DBUS_UNIX
2322   /* We can't test this in loopback.c with the rest of unix:runtime=yes,
2323    * because dbus_bus_get[_private] is the only way to use the default,
2324    * and that blocks on a round-trip to the dbus-daemon */
2325   g_test_add ("/unix-runtime-is-default", Fixture, &listen_unix_runtime_config,
2326       setup, test_echo, teardown);
2327
2328   g_test_add ("/fd-limit/session", Fixture, NULL,
2329               setup, test_fd_limit, teardown);
2330   g_test_add ("/fd-limit/system", Fixture, &as_another_user_config,
2331               setup, test_fd_limit, teardown);
2332 #endif
2333
2334   return g_test_run ();
2335 }