|
D-Bus
1.8.20
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-object-tree.c DBusObjectTree (internals of DBusConnection) 00003 * 00004 * Copyright (C) 2003, 2005 Red Hat Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-object-tree.h" 00026 #include "dbus-connection-internal.h" 00027 #include "dbus-internals.h" 00028 #include "dbus-hash.h" 00029 #include "dbus-protocol.h" 00030 #include "dbus-string.h" 00031 #include <string.h> 00032 #include <stdlib.h> 00033 00046 typedef struct DBusObjectSubtree DBusObjectSubtree; 00047 00048 static DBusObjectSubtree* _dbus_object_subtree_new (const char *name, 00049 const DBusObjectPathVTable *vtable, 00050 void *user_data); 00051 static DBusObjectSubtree* _dbus_object_subtree_ref (DBusObjectSubtree *subtree); 00052 static void _dbus_object_subtree_unref (DBusObjectSubtree *subtree); 00053 00057 struct DBusObjectTree 00058 { 00059 int refcount; 00060 DBusConnection *connection; 00062 DBusObjectSubtree *root; 00063 }; 00064 00070 struct DBusObjectSubtree 00071 { 00072 DBusAtomic refcount; 00073 DBusObjectSubtree *parent; 00074 DBusObjectPathUnregisterFunction unregister_function; 00075 DBusObjectPathMessageFunction message_function; 00076 void *user_data; 00077 DBusObjectSubtree **subtrees; 00078 int n_subtrees; 00079 int max_subtrees; 00080 unsigned int invoke_as_fallback : 1; 00081 char name[1]; 00082 }; 00083 00091 DBusObjectTree* 00092 _dbus_object_tree_new (DBusConnection *connection) 00093 { 00094 DBusObjectTree *tree; 00095 00096 /* the connection passed in here isn't fully constructed, 00097 * so don't do anything more than store a pointer to 00098 * it 00099 */ 00100 00101 tree = dbus_new0 (DBusObjectTree, 1); 00102 if (tree == NULL) 00103 goto oom; 00104 00105 tree->refcount = 1; 00106 tree->connection = connection; 00107 tree->root = _dbus_object_subtree_new ("/", NULL, NULL); 00108 if (tree->root == NULL) 00109 goto oom; 00110 tree->root->invoke_as_fallback = TRUE; 00111 00112 return tree; 00113 00114 oom: 00115 if (tree) 00116 { 00117 dbus_free (tree); 00118 } 00119 00120 return NULL; 00121 } 00122 00128 DBusObjectTree * 00129 _dbus_object_tree_ref (DBusObjectTree *tree) 00130 { 00131 _dbus_assert (tree->refcount > 0); 00132 00133 tree->refcount += 1; 00134 00135 return tree; 00136 } 00137 00142 void 00143 _dbus_object_tree_unref (DBusObjectTree *tree) 00144 { 00145 _dbus_assert (tree->refcount > 0); 00146 00147 tree->refcount -= 1; 00148 00149 if (tree->refcount == 0) 00150 { 00151 _dbus_object_tree_free_all_unlocked (tree); 00152 00153 dbus_free (tree); 00154 } 00155 } 00156 00160 #define VERBOSE_FIND 0 00161 00162 static DBusObjectSubtree* 00163 find_subtree_recurse (DBusObjectSubtree *subtree, 00164 const char **path, 00165 dbus_bool_t create_if_not_found, 00166 int *index_in_parent, 00167 dbus_bool_t *exact_match) 00168 { 00169 int i, j; 00170 dbus_bool_t return_deepest_match; 00171 00172 return_deepest_match = exact_match != NULL; 00173 00174 _dbus_assert (!(return_deepest_match && create_if_not_found)); 00175 00176 if (path[0] == NULL) 00177 { 00178 #if VERBOSE_FIND 00179 _dbus_verbose (" path exhausted, returning %s\n", 00180 subtree->name); 00181 #endif 00182 if (exact_match != NULL) 00183 *exact_match = TRUE; 00184 return subtree; 00185 } 00186 00187 #if VERBOSE_FIND 00188 _dbus_verbose (" searching children of %s for %s\n", 00189 subtree->name, path[0]); 00190 #endif 00191 00192 i = 0; 00193 j = subtree->n_subtrees; 00194 while (i < j) 00195 { 00196 int k, v; 00197 00198 k = (i + j) / 2; 00199 v = strcmp (path[0], subtree->subtrees[k]->name); 00200 00201 #if VERBOSE_FIND 00202 _dbus_verbose (" %s cmp %s = %d\n", 00203 path[0], subtree->subtrees[k]->name, 00204 v); 00205 #endif 00206 00207 if (v == 0) 00208 { 00209 if (index_in_parent) 00210 { 00211 #if VERBOSE_FIND 00212 _dbus_verbose (" storing parent index %d\n", k); 00213 #endif 00214 *index_in_parent = k; 00215 } 00216 00217 if (return_deepest_match) 00218 { 00219 DBusObjectSubtree *next; 00220 00221 next = find_subtree_recurse (subtree->subtrees[k], 00222 &path[1], create_if_not_found, 00223 index_in_parent, exact_match); 00224 if (next == NULL && 00225 subtree->invoke_as_fallback) 00226 { 00227 #if VERBOSE_FIND 00228 _dbus_verbose (" no deeper match found, returning %s\n", 00229 subtree->name); 00230 #endif 00231 if (exact_match != NULL) 00232 *exact_match = FALSE; 00233 return subtree; 00234 } 00235 else 00236 return next; 00237 } 00238 else 00239 return find_subtree_recurse (subtree->subtrees[k], 00240 &path[1], create_if_not_found, 00241 index_in_parent, exact_match); 00242 } 00243 else if (v < 0) 00244 { 00245 j = k; 00246 } 00247 else 00248 { 00249 i = k + 1; 00250 } 00251 } 00252 00253 #if VERBOSE_FIND 00254 _dbus_verbose (" no match found, current tree %s, create_if_not_found = %d\n", 00255 subtree->name, create_if_not_found); 00256 #endif 00257 00258 if (create_if_not_found) 00259 { 00260 DBusObjectSubtree* child; 00261 int child_pos, new_n_subtrees; 00262 00263 #if VERBOSE_FIND 00264 _dbus_verbose (" creating subtree %s\n", 00265 path[0]); 00266 #endif 00267 00268 child = _dbus_object_subtree_new (path[0], 00269 NULL, NULL); 00270 if (child == NULL) 00271 return NULL; 00272 00273 new_n_subtrees = subtree->n_subtrees + 1; 00274 if (new_n_subtrees > subtree->max_subtrees) 00275 { 00276 int new_max_subtrees; 00277 DBusObjectSubtree **new_subtrees; 00278 00279 new_max_subtrees = subtree->max_subtrees == 0 ? 1 : 2 * subtree->max_subtrees; 00280 new_subtrees = dbus_realloc (subtree->subtrees, 00281 new_max_subtrees * sizeof (DBusObjectSubtree*)); 00282 if (new_subtrees == NULL) 00283 { 00284 _dbus_object_subtree_unref (child); 00285 return NULL; 00286 } 00287 subtree->subtrees = new_subtrees; 00288 subtree->max_subtrees = new_max_subtrees; 00289 } 00290 00291 /* The binary search failed, so i == j points to the 00292 place the child should be inserted. */ 00293 child_pos = i; 00294 _dbus_assert (child_pos < new_n_subtrees && 00295 new_n_subtrees <= subtree->max_subtrees); 00296 if (child_pos + 1 < new_n_subtrees) 00297 { 00298 memmove (&subtree->subtrees[child_pos+1], 00299 &subtree->subtrees[child_pos], 00300 (new_n_subtrees - child_pos - 1) * 00301 sizeof subtree->subtrees[0]); 00302 } 00303 subtree->subtrees[child_pos] = child; 00304 00305 if (index_in_parent) 00306 *index_in_parent = child_pos; 00307 subtree->n_subtrees = new_n_subtrees; 00308 child->parent = subtree; 00309 00310 return find_subtree_recurse (child, 00311 &path[1], create_if_not_found, 00312 index_in_parent, exact_match); 00313 } 00314 else 00315 { 00316 if (exact_match != NULL) 00317 *exact_match = FALSE; 00318 return (return_deepest_match && subtree->invoke_as_fallback) ? subtree : NULL; 00319 } 00320 } 00321 00322 static DBusObjectSubtree* 00323 find_subtree (DBusObjectTree *tree, 00324 const char **path, 00325 int *index_in_parent) 00326 { 00327 DBusObjectSubtree *subtree; 00328 00329 #if VERBOSE_FIND 00330 _dbus_verbose ("Looking for exact registered subtree\n"); 00331 #endif 00332 00333 subtree = find_subtree_recurse (tree->root, path, FALSE, index_in_parent, NULL); 00334 00335 if (subtree && subtree->message_function == NULL) 00336 return NULL; 00337 else 00338 return subtree; 00339 } 00340 00341 static DBusObjectSubtree* 00342 lookup_subtree (DBusObjectTree *tree, 00343 const char **path) 00344 { 00345 #if VERBOSE_FIND 00346 _dbus_verbose ("Looking for subtree\n"); 00347 #endif 00348 return find_subtree_recurse (tree->root, path, FALSE, NULL, NULL); 00349 } 00350 00351 static DBusObjectSubtree* 00352 find_handler (DBusObjectTree *tree, 00353 const char **path, 00354 dbus_bool_t *exact_match) 00355 { 00356 #if VERBOSE_FIND 00357 _dbus_verbose ("Looking for deepest handler\n"); 00358 #endif 00359 _dbus_assert (exact_match != NULL); 00360 00361 *exact_match = FALSE; /* ensure always initialized */ 00362 00363 return find_subtree_recurse (tree->root, path, FALSE, NULL, exact_match); 00364 } 00365 00366 static DBusObjectSubtree* 00367 ensure_subtree (DBusObjectTree *tree, 00368 const char **path) 00369 { 00370 #if VERBOSE_FIND 00371 _dbus_verbose ("Ensuring subtree\n"); 00372 #endif 00373 return find_subtree_recurse (tree->root, path, TRUE, NULL, NULL); 00374 } 00375 00376 static char *flatten_path (const char **path); 00377 00390 dbus_bool_t 00391 _dbus_object_tree_register (DBusObjectTree *tree, 00392 dbus_bool_t fallback, 00393 const char **path, 00394 const DBusObjectPathVTable *vtable, 00395 void *user_data, 00396 DBusError *error) 00397 { 00398 DBusObjectSubtree *subtree; 00399 00400 _dbus_assert (tree != NULL); 00401 _dbus_assert (vtable->message_function != NULL); 00402 _dbus_assert (path != NULL); 00403 00404 subtree = ensure_subtree (tree, path); 00405 if (subtree == NULL) 00406 { 00407 _DBUS_SET_OOM (error); 00408 return FALSE; 00409 } 00410 00411 if (subtree->message_function != NULL) 00412 { 00413 if (error != NULL) 00414 { 00415 char *complete_path = flatten_path (path); 00416 00417 dbus_set_error (error, DBUS_ERROR_OBJECT_PATH_IN_USE, 00418 "A handler is already registered for %s", 00419 complete_path ? complete_path 00420 : "(cannot represent path: out of memory!)"); 00421 00422 dbus_free (complete_path); 00423 } 00424 00425 return FALSE; 00426 } 00427 00428 subtree->message_function = vtable->message_function; 00429 subtree->unregister_function = vtable->unregister_function; 00430 subtree->user_data = user_data; 00431 subtree->invoke_as_fallback = fallback != FALSE; 00432 00433 return TRUE; 00434 } 00435 00447 static dbus_bool_t 00448 unregister_subtree (DBusObjectSubtree *subtree, 00449 DBusObjectPathUnregisterFunction *unregister_function_out, 00450 void **user_data_out) 00451 { 00452 _dbus_assert (subtree != NULL); 00453 _dbus_assert (unregister_function_out != NULL); 00454 _dbus_assert (user_data_out != NULL); 00455 00456 /* Confirm subtree is registered */ 00457 if (subtree->message_function != NULL) 00458 { 00459 subtree->message_function = NULL; 00460 00461 *unregister_function_out = subtree->unregister_function; 00462 *user_data_out = subtree->user_data; 00463 00464 subtree->unregister_function = NULL; 00465 subtree->user_data = NULL; 00466 00467 return TRUE; 00468 } 00469 else 00470 { 00471 /* Assert that this unregistered subtree is either the root node or has 00472 children, otherwise we have a dangling path which should never 00473 happen */ 00474 _dbus_assert (subtree->parent == NULL || subtree->n_subtrees > 0); 00475 00476 /* The subtree is not registered */ 00477 return FALSE; 00478 } 00479 } 00480 00492 static dbus_bool_t 00493 attempt_child_removal (DBusObjectSubtree *parent, 00494 int child_index) 00495 { 00496 /* Candidate for removal */ 00497 DBusObjectSubtree* candidate; 00498 00499 _dbus_assert (parent != NULL); 00500 _dbus_assert (child_index >= 0 && child_index < parent->n_subtrees); 00501 00502 candidate = parent->subtrees[child_index]; 00503 _dbus_assert (candidate != NULL); 00504 00505 if (candidate->n_subtrees == 0 && candidate->message_function == NULL) 00506 { 00507 /* The candidate node is childless and is not a registered 00508 path, so... */ 00509 00510 /* ... remove it from its parent... */ 00511 /* Assumes a 0-byte memmove is OK */ 00512 memmove (&parent->subtrees[child_index], 00513 &parent->subtrees[child_index + 1], 00514 (parent->n_subtrees - child_index - 1) 00515 * sizeof (parent->subtrees[0])); 00516 parent->n_subtrees -= 1; 00517 00518 /* ... and free it */ 00519 candidate->parent = NULL; 00520 _dbus_object_subtree_unref (candidate); 00521 00522 return TRUE; 00523 } 00524 return FALSE; 00525 } 00526 00564 static dbus_bool_t 00565 unregister_and_free_path_recurse 00566 (DBusObjectSubtree *subtree, 00567 const char **path, 00568 dbus_bool_t *continue_removal_attempts, 00569 DBusObjectPathUnregisterFunction *unregister_function_out, 00570 void **user_data_out) 00571 { 00572 int i, j; 00573 00574 _dbus_assert (continue_removal_attempts != NULL); 00575 _dbus_assert (*continue_removal_attempts); 00576 _dbus_assert (unregister_function_out != NULL); 00577 _dbus_assert (user_data_out != NULL); 00578 00579 if (path[0] == NULL) 00580 return unregister_subtree (subtree, unregister_function_out, user_data_out); 00581 00582 i = 0; 00583 j = subtree->n_subtrees; 00584 while (i < j) 00585 { 00586 int k, v; 00587 00588 k = (i + j) / 2; 00589 v = strcmp (path[0], subtree->subtrees[k]->name); 00590 00591 if (v == 0) 00592 { 00593 dbus_bool_t freed; 00594 freed = unregister_and_free_path_recurse (subtree->subtrees[k], 00595 &path[1], 00596 continue_removal_attempts, 00597 unregister_function_out, 00598 user_data_out); 00599 if (freed && *continue_removal_attempts) 00600 *continue_removal_attempts = attempt_child_removal (subtree, k); 00601 return freed; 00602 } 00603 else if (v < 0) 00604 { 00605 j = k; 00606 } 00607 else 00608 { 00609 i = k + 1; 00610 } 00611 } 00612 return FALSE; 00613 } 00614 00622 void 00623 _dbus_object_tree_unregister_and_unlock (DBusObjectTree *tree, 00624 const char **path) 00625 { 00626 dbus_bool_t found_subtree; 00627 dbus_bool_t continue_removal_attempts; 00628 DBusObjectPathUnregisterFunction unregister_function; 00629 void *user_data; 00630 DBusConnection *connection; 00631 00632 _dbus_assert (tree != NULL); 00633 _dbus_assert (path != NULL); 00634 00635 continue_removal_attempts = TRUE; 00636 unregister_function = NULL; 00637 user_data = NULL; 00638 00639 found_subtree = unregister_and_free_path_recurse (tree->root, 00640 path, 00641 &continue_removal_attempts, 00642 &unregister_function, 00643 &user_data); 00644 00645 #ifndef DBUS_DISABLE_CHECKS 00646 if (found_subtree == FALSE) 00647 { 00648 _dbus_warn ("Attempted to unregister path (path[0] = %s path[1] = %s) which isn't registered\n", 00649 path[0] ? path[0] : "null", 00650 (path[0] && path[1]) ? path[1] : "null"); 00651 goto unlock; 00652 } 00653 #else 00654 _dbus_assert (found_subtree == TRUE); 00655 #endif 00656 00657 unlock: 00658 connection = tree->connection; 00659 00660 /* Unlock and call application code */ 00661 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00662 if (connection) 00663 #endif 00664 { 00665 _dbus_connection_ref_unlocked (connection); 00666 _dbus_verbose ("unlock\n"); 00667 _dbus_connection_unlock (connection); 00668 } 00669 00670 if (unregister_function) 00671 (* unregister_function) (connection, user_data); 00672 00673 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00674 if (connection) 00675 #endif 00676 dbus_connection_unref (connection); 00677 } 00678 00679 static void 00680 free_subtree_recurse (DBusConnection *connection, 00681 DBusObjectSubtree *subtree) 00682 { 00683 /* Delete them from the end, for slightly 00684 * more robustness against odd reentrancy. 00685 */ 00686 while (subtree->n_subtrees > 0) 00687 { 00688 DBusObjectSubtree *child; 00689 00690 child = subtree->subtrees[subtree->n_subtrees - 1]; 00691 subtree->subtrees[subtree->n_subtrees - 1] = NULL; 00692 subtree->n_subtrees -= 1; 00693 child->parent = NULL; 00694 00695 free_subtree_recurse (connection, child); 00696 } 00697 00698 /* Call application code */ 00699 if (subtree->unregister_function) 00700 (* subtree->unregister_function) (connection, 00701 subtree->user_data); 00702 00703 subtree->message_function = NULL; 00704 subtree->unregister_function = NULL; 00705 subtree->user_data = NULL; 00706 00707 /* Now free ourselves */ 00708 _dbus_object_subtree_unref (subtree); 00709 } 00710 00717 void 00718 _dbus_object_tree_free_all_unlocked (DBusObjectTree *tree) 00719 { 00720 if (tree->root) 00721 free_subtree_recurse (tree->connection, 00722 tree->root); 00723 tree->root = NULL; 00724 } 00725 00726 static dbus_bool_t 00727 _dbus_object_tree_list_registered_unlocked (DBusObjectTree *tree, 00728 const char **parent_path, 00729 char ***child_entries) 00730 { 00731 DBusObjectSubtree *subtree; 00732 char **retval; 00733 00734 _dbus_assert (parent_path != NULL); 00735 _dbus_assert (child_entries != NULL); 00736 00737 *child_entries = NULL; 00738 00739 subtree = lookup_subtree (tree, parent_path); 00740 if (subtree == NULL) 00741 { 00742 retval = dbus_new0 (char *, 1); 00743 } 00744 else 00745 { 00746 int i; 00747 retval = dbus_new0 (char*, subtree->n_subtrees + 1); 00748 if (retval == NULL) 00749 goto out; 00750 i = 0; 00751 while (i < subtree->n_subtrees) 00752 { 00753 retval[i] = _dbus_strdup (subtree->subtrees[i]->name); 00754 if (retval[i] == NULL) 00755 { 00756 dbus_free_string_array (retval); 00757 retval = NULL; 00758 goto out; 00759 } 00760 ++i; 00761 } 00762 } 00763 00764 out: 00765 00766 *child_entries = retval; 00767 return retval != NULL; 00768 } 00769 00770 static DBusHandlerResult 00771 handle_default_introspect_and_unlock (DBusObjectTree *tree, 00772 DBusMessage *message, 00773 const char **path) 00774 { 00775 DBusString xml; 00776 DBusHandlerResult result; 00777 char **children; 00778 int i; 00779 DBusMessage *reply; 00780 DBusMessageIter iter; 00781 const char *v_STRING; 00782 dbus_bool_t already_unlocked; 00783 00784 /* We have the connection lock here */ 00785 00786 already_unlocked = FALSE; 00787 00788 _dbus_verbose (" considering default Introspect() handler...\n"); 00789 00790 reply = NULL; 00791 00792 if (!dbus_message_is_method_call (message, 00793 DBUS_INTERFACE_INTROSPECTABLE, 00794 "Introspect")) 00795 { 00796 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00797 if (tree->connection) 00798 #endif 00799 { 00800 _dbus_verbose ("unlock\n"); 00801 _dbus_connection_unlock (tree->connection); 00802 } 00803 00804 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00805 } 00806 00807 _dbus_verbose (" using default Introspect() handler!\n"); 00808 00809 if (!_dbus_string_init (&xml)) 00810 { 00811 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00812 if (tree->connection) 00813 #endif 00814 { 00815 _dbus_verbose ("unlock\n"); 00816 _dbus_connection_unlock (tree->connection); 00817 } 00818 00819 return DBUS_HANDLER_RESULT_NEED_MEMORY; 00820 } 00821 00822 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 00823 00824 children = NULL; 00825 if (!_dbus_object_tree_list_registered_unlocked (tree, path, &children)) 00826 goto out; 00827 00828 if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE)) 00829 goto out; 00830 00831 if (!_dbus_string_append (&xml, "<node>\n")) 00832 goto out; 00833 00834 i = 0; 00835 while (children[i] != NULL) 00836 { 00837 if (!_dbus_string_append_printf (&xml, " <node name=\"%s\"/>\n", 00838 children[i])) 00839 goto out; 00840 00841 ++i; 00842 } 00843 00844 if (!_dbus_string_append (&xml, "</node>\n")) 00845 goto out; 00846 00847 reply = dbus_message_new_method_return (message); 00848 if (reply == NULL) 00849 goto out; 00850 00851 dbus_message_iter_init_append (reply, &iter); 00852 v_STRING = _dbus_string_get_const_data (&xml); 00853 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &v_STRING)) 00854 goto out; 00855 00856 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00857 if (tree->connection) 00858 #endif 00859 { 00860 already_unlocked = TRUE; 00861 00862 if (!_dbus_connection_send_and_unlock (tree->connection, reply, NULL)) 00863 goto out; 00864 } 00865 00866 result = DBUS_HANDLER_RESULT_HANDLED; 00867 00868 out: 00869 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00870 if (tree->connection) 00871 #endif 00872 { 00873 if (!already_unlocked) 00874 { 00875 _dbus_verbose ("unlock\n"); 00876 _dbus_connection_unlock (tree->connection); 00877 } 00878 } 00879 00880 _dbus_string_free (&xml); 00881 dbus_free_string_array (children); 00882 if (reply) 00883 dbus_message_unref (reply); 00884 00885 return result; 00886 } 00887 00902 DBusHandlerResult 00903 _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree, 00904 DBusMessage *message, 00905 dbus_bool_t *found_object) 00906 { 00907 char **path; 00908 dbus_bool_t exact_match; 00909 DBusList *list; 00910 DBusList *link; 00911 DBusHandlerResult result; 00912 DBusObjectSubtree *subtree; 00913 00914 #if 0 00915 _dbus_verbose ("Dispatch of message by object path\n"); 00916 #endif 00917 00918 path = NULL; 00919 if (!dbus_message_get_path_decomposed (message, &path)) 00920 { 00921 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00922 if (tree->connection) 00923 #endif 00924 { 00925 _dbus_verbose ("unlock\n"); 00926 _dbus_connection_unlock (tree->connection); 00927 } 00928 00929 _dbus_verbose ("No memory to get decomposed path\n"); 00930 00931 return DBUS_HANDLER_RESULT_NEED_MEMORY; 00932 } 00933 00934 if (path == NULL) 00935 { 00936 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00937 if (tree->connection) 00938 #endif 00939 { 00940 _dbus_verbose ("unlock\n"); 00941 _dbus_connection_unlock (tree->connection); 00942 } 00943 00944 _dbus_verbose ("No path field in message\n"); 00945 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00946 } 00947 00948 /* Find the deepest path that covers the path in the message */ 00949 subtree = find_handler (tree, (const char**) path, &exact_match); 00950 00951 if (found_object) 00952 *found_object = !!subtree; 00953 00954 /* Build a list of all paths that cover the path in the message */ 00955 00956 list = NULL; 00957 00958 while (subtree != NULL) 00959 { 00960 if (subtree->message_function != NULL && (exact_match || subtree->invoke_as_fallback)) 00961 { 00962 _dbus_object_subtree_ref (subtree); 00963 00964 /* run deepest paths first */ 00965 if (!_dbus_list_append (&list, subtree)) 00966 { 00967 result = DBUS_HANDLER_RESULT_NEED_MEMORY; 00968 _dbus_object_subtree_unref (subtree); 00969 goto free_and_return; 00970 } 00971 } 00972 00973 exact_match = FALSE; 00974 subtree = subtree->parent; 00975 } 00976 00977 _dbus_verbose ("%d handlers in the path tree for this message\n", 00978 _dbus_list_get_length (&list)); 00979 00980 /* Invoke each handler in the list */ 00981 00982 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 00983 00984 link = _dbus_list_get_first_link (&list); 00985 while (link != NULL) 00986 { 00987 DBusList *next = _dbus_list_get_next_link (&list, link); 00988 subtree = link->data; 00989 00990 /* message_function is NULL if we're unregistered 00991 * due to reentrancy 00992 */ 00993 if (subtree->message_function) 00994 { 00995 DBusObjectPathMessageFunction message_function; 00996 void *user_data; 00997 00998 message_function = subtree->message_function; 00999 user_data = subtree->user_data; 01000 01001 #if 0 01002 _dbus_verbose (" (invoking a handler)\n"); 01003 #endif 01004 01005 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 01006 if (tree->connection) 01007 #endif 01008 { 01009 _dbus_verbose ("unlock\n"); 01010 _dbus_connection_unlock (tree->connection); 01011 } 01012 01013 /* FIXME you could unregister the subtree in another thread 01014 * before we invoke the callback, and I can't figure out a 01015 * good way to solve this. 01016 */ 01017 01018 result = (* message_function) (tree->connection, 01019 message, 01020 user_data); 01021 01022 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 01023 if (tree->connection) 01024 #endif 01025 _dbus_connection_lock (tree->connection); 01026 01027 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 01028 goto free_and_return; 01029 } 01030 01031 link = next; 01032 } 01033 01034 free_and_return: 01035 01036 if (result == DBUS_HANDLER_RESULT_NOT_YET_HANDLED) 01037 { 01038 /* This hardcoded default handler does a minimal Introspect() 01039 */ 01040 result = handle_default_introspect_and_unlock (tree, message, 01041 (const char**) path); 01042 } 01043 else 01044 { 01045 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 01046 if (tree->connection) 01047 #endif 01048 { 01049 _dbus_verbose ("unlock\n"); 01050 _dbus_connection_unlock (tree->connection); 01051 } 01052 } 01053 01054 while (list != NULL) 01055 { 01056 link = _dbus_list_get_first_link (&list); 01057 _dbus_object_subtree_unref (link->data); 01058 _dbus_list_remove_link (&list, link); 01059 } 01060 01061 dbus_free_string_array (path); 01062 01063 return result; 01064 } 01065 01074 void* 01075 _dbus_object_tree_get_user_data_unlocked (DBusObjectTree *tree, 01076 const char **path) 01077 { 01078 dbus_bool_t exact_match; 01079 DBusObjectSubtree *subtree; 01080 01081 _dbus_assert (tree != NULL); 01082 _dbus_assert (path != NULL); 01083 01084 /* Find the deepest path that covers the path in the message */ 01085 subtree = find_handler (tree, (const char**) path, &exact_match); 01086 01087 if ((subtree == NULL) || !exact_match) 01088 { 01089 _dbus_verbose ("No object at specified path found\n"); 01090 return NULL; 01091 } 01092 01093 return subtree->user_data; 01094 } 01095 01102 static DBusObjectSubtree* 01103 allocate_subtree_object (const char *name) 01104 { 01105 int len; 01106 DBusObjectSubtree *subtree; 01107 const size_t front_padding = _DBUS_STRUCT_OFFSET (DBusObjectSubtree, name); 01108 01109 _dbus_assert (name != NULL); 01110 01111 len = strlen (name); 01112 01113 subtree = dbus_malloc0 (MAX (front_padding + (len + 1), sizeof (DBusObjectSubtree))); 01114 01115 if (subtree == NULL) 01116 return NULL; 01117 01118 memcpy (subtree->name, name, len + 1); 01119 01120 return subtree; 01121 } 01122 01123 static DBusObjectSubtree* 01124 _dbus_object_subtree_new (const char *name, 01125 const DBusObjectPathVTable *vtable, 01126 void *user_data) 01127 { 01128 DBusObjectSubtree *subtree; 01129 01130 subtree = allocate_subtree_object (name); 01131 if (subtree == NULL) 01132 goto oom; 01133 01134 _dbus_assert (name != NULL); 01135 01136 subtree->parent = NULL; 01137 01138 if (vtable) 01139 { 01140 subtree->message_function = vtable->message_function; 01141 subtree->unregister_function = vtable->unregister_function; 01142 } 01143 else 01144 { 01145 subtree->message_function = NULL; 01146 subtree->unregister_function = NULL; 01147 } 01148 01149 subtree->user_data = user_data; 01150 _dbus_atomic_inc (&subtree->refcount); 01151 subtree->subtrees = NULL; 01152 subtree->n_subtrees = 0; 01153 subtree->max_subtrees = 0; 01154 subtree->invoke_as_fallback = FALSE; 01155 01156 return subtree; 01157 01158 oom: 01159 return NULL; 01160 } 01161 01162 static DBusObjectSubtree * 01163 _dbus_object_subtree_ref (DBusObjectSubtree *subtree) 01164 { 01165 #ifdef DBUS_DISABLE_ASSERT 01166 _dbus_atomic_inc (&subtree->refcount); 01167 #else 01168 dbus_int32_t old_value; 01169 01170 old_value = _dbus_atomic_inc (&subtree->refcount); 01171 _dbus_assert (old_value > 0); 01172 #endif 01173 01174 return subtree; 01175 } 01176 01177 static void 01178 _dbus_object_subtree_unref (DBusObjectSubtree *subtree) 01179 { 01180 dbus_int32_t old_value; 01181 01182 old_value = _dbus_atomic_dec (&subtree->refcount); 01183 _dbus_assert (old_value > 0); 01184 01185 if (old_value == 1) 01186 { 01187 _dbus_assert (subtree->unregister_function == NULL); 01188 _dbus_assert (subtree->message_function == NULL); 01189 01190 dbus_free (subtree->subtrees); 01191 dbus_free (subtree); 01192 } 01193 } 01194 01205 dbus_bool_t 01206 _dbus_object_tree_list_registered_and_unlock (DBusObjectTree *tree, 01207 const char **parent_path, 01208 char ***child_entries) 01209 { 01210 dbus_bool_t result; 01211 01212 result = _dbus_object_tree_list_registered_unlocked (tree, 01213 parent_path, 01214 child_entries); 01215 01216 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 01217 if (tree->connection) 01218 #endif 01219 { 01220 _dbus_verbose ("unlock\n"); 01221 _dbus_connection_unlock (tree->connection); 01222 } 01223 01224 return result; 01225 } 01226 01227 01229 #define VERBOSE_DECOMPOSE 0 01230 01241 dbus_bool_t 01242 _dbus_decompose_path (const char* data, 01243 int len, 01244 char ***path, 01245 int *path_len) 01246 { 01247 char **retval; 01248 int n_components; 01249 int i, j, comp; 01250 01251 _dbus_assert (data != NULL); 01252 _dbus_assert (path != NULL); 01253 01254 #if VERBOSE_DECOMPOSE 01255 _dbus_verbose ("Decomposing path \"%s\"\n", 01256 data); 01257 #endif 01258 01259 n_components = 0; 01260 if (len > 1) /* if path is not just "/" */ 01261 { 01262 i = 0; 01263 while (i < len) 01264 { 01265 _dbus_assert (data[i] != '\0'); 01266 if (data[i] == '/') 01267 n_components += 1; 01268 ++i; 01269 } 01270 } 01271 01272 retval = dbus_new0 (char*, n_components + 1); 01273 01274 if (retval == NULL) 01275 return FALSE; 01276 01277 comp = 0; 01278 if (n_components == 0) 01279 i = 1; 01280 else 01281 i = 0; 01282 while (comp < n_components) 01283 { 01284 _dbus_assert (i < len); 01285 01286 if (data[i] == '/') 01287 ++i; 01288 j = i; 01289 01290 while (j < len && data[j] != '/') 01291 ++j; 01292 01293 /* Now [i, j) is the path component */ 01294 _dbus_assert (i < j); 01295 _dbus_assert (data[i] != '/'); 01296 _dbus_assert (j == len || data[j] == '/'); 01297 01298 #if VERBOSE_DECOMPOSE 01299 _dbus_verbose (" (component in [%d,%d))\n", 01300 i, j); 01301 #endif 01302 01303 retval[comp] = _dbus_memdup (&data[i], j - i + 1); 01304 if (retval[comp] == NULL) 01305 { 01306 dbus_free_string_array (retval); 01307 return FALSE; 01308 } 01309 retval[comp][j-i] = '\0'; 01310 #if VERBOSE_DECOMPOSE 01311 _dbus_verbose (" (component %d = \"%s\")\n", 01312 comp, retval[comp]); 01313 #endif 01314 01315 ++comp; 01316 i = j; 01317 } 01318 _dbus_assert (i == len); 01319 01320 *path = retval; 01321 if (path_len) 01322 *path_len = n_components; 01323 01324 return TRUE; 01325 } 01326 01329 static char* 01330 flatten_path (const char **path) 01331 { 01332 DBusString str; 01333 char *s; 01334 01335 if (!_dbus_string_init (&str)) 01336 return NULL; 01337 01338 if (path[0] == NULL) 01339 { 01340 if (!_dbus_string_append_byte (&str, '/')) 01341 goto nomem; 01342 } 01343 else 01344 { 01345 int i; 01346 01347 i = 0; 01348 while (path[i]) 01349 { 01350 if (!_dbus_string_append_byte (&str, '/')) 01351 goto nomem; 01352 01353 if (!_dbus_string_append (&str, path[i])) 01354 goto nomem; 01355 01356 ++i; 01357 } 01358 } 01359 01360 if (!_dbus_string_steal_data (&str, &s)) 01361 goto nomem; 01362 01363 _dbus_string_free (&str); 01364 01365 return s; 01366 01367 nomem: 01368 _dbus_string_free (&str); 01369 return NULL; 01370 } 01371 01372 01373 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 01374 01375 #ifndef DOXYGEN_SHOULD_SKIP_THIS 01376 01377 #include "dbus-test.h" 01378 #include <stdio.h> 01379 01380 typedef enum 01381 { 01382 STR_EQUAL, 01383 STR_PREFIX, 01384 STR_DIFFERENT 01385 } StrComparison; 01386 01387 /* Returns TRUE if container is a parent of child 01388 */ 01389 static StrComparison 01390 path_contains (const char **container, 01391 const char **child) 01392 { 01393 int i; 01394 01395 i = 0; 01396 while (child[i] != NULL) 01397 { 01398 int v; 01399 01400 if (container[i] == NULL) 01401 return STR_PREFIX; /* container ran out, child continues; 01402 * thus the container is a parent of the 01403 * child. 01404 */ 01405 01406 _dbus_assert (container[i] != NULL); 01407 _dbus_assert (child[i] != NULL); 01408 01409 v = strcmp (container[i], child[i]); 01410 01411 if (v != 0) 01412 return STR_DIFFERENT; /* they overlap until here and then are different, 01413 * not overlapping 01414 */ 01415 01416 ++i; 01417 } 01418 01419 /* Child ran out; if container also did, they are equal; 01420 * otherwise, the child is a parent of the container. 01421 */ 01422 if (container[i] == NULL) 01423 return STR_EQUAL; 01424 else 01425 return STR_DIFFERENT; 01426 } 01427 01428 #if 0 01429 static void 01430 spew_subtree_recurse (DBusObjectSubtree *subtree, 01431 int indent) 01432 { 01433 int i; 01434 01435 i = 0; 01436 while (i < indent) 01437 { 01438 _dbus_verbose (" "); 01439 ++i; 01440 } 01441 01442 _dbus_verbose ("%s (%d children)\n", 01443 subtree->name, subtree->n_subtrees); 01444 01445 i = 0; 01446 while (i < subtree->n_subtrees) 01447 { 01448 spew_subtree_recurse (subtree->subtrees[i], indent + 2); 01449 01450 ++i; 01451 } 01452 } 01453 01454 static void 01455 spew_tree (DBusObjectTree *tree) 01456 { 01457 spew_subtree_recurse (tree->root, 0); 01458 } 01459 #endif 01460 01464 typedef struct 01465 { 01466 const char **path; 01467 dbus_bool_t handler_fallback; 01468 dbus_bool_t message_handled; 01469 dbus_bool_t handler_unregistered; 01470 } TreeTestData; 01471 01472 01473 static void 01474 test_unregister_function (DBusConnection *connection, 01475 void *user_data) 01476 { 01477 TreeTestData *ttd = user_data; 01478 01479 ttd->handler_unregistered = TRUE; 01480 } 01481 01482 static DBusHandlerResult 01483 test_message_function (DBusConnection *connection, 01484 DBusMessage *message, 01485 void *user_data) 01486 { 01487 TreeTestData *ttd = user_data; 01488 01489 ttd->message_handled = TRUE; 01490 01491 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 01492 } 01493 01494 static dbus_bool_t 01495 do_register (DBusObjectTree *tree, 01496 const char **path, 01497 dbus_bool_t fallback, 01498 int i, 01499 TreeTestData *tree_test_data) 01500 { 01501 DBusObjectPathVTable vtable = { test_unregister_function, 01502 test_message_function, NULL }; 01503 01504 tree_test_data[i].message_handled = FALSE; 01505 tree_test_data[i].handler_unregistered = FALSE; 01506 tree_test_data[i].handler_fallback = fallback; 01507 tree_test_data[i].path = path; 01508 01509 if (!_dbus_object_tree_register (tree, fallback, path, 01510 &vtable, 01511 &tree_test_data[i], 01512 NULL)) 01513 return FALSE; 01514 01515 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path) == 01516 &tree_test_data[i]); 01517 01518 return TRUE; 01519 } 01520 01521 static dbus_bool_t 01522 do_test_dispatch (DBusObjectTree *tree, 01523 const char **path, 01524 int i, 01525 TreeTestData *tree_test_data, 01526 int n_test_data) 01527 { 01528 DBusMessage *message; 01529 int j; 01530 DBusHandlerResult result; 01531 char *flat; 01532 01533 message = NULL; 01534 01535 flat = flatten_path (path); 01536 if (flat == NULL) 01537 goto oom; 01538 01539 message = dbus_message_new_method_call (NULL, 01540 flat, 01541 "org.freedesktop.TestInterface", 01542 "Foo"); 01543 dbus_free (flat); 01544 if (message == NULL) 01545 goto oom; 01546 01547 j = 0; 01548 while (j < n_test_data) 01549 { 01550 tree_test_data[j].message_handled = FALSE; 01551 ++j; 01552 } 01553 01554 result = _dbus_object_tree_dispatch_and_unlock (tree, message, NULL); 01555 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) 01556 goto oom; 01557 01558 _dbus_assert (tree_test_data[i].message_handled); 01559 01560 j = 0; 01561 while (j < n_test_data) 01562 { 01563 if (tree_test_data[j].message_handled) 01564 { 01565 if (tree_test_data[j].handler_fallback) 01566 _dbus_assert (path_contains (tree_test_data[j].path, 01567 path) != STR_DIFFERENT); 01568 else 01569 _dbus_assert (path_contains (tree_test_data[j].path, path) == STR_EQUAL); 01570 } 01571 else 01572 { 01573 if (tree_test_data[j].handler_fallback) 01574 _dbus_assert (path_contains (tree_test_data[j].path, 01575 path) == STR_DIFFERENT); 01576 else 01577 _dbus_assert (path_contains (tree_test_data[j].path, path) != STR_EQUAL); 01578 } 01579 01580 ++j; 01581 } 01582 01583 dbus_message_unref (message); 01584 01585 return TRUE; 01586 01587 oom: 01588 if (message) 01589 dbus_message_unref (message); 01590 return FALSE; 01591 } 01592 01593 static size_t 01594 string_array_length (const char **array) 01595 { 01596 size_t i; 01597 for (i = 0; array[i]; i++) ; 01598 return i; 01599 } 01600 01601 typedef struct 01602 { 01603 const char *path; 01604 const char *result[20]; 01605 } DecomposePathTest; 01606 01607 static DecomposePathTest decompose_tests[] = { 01608 { "/foo", { "foo", NULL } }, 01609 { "/foo/bar", { "foo", "bar", NULL } }, 01610 { "/", { NULL } }, 01611 { "/a/b", { "a", "b", NULL } }, 01612 { "/a/b/c", { "a", "b", "c", NULL } }, 01613 { "/a/b/c/d", { "a", "b", "c", "d", NULL } }, 01614 { "/foo/bar/q", { "foo", "bar", "q", NULL } }, 01615 { "/foo/bar/this/is/longer", { "foo", "bar", "this", "is", "longer", NULL } } 01616 }; 01617 01618 static dbus_bool_t 01619 run_decompose_tests (void) 01620 { 01621 int i; 01622 01623 i = 0; 01624 while (i < _DBUS_N_ELEMENTS (decompose_tests)) 01625 { 01626 char **result; 01627 int result_len; 01628 int expected_len; 01629 01630 if (!_dbus_decompose_path (decompose_tests[i].path, 01631 strlen (decompose_tests[i].path), 01632 &result, &result_len)) 01633 return FALSE; 01634 01635 expected_len = string_array_length (decompose_tests[i].result); 01636 01637 if (result_len != (int) string_array_length ((const char**)result) || 01638 expected_len != result_len || 01639 path_contains (decompose_tests[i].result, 01640 (const char**) result) != STR_EQUAL) 01641 { 01642 int real_len = string_array_length ((const char**)result); 01643 _dbus_warn ("Expected decompose of %s to have len %d, returned %d, appears to have %d\n", 01644 decompose_tests[i].path, expected_len, result_len, 01645 real_len); 01646 _dbus_warn ("Decompose resulted in elements: { "); 01647 i = 0; 01648 while (i < real_len) 01649 { 01650 _dbus_warn ("\"%s\"%s", result[i], 01651 (i + 1) == real_len ? "" : ", "); 01652 ++i; 01653 } 01654 _dbus_warn ("}\n"); 01655 _dbus_assert_not_reached ("path decompose failed\n"); 01656 } 01657 01658 dbus_free_string_array (result); 01659 01660 ++i; 01661 } 01662 01663 return TRUE; 01664 } 01665 01666 static DBusObjectSubtree* 01667 find_subtree_registered_or_unregistered (DBusObjectTree *tree, 01668 const char **path) 01669 { 01670 #if VERBOSE_FIND 01671 _dbus_verbose ("Looking for exact subtree, registered or unregistered\n"); 01672 #endif 01673 01674 return find_subtree_recurse (tree->root, path, FALSE, NULL, NULL); 01675 } 01676 01677 static dbus_bool_t 01678 object_tree_test_iteration (void *data) 01679 { 01680 const char *path0[] = { NULL }; 01681 const char *path1[] = { "foo", NULL }; 01682 const char *path2[] = { "foo", "bar", NULL }; 01683 const char *path3[] = { "foo", "bar", "baz", NULL }; 01684 const char *path4[] = { "foo", "bar", "boo", NULL }; 01685 const char *path5[] = { "blah", NULL }; 01686 const char *path6[] = { "blah", "boof", NULL }; 01687 const char *path7[] = { "blah", "boof", "this", "is", "really", "long", NULL }; 01688 const char *path8[] = { "childless", NULL }; 01689 const char *path9[] = { "blah", "a", NULL }; 01690 const char *path10[] = { "blah", "b", NULL }; 01691 const char *path11[] = { "blah", "c", NULL }; 01692 const char *path12[] = { "blah", "a", "d", NULL }; 01693 const char *path13[] = { "blah", "b", "d", NULL }; 01694 const char *path14[] = { "blah", "c", "d", NULL }; 01695 DBusObjectPathVTable test_vtable = { NULL, test_message_function, NULL }; 01696 DBusObjectTree *tree; 01697 TreeTestData tree_test_data[9]; 01698 int i; 01699 dbus_bool_t exact_match; 01700 01701 if (!run_decompose_tests ()) 01702 return FALSE; 01703 01704 tree = NULL; 01705 01706 tree = _dbus_object_tree_new (NULL); 01707 if (tree == NULL) 01708 goto out; 01709 01710 if (!do_register (tree, path0, TRUE, 0, tree_test_data)) 01711 goto out; 01712 01713 _dbus_assert (find_subtree (tree, path0, NULL)); 01714 _dbus_assert (!find_subtree (tree, path1, NULL)); 01715 _dbus_assert (!find_subtree (tree, path2, NULL)); 01716 _dbus_assert (!find_subtree (tree, path3, NULL)); 01717 _dbus_assert (!find_subtree (tree, path4, NULL)); 01718 _dbus_assert (!find_subtree (tree, path5, NULL)); 01719 _dbus_assert (!find_subtree (tree, path6, NULL)); 01720 _dbus_assert (!find_subtree (tree, path7, NULL)); 01721 _dbus_assert (!find_subtree (tree, path8, NULL)); 01722 01723 _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match); 01724 _dbus_assert (find_handler (tree, path1, &exact_match) == tree->root && !exact_match); 01725 _dbus_assert (find_handler (tree, path2, &exact_match) == tree->root && !exact_match); 01726 _dbus_assert (find_handler (tree, path3, &exact_match) == tree->root && !exact_match); 01727 _dbus_assert (find_handler (tree, path4, &exact_match) == tree->root && !exact_match); 01728 _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match); 01729 _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match); 01730 _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match); 01731 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match); 01732 01733 if (!do_register (tree, path1, TRUE, 1, tree_test_data)) 01734 goto out; 01735 01736 _dbus_assert (find_subtree (tree, path0, NULL)); 01737 _dbus_assert (find_subtree (tree, path1, NULL)); 01738 _dbus_assert (!find_subtree (tree, path2, NULL)); 01739 _dbus_assert (!find_subtree (tree, path3, NULL)); 01740 _dbus_assert (!find_subtree (tree, path4, NULL)); 01741 _dbus_assert (!find_subtree (tree, path5, NULL)); 01742 _dbus_assert (!find_subtree (tree, path6, NULL)); 01743 _dbus_assert (!find_subtree (tree, path7, NULL)); 01744 _dbus_assert (!find_subtree (tree, path8, NULL)); 01745 01746 _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match); 01747 _dbus_assert (find_handler (tree, path1, &exact_match) && exact_match); 01748 _dbus_assert (find_handler (tree, path2, &exact_match) && !exact_match); 01749 _dbus_assert (find_handler (tree, path3, &exact_match) && !exact_match); 01750 _dbus_assert (find_handler (tree, path4, &exact_match) && !exact_match); 01751 _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match); 01752 _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match); 01753 _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match); 01754 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match); 01755 01756 if (!do_register (tree, path2, TRUE, 2, tree_test_data)) 01757 goto out; 01758 01759 _dbus_assert (find_subtree (tree, path1, NULL)); 01760 _dbus_assert (find_subtree (tree, path2, NULL)); 01761 _dbus_assert (!find_subtree (tree, path3, NULL)); 01762 _dbus_assert (!find_subtree (tree, path4, NULL)); 01763 _dbus_assert (!find_subtree (tree, path5, NULL)); 01764 _dbus_assert (!find_subtree (tree, path6, NULL)); 01765 _dbus_assert (!find_subtree (tree, path7, NULL)); 01766 _dbus_assert (!find_subtree (tree, path8, NULL)); 01767 01768 if (!do_register (tree, path3, TRUE, 3, tree_test_data)) 01769 goto out; 01770 01771 _dbus_assert (find_subtree (tree, path0, NULL)); 01772 _dbus_assert (find_subtree (tree, path1, NULL)); 01773 _dbus_assert (find_subtree (tree, path2, NULL)); 01774 _dbus_assert (find_subtree (tree, path3, NULL)); 01775 _dbus_assert (!find_subtree (tree, path4, NULL)); 01776 _dbus_assert (!find_subtree (tree, path5, NULL)); 01777 _dbus_assert (!find_subtree (tree, path6, NULL)); 01778 _dbus_assert (!find_subtree (tree, path7, NULL)); 01779 _dbus_assert (!find_subtree (tree, path8, NULL)); 01780 01781 if (!do_register (tree, path4, TRUE, 4, tree_test_data)) 01782 goto out; 01783 01784 _dbus_assert (find_subtree (tree, path0, NULL)); 01785 _dbus_assert (find_subtree (tree, path1, NULL)); 01786 _dbus_assert (find_subtree (tree, path2, NULL)); 01787 _dbus_assert (find_subtree (tree, path3, NULL)); 01788 _dbus_assert (find_subtree (tree, path4, NULL)); 01789 _dbus_assert (!find_subtree (tree, path5, NULL)); 01790 _dbus_assert (!find_subtree (tree, path6, NULL)); 01791 _dbus_assert (!find_subtree (tree, path7, NULL)); 01792 _dbus_assert (!find_subtree (tree, path8, NULL)); 01793 01794 if (!do_register (tree, path5, TRUE, 5, tree_test_data)) 01795 goto out; 01796 01797 _dbus_assert (find_subtree (tree, path0, NULL)); 01798 _dbus_assert (find_subtree (tree, path1, NULL)); 01799 _dbus_assert (find_subtree (tree, path2, NULL)); 01800 _dbus_assert (find_subtree (tree, path3, NULL)); 01801 _dbus_assert (find_subtree (tree, path4, NULL)); 01802 _dbus_assert (find_subtree (tree, path5, NULL)); 01803 _dbus_assert (!find_subtree (tree, path6, NULL)); 01804 _dbus_assert (!find_subtree (tree, path7, NULL)); 01805 _dbus_assert (!find_subtree (tree, path8, NULL)); 01806 01807 _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root && exact_match); 01808 _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match); 01809 _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match); 01810 _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match); 01811 _dbus_assert (find_handler (tree, path4, &exact_match) != tree->root && exact_match); 01812 _dbus_assert (find_handler (tree, path5, &exact_match) != tree->root && exact_match); 01813 _dbus_assert (find_handler (tree, path6, &exact_match) != tree->root && !exact_match); 01814 _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && !exact_match); 01815 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match); 01816 01817 if (!do_register (tree, path6, TRUE, 6, tree_test_data)) 01818 goto out; 01819 01820 _dbus_assert (find_subtree (tree, path0, NULL)); 01821 _dbus_assert (find_subtree (tree, path1, NULL)); 01822 _dbus_assert (find_subtree (tree, path2, NULL)); 01823 _dbus_assert (find_subtree (tree, path3, NULL)); 01824 _dbus_assert (find_subtree (tree, path4, NULL)); 01825 _dbus_assert (find_subtree (tree, path5, NULL)); 01826 _dbus_assert (find_subtree (tree, path6, NULL)); 01827 _dbus_assert (!find_subtree (tree, path7, NULL)); 01828 _dbus_assert (!find_subtree (tree, path8, NULL)); 01829 01830 if (!do_register (tree, path7, TRUE, 7, tree_test_data)) 01831 goto out; 01832 01833 _dbus_assert (find_subtree (tree, path0, NULL)); 01834 _dbus_assert (find_subtree (tree, path1, NULL)); 01835 _dbus_assert (find_subtree (tree, path2, NULL)); 01836 _dbus_assert (find_subtree (tree, path3, NULL)); 01837 _dbus_assert (find_subtree (tree, path4, NULL)); 01838 _dbus_assert (find_subtree (tree, path5, NULL)); 01839 _dbus_assert (find_subtree (tree, path6, NULL)); 01840 _dbus_assert (find_subtree (tree, path7, NULL)); 01841 _dbus_assert (!find_subtree (tree, path8, NULL)); 01842 01843 if (!do_register (tree, path8, TRUE, 8, tree_test_data)) 01844 goto out; 01845 01846 _dbus_assert (find_subtree (tree, path0, NULL)); 01847 _dbus_assert (find_subtree (tree, path1, NULL)); 01848 _dbus_assert (find_subtree (tree, path2, NULL)); 01849 _dbus_assert (find_subtree (tree, path3, NULL)); 01850 _dbus_assert (find_subtree (tree, path4, NULL)); 01851 _dbus_assert (find_subtree (tree, path5, NULL)); 01852 _dbus_assert (find_subtree (tree, path6, NULL)); 01853 _dbus_assert (find_subtree (tree, path7, NULL)); 01854 _dbus_assert (find_subtree (tree, path8, NULL)); 01855 01856 _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root && exact_match); 01857 _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match); 01858 _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match); 01859 _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match); 01860 _dbus_assert (find_handler (tree, path4, &exact_match) != tree->root && exact_match); 01861 _dbus_assert (find_handler (tree, path5, &exact_match) != tree->root && exact_match); 01862 _dbus_assert (find_handler (tree, path6, &exact_match) != tree->root && exact_match); 01863 _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && exact_match); 01864 _dbus_assert (find_handler (tree, path8, &exact_match) != tree->root && exact_match); 01865 01866 /* test the list_registered function */ 01867 01868 { 01869 const char *root[] = { NULL }; 01870 char **child_entries; 01871 int nb; 01872 01873 _dbus_object_tree_list_registered_unlocked (tree, path1, &child_entries); 01874 if (child_entries != NULL) 01875 { 01876 nb = string_array_length ((const char**)child_entries); 01877 _dbus_assert (nb == 1); 01878 dbus_free_string_array (child_entries); 01879 } 01880 01881 _dbus_object_tree_list_registered_unlocked (tree, path2, &child_entries); 01882 if (child_entries != NULL) 01883 { 01884 nb = string_array_length ((const char**)child_entries); 01885 _dbus_assert (nb == 2); 01886 dbus_free_string_array (child_entries); 01887 } 01888 01889 _dbus_object_tree_list_registered_unlocked (tree, path8, &child_entries); 01890 if (child_entries != NULL) 01891 { 01892 nb = string_array_length ((const char**)child_entries); 01893 _dbus_assert (nb == 0); 01894 dbus_free_string_array (child_entries); 01895 } 01896 01897 _dbus_object_tree_list_registered_unlocked (tree, root, &child_entries); 01898 if (child_entries != NULL) 01899 { 01900 nb = string_array_length ((const char**)child_entries); 01901 _dbus_assert (nb == 3); 01902 dbus_free_string_array (child_entries); 01903 } 01904 } 01905 01906 /* Check that destroying tree calls unregister funcs */ 01907 _dbus_object_tree_unref (tree); 01908 01909 i = 0; 01910 while (i < (int) _DBUS_N_ELEMENTS (tree_test_data)) 01911 { 01912 _dbus_assert (tree_test_data[i].handler_unregistered); 01913 _dbus_assert (!tree_test_data[i].message_handled); 01914 ++i; 01915 } 01916 01917 /* Now start again and try the individual unregister function */ 01918 tree = _dbus_object_tree_new (NULL); 01919 if (tree == NULL) 01920 goto out; 01921 01922 if (!do_register (tree, path0, TRUE, 0, tree_test_data)) 01923 goto out; 01924 if (!do_register (tree, path1, TRUE, 1, tree_test_data)) 01925 goto out; 01926 if (!do_register (tree, path2, TRUE, 2, tree_test_data)) 01927 goto out; 01928 if (!do_register (tree, path3, TRUE, 3, tree_test_data)) 01929 goto out; 01930 if (!do_register (tree, path4, TRUE, 4, tree_test_data)) 01931 goto out; 01932 if (!do_register (tree, path5, TRUE, 5, tree_test_data)) 01933 goto out; 01934 if (!do_register (tree, path6, TRUE, 6, tree_test_data)) 01935 goto out; 01936 if (!do_register (tree, path7, TRUE, 7, tree_test_data)) 01937 goto out; 01938 if (!do_register (tree, path8, TRUE, 8, tree_test_data)) 01939 goto out; 01940 01941 _dbus_object_tree_unregister_and_unlock (tree, path0); 01942 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path0) == NULL); 01943 01944 _dbus_assert (!find_subtree (tree, path0, NULL)); 01945 _dbus_assert (find_subtree (tree, path1, NULL)); 01946 _dbus_assert (find_subtree (tree, path2, NULL)); 01947 _dbus_assert (find_subtree (tree, path3, NULL)); 01948 _dbus_assert (find_subtree (tree, path4, NULL)); 01949 _dbus_assert (find_subtree (tree, path5, NULL)); 01950 _dbus_assert (find_subtree (tree, path6, NULL)); 01951 _dbus_assert (find_subtree (tree, path7, NULL)); 01952 _dbus_assert (find_subtree (tree, path8, NULL)); 01953 01954 _dbus_object_tree_unregister_and_unlock (tree, path1); 01955 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path1) == NULL); 01956 01957 _dbus_assert (!find_subtree (tree, path0, NULL)); 01958 _dbus_assert (!find_subtree (tree, path1, NULL)); 01959 _dbus_assert (find_subtree (tree, path2, NULL)); 01960 _dbus_assert (find_subtree (tree, path3, NULL)); 01961 _dbus_assert (find_subtree (tree, path4, NULL)); 01962 _dbus_assert (find_subtree (tree, path5, NULL)); 01963 _dbus_assert (find_subtree (tree, path6, NULL)); 01964 _dbus_assert (find_subtree (tree, path7, NULL)); 01965 _dbus_assert (find_subtree (tree, path8, NULL)); 01966 01967 _dbus_object_tree_unregister_and_unlock (tree, path2); 01968 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path2) == NULL); 01969 01970 _dbus_assert (!find_subtree (tree, path0, NULL)); 01971 _dbus_assert (!find_subtree (tree, path1, NULL)); 01972 _dbus_assert (!find_subtree (tree, path2, NULL)); 01973 _dbus_assert (find_subtree (tree, path3, NULL)); 01974 _dbus_assert (find_subtree (tree, path4, NULL)); 01975 _dbus_assert (find_subtree (tree, path5, NULL)); 01976 _dbus_assert (find_subtree (tree, path6, NULL)); 01977 _dbus_assert (find_subtree (tree, path7, NULL)); 01978 _dbus_assert (find_subtree (tree, path8, NULL)); 01979 01980 _dbus_object_tree_unregister_and_unlock (tree, path3); 01981 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path3) == NULL); 01982 01983 _dbus_assert (!find_subtree (tree, path0, NULL)); 01984 _dbus_assert (!find_subtree (tree, path1, NULL)); 01985 _dbus_assert (!find_subtree (tree, path2, NULL)); 01986 _dbus_assert (!find_subtree (tree, path3, NULL)); 01987 _dbus_assert (find_subtree (tree, path4, NULL)); 01988 _dbus_assert (find_subtree (tree, path5, NULL)); 01989 _dbus_assert (find_subtree (tree, path6, NULL)); 01990 _dbus_assert (find_subtree (tree, path7, NULL)); 01991 _dbus_assert (find_subtree (tree, path8, NULL)); 01992 01993 _dbus_object_tree_unregister_and_unlock (tree, path4); 01994 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path4) == NULL); 01995 01996 _dbus_assert (!find_subtree (tree, path0, NULL)); 01997 _dbus_assert (!find_subtree (tree, path1, NULL)); 01998 _dbus_assert (!find_subtree (tree, path2, NULL)); 01999 _dbus_assert (!find_subtree (tree, path3, NULL)); 02000 _dbus_assert (!find_subtree (tree, path4, NULL)); 02001 _dbus_assert (find_subtree (tree, path5, NULL)); 02002 _dbus_assert (find_subtree (tree, path6, NULL)); 02003 _dbus_assert (find_subtree (tree, path7, NULL)); 02004 _dbus_assert (find_subtree (tree, path8, NULL)); 02005 02006 _dbus_object_tree_unregister_and_unlock (tree, path5); 02007 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path5) == NULL); 02008 02009 _dbus_assert (!find_subtree (tree, path0, NULL)); 02010 _dbus_assert (!find_subtree (tree, path1, NULL)); 02011 _dbus_assert (!find_subtree (tree, path2, NULL)); 02012 _dbus_assert (!find_subtree (tree, path3, NULL)); 02013 _dbus_assert (!find_subtree (tree, path4, NULL)); 02014 _dbus_assert (!find_subtree (tree, path5, NULL)); 02015 _dbus_assert (find_subtree (tree, path6, NULL)); 02016 _dbus_assert (find_subtree (tree, path7, NULL)); 02017 _dbus_assert (find_subtree (tree, path8, NULL)); 02018 02019 _dbus_object_tree_unregister_and_unlock (tree, path6); 02020 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path6) == NULL); 02021 02022 _dbus_assert (!find_subtree (tree, path0, NULL)); 02023 _dbus_assert (!find_subtree (tree, path1, NULL)); 02024 _dbus_assert (!find_subtree (tree, path2, NULL)); 02025 _dbus_assert (!find_subtree (tree, path3, NULL)); 02026 _dbus_assert (!find_subtree (tree, path4, NULL)); 02027 _dbus_assert (!find_subtree (tree, path5, NULL)); 02028 _dbus_assert (!find_subtree (tree, path6, NULL)); 02029 _dbus_assert (find_subtree (tree, path7, NULL)); 02030 _dbus_assert (find_subtree (tree, path8, NULL)); 02031 02032 _dbus_object_tree_unregister_and_unlock (tree, path7); 02033 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path7) == NULL); 02034 02035 _dbus_assert (!find_subtree (tree, path0, NULL)); 02036 _dbus_assert (!find_subtree (tree, path1, NULL)); 02037 _dbus_assert (!find_subtree (tree, path2, NULL)); 02038 _dbus_assert (!find_subtree (tree, path3, NULL)); 02039 _dbus_assert (!find_subtree (tree, path4, NULL)); 02040 _dbus_assert (!find_subtree (tree, path5, NULL)); 02041 _dbus_assert (!find_subtree (tree, path6, NULL)); 02042 _dbus_assert (!find_subtree (tree, path7, NULL)); 02043 _dbus_assert (find_subtree (tree, path8, NULL)); 02044 02045 _dbus_object_tree_unregister_and_unlock (tree, path8); 02046 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path8) == NULL); 02047 02048 _dbus_assert (!find_subtree (tree, path0, NULL)); 02049 _dbus_assert (!find_subtree (tree, path1, NULL)); 02050 _dbus_assert (!find_subtree (tree, path2, NULL)); 02051 _dbus_assert (!find_subtree (tree, path3, NULL)); 02052 _dbus_assert (!find_subtree (tree, path4, NULL)); 02053 _dbus_assert (!find_subtree (tree, path5, NULL)); 02054 _dbus_assert (!find_subtree (tree, path6, NULL)); 02055 _dbus_assert (!find_subtree (tree, path7, NULL)); 02056 _dbus_assert (!find_subtree (tree, path8, NULL)); 02057 02058 i = 0; 02059 while (i < (int) _DBUS_N_ELEMENTS (tree_test_data)) 02060 { 02061 _dbus_assert (tree_test_data[i].handler_unregistered); 02062 _dbus_assert (!tree_test_data[i].message_handled); 02063 ++i; 02064 } 02065 02066 /* Test removal of newly-childless unregistered nodes */ 02067 if (!do_register (tree, path2, TRUE, 2, tree_test_data)) 02068 goto out; 02069 02070 _dbus_object_tree_unregister_and_unlock (tree, path2); 02071 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); 02072 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); 02073 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); 02074 02075 /* Test that unregistered parents cannot be freed out from under their 02076 children */ 02077 if (!do_register (tree, path2, TRUE, 2, tree_test_data)) 02078 goto out; 02079 02080 _dbus_assert (!find_subtree (tree, path1, NULL)); 02081 _dbus_assert (find_subtree_registered_or_unregistered (tree, path1)); 02082 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); 02083 02084 #if 0 02085 /* This triggers the "Attempted to unregister path ..." warning message */ 02086 _dbus_object_tree_unregister_and_unlock (tree, path1); 02087 #endif 02088 _dbus_assert (find_subtree (tree, path2, NULL)); 02089 _dbus_assert (!find_subtree (tree, path1, NULL)); 02090 _dbus_assert (find_subtree_registered_or_unregistered (tree, path1)); 02091 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); 02092 02093 _dbus_object_tree_unregister_and_unlock (tree, path2); 02094 _dbus_assert (!find_subtree (tree, path2, NULL)); 02095 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); 02096 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); 02097 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); 02098 02099 /* Test that registered parents cannot be freed out from under their 02100 children, and that if they are unregistered before their children, they 02101 are still freed when their children are unregistered */ 02102 if (!do_register (tree, path1, TRUE, 1, tree_test_data)) 02103 goto out; 02104 if (!do_register (tree, path2, TRUE, 2, tree_test_data)) 02105 goto out; 02106 02107 _dbus_assert (find_subtree (tree, path1, NULL)); 02108 _dbus_assert (find_subtree (tree, path2, NULL)); 02109 02110 _dbus_object_tree_unregister_and_unlock (tree, path1); 02111 _dbus_assert (!find_subtree (tree, path1, NULL)); 02112 _dbus_assert (find_subtree (tree, path2, NULL)); 02113 _dbus_assert (find_subtree_registered_or_unregistered (tree, path1)); 02114 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); 02115 02116 _dbus_object_tree_unregister_and_unlock (tree, path2); 02117 _dbus_assert (!find_subtree (tree, path1, NULL)); 02118 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); 02119 _dbus_assert (!find_subtree (tree, path2, NULL)); 02120 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); 02121 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); 02122 02123 /* Test with NULL unregister_function and user_data */ 02124 if (!_dbus_object_tree_register (tree, TRUE, path2, 02125 &test_vtable, 02126 NULL, 02127 NULL)) 02128 goto out; 02129 02130 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path2) == NULL); 02131 _dbus_object_tree_unregister_and_unlock (tree, path2); 02132 _dbus_assert (!find_subtree (tree, path2, NULL)); 02133 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); 02134 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); 02135 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); 02136 02137 /* Test freeing a long path */ 02138 if (!do_register (tree, path3, TRUE, 3, tree_test_data)) 02139 goto out; 02140 02141 _dbus_object_tree_unregister_and_unlock (tree, path3); 02142 _dbus_assert (!find_subtree (tree, path3, NULL)); 02143 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3)); 02144 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); 02145 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); 02146 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0)); 02147 02148 /* Test freeing multiple children from the same path */ 02149 if (!do_register (tree, path3, TRUE, 3, tree_test_data)) 02150 goto out; 02151 if (!do_register (tree, path4, TRUE, 4, tree_test_data)) 02152 goto out; 02153 02154 _dbus_assert (find_subtree (tree, path3, NULL)); 02155 _dbus_assert (find_subtree (tree, path4, NULL)); 02156 02157 _dbus_object_tree_unregister_and_unlock (tree, path3); 02158 _dbus_assert (!find_subtree (tree, path3, NULL)); 02159 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3)); 02160 _dbus_assert (find_subtree (tree, path4, NULL)); 02161 _dbus_assert (find_subtree_registered_or_unregistered (tree, path4)); 02162 _dbus_assert (find_subtree_registered_or_unregistered (tree, path2)); 02163 _dbus_assert (find_subtree_registered_or_unregistered (tree, path1)); 02164 02165 _dbus_object_tree_unregister_and_unlock (tree, path4); 02166 _dbus_assert (!find_subtree (tree, path4, NULL)); 02167 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path4)); 02168 _dbus_assert (!find_subtree (tree, path3, NULL)); 02169 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3)); 02170 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2)); 02171 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1)); 02172 02173 /* Test subtree removal */ 02174 if (!_dbus_object_tree_register (tree, TRUE, path12, 02175 &test_vtable, 02176 NULL, 02177 NULL)) 02178 goto out; 02179 02180 _dbus_assert (find_subtree (tree, path12, NULL)); 02181 02182 if (!_dbus_object_tree_register (tree, TRUE, path13, 02183 &test_vtable, 02184 NULL, 02185 NULL)) 02186 goto out; 02187 02188 _dbus_assert (find_subtree (tree, path13, NULL)); 02189 02190 if (!_dbus_object_tree_register (tree, TRUE, path14, 02191 &test_vtable, 02192 NULL, 02193 NULL)) 02194 goto out; 02195 02196 _dbus_assert (find_subtree (tree, path14, NULL)); 02197 02198 _dbus_object_tree_unregister_and_unlock (tree, path12); 02199 02200 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path12)); 02201 _dbus_assert (find_subtree (tree, path13, NULL)); 02202 _dbus_assert (find_subtree (tree, path14, NULL)); 02203 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path9)); 02204 _dbus_assert (find_subtree_registered_or_unregistered (tree, path5)); 02205 02206 if (!_dbus_object_tree_register (tree, TRUE, path12, 02207 &test_vtable, 02208 NULL, 02209 NULL)) 02210 goto out; 02211 02212 _dbus_assert (find_subtree (tree, path12, NULL)); 02213 02214 _dbus_object_tree_unregister_and_unlock (tree, path13); 02215 02216 _dbus_assert (find_subtree (tree, path12, NULL)); 02217 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path13)); 02218 _dbus_assert (find_subtree (tree, path14, NULL)); 02219 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path10)); 02220 _dbus_assert (find_subtree_registered_or_unregistered (tree, path5)); 02221 02222 if (!_dbus_object_tree_register (tree, TRUE, path13, 02223 &test_vtable, 02224 NULL, 02225 NULL)) 02226 goto out; 02227 02228 _dbus_assert (find_subtree (tree, path13, NULL)); 02229 02230 _dbus_object_tree_unregister_and_unlock (tree, path14); 02231 02232 _dbus_assert (find_subtree (tree, path12, NULL)); 02233 _dbus_assert (find_subtree (tree, path13, NULL)); 02234 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path14)); 02235 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path11)); 02236 _dbus_assert (find_subtree_registered_or_unregistered (tree, path5)); 02237 02238 _dbus_object_tree_unregister_and_unlock (tree, path12); 02239 02240 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path12)); 02241 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path9)); 02242 _dbus_assert (find_subtree_registered_or_unregistered (tree, path5)); 02243 02244 _dbus_object_tree_unregister_and_unlock (tree, path13); 02245 02246 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path13)); 02247 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path10)); 02248 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path5)); 02249 02250 #if 0 02251 /* Test attempting to unregister non-existent paths. These trigger 02252 "Attempted to unregister path ..." warning messages */ 02253 _dbus_object_tree_unregister_and_unlock (tree, path0); 02254 _dbus_object_tree_unregister_and_unlock (tree, path1); 02255 _dbus_object_tree_unregister_and_unlock (tree, path2); 02256 _dbus_object_tree_unregister_and_unlock (tree, path3); 02257 _dbus_object_tree_unregister_and_unlock (tree, path4); 02258 #endif 02259 02260 /* Register it all again, and test dispatch */ 02261 02262 if (!do_register (tree, path0, TRUE, 0, tree_test_data)) 02263 goto out; 02264 if (!do_register (tree, path1, FALSE, 1, tree_test_data)) 02265 goto out; 02266 if (!do_register (tree, path2, TRUE, 2, tree_test_data)) 02267 goto out; 02268 if (!do_register (tree, path3, TRUE, 3, tree_test_data)) 02269 goto out; 02270 if (!do_register (tree, path4, TRUE, 4, tree_test_data)) 02271 goto out; 02272 if (!do_register (tree, path5, TRUE, 5, tree_test_data)) 02273 goto out; 02274 if (!do_register (tree, path6, FALSE, 6, tree_test_data)) 02275 goto out; 02276 if (!do_register (tree, path7, TRUE, 7, tree_test_data)) 02277 goto out; 02278 if (!do_register (tree, path8, TRUE, 8, tree_test_data)) 02279 goto out; 02280 02281 #if 0 02282 spew_tree (tree); 02283 #endif 02284 02285 if (!do_test_dispatch (tree, path0, 0, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 02286 goto out; 02287 if (!do_test_dispatch (tree, path1, 1, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 02288 goto out; 02289 if (!do_test_dispatch (tree, path2, 2, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 02290 goto out; 02291 if (!do_test_dispatch (tree, path3, 3, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 02292 goto out; 02293 if (!do_test_dispatch (tree, path4, 4, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 02294 goto out; 02295 if (!do_test_dispatch (tree, path5, 5, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 02296 goto out; 02297 if (!do_test_dispatch (tree, path6, 6, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 02298 goto out; 02299 if (!do_test_dispatch (tree, path7, 7, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 02300 goto out; 02301 if (!do_test_dispatch (tree, path8, 8, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data))) 02302 goto out; 02303 02304 out: 02305 if (tree) 02306 { 02307 /* test ref */ 02308 _dbus_object_tree_ref (tree); 02309 _dbus_object_tree_unref (tree); 02310 _dbus_object_tree_unref (tree); 02311 } 02312 02313 return TRUE; 02314 } 02315 02321 dbus_bool_t 02322 _dbus_object_tree_test (void) 02323 { 02324 _dbus_test_oom_handling ("object tree", 02325 object_tree_test_iteration, 02326 NULL); 02327 02328 return TRUE; 02329 } 02330 02331 #endif /* !DOXYGEN_SHOULD_SKIP_THIS */ 02332 02333 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
1.7.6.1