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