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