blob: df152c222f8db8fe3ac1ecc186dabe3f384c7ae6 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dispatch.c Message dispatcher
3 *
4 * Copyright (C) 2003 CodeFactory AB
5 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
6 * Copyright (C) 2004 Imendio HB
7 *
8 * Licensed under the Academic Free License version 2.1
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25
26#include <config.h>
27#include "dispatch.h"
28#include "connection.h"
29#include "driver.h"
30#include "services.h"
31#include "activation.h"
32#include "utils.h"
33#include "bus.h"
34#include "signals.h"
35#include "test.h"
36#include <dbus/dbus-internals.h>
37#include <string.h>
38
39#ifdef HAVE_UNIX_FD_PASSING
40#include <dbus/dbus-sysdeps-unix.h>
41#include <unistd.h>
42#endif
43
44#ifndef TEST_CONNECTION
45/*
46 TODO autotools:
47 move to build system as already done for cmake
48*/
49#ifdef DBUS_UNIX
50#define TEST_CONNECTION "debug-pipe:name=test-server"
51#else
52#define TEST_CONNECTION "tcp:host=localhost,port=1234"
53#endif
54#endif
55
56static dbus_bool_t
57send_one_message (DBusConnection *connection,
58 BusContext *context,
59 DBusConnection *sender,
60 DBusConnection *addressed_recipient,
61 DBusMessage *message,
62 BusTransaction *transaction,
63 DBusError *error)
64{
65 if (!bus_context_check_security_policy (context, transaction,
66 sender,
67 addressed_recipient,
68 connection,
69 message,
70 NULL))
71 return TRUE; /* silently don't send it */
72
73 if (dbus_message_contains_unix_fds(message) &&
74 !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD))
75 return TRUE; /* silently don't send it */
76
77 if (!bus_transaction_send (transaction,
78 connection,
79 message))
80 {
81 BUS_SET_OOM (error);
82 return FALSE;
83 }
84
85 return TRUE;
86}
87
88dbus_bool_t
89bus_dispatch_matches (BusTransaction *transaction,
90 DBusConnection *sender,
91 DBusConnection *addressed_recipient,
92 DBusMessage *message,
93 DBusError *error)
94{
95 DBusError tmp_error;
96 BusConnections *connections;
97 DBusList *recipients;
98 BusMatchmaker *matchmaker;
99 DBusList *link;
100 BusContext *context;
101
102 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
103
104 /* sender and recipient can both be NULL for the bus driver,
105 * or for signals with no particular recipient
106 */
107
108 _dbus_assert (sender == NULL || bus_connection_is_active (sender));
109 _dbus_assert (dbus_message_get_sender (message) != NULL);
110
111 context = bus_transaction_get_context (transaction);
112
113 /* First, send the message to the addressed_recipient, if there is one. */
114 if (addressed_recipient != NULL)
115 {
116 if (!bus_context_check_security_policy (context, transaction,
117 sender, addressed_recipient,
118 addressed_recipient,
119 message, error))
120 return FALSE;
121
122 if (dbus_message_contains_unix_fds (message) &&
123 !dbus_connection_can_send_type (addressed_recipient,
124 DBUS_TYPE_UNIX_FD))
125 {
126 dbus_set_error (error,
127 DBUS_ERROR_NOT_SUPPORTED,
128 "Tried to send message with Unix file descriptors"
129 "to a client that doesn't support that.");
130 return FALSE;
131 }
132
133 /* Dispatch the message */
134 if (!bus_transaction_send (transaction, addressed_recipient, message))
135 {
136 BUS_SET_OOM (error);
137 return FALSE;
138 }
139 }
140
141 /* Now dispatch to others who look interested in this message */
142 connections = bus_transaction_get_connections (transaction);
143 dbus_error_init (&tmp_error);
144 matchmaker = bus_context_get_matchmaker (context);
145
146 recipients = NULL;
147 if (!bus_matchmaker_get_recipients (matchmaker, connections,
148 sender, addressed_recipient, message,
149 &recipients))
150 {
151 BUS_SET_OOM (error);
152 return FALSE;
153 }
154
155 link = _dbus_list_get_first_link (&recipients);
156 while (link != NULL)
157 {
158 DBusConnection *dest;
159
160 dest = link->data;
161
162 if (!send_one_message (dest, context, sender, addressed_recipient,
163 message, transaction, &tmp_error))
164 break;
165
166 link = _dbus_list_get_next_link (&recipients, link);
167 }
168
169 _dbus_list_clear (&recipients);
170
171 if (dbus_error_is_set (&tmp_error))
172 {
173 dbus_move_error (&tmp_error, error);
174 return FALSE;
175 }
176 else
177 return TRUE;
178}
179
180static DBusHandlerResult
181bus_dispatch (DBusConnection *connection,
182 DBusMessage *message)
183{
184 const char *sender, *service_name;
185 DBusError error;
186 BusTransaction *transaction;
187 BusContext *context;
188 DBusHandlerResult result;
189 DBusConnection *addressed_recipient;
190
191 result = DBUS_HANDLER_RESULT_HANDLED;
192
193 transaction = NULL;
194 addressed_recipient = NULL;
195 dbus_error_init (&error);
196
197 context = bus_connection_get_context (connection);
198 _dbus_assert (context != NULL);
199
200 /* If we can't even allocate an OOM error, we just go to sleep
201 * until we can.
202 */
203 while (!bus_connection_preallocate_oom_error (connection))
204 _dbus_wait_for_memory ();
205
206 /* Ref connection in case we disconnect it at some point in here */
207 dbus_connection_ref (connection);
208
209 service_name = dbus_message_get_destination (message);
210
211#ifdef DBUS_ENABLE_VERBOSE_MODE
212 {
213 const char *interface_name, *member_name, *error_name;
214
215 interface_name = dbus_message_get_interface (message);
216 member_name = dbus_message_get_member (message);
217 error_name = dbus_message_get_error_name (message);
218
219 _dbus_verbose ("DISPATCH: %s %s %s to %s\n",
220 interface_name ? interface_name : "(no interface)",
221 member_name ? member_name : "(no member)",
222 error_name ? error_name : "(no error name)",
223 service_name ? service_name : "peer");
224 }
225#endif /* DBUS_ENABLE_VERBOSE_MODE */
226
227 /* If service_name is NULL, if it's a signal we send it to all
228 * connections with a match rule. If it's not a signal, there
229 * are some special cases here but mostly we just bail out.
230 */
231 if (service_name == NULL)
232 {
233 if (dbus_message_is_signal (message,
234 DBUS_INTERFACE_LOCAL,
235 "Disconnected"))
236 {
237 bus_connection_disconnected (connection);
238 goto out;
239 }
240
241 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
242 {
243 /* DBusConnection also handles some of these automatically, we leave
244 * it to do so.
245 */
246 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
247 goto out;
248 }
249 }
250
251 /* Create our transaction */
252 transaction = bus_transaction_new (context);
253 if (transaction == NULL)
254 {
255 BUS_SET_OOM (&error);
256 goto out;
257 }
258
259 /* Assign a sender to the message */
260 if (bus_connection_is_active (connection))
261 {
262 sender = bus_connection_get_name (connection);
263 _dbus_assert (sender != NULL);
264
265 if (!dbus_message_set_sender (message, sender))
266 {
267 BUS_SET_OOM (&error);
268 goto out;
269 }
270
271 /* We need to refetch the service name here, because
272 * dbus_message_set_sender can cause the header to be
273 * reallocated, and thus the service_name pointer will become
274 * invalid.
275 */
276 service_name = dbus_message_get_destination (message);
277 }
278
279 if (service_name &&
280 strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
281 {
282 if (!bus_context_check_security_policy (context, transaction,
283 connection, NULL, NULL, message, &error))
284 {
285 _dbus_verbose ("Security policy rejected message\n");
286 goto out;
287 }
288
289 _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
290 if (!bus_driver_handle_message (connection, transaction, message, &error))
291 goto out;
292 }
293 else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */
294 {
295 _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
296 dbus_connection_close (connection);
297 goto out;
298 }
299 else if (service_name != NULL) /* route to named service */
300 {
301 DBusString service_string;
302 BusService *service;
303 BusRegistry *registry;
304
305 _dbus_assert (service_name != NULL);
306
307 registry = bus_connection_get_registry (connection);
308
309 _dbus_string_init_const (&service_string, service_name);
310 service = bus_registry_lookup (registry, &service_string);
311
312 if (service == NULL && dbus_message_get_auto_start (message))
313 {
314 BusActivation *activation;
315 /* We can't do the security policy check here, since the addressed
316 * recipient service doesn't exist yet. We do it before sending the
317 * message after the service has been created.
318 */
319 activation = bus_connection_get_activation (connection);
320
321 if (!bus_activation_activate_service (activation, connection, transaction, TRUE,
322 message, service_name, &error))
323 {
324 _DBUS_ASSERT_ERROR_CONTENT_IS_SET (&error);
325 _dbus_verbose ("bus_activation_activate_service() failed: %s\n", error.name);
326 goto out;
327 }
328
329 goto out;
330 }
331 else if (service == NULL)
332 {
333 dbus_set_error (&error,
334 DBUS_ERROR_NAME_HAS_NO_OWNER,
335 "Name \"%s\" does not exist",
336 service_name);
337 goto out;
338 }
339 else
340 {
341 addressed_recipient = bus_service_get_primary_owners_connection (service);
342 _dbus_assert (addressed_recipient != NULL);
343 }
344 }
345
346 /* Now send the message to its destination (or not, if
347 * addressed_recipient == NULL), and match it against other connections'
348 * match rules.
349 */
350 if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error))
351 goto out;
352
353 out:
354 if (dbus_error_is_set (&error))
355 {
356 if (!dbus_connection_get_is_connected (connection))
357 {
358 /* If we disconnected it, we won't bother to send it any error
359 * messages.
360 */
361 _dbus_verbose ("Not sending error to connection we disconnected\n");
362 }
363 else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
364 {
365 bus_connection_send_oom_error (connection, message);
366
367 /* cancel transaction due to OOM */
368 if (transaction != NULL)
369 {
370 bus_transaction_cancel_and_free (transaction);
371 transaction = NULL;
372 }
373 }
374 else
375 {
376 /* Try to send the real error, if no mem to do that, send
377 * the OOM error
378 */
379 _dbus_assert (transaction != NULL);
380 if (!bus_transaction_send_error_reply (transaction, connection,
381 &error, message))
382 {
383 bus_connection_send_oom_error (connection, message);
384
385 /* cancel transaction due to OOM */
386 if (transaction != NULL)
387 {
388 bus_transaction_cancel_and_free (transaction);
389 transaction = NULL;
390 }
391 }
392 }
393
394
395 dbus_error_free (&error);
396 }
397
398 if (transaction != NULL)
399 {
400 bus_transaction_execute_and_free (transaction);
401 }
402
403 dbus_connection_unref (connection);
404
405 return result;
406}
407
408static DBusHandlerResult
409bus_dispatch_message_filter (DBusConnection *connection,
410 DBusMessage *message,
411 void *user_data)
412{
413 return bus_dispatch (connection, message);
414}
415
416dbus_bool_t
417bus_dispatch_add_connection (DBusConnection *connection)
418{
419 if (!dbus_connection_add_filter (connection,
420 bus_dispatch_message_filter,
421 NULL, NULL))
422 return FALSE;
423
424 return TRUE;
425}
426
427void
428bus_dispatch_remove_connection (DBusConnection *connection)
429{
430 /* Here we tell the bus driver that we want to get off. */
431 bus_driver_remove_connection (connection);
432
433 dbus_connection_remove_filter (connection,
434 bus_dispatch_message_filter,
435 NULL);
436}
437
438#ifdef DBUS_BUILD_TESTS
439
440#include <stdio.h>
441
442/* This is used to know whether we need to block in order to finish
443 * sending a message, or whether the initial dbus_connection_send()
444 * already flushed the queue.
445 */
446#define SEND_PENDING(connection) (dbus_connection_has_messages_to_send (connection))
447
448typedef dbus_bool_t (* Check1Func) (BusContext *context);
449typedef dbus_bool_t (* Check2Func) (BusContext *context,
450 DBusConnection *connection);
451
452static dbus_bool_t check_no_leftovers (BusContext *context);
453
454static void
455block_connection_until_message_from_bus (BusContext *context,
456 DBusConnection *connection,
457 const char *what_is_expected)
458{
459 _dbus_verbose ("expecting: %s\n", what_is_expected);
460
461 while (dbus_connection_get_dispatch_status (connection) ==
462 DBUS_DISPATCH_COMPLETE &&
463 dbus_connection_get_is_connected (connection))
464 {
465 bus_test_run_bus_loop (context, TRUE);
466 bus_test_run_clients_loop (FALSE);
467 }
468}
469
470static void
471spin_connection_until_authenticated (BusContext *context,
472 DBusConnection *connection)
473{
474 _dbus_verbose ("Spinning to auth connection %p\n", connection);
475 while (!dbus_connection_get_is_authenticated (connection) &&
476 dbus_connection_get_is_connected (connection))
477 {
478 bus_test_run_bus_loop (context, FALSE);
479 bus_test_run_clients_loop (FALSE);
480 }
481 _dbus_verbose (" ... done spinning to auth connection %p\n", connection);
482}
483
484/* compensate for fact that pop_message() can return #NULL due to OOM */
485static DBusMessage*
486pop_message_waiting_for_memory (DBusConnection *connection)
487{
488 while (dbus_connection_get_dispatch_status (connection) ==
489 DBUS_DISPATCH_NEED_MEMORY)
490 _dbus_wait_for_memory ();
491
492 return dbus_connection_pop_message (connection);
493}
494
495static DBusMessage*
496borrow_message_waiting_for_memory (DBusConnection *connection)
497{
498 while (dbus_connection_get_dispatch_status (connection) ==
499 DBUS_DISPATCH_NEED_MEMORY)
500 _dbus_wait_for_memory ();
501
502 return dbus_connection_borrow_message (connection);
503}
504
505static void
506warn_unexpected_real (DBusConnection *connection,
507 DBusMessage *message,
508 const char *expected,
509 const char *function,
510 int line)
511{
512 if (message)
513 _dbus_warn ("%s:%d received message interface \"%s\" member \"%s\" error name \"%s\" on %p, expecting %s\n",
514 function, line,
515 dbus_message_get_interface (message) ?
516 dbus_message_get_interface (message) : "(unset)",
517 dbus_message_get_member (message) ?
518 dbus_message_get_member (message) : "(unset)",
519 dbus_message_get_error_name (message) ?
520 dbus_message_get_error_name (message) : "(unset)",
521 connection,
522 expected);
523 else
524 _dbus_warn ("%s:%d received no message on %p, expecting %s\n",
525 function, line, connection, expected);
526}
527
528#define warn_unexpected(connection, message, expected) \
529 warn_unexpected_real (connection, message, expected, _DBUS_FUNCTION_NAME, __LINE__)
530
531static void
532verbose_message_received (DBusConnection *connection,
533 DBusMessage *message)
534{
535 _dbus_verbose ("Received message interface \"%s\" member \"%s\" error name \"%s\" on %p\n",
536 dbus_message_get_interface (message) ?
537 dbus_message_get_interface (message) : "(unset)",
538 dbus_message_get_member (message) ?
539 dbus_message_get_member (message) : "(unset)",
540 dbus_message_get_error_name (message) ?
541 dbus_message_get_error_name (message) : "(unset)",
542 connection);
543}
544
545typedef enum
546{
547 SERVICE_CREATED,
548 OWNER_CHANGED,
549 SERVICE_DELETED
550} ServiceInfoKind;
551
552typedef struct
553{
554 ServiceInfoKind expected_kind;
555 const char *expected_service_name;
556 dbus_bool_t failed;
557 DBusConnection *skip_connection;
558} CheckServiceOwnerChangedData;
559
560static dbus_bool_t
561check_service_owner_changed_foreach (DBusConnection *connection,
562 void *data)
563{
564 CheckServiceOwnerChangedData *d = data;
565 DBusMessage *message;
566 DBusError error;
567 const char *service_name, *old_owner, *new_owner;
568
569 if (d->expected_kind == SERVICE_CREATED
570 && connection == d->skip_connection)
571 return TRUE;
572
573 dbus_error_init (&error);
574 d->failed = TRUE;
575
576 message = pop_message_waiting_for_memory (connection);
577 if (message == NULL)
578 {
579 _dbus_warn ("Did not receive a message on %p, expecting %s\n",
580 connection, "NameOwnerChanged");
581 goto out;
582 }
583 else if (!dbus_message_is_signal (message,
584 DBUS_INTERFACE_DBUS,
585 "NameOwnerChanged"))
586 {
587 warn_unexpected (connection, message, "NameOwnerChanged");
588
589 goto out;
590 }
591 else
592 {
593 reget_service_info_data:
594 service_name = NULL;
595 old_owner = NULL;
596 new_owner = NULL;
597
598 dbus_message_get_args (message, &error,
599 DBUS_TYPE_STRING, &service_name,
600 DBUS_TYPE_STRING, &old_owner,
601 DBUS_TYPE_STRING, &new_owner,
602 DBUS_TYPE_INVALID);
603
604 if (dbus_error_is_set (&error))
605 {
606 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
607 {
608 dbus_error_free (&error);
609 _dbus_wait_for_memory ();
610 goto reget_service_info_data;
611 }
612 else
613 {
614 _dbus_warn ("Did not get the expected arguments\n");
615 goto out;
616 }
617 }
618
619 if ((d->expected_kind == SERVICE_CREATED && ( old_owner[0] || !new_owner[0]))
620 || (d->expected_kind == OWNER_CHANGED && (!old_owner[0] || !new_owner[0]))
621 || (d->expected_kind == SERVICE_DELETED && (!old_owner[0] || new_owner[0])))
622 {
623 _dbus_warn ("inconsistent NameOwnerChanged arguments\n");
624 goto out;
625 }
626
627 if (strcmp (service_name, d->expected_service_name) != 0)
628 {
629 _dbus_warn ("expected info on service %s, got info on %s\n",
630 d->expected_service_name,
631 service_name);
632 goto out;
633 }
634
635 if (*service_name == ':' && new_owner[0]
636 && strcmp (service_name, new_owner) != 0)
637 {
638 _dbus_warn ("inconsistent ServiceOwnedChanged message (\"%s\" [ %s -> %s ])\n",
639 service_name, old_owner, new_owner);
640 goto out;
641 }
642 }
643
644 d->failed = FALSE;
645
646 out:
647 dbus_error_free (&error);
648
649 if (message)
650 dbus_message_unref (message);
651
652 return !d->failed;
653}
654
655
656static void
657kill_client_connection (BusContext *context,
658 DBusConnection *connection)
659{
660 char *base_service;
661 const char *s;
662 CheckServiceOwnerChangedData socd;
663
664 _dbus_verbose ("killing connection %p\n", connection);
665
666 s = dbus_bus_get_unique_name (connection);
667 _dbus_assert (s != NULL);
668
669 while ((base_service = _dbus_strdup (s)) == NULL)
670 _dbus_wait_for_memory ();
671
672 dbus_connection_ref (connection);
673
674 /* kick in the disconnect handler that unrefs the connection */
675 dbus_connection_close (connection);
676
677 bus_test_run_everything (context);
678
679 _dbus_assert (bus_test_client_listed (connection));
680
681 /* Run disconnect handler in test.c */
682 if (bus_connection_dispatch_one_message (connection))
683 _dbus_assert_not_reached ("something received on connection being killed other than the disconnect");
684
685 _dbus_assert (!dbus_connection_get_is_connected (connection));
686 dbus_connection_unref (connection);
687 connection = NULL;
688 _dbus_assert (!bus_test_client_listed (connection));
689
690 socd.expected_kind = SERVICE_DELETED;
691 socd.expected_service_name = base_service;
692 socd.failed = FALSE;
693 socd.skip_connection = NULL;
694
695 bus_test_clients_foreach (check_service_owner_changed_foreach,
696 &socd);
697
698 dbus_free (base_service);
699
700 if (socd.failed)
701 _dbus_assert_not_reached ("didn't get the expected NameOwnerChanged (deletion) messages");
702
703 if (!check_no_leftovers (context))
704 _dbus_assert_not_reached ("stuff left in message queues after disconnecting a client");
705}
706
707static void
708kill_client_connection_unchecked (DBusConnection *connection)
709{
710 /* This kills the connection without expecting it to affect
711 * the rest of the bus.
712 */
713 _dbus_verbose ("Unchecked kill of connection %p\n", connection);
714
715 dbus_connection_ref (connection);
716 dbus_connection_close (connection);
717 /* dispatching disconnect handler will unref once */
718 if (bus_connection_dispatch_one_message (connection))
719 _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
720
721 _dbus_assert (!bus_test_client_listed (connection));
722 dbus_connection_unref (connection);
723}
724
725typedef struct
726{
727 dbus_bool_t failed;
728} CheckNoMessagesData;
729
730static dbus_bool_t
731check_no_messages_foreach (DBusConnection *connection,
732 void *data)
733{
734 CheckNoMessagesData *d = data;
735 DBusMessage *message;
736
737 message = pop_message_waiting_for_memory (connection);
738 if (message != NULL)
739 {
740 warn_unexpected (connection, message, "no messages");
741
742 d->failed = TRUE;
743 }
744
745 if (message)
746 dbus_message_unref (message);
747 return !d->failed;
748}
749
750static dbus_bool_t
751check_no_leftovers (BusContext *context)
752{
753 CheckNoMessagesData nmd;
754
755 nmd.failed = FALSE;
756 bus_test_clients_foreach (check_no_messages_foreach,
757 &nmd);
758
759 if (nmd.failed)
760 {
761 _dbus_verbose ("leftover message found\n");
762 return FALSE;
763 }
764 else
765 return TRUE;
766}
767
768/* returns TRUE if the correct thing happens,
769 * but the correct thing may include OOM errors.
770 */
771static dbus_bool_t
772check_hello_message (BusContext *context,
773 DBusConnection *connection)
774{
775 DBusMessage *message;
776 DBusMessage *name_message;
777 dbus_uint32_t serial;
778 dbus_bool_t retval;
779 DBusError error;
780 const char *name;
781 const char *acquired;
782
783 retval = FALSE;
784 dbus_error_init (&error);
785 name = NULL;
786 acquired = NULL;
787 message = NULL;
788 name_message = NULL;
789
790 _dbus_verbose ("check_hello_message for %p\n", connection);
791
792 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
793 DBUS_PATH_DBUS,
794 DBUS_INTERFACE_DBUS,
795 "Hello");
796
797 if (message == NULL)
798 return TRUE;
799
800 dbus_connection_ref (connection); /* because we may get disconnected */
801
802 if (!dbus_connection_send (connection, message, &serial))
803 {
804 dbus_message_unref (message);
805 dbus_connection_unref (connection);
806 return TRUE;
807 }
808
809 _dbus_assert (dbus_message_has_signature (message, ""));
810
811 dbus_message_unref (message);
812 message = NULL;
813
814 if (!dbus_connection_get_is_connected (connection))
815 {
816 _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
817
818 dbus_connection_unref (connection);
819
820 return TRUE;
821 }
822
823 /* send our message */
824 bus_test_run_clients_loop (SEND_PENDING (connection));
825
826 if (!dbus_connection_get_is_connected (connection))
827 {
828 _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
829
830 dbus_connection_unref (connection);
831
832 return TRUE;
833 }
834
835 block_connection_until_message_from_bus (context, connection, "reply to Hello");
836
837 if (!dbus_connection_get_is_connected (connection))
838 {
839 _dbus_verbose ("connection was disconnected (presumably auth failed)\n");
840
841 dbus_connection_unref (connection);
842
843 return TRUE;
844 }
845
846 dbus_connection_unref (connection);
847
848 message = pop_message_waiting_for_memory (connection);
849 if (message == NULL)
850 {
851 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
852 "Hello", serial, connection);
853 goto out;
854 }
855
856 verbose_message_received (connection, message);
857
858 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
859 {
860 _dbus_warn ("Message has wrong sender %s\n",
861 dbus_message_get_sender (message) ?
862 dbus_message_get_sender (message) : "(none)");
863 goto out;
864 }
865
866 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
867 {
868 if (dbus_message_is_error (message,
869 DBUS_ERROR_NO_MEMORY))
870 {
871 ; /* good, this is a valid response */
872 }
873 else
874 {
875 warn_unexpected (connection, message, "not this error");
876
877 goto out;
878 }
879 }
880 else
881 {
882 CheckServiceOwnerChangedData socd;
883
884 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
885 {
886 ; /* good, expected */
887 }
888 else
889 {
890 warn_unexpected (connection, message, "method return for Hello");
891
892 goto out;
893 }
894
895 retry_get_hello_name:
896 if (!dbus_message_get_args (message, &error,
897 DBUS_TYPE_STRING, &name,
898 DBUS_TYPE_INVALID))
899 {
900 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
901 {
902 _dbus_verbose ("no memory to get service name arg from hello\n");
903 dbus_error_free (&error);
904 _dbus_wait_for_memory ();
905 goto retry_get_hello_name;
906 }
907 else
908 {
909 _dbus_assert (dbus_error_is_set (&error));
910 _dbus_warn ("Did not get the expected single string argument to hello\n");
911 goto out;
912 }
913 }
914
915 _dbus_verbose ("Got hello name: %s\n", name);
916
917 while (!dbus_bus_set_unique_name (connection, name))
918 _dbus_wait_for_memory ();
919
920 socd.expected_kind = SERVICE_CREATED;
921 socd.expected_service_name = name;
922 socd.failed = FALSE;
923 socd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
924 bus_test_clients_foreach (check_service_owner_changed_foreach,
925 &socd);
926
927 if (socd.failed)
928 goto out;
929
930 name_message = message;
931 /* Client should also have gotten ServiceAcquired */
932
933 message = pop_message_waiting_for_memory (connection);
934 if (message == NULL)
935 {
936 _dbus_warn ("Expecting %s, got nothing\n",
937 "NameAcquired");
938 goto out;
939 }
940 if (! dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
941 "NameAcquired"))
942 {
943 _dbus_warn ("Expecting %s, got smthg else\n",
944 "NameAcquired");
945 goto out;
946 }
947
948 retry_get_acquired_name:
949 if (!dbus_message_get_args (message, &error,
950 DBUS_TYPE_STRING, &acquired,
951 DBUS_TYPE_INVALID))
952 {
953 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
954 {
955 _dbus_verbose ("no memory to get service name arg from acquired\n");
956 dbus_error_free (&error);
957 _dbus_wait_for_memory ();
958 goto retry_get_acquired_name;
959 }
960 else
961 {
962 _dbus_assert (dbus_error_is_set (&error));
963 _dbus_warn ("Did not get the expected single string argument to ServiceAcquired\n");
964 goto out;
965 }
966 }
967
968 _dbus_verbose ("Got acquired name: %s\n", acquired);
969
970 if (strcmp (acquired, name) != 0)
971 {
972 _dbus_warn ("Acquired name is %s but expected %s\n",
973 acquired, name);
974 goto out;
975 }
976 acquired = NULL;
977 }
978
979 if (!check_no_leftovers (context))
980 goto out;
981
982 retval = TRUE;
983
984 out:
985 _dbus_verbose ("ending - retval = %d\n", retval);
986
987 dbus_error_free (&error);
988
989 if (message)
990 dbus_message_unref (message);
991
992 if (name_message)
993 dbus_message_unref (name_message);
994
995 return retval;
996}
997
998/* returns TRUE if the correct thing happens,
999 * but the correct thing may include OOM errors.
1000 */
1001static dbus_bool_t
1002check_double_hello_message (BusContext *context,
1003 DBusConnection *connection)
1004{
1005 DBusMessage *message;
1006 dbus_uint32_t serial;
1007 dbus_bool_t retval;
1008 DBusError error;
1009
1010 retval = FALSE;
1011 dbus_error_init (&error);
1012 message = NULL;
1013
1014 _dbus_verbose ("check_double_hello_message for %p\n", connection);
1015
1016 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1017 DBUS_PATH_DBUS,
1018 DBUS_INTERFACE_DBUS,
1019 "Hello");
1020
1021 if (message == NULL)
1022 return TRUE;
1023
1024 if (!dbus_connection_send (connection, message, &serial))
1025 {
1026 dbus_message_unref (message);
1027 return TRUE;
1028 }
1029
1030 dbus_message_unref (message);
1031 message = NULL;
1032
1033 /* send our message */
1034 bus_test_run_clients_loop (SEND_PENDING (connection));
1035
1036 dbus_connection_ref (connection); /* because we may get disconnected */
1037 block_connection_until_message_from_bus (context, connection, "reply to Hello");
1038
1039 if (!dbus_connection_get_is_connected (connection))
1040 {
1041 _dbus_verbose ("connection was disconnected\n");
1042
1043 dbus_connection_unref (connection);
1044
1045 return TRUE;
1046 }
1047
1048 dbus_connection_unref (connection);
1049
1050 message = pop_message_waiting_for_memory (connection);
1051 if (message == NULL)
1052 {
1053 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1054 "Hello", serial, connection);
1055 goto out;
1056 }
1057
1058 verbose_message_received (connection, message);
1059
1060 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1061 {
1062 _dbus_warn ("Message has wrong sender %s\n",
1063 dbus_message_get_sender (message) ?
1064 dbus_message_get_sender (message) : "(none)");
1065 goto out;
1066 }
1067
1068 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
1069 {
1070 warn_unexpected (connection, message, "method return for Hello");
1071 goto out;
1072 }
1073
1074 if (!check_no_leftovers (context))
1075 goto out;
1076
1077 retval = TRUE;
1078
1079 out:
1080 dbus_error_free (&error);
1081
1082 if (message)
1083 dbus_message_unref (message);
1084
1085 return retval;
1086}
1087
1088/* returns TRUE if the correct thing happens,
1089 * but the correct thing may include OOM errors.
1090 */
1091static dbus_bool_t
1092check_get_connection_unix_user (BusContext *context,
1093 DBusConnection *connection)
1094{
1095 DBusMessage *message;
1096 dbus_uint32_t serial;
1097 dbus_bool_t retval;
1098 DBusError error;
1099 const char *base_service_name;
1100 dbus_uint32_t uid;
1101
1102 retval = FALSE;
1103 dbus_error_init (&error);
1104 message = NULL;
1105
1106 _dbus_verbose ("check_get_connection_unix_user for %p\n", connection);
1107
1108 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1109 DBUS_PATH_DBUS,
1110 DBUS_INTERFACE_DBUS,
1111 "GetConnectionUnixUser");
1112
1113 if (message == NULL)
1114 return TRUE;
1115
1116 base_service_name = dbus_bus_get_unique_name (connection);
1117
1118 if (!dbus_message_append_args (message,
1119 DBUS_TYPE_STRING, &base_service_name,
1120 DBUS_TYPE_INVALID))
1121 {
1122 dbus_message_unref (message);
1123 return TRUE;
1124 }
1125
1126 if (!dbus_connection_send (connection, message, &serial))
1127 {
1128 dbus_message_unref (message);
1129 return TRUE;
1130 }
1131
1132 /* send our message */
1133 bus_test_run_clients_loop (SEND_PENDING (connection));
1134
1135 dbus_message_unref (message);
1136 message = NULL;
1137
1138 dbus_connection_ref (connection); /* because we may get disconnected */
1139 block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixUser");
1140
1141 if (!dbus_connection_get_is_connected (connection))
1142 {
1143 _dbus_verbose ("connection was disconnected\n");
1144
1145 dbus_connection_unref (connection);
1146
1147 return TRUE;
1148 }
1149
1150 dbus_connection_unref (connection);
1151
1152 message = pop_message_waiting_for_memory (connection);
1153 if (message == NULL)
1154 {
1155 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1156 "GetConnectionUnixUser", serial, connection);
1157 goto out;
1158 }
1159
1160 verbose_message_received (connection, message);
1161
1162 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1163 {
1164 if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
1165 {
1166 ; /* good, this is a valid response */
1167 }
1168 else
1169 {
1170 warn_unexpected (connection, message, "not this error");
1171
1172 goto out;
1173 }
1174 }
1175 else
1176 {
1177 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1178 {
1179 ; /* good, expected */
1180 }
1181 else
1182 {
1183 warn_unexpected (connection, message,
1184 "method_return for GetConnectionUnixUser");
1185
1186 goto out;
1187 }
1188
1189 retry_get_property:
1190
1191 if (!dbus_message_get_args (message, &error,
1192 DBUS_TYPE_UINT32, &uid,
1193 DBUS_TYPE_INVALID))
1194 {
1195 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1196 {
1197 _dbus_verbose ("no memory to get uid by GetConnectionUnixUser\n");
1198 dbus_error_free (&error);
1199 _dbus_wait_for_memory ();
1200 goto retry_get_property;
1201 }
1202 else
1203 {
1204 _dbus_assert (dbus_error_is_set (&error));
1205 _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixUser\n");
1206 goto out;
1207 }
1208 }
1209 }
1210
1211 if (!check_no_leftovers (context))
1212 goto out;
1213
1214 retval = TRUE;
1215
1216 out:
1217 dbus_error_free (&error);
1218
1219 if (message)
1220 dbus_message_unref (message);
1221
1222 return retval;
1223}
1224
1225/* returns TRUE if the correct thing happens,
1226 * but the correct thing may include OOM errors.
1227 */
1228static dbus_bool_t
1229check_get_connection_unix_process_id (BusContext *context,
1230 DBusConnection *connection)
1231{
1232 DBusMessage *message;
1233 dbus_uint32_t serial;
1234 dbus_bool_t retval;
1235 DBusError error;
1236 const char *base_service_name;
1237 dbus_uint32_t pid;
1238
1239 retval = FALSE;
1240 dbus_error_init (&error);
1241 message = NULL;
1242
1243 _dbus_verbose ("check_get_connection_unix_process_id for %p\n", connection);
1244
1245 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1246 DBUS_PATH_DBUS,
1247 DBUS_INTERFACE_DBUS,
1248 "GetConnectionUnixProcessID");
1249
1250 if (message == NULL)
1251 return TRUE;
1252
1253 base_service_name = dbus_bus_get_unique_name (connection);
1254
1255 if (!dbus_message_append_args (message,
1256 DBUS_TYPE_STRING, &base_service_name,
1257 DBUS_TYPE_INVALID))
1258 {
1259 dbus_message_unref (message);
1260 return TRUE;
1261 }
1262
1263 if (!dbus_connection_send (connection, message, &serial))
1264 {
1265 dbus_message_unref (message);
1266 return TRUE;
1267 }
1268
1269 /* send our message */
1270 bus_test_run_clients_loop (SEND_PENDING (connection));
1271
1272 dbus_message_unref (message);
1273 message = NULL;
1274
1275 dbus_connection_ref (connection); /* because we may get disconnected */
1276 block_connection_until_message_from_bus (context, connection, "reply to GetConnectionUnixProcessID");
1277
1278 if (!dbus_connection_get_is_connected (connection))
1279 {
1280 _dbus_verbose ("connection was disconnected\n");
1281
1282 dbus_connection_unref (connection);
1283
1284 return TRUE;
1285 }
1286
1287 dbus_connection_unref (connection);
1288
1289 message = pop_message_waiting_for_memory (connection);
1290 if (message == NULL)
1291 {
1292 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1293 "GetConnectionUnixProcessID", serial, connection);
1294 goto out;
1295 }
1296
1297 verbose_message_received (connection, message);
1298
1299 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1300 {
1301 if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
1302 {
1303 ; /* good, this is a valid response */
1304 }
1305#ifdef DBUS_WIN
1306 else if (dbus_message_is_error (message, DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN))
1307 {
1308 /* We are expecting this error, since we know in the test suite we aren't
1309 * talking to a client running on UNIX
1310 */
1311 _dbus_verbose ("Windows correctly does not support GetConnectionUnixProcessID\n");
1312 }
1313#endif
1314 else
1315 {
1316 warn_unexpected (connection, message, "not this error");
1317
1318 goto out;
1319 }
1320 }
1321 else
1322 {
1323#ifdef DBUS_WIN
1324 warn_unexpected (connection, message, "GetConnectionUnixProcessID to fail on Windows");
1325 goto out;
1326#else
1327 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1328 {
1329 ; /* good, expected */
1330 }
1331 else
1332 {
1333 warn_unexpected (connection, message,
1334 "method_return for GetConnectionUnixProcessID");
1335
1336 goto out;
1337 }
1338
1339 retry_get_property:
1340
1341 if (!dbus_message_get_args (message, &error,
1342 DBUS_TYPE_UINT32, &pid,
1343 DBUS_TYPE_INVALID))
1344 {
1345 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1346 {
1347 _dbus_verbose ("no memory to get pid by GetConnectionUnixProcessID\n");
1348 dbus_error_free (&error);
1349 _dbus_wait_for_memory ();
1350 goto retry_get_property;
1351 }
1352 else
1353 {
1354 _dbus_assert (dbus_error_is_set (&error));
1355 _dbus_warn ("Did not get the expected DBUS_TYPE_UINT32 from GetConnectionUnixProcessID\n");
1356 goto out;
1357 }
1358 }
1359 else
1360 {
1361 /* test if returned pid is the same as our own pid
1362 *
1363 * @todo It would probably be good to restructure the tests
1364 * in a way so our parent is the bus that we're testing
1365 * cause then we can test that the pid returned matches
1366 * getppid()
1367 */
1368 if (pid != (dbus_uint32_t) _dbus_getpid ())
1369 {
1370 _dbus_assert (dbus_error_is_set (&error));
1371 _dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid\n");
1372 goto out;
1373 }
1374 }
1375#endif /* !DBUS_WIN */
1376 }
1377
1378 if (!check_no_leftovers (context))
1379 goto out;
1380
1381 retval = TRUE;
1382
1383 out:
1384 dbus_error_free (&error);
1385
1386 if (message)
1387 dbus_message_unref (message);
1388
1389 return retval;
1390}
1391
1392/* returns TRUE if the correct thing happens,
1393 * but the correct thing may include OOM errors.
1394 */
1395static dbus_bool_t
1396check_add_match_all (BusContext *context,
1397 DBusConnection *connection)
1398{
1399 DBusMessage *message;
1400 dbus_bool_t retval;
1401 dbus_uint32_t serial;
1402 DBusError error;
1403 const char *empty = "";
1404
1405 retval = FALSE;
1406 dbus_error_init (&error);
1407 message = NULL;
1408
1409 _dbus_verbose ("check_add_match_all for %p\n", connection);
1410
1411 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1412 DBUS_PATH_DBUS,
1413 DBUS_INTERFACE_DBUS,
1414 "AddMatch");
1415
1416 if (message == NULL)
1417 return TRUE;
1418
1419 /* empty string match rule matches everything */
1420 if (!dbus_message_append_args (message, DBUS_TYPE_STRING, &empty,
1421 DBUS_TYPE_INVALID))
1422 {
1423 dbus_message_unref (message);
1424 return TRUE;
1425 }
1426
1427 if (!dbus_connection_send (connection, message, &serial))
1428 {
1429 dbus_message_unref (message);
1430 return TRUE;
1431 }
1432
1433 dbus_message_unref (message);
1434 message = NULL;
1435
1436 dbus_connection_ref (connection); /* because we may get disconnected */
1437
1438 /* send our message */
1439 bus_test_run_clients_loop (SEND_PENDING (connection));
1440
1441 if (!dbus_connection_get_is_connected (connection))
1442 {
1443 _dbus_verbose ("connection was disconnected\n");
1444
1445 dbus_connection_unref (connection);
1446
1447 return TRUE;
1448 }
1449
1450 block_connection_until_message_from_bus (context, connection, "reply to AddMatch");
1451
1452 if (!dbus_connection_get_is_connected (connection))
1453 {
1454 _dbus_verbose ("connection was disconnected\n");
1455
1456 dbus_connection_unref (connection);
1457
1458 return TRUE;
1459 }
1460
1461 dbus_connection_unref (connection);
1462
1463 message = pop_message_waiting_for_memory (connection);
1464 if (message == NULL)
1465 {
1466 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1467 "AddMatch", serial, connection);
1468 goto out;
1469 }
1470
1471 verbose_message_received (connection, message);
1472
1473 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1474 {
1475 _dbus_warn ("Message has wrong sender %s\n",
1476 dbus_message_get_sender (message) ?
1477 dbus_message_get_sender (message) : "(none)");
1478 goto out;
1479 }
1480
1481 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1482 {
1483 if (dbus_message_is_error (message,
1484 DBUS_ERROR_NO_MEMORY))
1485 {
1486 ; /* good, this is a valid response */
1487 }
1488 else
1489 {
1490 warn_unexpected (connection, message, "not this error");
1491
1492 goto out;
1493 }
1494 }
1495 else
1496 {
1497 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1498 {
1499 ; /* good, expected */
1500 _dbus_assert (dbus_message_get_reply_serial (message) == serial);
1501 }
1502 else
1503 {
1504 warn_unexpected (connection, message, "method return for AddMatch");
1505
1506 goto out;
1507 }
1508 }
1509
1510 if (!check_no_leftovers (context))
1511 goto out;
1512
1513 retval = TRUE;
1514
1515 out:
1516 dbus_error_free (&error);
1517
1518 if (message)
1519 dbus_message_unref (message);
1520
1521 return retval;
1522}
1523
1524/* returns TRUE if the correct thing happens,
1525 * but the correct thing may include OOM errors.
1526 */
1527static dbus_bool_t
1528check_hello_connection (BusContext *context)
1529{
1530 DBusConnection *connection;
1531 DBusError error;
1532
1533 dbus_error_init (&error);
1534
1535 connection = dbus_connection_open_private (TEST_CONNECTION, &error);
1536 if (connection == NULL)
1537 {
1538 _DBUS_ASSERT_ERROR_IS_SET (&error);
1539 dbus_error_free (&error);
1540 return TRUE;
1541 }
1542
1543 if (!bus_setup_debug_client (connection))
1544 {
1545 dbus_connection_close (connection);
1546 dbus_connection_unref (connection);
1547 return TRUE;
1548 }
1549
1550 spin_connection_until_authenticated (context, connection);
1551
1552 if (!check_hello_message (context, connection))
1553 return FALSE;
1554
1555 if (dbus_bus_get_unique_name (connection) == NULL)
1556 {
1557 /* We didn't successfully register, so we can't
1558 * do the usual kill_client_connection() checks
1559 */
1560 kill_client_connection_unchecked (connection);
1561 }
1562 else
1563 {
1564 if (!check_add_match_all (context, connection))
1565 return FALSE;
1566
1567 kill_client_connection (context, connection);
1568 }
1569
1570 return TRUE;
1571}
1572
1573#define NONEXISTENT_SERVICE_NAME "test.this.service.does.not.exist.ewuoiurjdfxcvn"
1574
1575/* returns TRUE if the correct thing happens,
1576 * but the correct thing may include OOM errors.
1577 */
1578static dbus_bool_t
1579check_nonexistent_service_no_auto_start (BusContext *context,
1580 DBusConnection *connection)
1581{
1582 DBusMessage *message;
1583 dbus_uint32_t serial;
1584 dbus_bool_t retval;
1585 const char *nonexistent = NONEXISTENT_SERVICE_NAME;
1586 dbus_uint32_t flags;
1587
1588 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
1589 DBUS_PATH_DBUS,
1590 DBUS_INTERFACE_DBUS,
1591 "StartServiceByName");
1592
1593 if (message == NULL)
1594 return TRUE;
1595
1596 dbus_message_set_auto_start (message, FALSE);
1597
1598 flags = 0;
1599 if (!dbus_message_append_args (message,
1600 DBUS_TYPE_STRING, &nonexistent,
1601 DBUS_TYPE_UINT32, &flags,
1602 DBUS_TYPE_INVALID))
1603 {
1604 dbus_message_unref (message);
1605 return TRUE;
1606 }
1607
1608 if (!dbus_connection_send (connection, message, &serial))
1609 {
1610 dbus_message_unref (message);
1611 return TRUE;
1612 }
1613
1614 dbus_message_unref (message);
1615 message = NULL;
1616
1617 bus_test_run_everything (context);
1618 block_connection_until_message_from_bus (context, connection, "reply to ActivateService on nonexistent");
1619 bus_test_run_everything (context);
1620
1621 if (!dbus_connection_get_is_connected (connection))
1622 {
1623 _dbus_verbose ("connection was disconnected\n");
1624 return TRUE;
1625 }
1626
1627 retval = FALSE;
1628
1629 message = pop_message_waiting_for_memory (connection);
1630 if (message == NULL)
1631 {
1632 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1633 "StartServiceByName", serial, connection);
1634 goto out;
1635 }
1636
1637 verbose_message_received (connection, message);
1638
1639 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1640 {
1641 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1642 {
1643 _dbus_warn ("Message has wrong sender %s\n",
1644 dbus_message_get_sender (message) ?
1645 dbus_message_get_sender (message) : "(none)");
1646 goto out;
1647 }
1648
1649 if (dbus_message_is_error (message,
1650 DBUS_ERROR_NO_MEMORY))
1651 {
1652 ; /* good, this is a valid response */
1653 }
1654 else if (dbus_message_is_error (message,
1655 DBUS_ERROR_SERVICE_UNKNOWN))
1656 {
1657 ; /* good, this is expected also */
1658 }
1659 else
1660 {
1661 warn_unexpected (connection, message, "not this error");
1662 goto out;
1663 }
1664 }
1665 else
1666 {
1667 _dbus_warn ("Did not expect to successfully activate %s\n",
1668 NONEXISTENT_SERVICE_NAME);
1669 goto out;
1670 }
1671
1672 retval = TRUE;
1673
1674 out:
1675 if (message)
1676 dbus_message_unref (message);
1677
1678 return retval;
1679}
1680
1681/* returns TRUE if the correct thing happens,
1682 * but the correct thing may include OOM errors.
1683 */
1684static dbus_bool_t
1685check_nonexistent_service_auto_start (BusContext *context,
1686 DBusConnection *connection)
1687{
1688 DBusMessage *message;
1689 dbus_uint32_t serial;
1690 dbus_bool_t retval;
1691
1692 message = dbus_message_new_method_call (NONEXISTENT_SERVICE_NAME,
1693 "/org/freedesktop/TestSuite",
1694 "org.freedesktop.TestSuite",
1695 "Echo");
1696
1697 if (message == NULL)
1698 return TRUE;
1699
1700 if (!dbus_connection_send (connection, message, &serial))
1701 {
1702 dbus_message_unref (message);
1703 return TRUE;
1704 }
1705
1706 dbus_message_unref (message);
1707 message = NULL;
1708
1709 bus_test_run_everything (context);
1710 block_connection_until_message_from_bus (context, connection, "reply to Echo");
1711 bus_test_run_everything (context);
1712
1713 if (!dbus_connection_get_is_connected (connection))
1714 {
1715 _dbus_verbose ("connection was disconnected\n");
1716 return TRUE;
1717 }
1718
1719 retval = FALSE;
1720
1721 message = pop_message_waiting_for_memory (connection);
1722
1723 if (message == NULL)
1724 {
1725 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
1726 "Echo message (auto activation)", serial, connection);
1727 goto out;
1728 }
1729
1730 verbose_message_received (connection, message);
1731
1732 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
1733 {
1734 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
1735 {
1736 _dbus_warn ("Message has wrong sender %s\n",
1737 dbus_message_get_sender (message) ?
1738 dbus_message_get_sender (message) : "(none)");
1739 goto out;
1740 }
1741
1742 if (dbus_message_is_error (message,
1743 DBUS_ERROR_NO_MEMORY))
1744 {
1745 ; /* good, this is a valid response */
1746 }
1747 else if (dbus_message_is_error (message,
1748 DBUS_ERROR_SERVICE_UNKNOWN))
1749 {
1750 ; /* good, this is expected also */
1751 }
1752 else
1753 {
1754 warn_unexpected (connection, message, "not this error");
1755 goto out;
1756 }
1757 }
1758 else
1759 {
1760 _dbus_warn ("Did not expect to successfully activate %s\n",
1761 NONEXISTENT_SERVICE_NAME);
1762 goto out;
1763 }
1764
1765 retval = TRUE;
1766
1767 out:
1768 if (message)
1769 dbus_message_unref (message);
1770
1771 return retval;
1772}
1773
1774static dbus_bool_t
1775check_base_service_activated (BusContext *context,
1776 DBusConnection *connection,
1777 DBusMessage *initial_message,
1778 const char **base_service_p)
1779{
1780 DBusMessage *message;
1781 dbus_bool_t retval;
1782 DBusError error;
1783 const char *base_service, *base_service_from_bus, *old_owner;
1784
1785 retval = FALSE;
1786
1787 dbus_error_init (&error);
1788 base_service = NULL;
1789 old_owner = NULL;
1790 base_service_from_bus = NULL;
1791
1792 message = initial_message;
1793 dbus_message_ref (message);
1794
1795 if (dbus_message_is_signal (message,
1796 DBUS_INTERFACE_DBUS,
1797 "NameOwnerChanged"))
1798 {
1799 CheckServiceOwnerChangedData socd;
1800
1801 reget_service_name_arg:
1802 base_service = NULL;
1803 old_owner = NULL;
1804 base_service_from_bus = NULL;
1805
1806 if (!dbus_message_get_args (message, &error,
1807 DBUS_TYPE_STRING, &base_service,
1808 DBUS_TYPE_STRING, &old_owner,
1809 DBUS_TYPE_STRING, &base_service_from_bus,
1810 DBUS_TYPE_INVALID))
1811 {
1812 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1813 {
1814 dbus_error_free (&error);
1815 _dbus_wait_for_memory ();
1816 goto reget_service_name_arg;
1817 }
1818 else
1819 {
1820 _dbus_warn ("Message %s doesn't have a service name: %s\n",
1821 "NameOwnerChanged (creation)",
1822 error.message);
1823 goto out;
1824 }
1825 }
1826
1827 if (*base_service != ':')
1828 {
1829 _dbus_warn ("Expected base service activation, got \"%s\" instead\n",
1830 base_service);
1831 goto out;
1832 }
1833
1834 if (strcmp (base_service, base_service_from_bus) != 0)
1835 {
1836 _dbus_warn ("Expected base service activation, got \"%s\" instead with owner \"%s\"\n",
1837 base_service, base_service_from_bus);
1838 goto out;
1839 }
1840
1841 if (old_owner[0])
1842 {
1843 _dbus_warn ("Received an old_owner argument during base service activation, \"%s\"\n",
1844 old_owner);
1845 goto out;
1846 }
1847
1848 socd.expected_kind = SERVICE_CREATED;
1849 socd.expected_service_name = base_service;
1850 socd.failed = FALSE;
1851 socd.skip_connection = connection;
1852 bus_test_clients_foreach (check_service_owner_changed_foreach,
1853 &socd);
1854
1855 if (socd.failed)
1856 goto out;
1857 }
1858 else
1859 {
1860 warn_unexpected (connection, message, "NameOwnerChanged (creation) for base service");
1861
1862 goto out;
1863 }
1864
1865 if (base_service_p)
1866 *base_service_p = base_service;
1867
1868 retval = TRUE;
1869
1870 out:
1871 if (message)
1872 dbus_message_unref (message);
1873 dbus_error_free (&error);
1874
1875 return retval;
1876}
1877
1878static dbus_bool_t
1879check_service_activated (BusContext *context,
1880 DBusConnection *connection,
1881 const char *activated_name,
1882 const char *base_service_name,
1883 DBusMessage *initial_message)
1884{
1885 DBusMessage *message;
1886 dbus_bool_t retval;
1887 DBusError error;
1888 dbus_uint32_t activation_result;
1889
1890 retval = FALSE;
1891
1892 dbus_error_init (&error);
1893
1894 message = initial_message;
1895 dbus_message_ref (message);
1896
1897 if (dbus_message_is_signal (message,
1898 DBUS_INTERFACE_DBUS,
1899 "NameOwnerChanged"))
1900 {
1901 CheckServiceOwnerChangedData socd;
1902 const char *service_name, *base_service_from_bus, *old_owner;
1903
1904 reget_service_name_arg:
1905 service_name = NULL;
1906 old_owner = NULL;
1907 base_service_from_bus = NULL;
1908
1909 if (!dbus_message_get_args (message, &error,
1910 DBUS_TYPE_STRING, &service_name,
1911 DBUS_TYPE_STRING, &old_owner,
1912 DBUS_TYPE_STRING, &base_service_from_bus,
1913 DBUS_TYPE_INVALID))
1914 {
1915 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1916 {
1917 dbus_error_free (&error);
1918 _dbus_wait_for_memory ();
1919 goto reget_service_name_arg;
1920 }
1921 else
1922 {
1923 _dbus_warn ("Message %s doesn't have a service name: %s\n",
1924 "NameOwnerChanged (creation)",
1925 error.message);
1926 goto out;
1927 }
1928 }
1929
1930 if (strcmp (service_name, activated_name) != 0)
1931 {
1932 _dbus_warn ("Expected to see service %s created, saw %s instead\n",
1933 activated_name, service_name);
1934 goto out;
1935 }
1936
1937 if (strcmp (base_service_name, base_service_from_bus) != 0)
1938 {
1939 _dbus_warn ("NameOwnerChanged reports wrong base service: %s owner, expected %s instead\n",
1940 base_service_from_bus, base_service_name);
1941 goto out;
1942 }
1943
1944 if (old_owner[0])
1945 {
1946 _dbus_warn ("expected a %s, got a %s\n",
1947 "NameOwnerChanged (creation)",
1948 "NameOwnerChanged (change)");
1949 goto out;
1950 }
1951
1952 socd.expected_kind = SERVICE_CREATED;
1953 socd.skip_connection = connection;
1954 socd.failed = FALSE;
1955 socd.expected_service_name = service_name;
1956 bus_test_clients_foreach (check_service_owner_changed_foreach,
1957 &socd);
1958
1959 if (socd.failed)
1960 goto out;
1961
1962 dbus_message_unref (message);
1963 service_name = NULL;
1964 old_owner = NULL;
1965 base_service_from_bus = NULL;
1966
1967 message = pop_message_waiting_for_memory (connection);
1968 if (message == NULL)
1969 {
1970 _dbus_warn ("Expected a reply to %s, got nothing\n",
1971 "StartServiceByName");
1972 goto out;
1973 }
1974 }
1975 else
1976 {
1977 warn_unexpected (connection, message, "NameOwnerChanged for the activated name");
1978
1979 goto out;
1980 }
1981
1982 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
1983 {
1984 warn_unexpected (connection, message, "reply to StartServiceByName");
1985
1986 goto out;
1987 }
1988
1989 activation_result = 0;
1990 if (!dbus_message_get_args (message, &error,
1991 DBUS_TYPE_UINT32, &activation_result,
1992 DBUS_TYPE_INVALID))
1993 {
1994 if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1995 {
1996 _dbus_warn ("Did not have activation result first argument to %s: %s\n",
1997 "StartServiceByName", error.message);
1998 goto out;
1999 }
2000
2001 dbus_error_free (&error);
2002 }
2003 else
2004 {
2005 if (activation_result == DBUS_START_REPLY_SUCCESS)
2006 ; /* Good */
2007 else if (activation_result == DBUS_START_REPLY_ALREADY_RUNNING)
2008 ; /* Good also */
2009 else
2010 {
2011 _dbus_warn ("Activation result was %u, no good.\n",
2012 activation_result);
2013 goto out;
2014 }
2015 }
2016
2017 dbus_message_unref (message);
2018 message = NULL;
2019
2020 if (!check_no_leftovers (context))
2021 {
2022 _dbus_warn ("Messages were left over after verifying existent activation results\n");
2023 goto out;
2024 }
2025
2026 retval = TRUE;
2027
2028 out:
2029 if (message)
2030 dbus_message_unref (message);
2031 dbus_error_free (&error);
2032
2033 return retval;
2034}
2035
2036static dbus_bool_t
2037check_service_auto_activated (BusContext *context,
2038 DBusConnection *connection,
2039 const char *activated_name,
2040 const char *base_service_name,
2041 DBusMessage *initial_message)
2042{
2043 DBusMessage *message;
2044 dbus_bool_t retval;
2045 DBusError error;
2046
2047 retval = FALSE;
2048
2049 dbus_error_init (&error);
2050
2051 message = initial_message;
2052 dbus_message_ref (message);
2053
2054 if (dbus_message_is_signal (message,
2055 DBUS_INTERFACE_DBUS,
2056 "NameOwnerChanged"))
2057 {
2058 const char *service_name;
2059 CheckServiceOwnerChangedData socd;
2060
2061 reget_service_name_arg:
2062 if (!dbus_message_get_args (message, &error,
2063 DBUS_TYPE_STRING, &service_name,
2064 DBUS_TYPE_INVALID))
2065 {
2066 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2067 {
2068 dbus_error_free (&error);
2069 _dbus_wait_for_memory ();
2070 goto reget_service_name_arg;
2071 }
2072 else
2073 {
2074 _dbus_warn ("Message %s doesn't have a service name: %s\n",
2075 "NameOwnerChanged",
2076 error.message);
2077 dbus_error_free (&error);
2078 goto out;
2079 }
2080 }
2081
2082 if (strcmp (service_name, activated_name) != 0)
2083 {
2084 _dbus_warn ("Expected to see service %s created, saw %s instead\n",
2085 activated_name, service_name);
2086 goto out;
2087 }
2088
2089 socd.expected_kind = SERVICE_CREATED;
2090 socd.expected_service_name = service_name;
2091 socd.failed = FALSE;
2092 socd.skip_connection = connection;
2093 bus_test_clients_foreach (check_service_owner_changed_foreach,
2094 &socd);
2095
2096 if (socd.failed)
2097 goto out;
2098
2099 /* Note that this differs from regular activation in that we don't get a
2100 * reply to ActivateService here.
2101 */
2102
2103 dbus_message_unref (message);
2104 message = NULL;
2105 service_name = NULL;
2106 }
2107 else
2108 {
2109 warn_unexpected (connection, message, "NameOwnerChanged for the activated name");
2110
2111 goto out;
2112 }
2113
2114 retval = TRUE;
2115
2116 out:
2117 if (message)
2118 dbus_message_unref (message);
2119
2120 return retval;
2121}
2122
2123static dbus_bool_t
2124check_service_deactivated (BusContext *context,
2125 DBusConnection *connection,
2126 const char *activated_name,
2127 const char *base_service)
2128{
2129 dbus_bool_t retval;
2130 CheckServiceOwnerChangedData socd;
2131
2132 retval = FALSE;
2133
2134 /* Now we are expecting ServiceOwnerChanged (deletion) messages for the base
2135 * service and the activated_name. The base service
2136 * notification is required to come last.
2137 */
2138 socd.expected_kind = SERVICE_DELETED;
2139 socd.expected_service_name = activated_name;
2140 socd.failed = FALSE;
2141 socd.skip_connection = NULL;
2142 bus_test_clients_foreach (check_service_owner_changed_foreach,
2143 &socd);
2144
2145 if (socd.failed)
2146 goto out;
2147
2148 socd.expected_kind = SERVICE_DELETED;
2149 socd.expected_service_name = base_service;
2150 socd.failed = FALSE;
2151 socd.skip_connection = NULL;
2152 bus_test_clients_foreach (check_service_owner_changed_foreach,
2153 &socd);
2154
2155 if (socd.failed)
2156 goto out;
2157
2158 retval = TRUE;
2159
2160 out:
2161 return retval;
2162}
2163
2164static dbus_bool_t
2165check_send_exit_to_service (BusContext *context,
2166 DBusConnection *connection,
2167 const char *service_name,
2168 const char *base_service)
2169{
2170 dbus_bool_t got_error;
2171 DBusMessage *message;
2172 dbus_uint32_t serial;
2173 dbus_bool_t retval;
2174
2175 _dbus_verbose ("Sending exit message to the test service\n");
2176
2177 retval = FALSE;
2178
2179 /* Kill off the test service by sending it a quit message */
2180 message = dbus_message_new_method_call (service_name,
2181 "/org/freedesktop/TestSuite",
2182 "org.freedesktop.TestSuite",
2183 "Exit");
2184
2185 if (message == NULL)
2186 {
2187 /* Do this again; we still need the service to exit... */
2188 if (!check_send_exit_to_service (context, connection,
2189 service_name, base_service))
2190 goto out;
2191
2192 return TRUE;
2193 }
2194
2195 if (!dbus_connection_send (connection, message, &serial))
2196 {
2197 dbus_message_unref (message);
2198
2199 /* Do this again; we still need the service to exit... */
2200 if (!check_send_exit_to_service (context, connection,
2201 service_name, base_service))
2202 goto out;
2203
2204 return TRUE;
2205 }
2206
2207 dbus_message_unref (message);
2208 message = NULL;
2209
2210 /* send message */
2211 bus_test_run_clients_loop (SEND_PENDING (connection));
2212
2213 /* read it in and write it out to test service */
2214 bus_test_run_bus_loop (context, FALSE);
2215
2216 /* see if we got an error during message bus dispatching */
2217 bus_test_run_clients_loop (FALSE);
2218 message = borrow_message_waiting_for_memory (connection);
2219 got_error = message != NULL && dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR;
2220 if (message)
2221 {
2222 dbus_connection_return_message (connection, message);
2223 message = NULL;
2224 }
2225
2226 if (!got_error)
2227 {
2228 /* If no error, wait for the test service to exit */
2229 block_connection_until_message_from_bus (context, connection, "test service to exit");
2230
2231 bus_test_run_everything (context);
2232 }
2233
2234 if (got_error)
2235 {
2236 message = pop_message_waiting_for_memory (connection);
2237 _dbus_assert (message != NULL);
2238
2239 if (dbus_message_get_reply_serial (message) != serial)
2240 {
2241 warn_unexpected (connection, message,
2242 "error with the correct reply serial");
2243 goto out;
2244 }
2245
2246 if (!dbus_message_is_error (message,
2247 DBUS_ERROR_NO_MEMORY))
2248 {
2249 warn_unexpected (connection, message,
2250 "a no memory error from asking test service to exit");
2251 goto out;
2252 }
2253
2254 _dbus_verbose ("Got error %s when asking test service to exit\n",
2255 dbus_message_get_error_name (message));
2256
2257 /* Do this again; we still need the service to exit... */
2258 if (!check_send_exit_to_service (context, connection,
2259 service_name, base_service))
2260 goto out;
2261 }
2262 else
2263 {
2264 if (!check_service_deactivated (context, connection,
2265 service_name, base_service))
2266 goto out;
2267
2268 /* Should now have a NoReply error from the Exit() method
2269 * call; it should have come after all the deactivation
2270 * stuff.
2271 */
2272 message = pop_message_waiting_for_memory (connection);
2273
2274 if (message == NULL)
2275 {
2276 warn_unexpected (connection, NULL,
2277 "reply to Exit() method call");
2278 goto out;
2279 }
2280 if (!dbus_message_is_error (message,
2281 DBUS_ERROR_NO_REPLY))
2282 {
2283 warn_unexpected (connection, message,
2284 "NoReply error from Exit() method call");
2285 goto out;
2286 }
2287
2288 if (dbus_message_get_reply_serial (message) != serial)
2289 {
2290 warn_unexpected (connection, message,
2291 "error with the correct reply serial");
2292 goto out;
2293 }
2294
2295 _dbus_verbose ("Got error %s after test service exited\n",
2296 dbus_message_get_error_name (message));
2297
2298 if (!check_no_leftovers (context))
2299 {
2300 _dbus_warn ("Messages were left over after %s\n",
2301 _DBUS_FUNCTION_NAME);
2302 goto out;
2303 }
2304 }
2305
2306 retval = TRUE;
2307
2308 out:
2309 if (message)
2310 dbus_message_unref (message);
2311
2312 return retval;
2313}
2314
2315static dbus_bool_t
2316check_got_error (BusContext *context,
2317 DBusConnection *connection,
2318 const char *first_error_name,
2319 ...)
2320{
2321 DBusMessage *message;
2322 dbus_bool_t retval;
2323 va_list ap;
2324 dbus_bool_t error_found;
2325 const char *error_name;
2326
2327 retval = FALSE;
2328
2329 message = pop_message_waiting_for_memory (connection);
2330 if (message == NULL)
2331 {
2332 _dbus_warn ("Did not get an expected error\n");
2333 goto out;
2334 }
2335
2336 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
2337 {
2338 warn_unexpected (connection, message, "an error");
2339
2340 goto out;
2341 }
2342
2343 error_found = FALSE;
2344
2345 va_start (ap, first_error_name);
2346 error_name = first_error_name;
2347 while (error_name != NULL)
2348 {
2349 if (dbus_message_is_error (message, error_name))
2350 {
2351 error_found = TRUE;
2352 break;
2353 }
2354 error_name = va_arg (ap, char*);
2355 }
2356 va_end (ap);
2357
2358 if (!error_found)
2359 {
2360 _dbus_warn ("Expected error %s or other, got %s instead\n",
2361 first_error_name,
2362 dbus_message_get_error_name (message));
2363 goto out;
2364 }
2365
2366 retval = TRUE;
2367
2368 out:
2369 if (message)
2370 dbus_message_unref (message);
2371
2372 return retval;
2373}
2374
2375typedef enum
2376{
2377 GOT_SERVICE_CREATED,
2378 GOT_SERVICE_DELETED,
2379 GOT_ERROR,
2380 GOT_SOMETHING_ELSE
2381} GotServiceInfo;
2382
2383static GotServiceInfo
2384check_got_service_info (DBusMessage *message)
2385{
2386 GotServiceInfo message_kind;
2387
2388 if (dbus_message_is_signal (message,
2389 DBUS_INTERFACE_DBUS,
2390 "NameOwnerChanged"))
2391 {
2392 DBusError error;
2393 const char *service_name, *old_owner, *new_owner;
2394 dbus_error_init (&error);
2395
2396 reget_service_info_data:
2397 service_name = NULL;
2398 old_owner = NULL;
2399 new_owner = NULL;
2400
2401 dbus_message_get_args (message, &error,
2402 DBUS_TYPE_STRING, &service_name,
2403 DBUS_TYPE_STRING, &old_owner,
2404 DBUS_TYPE_STRING, &new_owner,
2405 DBUS_TYPE_INVALID);
2406 if (dbus_error_is_set (&error))
2407 {
2408 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2409 {
2410 dbus_error_free (&error);
2411 goto reget_service_info_data;
2412 }
2413 else
2414 {
2415 _dbus_warn ("unexpected arguments for NameOwnerChanged message\n");
2416 message_kind = GOT_SOMETHING_ELSE;
2417 }
2418 }
2419 else if (!old_owner[0])
2420 message_kind = GOT_SERVICE_CREATED;
2421 else if (!new_owner[0])
2422 message_kind = GOT_SERVICE_DELETED;
2423 else
2424 message_kind = GOT_SOMETHING_ELSE;
2425
2426 dbus_error_free (&error);
2427 }
2428 else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2429 message_kind = GOT_ERROR;
2430 else
2431 message_kind = GOT_SOMETHING_ELSE;
2432
2433 return message_kind;
2434}
2435
2436#define EXISTENT_SERVICE_NAME "org.freedesktop.DBus.TestSuiteEchoService"
2437
2438/* returns TRUE if the correct thing happens,
2439 * but the correct thing may include OOM errors.
2440 */
2441static dbus_bool_t
2442check_existent_service_no_auto_start (BusContext *context,
2443 DBusConnection *connection)
2444{
2445 DBusMessage *message;
2446 DBusMessage *base_service_message;
2447 const char *base_service;
2448 dbus_uint32_t serial;
2449 dbus_bool_t retval;
2450 const char *existent = EXISTENT_SERVICE_NAME;
2451 dbus_uint32_t flags;
2452
2453 base_service_message = NULL;
2454
2455 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
2456 DBUS_PATH_DBUS,
2457 DBUS_INTERFACE_DBUS,
2458 "StartServiceByName");
2459
2460 if (message == NULL)
2461 return TRUE;
2462
2463 dbus_message_set_auto_start (message, FALSE);
2464
2465 flags = 0;
2466 if (!dbus_message_append_args (message,
2467 DBUS_TYPE_STRING, &existent,
2468 DBUS_TYPE_UINT32, &flags,
2469 DBUS_TYPE_INVALID))
2470 {
2471 dbus_message_unref (message);
2472 return TRUE;
2473 }
2474
2475 if (!dbus_connection_send (connection, message, &serial))
2476 {
2477 dbus_message_unref (message);
2478 return TRUE;
2479 }
2480
2481 dbus_message_unref (message);
2482 message = NULL;
2483
2484 bus_test_run_everything (context);
2485
2486 /* now wait for the message bus to hear back from the activated
2487 * service.
2488 */
2489 block_connection_until_message_from_bus (context, connection, "activated service to connect");
2490
2491 bus_test_run_everything (context);
2492
2493 if (!dbus_connection_get_is_connected (connection))
2494 {
2495 _dbus_verbose ("connection was disconnected\n");
2496 return TRUE;
2497 }
2498
2499 retval = FALSE;
2500
2501 message = pop_message_waiting_for_memory (connection);
2502 if (message == NULL)
2503 {
2504 _dbus_warn ("Did not receive any messages after %s %d on %p\n",
2505 "StartServiceByName", serial, connection);
2506 goto out;
2507 }
2508
2509 verbose_message_received (connection, message);
2510 _dbus_verbose (" (after sending %s)\n", "StartServiceByName");
2511
2512 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2513 {
2514 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
2515 {
2516 _dbus_warn ("Message has wrong sender %s\n",
2517 dbus_message_get_sender (message) ?
2518 dbus_message_get_sender (message) : "(none)");
2519 goto out;
2520 }
2521
2522 if (dbus_message_is_error (message,
2523 DBUS_ERROR_NO_MEMORY))
2524 {
2525 ; /* good, this is a valid response */
2526 }
2527 else if (dbus_message_is_error (message,
2528 DBUS_ERROR_SPAWN_CHILD_EXITED) ||
2529 dbus_message_is_error (message,
2530 DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
2531 dbus_message_is_error (message,
2532 DBUS_ERROR_SPAWN_EXEC_FAILED))
2533 {
2534 ; /* good, this is expected also */
2535 }
2536 else
2537 {
2538 _dbus_warn ("Did not expect error %s\n",
2539 dbus_message_get_error_name (message));
2540 goto out;
2541 }
2542 }
2543 else
2544 {
2545 GotServiceInfo message_kind;
2546
2547 if (!check_base_service_activated (context, connection,
2548 message, &base_service))
2549 goto out;
2550
2551 base_service_message = message;
2552 message = NULL;
2553
2554 /* We may need to block here for the test service to exit or finish up */
2555 block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
2556
2557 message = dbus_connection_borrow_message (connection);
2558 if (message == NULL)
2559 {
2560 _dbus_warn ("Did not receive any messages after base service creation notification\n");
2561 goto out;
2562 }
2563
2564 message_kind = check_got_service_info (message);
2565
2566 dbus_connection_return_message (connection, message);
2567 message = NULL;
2568
2569 switch (message_kind)
2570 {
2571 case GOT_SOMETHING_ELSE:
2572 _dbus_warn ("Unexpected message after ActivateService "
2573 "(should be an error or a service announcement");
2574 goto out;
2575
2576 case GOT_ERROR:
2577 if (!check_got_error (context, connection,
2578 DBUS_ERROR_SPAWN_CHILD_EXITED,
2579 DBUS_ERROR_NO_MEMORY,
2580 NULL))
2581 goto out;
2582 /* A service deleted should be coming along now after this error.
2583 * We can also get the error *after* the service deleted.
2584 */
2585
2586 /* fall through */
2587
2588 case GOT_SERVICE_DELETED:
2589 {
2590 /* The service started up and got a base address, but then
2591 * failed to register under EXISTENT_SERVICE_NAME
2592 */
2593 CheckServiceOwnerChangedData socd;
2594
2595 socd.expected_kind = SERVICE_DELETED;
2596 socd.expected_service_name = base_service;
2597 socd.failed = FALSE;
2598 socd.skip_connection = NULL;
2599
2600 bus_test_clients_foreach (check_service_owner_changed_foreach,
2601 &socd);
2602
2603 if (socd.failed)
2604 goto out;
2605
2606 /* Now we should get an error about the service exiting
2607 * if we didn't get it before.
2608 */
2609 if (message_kind != GOT_ERROR)
2610 {
2611 block_connection_until_message_from_bus (context, connection, "error about service exiting");
2612
2613 /* and process everything again */
2614 bus_test_run_everything (context);
2615
2616 if (!check_got_error (context, connection,
2617 DBUS_ERROR_SPAWN_CHILD_EXITED,
2618 DBUS_ERROR_NO_MEMORY,
2619 NULL))
2620 goto out;
2621 }
2622 break;
2623 }
2624
2625 case GOT_SERVICE_CREATED:
2626 message = pop_message_waiting_for_memory (connection);
2627 if (message == NULL)
2628 {
2629 _dbus_warn ("Failed to pop message we just put back! "
2630 "should have been a NameOwnerChanged (creation)\n");
2631 goto out;
2632 }
2633
2634 if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
2635 base_service, message))
2636 goto out;
2637
2638 dbus_message_unref (message);
2639 message = NULL;
2640
2641 if (!check_no_leftovers (context))
2642 {
2643 _dbus_warn ("Messages were left over after successful activation\n");
2644 goto out;
2645 }
2646
2647 if (!check_send_exit_to_service (context, connection,
2648 EXISTENT_SERVICE_NAME, base_service))
2649 goto out;
2650
2651 break;
2652 }
2653 }
2654
2655 retval = TRUE;
2656
2657 out:
2658 if (message)
2659 dbus_message_unref (message);
2660
2661 if (base_service_message)
2662 dbus_message_unref (base_service_message);
2663
2664 return retval;
2665}
2666
2667#ifndef DBUS_WIN_FIXME
2668/* returns TRUE if the correct thing happens,
2669 * but the correct thing may include OOM errors.
2670 */
2671static dbus_bool_t
2672check_segfault_service_no_auto_start (BusContext *context,
2673 DBusConnection *connection)
2674{
2675 DBusMessage *message;
2676 dbus_uint32_t serial;
2677 dbus_bool_t retval;
2678 const char *segv_service;
2679 dbus_uint32_t flags;
2680
2681 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
2682 DBUS_PATH_DBUS,
2683 DBUS_INTERFACE_DBUS,
2684 "StartServiceByName");
2685
2686 if (message == NULL)
2687 return TRUE;
2688
2689 dbus_message_set_auto_start (message, FALSE);
2690
2691 segv_service = "org.freedesktop.DBus.TestSuiteSegfaultService";
2692 flags = 0;
2693 if (!dbus_message_append_args (message,
2694 DBUS_TYPE_STRING, &segv_service,
2695 DBUS_TYPE_UINT32, &flags,
2696 DBUS_TYPE_INVALID))
2697 {
2698 dbus_message_unref (message);
2699 return TRUE;
2700 }
2701
2702 if (!dbus_connection_send (connection, message, &serial))
2703 {
2704 dbus_message_unref (message);
2705 return TRUE;
2706 }
2707
2708 dbus_message_unref (message);
2709 message = NULL;
2710
2711 bus_test_run_everything (context);
2712 block_connection_until_message_from_bus (context, connection, "reply to activating segfault service");
2713 bus_test_run_everything (context);
2714
2715 if (!dbus_connection_get_is_connected (connection))
2716 {
2717 _dbus_verbose ("connection was disconnected\n");
2718 return TRUE;
2719 }
2720
2721 retval = FALSE;
2722
2723 message = pop_message_waiting_for_memory (connection);
2724 if (message == NULL)
2725 {
2726 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
2727 "StartServiceByName", serial, connection);
2728 goto out;
2729 }
2730
2731 verbose_message_received (connection, message);
2732
2733 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2734 {
2735 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
2736 {
2737 _dbus_warn ("Message has wrong sender %s\n",
2738 dbus_message_get_sender (message) ?
2739 dbus_message_get_sender (message) : "(none)");
2740 goto out;
2741 }
2742
2743 if (dbus_message_is_error (message,
2744 DBUS_ERROR_NO_MEMORY))
2745 {
2746 ; /* good, this is a valid response */
2747 }
2748 else if (dbus_message_is_error (message,
2749 DBUS_ERROR_FAILED))
2750 {
2751 const char *servicehelper;
2752 servicehelper = bus_context_get_servicehelper (context);
2753 /* make sure this only happens with the launch helper */
2754 _dbus_assert (servicehelper != NULL);
2755 }
2756 else if (dbus_message_is_error (message,
2757 DBUS_ERROR_SPAWN_CHILD_SIGNALED))
2758 {
2759 ; /* good, this is expected also */
2760 }
2761 else
2762 {
2763 warn_unexpected (connection, message, "not this error");
2764
2765 goto out;
2766 }
2767 }
2768 else
2769 {
2770 _dbus_warn ("Did not expect to successfully activate segfault service\n");
2771 goto out;
2772 }
2773
2774 retval = TRUE;
2775
2776 out:
2777 if (message)
2778 dbus_message_unref (message);
2779
2780 return retval;
2781}
2782
2783
2784/* returns TRUE if the correct thing happens,
2785 * but the correct thing may include OOM errors.
2786 */
2787static dbus_bool_t
2788check_segfault_service_auto_start (BusContext *context,
2789 DBusConnection *connection)
2790{
2791 DBusMessage *message;
2792 dbus_uint32_t serial;
2793 dbus_bool_t retval;
2794
2795 message = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuiteSegfaultService",
2796 "/org/freedesktop/TestSuite",
2797 "org.freedesktop.TestSuite",
2798 "Echo");
2799
2800 if (message == NULL)
2801 return TRUE;
2802
2803 if (!dbus_connection_send (connection, message, &serial))
2804 {
2805 dbus_message_unref (message);
2806 return TRUE;
2807 }
2808
2809 dbus_message_unref (message);
2810 message = NULL;
2811
2812 bus_test_run_everything (context);
2813 block_connection_until_message_from_bus (context, connection, "reply to Echo on segfault service");
2814 bus_test_run_everything (context);
2815
2816 if (!dbus_connection_get_is_connected (connection))
2817 {
2818 _dbus_verbose ("connection was disconnected\n");
2819 return TRUE;
2820 }
2821
2822 retval = FALSE;
2823
2824 message = pop_message_waiting_for_memory (connection);
2825 if (message == NULL)
2826 {
2827 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
2828 "Echo message (auto activation)", serial, connection);
2829 goto out;
2830 }
2831
2832 verbose_message_received (connection, message);
2833
2834 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
2835 {
2836 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
2837 {
2838 _dbus_warn ("Message has wrong sender %s\n",
2839 dbus_message_get_sender (message) ?
2840 dbus_message_get_sender (message) : "(none)");
2841 goto out;
2842 }
2843
2844 if (dbus_message_is_error (message,
2845 DBUS_ERROR_NO_MEMORY))
2846 {
2847 ; /* good, this is a valid response */
2848 }
2849 else if (dbus_message_is_error (message,
2850 DBUS_ERROR_SPAWN_CHILD_SIGNALED))
2851 {
2852 ; /* good, this is expected also */
2853 }
2854 else
2855 {
2856 warn_unexpected (connection, message, "not this error");
2857
2858 goto out;
2859 }
2860 }
2861 else
2862 {
2863 _dbus_warn ("Did not expect to successfully activate segfault service\n");
2864 goto out;
2865 }
2866
2867 retval = TRUE;
2868
2869 out:
2870 if (message)
2871 dbus_message_unref (message);
2872
2873 return retval;
2874}
2875#endif
2876
2877#define TEST_ECHO_MESSAGE "Test echo message"
2878#define TEST_RUN_HELLO_FROM_SELF_MESSAGE "Test sending message to self"
2879
2880/* returns TRUE if the correct thing happens,
2881 * but the correct thing may include OOM errors.
2882 */
2883static dbus_bool_t
2884check_existent_hello_from_self (BusContext *context,
2885 DBusConnection *connection)
2886{
2887 DBusMessage *message;
2888 dbus_uint32_t serial;
2889 const char *text;
2890
2891 message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
2892 "/org/freedesktop/TestSuite",
2893 "org.freedesktop.TestSuite",
2894 "RunHelloFromSelf");
2895
2896 if (message == NULL)
2897 return TRUE;
2898
2899 text = TEST_RUN_HELLO_FROM_SELF_MESSAGE;
2900 if (!dbus_message_append_args (message,
2901 DBUS_TYPE_STRING, &text,
2902 DBUS_TYPE_INVALID))
2903 {
2904 dbus_message_unref (message);
2905 return TRUE;
2906 }
2907
2908 if (!dbus_connection_send (connection, message, &serial))
2909 {
2910 dbus_message_unref (message);
2911 return TRUE;
2912 }
2913
2914 dbus_message_unref (message);
2915 message = NULL;
2916
2917 bus_test_run_everything (context);
2918
2919 /* Note: if this test is run in OOM mode, it will block when the bus
2920 * doesn't send a reply due to OOM.
2921 */
2922 block_connection_until_message_from_bus (context, connection, "reply from running hello from self");
2923
2924 message = pop_message_waiting_for_memory (connection);
2925 if (message == NULL)
2926 {
2927 _dbus_warn ("Failed to pop message! Should have been reply from RunHelloFromSelf message\n");
2928 return FALSE;
2929 }
2930
2931 if (dbus_message_get_reply_serial (message) != serial)
2932 {
2933 _dbus_warn ("Wrong reply serial\n");
2934 dbus_message_unref (message);
2935 return FALSE;
2936 }
2937
2938 dbus_message_unref (message);
2939 message = NULL;
2940
2941 return TRUE;
2942}
2943
2944/* returns TRUE if the correct thing happens,
2945 * but the correct thing may include OOM errors.
2946 */
2947static dbus_bool_t
2948check_existent_ping (BusContext *context,
2949 DBusConnection *connection)
2950{
2951 DBusMessage *message;
2952 dbus_uint32_t serial;
2953 message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
2954 "/org/freedesktop/TestSuite",
2955 "org.freedesktop.DBus.Peer",
2956 "Ping");
2957
2958 if (message == NULL)
2959 return TRUE;
2960
2961 if (!dbus_connection_send (connection, message, &serial))
2962 {
2963 dbus_message_unref (message);
2964 return TRUE;
2965 }
2966
2967 dbus_message_unref (message);
2968 message = NULL;
2969
2970 bus_test_run_everything (context);
2971
2972 /* Note: if this test is run in OOM mode, it will block when the bus
2973 * doesn't send a reply due to OOM.
2974 */
2975 block_connection_until_message_from_bus (context, connection, "reply from running Ping");
2976
2977 message = pop_message_waiting_for_memory (connection);
2978 if (message == NULL)
2979 {
2980 _dbus_warn ("Failed to pop message! Should have been reply from Ping message\n");
2981 return FALSE;
2982 }
2983
2984 if (dbus_message_get_reply_serial (message) != serial)
2985 {
2986 _dbus_warn ("Wrong reply serial\n");
2987 dbus_message_unref (message);
2988 return FALSE;
2989 }
2990
2991 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
2992 {
2993 _dbus_warn ("Unexpected message return during Ping\n");
2994 dbus_message_unref (message);
2995 return FALSE;
2996 }
2997
2998 dbus_message_unref (message);
2999 message = NULL;
3000
3001 return TRUE;
3002}
3003
3004/* returns TRUE if the correct thing happens,
3005 * but the correct thing may include OOM errors.
3006 */
3007static dbus_bool_t
3008check_existent_get_machine_id (BusContext *context,
3009 DBusConnection *connection)
3010{
3011 DBusMessage *message;
3012 dbus_uint32_t serial;
3013 const char *machine_id;
3014
3015 message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
3016 "/org/freedesktop/TestSuite",
3017 "org.freedesktop.DBus.Peer",
3018 "GetMachineId");
3019
3020 if (message == NULL)
3021 return TRUE;
3022
3023 if (!dbus_connection_send (connection, message, &serial))
3024 {
3025 dbus_message_unref (message);
3026 return TRUE;
3027 }
3028
3029 dbus_message_unref (message);
3030 message = NULL;
3031
3032 bus_test_run_everything (context);
3033
3034 /* Note: if this test is run in OOM mode, it will block when the bus
3035 * doesn't send a reply due to OOM.
3036 */
3037 block_connection_until_message_from_bus (context, connection, "reply from running GetMachineId");
3038
3039 message = pop_message_waiting_for_memory (connection);
3040 if (message == NULL)
3041 {
3042 _dbus_warn ("Failed to pop message! Should have been reply from GetMachineId message\n");
3043 return FALSE;
3044 }
3045
3046 if (dbus_message_get_reply_serial (message) != serial)
3047 {
3048 _dbus_warn ("Wrong reply serial\n");
3049 dbus_message_unref (message);
3050 return FALSE;
3051 }
3052
3053 if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_RETURN)
3054 {
3055 _dbus_warn ("Unexpected message return during GetMachineId\n");
3056 dbus_message_unref (message);
3057 return FALSE;
3058 }
3059
3060 machine_id = NULL;
3061 if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &machine_id, DBUS_TYPE_INVALID))
3062 {
3063 _dbus_warn ("Did not get a machine ID in reply to GetMachineId\n");
3064 dbus_message_unref (message);
3065 return FALSE;
3066 }
3067
3068 if (machine_id == NULL || strlen (machine_id) != 32)
3069 {
3070 _dbus_warn ("Machine id looks bogus: '%s'\n", machine_id ? machine_id : "null");
3071 dbus_message_unref (message);
3072 return FALSE;
3073 }
3074
3075 /* We can't check that the machine id is correct because during make check it is
3076 * just made up for each process separately
3077 */
3078
3079 dbus_message_unref (message);
3080 message = NULL;
3081
3082 return TRUE;
3083}
3084
3085/* returns TRUE if the correct thing happens,
3086 * but the correct thing may include OOM errors.
3087 */
3088static dbus_bool_t
3089check_existent_service_auto_start (BusContext *context,
3090 DBusConnection *connection)
3091{
3092 DBusMessage *message;
3093 DBusMessage *base_service_message;
3094 dbus_uint32_t serial;
3095 dbus_bool_t retval;
3096 const char *base_service;
3097 const char *text;
3098
3099 base_service_message = NULL;
3100
3101 message = dbus_message_new_method_call (EXISTENT_SERVICE_NAME,
3102 "/org/freedesktop/TestSuite",
3103 "org.freedesktop.TestSuite",
3104 "Echo");
3105
3106 if (message == NULL)
3107 return TRUE;
3108
3109 text = TEST_ECHO_MESSAGE;
3110 if (!dbus_message_append_args (message,
3111 DBUS_TYPE_STRING, &text,
3112 DBUS_TYPE_INVALID))
3113 {
3114 dbus_message_unref (message);
3115 return TRUE;
3116 }
3117
3118 if (!dbus_connection_send (connection, message, &serial))
3119 {
3120 dbus_message_unref (message);
3121 return TRUE;
3122 }
3123
3124 dbus_message_unref (message);
3125 message = NULL;
3126
3127 bus_test_run_everything (context);
3128
3129 /* now wait for the message bus to hear back from the activated
3130 * service.
3131 */
3132 block_connection_until_message_from_bus (context, connection, "reply to Echo on existent service");
3133 bus_test_run_everything (context);
3134
3135 if (!dbus_connection_get_is_connected (connection))
3136 {
3137 _dbus_verbose ("connection was disconnected\n");
3138 return TRUE;
3139 }
3140
3141 retval = FALSE;
3142
3143 message = pop_message_waiting_for_memory (connection);
3144 if (message == NULL)
3145 {
3146 _dbus_warn ("Did not receive any messages after auto start %d on %p\n",
3147 serial, connection);
3148 goto out;
3149 }
3150
3151 verbose_message_received (connection, message);
3152 _dbus_verbose (" (after sending %s)\n", "auto start");
3153
3154 /* we should get zero or two ServiceOwnerChanged signals */
3155 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
3156 {
3157 GotServiceInfo message_kind;
3158
3159 if (!check_base_service_activated (context, connection,
3160 message, &base_service))
3161 goto out;
3162
3163 base_service_message = message;
3164 message = NULL;
3165
3166 /* We may need to block here for the test service to exit or finish up */
3167 block_connection_until_message_from_bus (context, connection, "service to exit");
3168
3169 /* Should get a service creation notification for the activated
3170 * service name, or a service deletion on the base service name
3171 */
3172 message = dbus_connection_borrow_message (connection);
3173 if (message == NULL)
3174 {
3175 _dbus_warn ("No message after auto activation "
3176 "(should be a service announcement)\n");
3177 dbus_connection_return_message (connection, message);
3178 message = NULL;
3179 goto out;
3180 }
3181
3182 message_kind = check_got_service_info (message);
3183
3184 dbus_connection_return_message (connection, message);
3185 message = NULL;
3186
3187 switch (message_kind)
3188 {
3189 case GOT_SERVICE_CREATED:
3190 message = pop_message_waiting_for_memory (connection);
3191 if (message == NULL)
3192 {
3193 _dbus_warn ("Failed to pop message we just put back! "
3194 "should have been a NameOwnerChanged (creation)\n");
3195 goto out;
3196 }
3197
3198 /* Check that ServiceOwnerChanged (creation) was correctly received */
3199 if (!check_service_auto_activated (context, connection, EXISTENT_SERVICE_NAME,
3200 base_service, message))
3201 goto out;
3202
3203 dbus_message_unref (message);
3204 message = NULL;
3205
3206 break;
3207
3208 case GOT_SERVICE_DELETED:
3209 {
3210 /* The service started up and got a base address, but then
3211 * failed to register under EXISTENT_SERVICE_NAME
3212 */
3213 CheckServiceOwnerChangedData socd;
3214
3215 socd.expected_kind = SERVICE_DELETED;
3216 socd.expected_service_name = base_service;
3217 socd.failed = FALSE;
3218 socd.skip_connection = NULL;
3219 bus_test_clients_foreach (check_service_owner_changed_foreach,
3220 &socd);
3221
3222 if (socd.failed)
3223 goto out;
3224
3225 break;
3226 }
3227
3228 case GOT_ERROR:
3229 case GOT_SOMETHING_ELSE:
3230 _dbus_warn ("Unexpected message after auto activation\n");
3231 goto out;
3232 }
3233 }
3234
3235 /* OK, now we've dealt with ServiceOwnerChanged signals, now should
3236 * come the method reply (or error) from the initial method call
3237 */
3238
3239 /* Note: if this test is run in OOM mode, it will block when the bus
3240 * doesn't send a reply due to OOM.
3241 */
3242 block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation");
3243
3244 message = pop_message_waiting_for_memory (connection);
3245 if (message == NULL)
3246 {
3247 _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
3248 goto out;
3249 }
3250
3251 if (dbus_message_get_reply_serial (message) != serial)
3252 {
3253 _dbus_warn ("Wrong reply serial\n");
3254 goto out;
3255 }
3256
3257 dbus_message_unref (message);
3258 message = NULL;
3259
3260 if (!check_existent_ping (context, connection))
3261 goto out;
3262
3263 if (!check_existent_get_machine_id (context, connection))
3264 goto out;
3265
3266 if (!check_existent_hello_from_self (context, connection))
3267 goto out;
3268
3269 if (!check_send_exit_to_service (context, connection,
3270 EXISTENT_SERVICE_NAME,
3271 base_service))
3272 goto out;
3273
3274 retval = TRUE;
3275
3276 out:
3277 if (message)
3278 dbus_message_unref (message);
3279
3280 if (base_service_message)
3281 dbus_message_unref (base_service_message);
3282
3283 return retval;
3284}
3285
3286#define SERVICE_FILE_MISSING_NAME "org.freedesktop.DBus.TestSuiteEchoServiceDotServiceFileDoesNotExist"
3287
3288/* returns TRUE if the correct thing happens,
3289 * but the correct thing may include OOM errors.
3290 */
3291static dbus_bool_t
3292check_launch_service_file_missing (BusContext *context,
3293 DBusConnection *connection)
3294{
3295 DBusMessage *message;
3296 dbus_uint32_t serial;
3297 dbus_bool_t retval;
3298
3299 message = dbus_message_new_method_call (SERVICE_FILE_MISSING_NAME,
3300 "/org/freedesktop/TestSuite",
3301 "org.freedesktop.TestSuite",
3302 "Echo");
3303
3304 if (message == NULL)
3305 return TRUE;
3306
3307 if (!dbus_connection_send (connection, message, &serial))
3308 {
3309 dbus_message_unref (message);
3310 return TRUE;
3311 }
3312
3313 dbus_message_unref (message);
3314 message = NULL;
3315
3316 bus_test_run_everything (context);
3317 block_connection_until_message_from_bus (context, connection, "reply to service file missing should fail to auto-start");
3318 bus_test_run_everything (context);
3319
3320 if (!dbus_connection_get_is_connected (connection))
3321 {
3322 _dbus_verbose ("connection was disconnected\n");
3323 return TRUE;
3324 }
3325
3326 retval = FALSE;
3327
3328 message = pop_message_waiting_for_memory (connection);
3329 if (message == NULL)
3330 {
3331 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
3332 "Echo message (auto activation)", serial, connection);
3333 goto out;
3334 }
3335
3336 verbose_message_received (connection, message);
3337
3338 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3339 {
3340 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3341 {
3342 _dbus_warn ("Message has wrong sender %s\n",
3343 dbus_message_get_sender (message) ?
3344 dbus_message_get_sender (message) : "(none)");
3345 goto out;
3346 }
3347
3348 if (dbus_message_is_error (message,
3349 DBUS_ERROR_NO_MEMORY))
3350 {
3351 ; /* good, this is a valid response */
3352 }
3353 else if (dbus_message_is_error (message,
3354 DBUS_ERROR_SERVICE_UNKNOWN))
3355 {
3356 _dbus_verbose("got service unknown\n");
3357 ; /* good, this is expected (only valid when using launch helper) */
3358 }
3359 else
3360 {
3361 warn_unexpected (connection, message, "not this error");
3362
3363 goto out;
3364 }
3365 }
3366 else
3367 {
3368 _dbus_warn ("Did not expect to successfully auto-start missing service\n");
3369 goto out;
3370 }
3371
3372 retval = TRUE;
3373
3374 out:
3375 if (message)
3376 dbus_message_unref (message);
3377
3378 return retval;
3379}
3380
3381#define SERVICE_USER_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoUser"
3382
3383/* returns TRUE if the correct thing happens,
3384 * but the correct thing may include OOM errors.
3385 */
3386static dbus_bool_t
3387check_launch_service_user_missing (BusContext *context,
3388 DBusConnection *connection)
3389{
3390 DBusMessage *message;
3391 dbus_uint32_t serial;
3392 dbus_bool_t retval;
3393
3394 message = dbus_message_new_method_call (SERVICE_USER_MISSING_NAME,
3395 "/org/freedesktop/TestSuite",
3396 "org.freedesktop.TestSuite",
3397 "Echo");
3398
3399 if (message == NULL)
3400 return TRUE;
3401
3402 if (!dbus_connection_send (connection, message, &serial))
3403 {
3404 dbus_message_unref (message);
3405 return TRUE;
3406 }
3407
3408 dbus_message_unref (message);
3409 message = NULL;
3410
3411 bus_test_run_everything (context);
3412 block_connection_until_message_from_bus (context, connection,
3413 "reply to service which should fail to auto-start (missing User)");
3414 bus_test_run_everything (context);
3415
3416 if (!dbus_connection_get_is_connected (connection))
3417 {
3418 _dbus_warn ("connection was disconnected\n");
3419 return TRUE;
3420 }
3421
3422 retval = FALSE;
3423
3424 message = pop_message_waiting_for_memory (connection);
3425 if (message == NULL)
3426 {
3427 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
3428 "Echo message (auto activation)", serial, connection);
3429 goto out;
3430 }
3431
3432 verbose_message_received (connection, message);
3433
3434 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3435 {
3436 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3437 {
3438 _dbus_warn ("Message has wrong sender %s\n",
3439 dbus_message_get_sender (message) ?
3440 dbus_message_get_sender (message) : "(none)");
3441 goto out;
3442 }
3443
3444 if (dbus_message_is_error (message,
3445 DBUS_ERROR_NO_MEMORY))
3446 {
3447 ; /* good, this is a valid response */
3448 }
3449 else if (dbus_message_is_error (message,
3450 DBUS_ERROR_SPAWN_FILE_INVALID))
3451 {
3452 _dbus_verbose("got service file invalid\n");
3453 ; /* good, this is expected (only valid when using launch helper) */
3454 }
3455 else
3456 {
3457 warn_unexpected (connection, message, "not this error");
3458
3459 goto out;
3460 }
3461 }
3462 else
3463 {
3464 _dbus_warn ("Did not expect to successfully auto-start missing service\n");
3465 goto out;
3466 }
3467
3468 retval = TRUE;
3469
3470 out:
3471 if (message)
3472 dbus_message_unref (message);
3473
3474 return retval;
3475}
3476
3477#define SERVICE_EXEC_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoExec"
3478
3479/* returns TRUE if the correct thing happens,
3480 * but the correct thing may include OOM errors.
3481 */
3482static dbus_bool_t
3483check_launch_service_exec_missing (BusContext *context,
3484 DBusConnection *connection)
3485{
3486 DBusMessage *message;
3487 dbus_uint32_t serial;
3488 dbus_bool_t retval;
3489
3490 message = dbus_message_new_method_call (SERVICE_EXEC_MISSING_NAME,
3491 "/org/freedesktop/TestSuite",
3492 "org.freedesktop.TestSuite",
3493 "Echo");
3494
3495 if (message == NULL)
3496 return TRUE;
3497
3498 if (!dbus_connection_send (connection, message, &serial))
3499 {
3500 dbus_message_unref (message);
3501 return TRUE;
3502 }
3503
3504 dbus_message_unref (message);
3505 message = NULL;
3506
3507 bus_test_run_everything (context);
3508 block_connection_until_message_from_bus (context, connection,
3509 "reply to service which should fail to auto-start (missing Exec)");
3510 bus_test_run_everything (context);
3511
3512 if (!dbus_connection_get_is_connected (connection))
3513 {
3514 _dbus_warn ("connection was disconnected\n");
3515 return TRUE;
3516 }
3517
3518 retval = FALSE;
3519
3520 message = pop_message_waiting_for_memory (connection);
3521 if (message == NULL)
3522 {
3523 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
3524 "Echo message (auto activation)", serial, connection);
3525 goto out;
3526 }
3527
3528 verbose_message_received (connection, message);
3529
3530 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3531 {
3532 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3533 {
3534 _dbus_warn ("Message has wrong sender %s\n",
3535 dbus_message_get_sender (message) ?
3536 dbus_message_get_sender (message) : "(none)");
3537 goto out;
3538 }
3539
3540 if (dbus_message_is_error (message,
3541 DBUS_ERROR_NO_MEMORY))
3542 {
3543 ; /* good, this is a valid response */
3544 }
3545 else if (dbus_message_is_error (message,
3546 DBUS_ERROR_SERVICE_UNKNOWN))
3547 {
3548 _dbus_verbose("could not activate as invalid service file was not added\n");
3549 ; /* good, this is expected as we shouldn't have been added to
3550 * the activation list with a missing Exec key */
3551 }
3552 else if (dbus_message_is_error (message,
3553 DBUS_ERROR_SPAWN_FILE_INVALID))
3554 {
3555 _dbus_verbose("got service file invalid\n");
3556 ; /* good, this is allowed, and is the message passed back from the
3557 * launch helper */
3558 }
3559 else
3560 {
3561 warn_unexpected (connection, message, "not this error");
3562
3563 goto out;
3564 }
3565 }
3566 else
3567 {
3568 _dbus_warn ("Did not expect to successfully auto-start missing service\n");
3569 goto out;
3570 }
3571
3572 retval = TRUE;
3573
3574 out:
3575 if (message)
3576 dbus_message_unref (message);
3577
3578 return retval;
3579}
3580
3581#define SERVICE_SERVICE_MISSING_NAME "org.freedesktop.DBus.TestSuiteNoService"
3582
3583/* returns TRUE if the correct thing happens,
3584 * but the correct thing may include OOM errors.
3585 */
3586static dbus_bool_t
3587check_launch_service_service_missing (BusContext *context,
3588 DBusConnection *connection)
3589{
3590 DBusMessage *message;
3591 dbus_uint32_t serial;
3592 dbus_bool_t retval;
3593
3594 message = dbus_message_new_method_call (SERVICE_SERVICE_MISSING_NAME,
3595 "/org/freedesktop/TestSuite",
3596 "org.freedesktop.TestSuite",
3597 "Echo");
3598
3599 if (message == NULL)
3600 return TRUE;
3601
3602 if (!dbus_connection_send (connection, message, &serial))
3603 {
3604 dbus_message_unref (message);
3605 return TRUE;
3606 }
3607
3608 dbus_message_unref (message);
3609 message = NULL;
3610
3611 bus_test_run_everything (context);
3612 block_connection_until_message_from_bus (context, connection,
3613 "reply to service which should fail to auto-start (missing Service)");
3614 bus_test_run_everything (context);
3615
3616 if (!dbus_connection_get_is_connected (connection))
3617 {
3618 _dbus_warn ("connection was disconnected\n");
3619 return TRUE;
3620 }
3621
3622 retval = FALSE;
3623
3624 message = pop_message_waiting_for_memory (connection);
3625 if (message == NULL)
3626 {
3627 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
3628 "Echo message (auto activation)", serial, connection);
3629 goto out;
3630 }
3631
3632 verbose_message_received (connection, message);
3633
3634 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3635 {
3636 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3637 {
3638 _dbus_warn ("Message has wrong sender %s\n",
3639 dbus_message_get_sender (message) ?
3640 dbus_message_get_sender (message) : "(none)");
3641 goto out;
3642 }
3643
3644 if (dbus_message_is_error (message,
3645 DBUS_ERROR_NO_MEMORY))
3646 {
3647 ; /* good, this is a valid response */
3648 }
3649 else if (dbus_message_is_error (message,
3650 DBUS_ERROR_SERVICE_UNKNOWN))
3651 {
3652 _dbus_verbose("could not activate as invalid service file was not added\n");
3653 ; /* good, this is expected as we shouldn't have been added to
3654 * the activation list with a missing Exec key */
3655 }
3656 else if (dbus_message_is_error (message,
3657 DBUS_ERROR_SPAWN_FILE_INVALID))
3658 {
3659 _dbus_verbose("got service file invalid\n");
3660 ; /* good, this is allowed, and is the message passed back from the
3661 * launch helper */
3662 }
3663 else
3664 {
3665 warn_unexpected (connection, message, "not this error");
3666
3667 goto out;
3668 }
3669 }
3670 else
3671 {
3672 _dbus_warn ("Did not expect to successfully auto-start missing service\n");
3673 goto out;
3674 }
3675
3676 retval = TRUE;
3677
3678 out:
3679 if (message)
3680 dbus_message_unref (message);
3681
3682 return retval;
3683}
3684
3685#define SHELL_FAIL_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceFail"
3686
3687/* returns TRUE if the correct thing happens,
3688 * but the correct thing may include OOM errors.
3689 */
3690static dbus_bool_t
3691check_shell_fail_service_auto_start (BusContext *context,
3692 DBusConnection *connection)
3693{
3694 DBusMessage *message;
3695 dbus_uint32_t serial;
3696 dbus_bool_t retval;
3697
3698 message = dbus_message_new_method_call (SHELL_FAIL_SERVICE_NAME,
3699 "/org/freedesktop/TestSuite",
3700 "org.freedesktop.TestSuite",
3701 "Echo");
3702
3703 if (message == NULL)
3704 return TRUE;
3705
3706 if (!dbus_connection_send (connection, message, &serial))
3707 {
3708 dbus_message_unref (message);
3709 return TRUE;
3710 }
3711
3712 dbus_message_unref (message);
3713 message = NULL;
3714
3715 bus_test_run_everything (context);
3716 block_connection_until_message_from_bus (context, connection, "reply to shell Echo on service which should fail to auto-start");
3717 bus_test_run_everything (context);
3718
3719 if (!dbus_connection_get_is_connected (connection))
3720 {
3721 _dbus_verbose ("connection was disconnected\n");
3722 return TRUE;
3723 }
3724
3725 retval = FALSE;
3726
3727 message = pop_message_waiting_for_memory (connection);
3728 if (message == NULL)
3729 {
3730 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
3731 "Echo message (auto activation)", serial, connection);
3732 goto out;
3733 }
3734
3735 verbose_message_received (connection, message);
3736
3737 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
3738 {
3739 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
3740 {
3741 _dbus_warn ("Message has wrong sender %s\n",
3742 dbus_message_get_sender (message) ?
3743 dbus_message_get_sender (message) : "(none)");
3744 goto out;
3745 }
3746
3747 if (dbus_message_is_error (message,
3748 DBUS_ERROR_NO_MEMORY))
3749 {
3750 ; /* good, this is a valid response */
3751 }
3752 else if (dbus_message_is_error (message,
3753 DBUS_ERROR_INVALID_ARGS))
3754 {
3755 _dbus_verbose("got invalid args\n");
3756 ; /* good, this is expected also */
3757 }
3758 else
3759 {
3760 warn_unexpected (connection, message, "not this error");
3761
3762 goto out;
3763 }
3764 }
3765 else
3766 {
3767 _dbus_warn ("Did not expect to successfully auto-start shell fail service\n");
3768 goto out;
3769 }
3770
3771 retval = TRUE;
3772
3773 out:
3774 if (message)
3775 dbus_message_unref (message);
3776
3777 return retval;
3778}
3779
3780#define SHELL_SUCCESS_SERVICE_NAME "org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess"
3781
3782/* returns TRUE if the correct thing happens,
3783 * but the correct thing may include OOM errors.
3784 */
3785static dbus_bool_t
3786check_shell_service_success_auto_start (BusContext *context,
3787 DBusConnection *connection)
3788{
3789 DBusMessage *message;
3790 DBusMessage *base_service_message;
3791 dbus_uint32_t serial;
3792 dbus_bool_t retval;
3793 const char *base_service;
3794 const char *argv[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
3795
3796 base_service_message = NULL;
3797
3798 message = dbus_message_new_method_call (SHELL_SUCCESS_SERVICE_NAME,
3799 "/org/freedesktop/TestSuite",
3800 "org.freedesktop.TestSuite",
3801 "Echo");
3802
3803 if (message == NULL)
3804 return TRUE;
3805
3806 if (!dbus_connection_send (connection, message, &serial))
3807 {
3808 dbus_message_unref (message);
3809 return TRUE;
3810 }
3811
3812 dbus_message_unref (message);
3813 message = NULL;
3814
3815 bus_test_run_everything (context);
3816
3817 /* now wait for the message bus to hear back from the activated
3818 * service.
3819 */
3820 block_connection_until_message_from_bus (context, connection, "reply to Echo on shell success service");
3821 bus_test_run_everything (context);
3822
3823 if (!dbus_connection_get_is_connected (connection))
3824 {
3825 _dbus_verbose ("connection was disconnected\n");
3826 return TRUE;
3827 }
3828
3829 retval = FALSE;
3830
3831 message = pop_message_waiting_for_memory (connection);
3832 if (message == NULL)
3833 {
3834 _dbus_warn ("Did not receive any messages after auto start %d on %p\n",
3835 serial, connection);
3836 goto out;
3837 }
3838
3839 verbose_message_received (connection, message);
3840 _dbus_verbose (" (after sending %s)\n", "auto start");
3841
3842 /* we should get zero or two ServiceOwnerChanged signals */
3843 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL)
3844 {
3845 GotServiceInfo message_kind;
3846
3847 if (!check_base_service_activated (context, connection,
3848 message, &base_service))
3849 goto out;
3850
3851 base_service_message = message;
3852 message = NULL;
3853
3854 /* We may need to block here for the test service to exit or finish up */
3855 block_connection_until_message_from_bus (context, connection, "service to exit");
3856
3857 /* Should get a service creation notification for the activated
3858 * service name, or a service deletion on the base service name
3859 */
3860 message = dbus_connection_borrow_message (connection);
3861 if (message == NULL)
3862 {
3863 _dbus_warn ("No message after auto activation "
3864 "(should be a service announcement)\n");
3865 dbus_connection_return_message (connection, message);
3866 message = NULL;
3867 goto out;
3868 }
3869
3870 message_kind = check_got_service_info (message);
3871
3872 dbus_connection_return_message (connection, message);
3873 message = NULL;
3874
3875 switch (message_kind)
3876 {
3877 case GOT_SERVICE_CREATED:
3878 message = pop_message_waiting_for_memory (connection);
3879 if (message == NULL)
3880 {
3881 _dbus_warn ("Failed to pop message we just put back! "
3882 "should have been a NameOwnerChanged (creation)\n");
3883 goto out;
3884 }
3885
3886 /* Check that ServiceOwnerChanged (creation) was correctly received */
3887 if (!check_service_auto_activated (context, connection, SHELL_SUCCESS_SERVICE_NAME,
3888 base_service, message))
3889 goto out;
3890
3891 dbus_message_unref (message);
3892 message = NULL;
3893
3894 break;
3895
3896 case GOT_SERVICE_DELETED:
3897 {
3898 /* The service started up and got a base address, but then
3899 * failed to register under SHELL_SUCCESS_SERVICE_NAME
3900 */
3901 CheckServiceOwnerChangedData socd;
3902
3903 socd.expected_kind = SERVICE_DELETED;
3904 socd.expected_service_name = base_service;
3905 socd.failed = FALSE;
3906 socd.skip_connection = NULL;
3907 bus_test_clients_foreach (check_service_owner_changed_foreach,
3908 &socd);
3909
3910 if (socd.failed)
3911 goto out;
3912
3913 break;
3914 }
3915
3916 case GOT_ERROR:
3917 case GOT_SOMETHING_ELSE:
3918 _dbus_warn ("Unexpected message after auto activation\n");
3919 goto out;
3920 }
3921 }
3922
3923 /* OK, now we've dealt with ServiceOwnerChanged signals, now should
3924 * come the method reply (or error) from the initial method call
3925 */
3926
3927 /* Note: if this test is run in OOM mode, it will block when the bus
3928 * doesn't send a reply due to OOM.
3929 */
3930 block_connection_until_message_from_bus (context, connection, "reply from echo message after auto-activation");
3931
3932 message = pop_message_waiting_for_memory (connection);
3933 if (message == NULL)
3934 {
3935 _dbus_warn ("Failed to pop message! Should have been reply from echo message\n");
3936 goto out;
3937 }
3938
3939 if (dbus_message_get_reply_serial (message) != serial)
3940 {
3941 _dbus_warn ("Wrong reply serial\n");
3942 goto out;
3943 }
3944
3945 if (!dbus_message_get_args (message, NULL,
3946 DBUS_TYPE_STRING, &argv[0],
3947 DBUS_TYPE_STRING, &argv[1],
3948 DBUS_TYPE_STRING, &argv[2],
3949 DBUS_TYPE_STRING, &argv[3],
3950 DBUS_TYPE_STRING, &argv[4],
3951 DBUS_TYPE_STRING, &argv[5],
3952 DBUS_TYPE_STRING, &argv[6],
3953 DBUS_TYPE_INVALID))
3954 {
3955 _dbus_warn ("Error getting arguments from return\n");
3956 goto out;
3957 }
3958
3959 /* don't worry about arg[0] as it may be different
3960 depending on the path to the tests
3961 */
3962 if (strcmp("-test", argv[1]) != 0)
3963 {
3964 _dbus_warn ("Unexpected argv[1] in shell success service test (expected: %s, got: %s)\n",
3965 "-test", argv[1]);
3966 goto out;
3967 }
3968
3969 if (strcmp("that", argv[2]) != 0)
3970 {
3971 _dbus_warn ("Unexpected argv[2] in shell success service test (expected: %s, got: %s)\n",
3972 "that", argv[2]);
3973 goto out;
3974 }
3975
3976 if (strcmp("we get", argv[3]) != 0)
3977 {
3978 _dbus_warn ("Unexpected argv[3] in shell success service test (expected: %s, got: %s)\n",
3979 "we get", argv[3]);
3980 goto out;
3981 }
3982
3983 if (strcmp("back", argv[4]) != 0)
3984 {
3985 _dbus_warn ("Unexpected argv[4] in shell success service test (expected: %s, got: %s)\n",
3986 "back", argv[4]);
3987 goto out;
3988 }
3989
3990 if (strcmp("--what", argv[5]) != 0)
3991 {
3992 _dbus_warn ("Unexpected argv[5] in shell success service test (expected: %s, got: %s)\n",
3993 "--what", argv[5]);
3994 goto out;
3995 }
3996
3997 if (strcmp("we put in", argv[6]) != 0)
3998 {
3999 _dbus_warn ("Unexpected argv[6] in shell success service test (expected: %s, got: %s)\n",
4000 "we put in", argv[6]);
4001 goto out;
4002 }
4003
4004 dbus_message_unref (message);
4005 message = NULL;
4006
4007 if (!check_send_exit_to_service (context, connection,
4008 SHELL_SUCCESS_SERVICE_NAME,
4009 base_service))
4010 goto out;
4011
4012 retval = TRUE;
4013
4014 out:
4015 if (message)
4016 dbus_message_unref (message);
4017
4018 if (base_service_message)
4019 dbus_message_unref (base_service_message);
4020
4021 return retval;
4022}
4023
4024typedef struct
4025{
4026 Check1Func func;
4027 BusContext *context;
4028} Check1Data;
4029
4030static dbus_bool_t
4031check_oom_check1_func (void *data)
4032{
4033 Check1Data *d = data;
4034
4035 if (! (* d->func) (d->context))
4036 return FALSE;
4037
4038 if (!check_no_leftovers (d->context))
4039 {
4040 _dbus_warn ("Messages were left over, should be covered by test suite\n");
4041 return FALSE;
4042 }
4043
4044 return TRUE;
4045}
4046
4047static void
4048check1_try_iterations (BusContext *context,
4049 const char *description,
4050 Check1Func func)
4051{
4052 Check1Data d;
4053
4054 d.func = func;
4055 d.context = context;
4056
4057 if (!_dbus_test_oom_handling (description, check_oom_check1_func,
4058 &d))
4059 _dbus_assert_not_reached ("test failed");
4060}
4061
4062static dbus_bool_t
4063check_get_services (BusContext *context,
4064 DBusConnection *connection,
4065 const char *method,
4066 char ***services,
4067 int *len)
4068{
4069 DBusMessage *message;
4070 dbus_uint32_t serial;
4071 dbus_bool_t retval;
4072 DBusError error;
4073 char **srvs;
4074 int l;
4075
4076 retval = FALSE;
4077 dbus_error_init (&error);
4078 message = NULL;
4079
4080 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
4081 DBUS_PATH_DBUS,
4082 DBUS_INTERFACE_DBUS,
4083 method);
4084
4085 if (message == NULL)
4086 return TRUE;
4087
4088 if (!dbus_connection_send (connection, message, &serial))
4089 {
4090 dbus_message_unref (message);
4091 return TRUE;
4092 }
4093
4094 /* send our message */
4095 bus_test_run_clients_loop (SEND_PENDING (connection));
4096
4097 dbus_message_unref (message);
4098 message = NULL;
4099
4100 dbus_connection_ref (connection); /* because we may get disconnected */
4101 block_connection_until_message_from_bus (context, connection, "reply to ListActivatableNames/ListNames");
4102
4103 if (!dbus_connection_get_is_connected (connection))
4104 {
4105 _dbus_verbose ("connection was disconnected\n");
4106
4107 dbus_connection_unref (connection);
4108
4109 return TRUE;
4110 }
4111
4112 dbus_connection_unref (connection);
4113
4114 message = pop_message_waiting_for_memory (connection);
4115 if (message == NULL)
4116 {
4117 _dbus_warn ("Did not receive a reply to %s %d on %p\n",
4118 method, serial, connection);
4119 goto out;
4120 }
4121
4122 verbose_message_received (connection, message);
4123
4124 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
4125 {
4126 if (dbus_message_is_error (message, DBUS_ERROR_NO_MEMORY))
4127 {
4128 ; /* good, this is a valid response */
4129 }
4130 else
4131 {
4132 warn_unexpected (connection, message, "not this error");
4133
4134 goto out;
4135 }
4136 }
4137 else
4138 {
4139 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
4140 {
4141 ; /* good, expected */
4142 }
4143 else
4144 {
4145 warn_unexpected (connection, message,
4146 "method_return for ListActivatableNames/ListNames");
4147
4148 goto out;
4149 }
4150
4151 retry_get_property:
4152
4153 if (!dbus_message_get_args (message, &error,
4154 DBUS_TYPE_ARRAY,
4155 DBUS_TYPE_STRING,
4156 &srvs, &l,
4157 DBUS_TYPE_INVALID))
4158 {
4159 if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
4160 {
4161 _dbus_verbose ("no memory to list services by %s\n", method);
4162 dbus_error_free (&error);
4163 _dbus_wait_for_memory ();
4164 goto retry_get_property;
4165 }
4166 else
4167 {
4168 _dbus_assert (dbus_error_is_set (&error));
4169 _dbus_warn ("Did not get the expected DBUS_TYPE_ARRAY from %s\n", method);
4170 goto out;
4171 }
4172 } else {
4173 *services = srvs;
4174 *len = l;
4175 }
4176 }
4177
4178 if (!check_no_leftovers (context))
4179 goto out;
4180
4181 retval = TRUE;
4182
4183 out:
4184 dbus_error_free (&error);
4185
4186 if (message)
4187 dbus_message_unref (message);
4188
4189 return retval;
4190}
4191
4192/* returns TRUE if the correct thing happens,
4193 * but the correct thing may include OOM errors.
4194 */
4195static dbus_bool_t
4196check_list_services (BusContext *context,
4197 DBusConnection *connection)
4198{
4199 DBusMessage *message;
4200 DBusMessage *base_service_message;
4201 const char *base_service;
4202 dbus_uint32_t serial;
4203 dbus_bool_t retval;
4204 const char *existent = EXISTENT_SERVICE_NAME;
4205 dbus_uint32_t flags;
4206 char **services;
4207 int len;
4208
4209 _dbus_verbose ("check_list_services for %p\n", connection);
4210
4211 if (!check_get_services (context, connection, "ListActivatableNames", &services, &len))
4212 {
4213 return TRUE;
4214 }
4215
4216 if (!_dbus_string_array_contains ((const char **)services, existent))
4217 {
4218 _dbus_warn ("Did not get the expected %s from ListActivatableNames\n", existent);
4219 dbus_free_string_array (services);
4220 return FALSE;
4221 }
4222
4223 dbus_free_string_array (services);
4224
4225 base_service_message = NULL;
4226
4227 message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
4228 DBUS_PATH_DBUS,
4229 DBUS_INTERFACE_DBUS,
4230 "StartServiceByName");
4231
4232 if (message == NULL)
4233 return TRUE;
4234
4235 dbus_message_set_auto_start (message, FALSE);
4236
4237 flags = 0;
4238 if (!dbus_message_append_args (message,
4239 DBUS_TYPE_STRING, &existent,
4240 DBUS_TYPE_UINT32, &flags,
4241 DBUS_TYPE_INVALID))
4242 {
4243 dbus_message_unref (message);
4244 return TRUE;
4245 }
4246
4247 if (!dbus_connection_send (connection, message, &serial))
4248 {
4249 dbus_message_unref (message);
4250 return TRUE;
4251 }
4252
4253 dbus_message_unref (message);
4254 message = NULL;
4255
4256 bus_test_run_everything (context);
4257
4258 /* now wait for the message bus to hear back from the activated
4259 * service.
4260 */
4261 block_connection_until_message_from_bus (context, connection, "activated service to connect");
4262
4263 bus_test_run_everything (context);
4264
4265 if (!dbus_connection_get_is_connected (connection))
4266 {
4267 _dbus_verbose ("connection was disconnected\n");
4268 return TRUE;
4269 }
4270
4271 retval = FALSE;
4272
4273 message = pop_message_waiting_for_memory (connection);
4274 if (message == NULL)
4275 {
4276 _dbus_warn ("Did not receive any messages after %s %d on %p\n",
4277 "StartServiceByName", serial, connection);
4278 goto out;
4279 }
4280
4281 verbose_message_received (connection, message);
4282 _dbus_verbose (" (after sending %s)\n", "StartServiceByName");
4283
4284 if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
4285 {
4286 if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
4287 {
4288 _dbus_warn ("Message has wrong sender %s\n",
4289 dbus_message_get_sender (message) ?
4290 dbus_message_get_sender (message) : "(none)");
4291 goto out;
4292 }
4293
4294 if (dbus_message_is_error (message,
4295 DBUS_ERROR_NO_MEMORY))
4296 {
4297 ; /* good, this is a valid response */
4298 }
4299 else if (dbus_message_is_error (message,
4300 DBUS_ERROR_SPAWN_CHILD_EXITED) ||
4301 dbus_message_is_error (message,
4302 DBUS_ERROR_SPAWN_CHILD_SIGNALED) ||
4303 dbus_message_is_error (message,
4304 DBUS_ERROR_SPAWN_EXEC_FAILED))
4305 {
4306 ; /* good, this is expected also */
4307 }
4308 else
4309 {
4310 _dbus_warn ("Did not expect error %s\n",
4311 dbus_message_get_error_name (message));
4312 goto out;
4313 }
4314 }
4315 else
4316 {
4317 GotServiceInfo message_kind;
4318
4319 if (!check_base_service_activated (context, connection,
4320 message, &base_service))
4321 goto out;
4322
4323 base_service_message = message;
4324 message = NULL;
4325
4326 /* We may need to block here for the test service to exit or finish up */
4327 block_connection_until_message_from_bus (context, connection, "test service to exit or finish up");
4328
4329 message = dbus_connection_borrow_message (connection);
4330 if (message == NULL)
4331 {
4332 _dbus_warn ("Did not receive any messages after base service creation notification\n");
4333 goto out;
4334 }
4335
4336 message_kind = check_got_service_info (message);
4337
4338 dbus_connection_return_message (connection, message);
4339 message = NULL;
4340
4341 switch (message_kind)
4342 {
4343 case GOT_SOMETHING_ELSE:
4344 case GOT_ERROR:
4345 case GOT_SERVICE_DELETED:
4346 _dbus_warn ("Unexpected message after ActivateService "
4347 "(should be an error or a service announcement)\n");
4348 goto out;
4349
4350 case GOT_SERVICE_CREATED:
4351 message = pop_message_waiting_for_memory (connection);
4352 if (message == NULL)
4353 {
4354 _dbus_warn ("Failed to pop message we just put back! "
4355 "should have been a NameOwnerChanged (creation)\n");
4356 goto out;
4357 }
4358
4359 if (!check_service_activated (context, connection, EXISTENT_SERVICE_NAME,
4360 base_service, message))
4361 goto out;
4362
4363 dbus_message_unref (message);
4364 message = NULL;
4365
4366 if (!check_no_leftovers (context))
4367 {
4368 _dbus_warn ("Messages were left over after successful activation\n");
4369 goto out;
4370 }
4371
4372 break;
4373 }
4374 }
4375
4376 if (!check_get_services (context, connection, "ListNames", &services, &len))
4377 {
4378 return TRUE;
4379 }
4380
4381 if (!_dbus_string_array_contains ((const char **)services, existent))
4382 {
4383 _dbus_warn ("Did not get the expected %s from ListNames\n", existent);
4384 goto out;
4385 }
4386
4387 dbus_free_string_array (services);
4388
4389 if (!check_send_exit_to_service (context, connection,
4390 EXISTENT_SERVICE_NAME, base_service))
4391 goto out;
4392
4393 retval = TRUE;
4394
4395 out:
4396 if (message)
4397 dbus_message_unref (message);
4398
4399 if (base_service_message)
4400 dbus_message_unref (base_service_message);
4401
4402 return retval;
4403}
4404
4405typedef struct
4406{
4407 Check2Func func;
4408 BusContext *context;
4409 DBusConnection *connection;
4410} Check2Data;
4411
4412static dbus_bool_t
4413check_oom_check2_func (void *data)
4414{
4415 Check2Data *d = data;
4416
4417 if (! (* d->func) (d->context, d->connection))
4418 return FALSE;
4419
4420 if (!check_no_leftovers (d->context))
4421 {
4422 _dbus_warn ("Messages were left over, should be covered by test suite\n");
4423 return FALSE;
4424 }
4425
4426 return TRUE;
4427}
4428
4429static void
4430check2_try_iterations (BusContext *context,
4431 DBusConnection *connection,
4432 const char *description,
4433 Check2Func func)
4434{
4435 Check2Data d;
4436
4437 d.func = func;
4438 d.context = context;
4439 d.connection = connection;
4440
4441 if (!_dbus_test_oom_handling (description, check_oom_check2_func,
4442 &d))
4443 {
4444 _dbus_warn ("%s failed during oom\n", description);
4445 _dbus_assert_not_reached ("test failed");
4446 }
4447}
4448
4449static dbus_bool_t
4450setenv_TEST_LAUNCH_HELPER_CONFIG(const DBusString *test_data_dir,
4451 const char *filename)
4452{
4453 DBusString full;
4454 DBusString file;
4455
4456 if (!_dbus_string_init (&full))
4457 return FALSE;
4458
4459 if (!_dbus_string_copy (test_data_dir, 0, &full, 0))
4460 {
4461 _dbus_string_free (&full);
4462 return FALSE;
4463 }
4464
4465 _dbus_string_init_const (&file, filename);
4466
4467 if (!_dbus_concat_dir_and_file (&full, &file))
4468 {
4469 _dbus_string_free (&full);
4470 return FALSE;
4471 }
4472
4473 _dbus_verbose ("Setting TEST_LAUNCH_HELPER_CONFIG to '%s'\n",
4474 _dbus_string_get_const_data (&full));
4475
4476 _dbus_setenv ("TEST_LAUNCH_HELPER_CONFIG", _dbus_string_get_const_data (&full));
4477
4478 _dbus_string_free (&full);
4479
4480 return TRUE;
4481}
4482
4483static dbus_bool_t
4484bus_dispatch_test_conf (const DBusString *test_data_dir,
4485 const char *filename,
4486 dbus_bool_t use_launcher)
4487{
4488 BusContext *context;
4489 DBusConnection *foo;
4490 DBusConnection *bar;
4491 DBusConnection *baz;
4492 DBusError error;
4493
4494 /* save the config name for the activation helper */
4495 if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename))
4496 _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG");
4497
4498 dbus_error_init (&error);
4499
4500 context = bus_context_new_test (test_data_dir, filename);
4501 if (context == NULL)
4502 return FALSE;
4503
4504 foo = dbus_connection_open_private (TEST_CONNECTION, &error);
4505 if (foo == NULL)
4506 _dbus_assert_not_reached ("could not alloc connection");
4507
4508 if (!bus_setup_debug_client (foo))
4509 _dbus_assert_not_reached ("could not set up connection");
4510
4511 spin_connection_until_authenticated (context, foo);
4512
4513 if (!check_hello_message (context, foo))
4514 _dbus_assert_not_reached ("hello message failed");
4515
4516 if (!check_double_hello_message (context, foo))
4517 _dbus_assert_not_reached ("double hello message failed");
4518
4519 if (!check_add_match_all (context, foo))
4520 _dbus_assert_not_reached ("AddMatch message failed");
4521
4522 bar = dbus_connection_open_private (TEST_CONNECTION, &error);
4523 if (bar == NULL)
4524 _dbus_assert_not_reached ("could not alloc connection");
4525
4526 if (!bus_setup_debug_client (bar))
4527 _dbus_assert_not_reached ("could not set up connection");
4528
4529 spin_connection_until_authenticated (context, bar);
4530
4531 if (!check_hello_message (context, bar))
4532 _dbus_assert_not_reached ("hello message failed");
4533
4534 if (!check_add_match_all (context, bar))
4535 _dbus_assert_not_reached ("AddMatch message failed");
4536
4537 baz = dbus_connection_open_private (TEST_CONNECTION, &error);
4538 if (baz == NULL)
4539 _dbus_assert_not_reached ("could not alloc connection");
4540
4541 if (!bus_setup_debug_client (baz))
4542 _dbus_assert_not_reached ("could not set up connection");
4543
4544 spin_connection_until_authenticated (context, baz);
4545
4546 if (!check_hello_message (context, baz))
4547 _dbus_assert_not_reached ("hello message failed");
4548
4549 if (!check_add_match_all (context, baz))
4550 _dbus_assert_not_reached ("AddMatch message failed");
4551
4552#ifdef DBUS_WIN_FIXME
4553 _dbus_warn("TODO: testing of GetConnectionUnixUser message skipped for now\n");
4554 _dbus_warn("TODO: testing of GetConnectionUnixProcessID message skipped for now\n");
4555#else
4556 if (!check_get_connection_unix_user (context, baz))
4557 _dbus_assert_not_reached ("GetConnectionUnixUser message failed");
4558
4559 if (!check_get_connection_unix_process_id (context, baz))
4560 _dbus_assert_not_reached ("GetConnectionUnixProcessID message failed");
4561#endif
4562
4563 if (!check_list_services (context, baz))
4564 _dbus_assert_not_reached ("ListActivatableNames message failed");
4565
4566 if (!check_no_leftovers (context))
4567 {
4568 _dbus_warn ("Messages were left over after setting up initial connections\n");
4569 _dbus_assert_not_reached ("initial connection setup failed");
4570 }
4571
4572 check1_try_iterations (context, "create_and_hello",
4573 check_hello_connection);
4574
4575 check2_try_iterations (context, foo, "nonexistent_service_no_auto_start",
4576 check_nonexistent_service_no_auto_start);
4577
4578#ifdef DBUS_WIN_FIXME
4579 _dbus_warn("TODO: dispatch.c segfault_service_no_auto_start test\n");
4580#else
4581 check2_try_iterations (context, foo, "segfault_service_no_auto_start",
4582 check_segfault_service_no_auto_start);
4583#endif
4584
4585 check2_try_iterations (context, foo, "existent_service_no_auto_start",
4586 check_existent_service_no_auto_start);
4587
4588 check2_try_iterations (context, foo, "nonexistent_service_auto_start",
4589 check_nonexistent_service_auto_start);
4590
4591
4592#ifdef DBUS_WIN_FIXME
4593 _dbus_warn("TODO: dispatch.c segfault_service_auto_start test\n");
4594#else
4595 /* only do the segfault test if we are not using the launcher */
4596 check2_try_iterations (context, foo, "segfault_service_auto_start",
4597 check_segfault_service_auto_start);
4598#endif
4599
4600 /* only do the shell fail test if we are not using the launcher */
4601 check2_try_iterations (context, foo, "shell_fail_service_auto_start",
4602 check_shell_fail_service_auto_start);
4603
4604 /* specific to launcher */
4605 if (use_launcher)
4606 if (!check_launch_service_file_missing (context, foo))
4607 _dbus_assert_not_reached ("did not get service file not found error");
4608
4609#if 0
4610 /* Note: need to resolve some issues with the testing code in order to run
4611 * this in oom (handle that we sometimes don't get replies back from the bus
4612 * when oom happens, without blocking the test).
4613 */
4614 check2_try_iterations (context, foo, "existent_service_auto_auto_start",
4615 check_existent_service_auto_start);
4616#endif
4617
4618 if (!check_existent_service_auto_start (context, foo))
4619 _dbus_assert_not_reached ("existent service auto start failed");
4620
4621 if (!check_shell_service_success_auto_start (context, foo))
4622 _dbus_assert_not_reached ("shell success service auto start failed");
4623
4624 _dbus_verbose ("Disconnecting foo, bar, and baz\n");
4625
4626 kill_client_connection_unchecked (foo);
4627 kill_client_connection_unchecked (bar);
4628 kill_client_connection_unchecked (baz);
4629
4630 bus_context_unref (context);
4631
4632 return TRUE;
4633}
4634
4635static dbus_bool_t
4636bus_dispatch_test_conf_fail (const DBusString *test_data_dir,
4637 const char *filename)
4638{
4639 BusContext *context;
4640 DBusConnection *foo;
4641 DBusError error;
4642
4643 /* save the config name for the activation helper */
4644 if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename))
4645 _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG");
4646
4647 dbus_error_init (&error);
4648
4649 context = bus_context_new_test (test_data_dir, filename);
4650 if (context == NULL)
4651 return FALSE;
4652
4653 foo = dbus_connection_open_private (TEST_CONNECTION, &error);
4654 if (foo == NULL)
4655 _dbus_assert_not_reached ("could not alloc connection");
4656
4657 if (!bus_setup_debug_client (foo))
4658 _dbus_assert_not_reached ("could not set up connection");
4659
4660 spin_connection_until_authenticated (context, foo);
4661
4662 if (!check_hello_message (context, foo))
4663 _dbus_assert_not_reached ("hello message failed");
4664
4665 if (!check_double_hello_message (context, foo))
4666 _dbus_assert_not_reached ("double hello message failed");
4667
4668 if (!check_add_match_all (context, foo))
4669 _dbus_assert_not_reached ("AddMatch message failed");
4670
4671 /* this only tests the activation.c user check */
4672 if (!check_launch_service_user_missing (context, foo))
4673 _dbus_assert_not_reached ("user missing did not trigger error");
4674
4675 /* this only tests the desktop.c exec check */
4676 if (!check_launch_service_exec_missing (context, foo))
4677 _dbus_assert_not_reached ("exec missing did not trigger error");
4678
4679 /* this only tests the desktop.c service check */
4680 if (!check_launch_service_service_missing (context, foo))
4681 _dbus_assert_not_reached ("service missing did not trigger error");
4682
4683 _dbus_verbose ("Disconnecting foo\n");
4684
4685 kill_client_connection_unchecked (foo);
4686
4687 bus_context_unref (context);
4688
4689 return TRUE;
4690}
4691
4692dbus_bool_t
4693bus_dispatch_test (const DBusString *test_data_dir)
4694{
4695 /* run normal activation tests */
4696 _dbus_verbose ("Normal activation tests\n");
4697 if (!bus_dispatch_test_conf (test_data_dir,
4698 "valid-config-files/debug-allow-all.conf", FALSE))
4699 return FALSE;
4700
4701#ifdef DBUS_WIN
4702 _dbus_warn("Info: Launch helper activation tests skipped because launch-helper is not supported yet\n");
4703#else
4704 /* run launch-helper activation tests */
4705 _dbus_verbose ("Launch helper activation tests\n");
4706 if (!bus_dispatch_test_conf (test_data_dir,
4707 "valid-config-files-system/debug-allow-all-pass.conf", TRUE))
4708 return FALSE;
4709
4710 /* run select launch-helper activation tests on broken service files */
4711 if (!bus_dispatch_test_conf_fail (test_data_dir,
4712 "valid-config-files-system/debug-allow-all-fail.conf"))
4713 return FALSE;
4714#endif
4715
4716 return TRUE;
4717}
4718
4719dbus_bool_t
4720bus_dispatch_sha1_test (const DBusString *test_data_dir)
4721{
4722 BusContext *context;
4723 DBusConnection *foo;
4724 DBusError error;
4725
4726 dbus_error_init (&error);
4727
4728 /* Test SHA1 authentication */
4729 _dbus_verbose ("Testing SHA1 context\n");
4730
4731 context = bus_context_new_test (test_data_dir,
4732 "valid-config-files/debug-allow-all-sha1.conf");
4733 if (context == NULL)
4734 return FALSE;
4735
4736 foo = dbus_connection_open_private (TEST_CONNECTION, &error);
4737 if (foo == NULL)
4738 _dbus_assert_not_reached ("could not alloc connection");
4739
4740 if (!bus_setup_debug_client (foo))
4741 _dbus_assert_not_reached ("could not set up connection");
4742
4743 spin_connection_until_authenticated (context, foo);
4744
4745 if (!check_hello_message (context, foo))
4746 _dbus_assert_not_reached ("hello message failed");
4747
4748 if (!check_add_match_all (context, foo))
4749 _dbus_assert_not_reached ("addmatch message failed");
4750
4751 if (!check_no_leftovers (context))
4752 {
4753 _dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n");
4754 _dbus_assert_not_reached ("initial connection setup failed");
4755 }
4756
4757 check1_try_iterations (context, "create_and_hello_sha1",
4758 check_hello_connection);
4759
4760 kill_client_connection_unchecked (foo);
4761
4762 bus_context_unref (context);
4763
4764 return TRUE;
4765}
4766
4767#ifdef HAVE_UNIX_FD_PASSING
4768
4769dbus_bool_t
4770bus_unix_fds_passing_test(const DBusString *test_data_dir)
4771{
4772 BusContext *context;
4773 DBusConnection *foo, *bar;
4774 DBusError error;
4775 DBusMessage *m;
4776 dbus_bool_t b;
4777 int one[2], two[2], x, y, z;
4778 char r;
4779
4780 dbus_error_init (&error);
4781
4782 context = bus_context_new_test (test_data_dir, "valid-config-files/debug-allow-all.conf");
4783 if (context == NULL)
4784 _dbus_assert_not_reached ("could not alloc context");
4785
4786 foo = dbus_connection_open_private (TEST_CONNECTION, &error);
4787 if (foo == NULL)
4788 _dbus_assert_not_reached ("could not alloc connection");
4789
4790 if (!bus_setup_debug_client (foo))
4791 _dbus_assert_not_reached ("could not set up connection");
4792
4793 spin_connection_until_authenticated (context, foo);
4794
4795 if (!check_hello_message (context, foo))
4796 _dbus_assert_not_reached ("hello message failed");
4797
4798 if (!check_add_match_all (context, foo))
4799 _dbus_assert_not_reached ("AddMatch message failed");
4800
4801 bar = dbus_connection_open_private (TEST_CONNECTION, &error);
4802 if (bar == NULL)
4803 _dbus_assert_not_reached ("could not alloc connection");
4804
4805 if (!bus_setup_debug_client (bar))
4806 _dbus_assert_not_reached ("could not set up connection");
4807
4808 spin_connection_until_authenticated (context, bar);
4809
4810 if (!check_hello_message (context, bar))
4811 _dbus_assert_not_reached ("hello message failed");
4812
4813 if (!check_add_match_all (context, bar))
4814 _dbus_assert_not_reached ("AddMatch message failed");
4815
4816 if (!(m = dbus_message_new_signal("/", "a.b.c", "d")))
4817 _dbus_assert_not_reached ("could not alloc message");
4818
4819 if (!(_dbus_full_duplex_pipe(one, one+1, TRUE, &error)))
4820 _dbus_assert_not_reached("Failed to allocate pipe #1");
4821
4822 if (!(_dbus_full_duplex_pipe(two, two+1, TRUE, &error)))
4823 _dbus_assert_not_reached("Failed to allocate pipe #2");
4824
4825 if (!dbus_message_append_args(m,
4826 DBUS_TYPE_UNIX_FD, one,
4827 DBUS_TYPE_UNIX_FD, two,
4828 DBUS_TYPE_UNIX_FD, two,
4829 DBUS_TYPE_INVALID))
4830 _dbus_assert_not_reached("Failed to attach fds.");
4831
4832 if (!_dbus_close(one[0], &error))
4833 _dbus_assert_not_reached("Failed to close pipe #1 ");
4834 if (!_dbus_close(two[0], &error))
4835 _dbus_assert_not_reached("Failed to close pipe #2 ");
4836
4837 if (!(dbus_connection_can_send_type(foo, DBUS_TYPE_UNIX_FD)))
4838 _dbus_assert_not_reached("Connection cannot do fd passing");
4839
4840 if (!(dbus_connection_can_send_type(bar, DBUS_TYPE_UNIX_FD)))
4841 _dbus_assert_not_reached("Connection cannot do fd passing");
4842
4843 if (!dbus_connection_send (foo, m, NULL))
4844 _dbus_assert_not_reached("Failed to send fds");
4845
4846 dbus_message_unref(m);
4847
4848 bus_test_run_clients_loop (SEND_PENDING (foo));
4849
4850 bus_test_run_everything (context);
4851
4852 block_connection_until_message_from_bus (context, foo, "unix fd reception on foo");
4853
4854 if (!(m = pop_message_waiting_for_memory (foo)))
4855 _dbus_assert_not_reached("Failed to receive msg");
4856
4857 if (!dbus_message_is_signal(m, "a.b.c", "d"))
4858 _dbus_assert_not_reached("bogus message received");
4859
4860 dbus_message_unref(m);
4861
4862 block_connection_until_message_from_bus (context, bar, "unix fd reception on bar");
4863
4864 if (!(m = pop_message_waiting_for_memory (bar)))
4865 _dbus_assert_not_reached("Failed to receive msg");
4866
4867 if (!dbus_message_is_signal(m, "a.b.c", "d"))
4868 _dbus_assert_not_reached("bogus message received");
4869
4870 if (!dbus_message_get_args(m,
4871 &error,
4872 DBUS_TYPE_UNIX_FD, &x,
4873 DBUS_TYPE_UNIX_FD, &y,
4874 DBUS_TYPE_UNIX_FD, &z,
4875 DBUS_TYPE_INVALID))
4876 _dbus_assert_not_reached("Failed to parse fds.");
4877
4878 dbus_message_unref(m);
4879
4880 if (write(x, "X", 1) != 1)
4881 _dbus_assert_not_reached("Failed to write to pipe #1");
4882 if (write(y, "Y", 1) != 1)
4883 _dbus_assert_not_reached("Failed to write to pipe #2");
4884 if (write(z, "Z", 1) != 1)
4885 _dbus_assert_not_reached("Failed to write to pipe #2/2nd fd");
4886
4887 if (!_dbus_close(x, &error))
4888 _dbus_assert_not_reached("Failed to close pipe #1/other side ");
4889 if (!_dbus_close(y, &error))
4890 _dbus_assert_not_reached("Failed to close pipe #2/other side ");
4891 if (!_dbus_close(z, &error))
4892 _dbus_assert_not_reached("Failed to close pipe #2/other size 2nd fd ");
4893
4894 if (read(one[1], &r, 1) != 1 || r != 'X')
4895 _dbus_assert_not_reached("Failed to read value from pipe.");
4896 if (read(two[1], &r, 1) != 1 || r != 'Y')
4897 _dbus_assert_not_reached("Failed to read value from pipe.");
4898 if (read(two[1], &r, 1) != 1 || r != 'Z')
4899 _dbus_assert_not_reached("Failed to read value from pipe.");
4900
4901 if (!_dbus_close(one[1], &error))
4902 _dbus_assert_not_reached("Failed to close pipe #1 ");
4903 if (!_dbus_close(two[1], &error))
4904 _dbus_assert_not_reached("Failed to close pipe #2 ");
4905
4906 _dbus_verbose ("Disconnecting foo\n");
4907 kill_client_connection_unchecked (foo);
4908
4909 _dbus_verbose ("Disconnecting bar\n");
4910 kill_client_connection_unchecked (bar);
4911
4912 bus_context_unref (context);
4913
4914 return TRUE;
4915}
4916#endif
4917
4918#endif /* DBUS_BUILD_TESTS */