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