00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00097
00098
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
00292
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 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00323 static DBusObjectSubtree*
00324 find_subtree (DBusObjectTree *tree,
00325 const char **path,
00326 int *index_in_parent)
00327 {
00328 DBusObjectSubtree *subtree;
00329
00330 #if VERBOSE_FIND
00331 _dbus_verbose ("Looking for exact registered subtree\n");
00332 #endif
00333
00334 subtree = find_subtree_recurse (tree->root, path, FALSE, index_in_parent, NULL);
00335
00336 if (subtree && subtree->message_function == NULL)
00337 return NULL;
00338 else
00339 return subtree;
00340 }
00341 #endif
00342
00343 static DBusObjectSubtree*
00344 lookup_subtree (DBusObjectTree *tree,
00345 const char **path)
00346 {
00347 #if VERBOSE_FIND
00348 _dbus_verbose ("Looking for subtree\n");
00349 #endif
00350 return find_subtree_recurse (tree->root, path, FALSE, NULL, NULL);
00351 }
00352
00353 static DBusObjectSubtree*
00354 find_handler (DBusObjectTree *tree,
00355 const char **path,
00356 dbus_bool_t *exact_match)
00357 {
00358 #if VERBOSE_FIND
00359 _dbus_verbose ("Looking for deepest handler\n");
00360 #endif
00361 _dbus_assert (exact_match != NULL);
00362
00363 *exact_match = FALSE;
00364
00365 return find_subtree_recurse (tree->root, path, FALSE, NULL, exact_match);
00366 }
00367
00368 static DBusObjectSubtree*
00369 ensure_subtree (DBusObjectTree *tree,
00370 const char **path)
00371 {
00372 #if VERBOSE_FIND
00373 _dbus_verbose ("Ensuring subtree\n");
00374 #endif
00375 return find_subtree_recurse (tree->root, path, TRUE, NULL, NULL);
00376 }
00377
00378 static char *flatten_path (const char **path);
00379
00392 dbus_bool_t
00393 _dbus_object_tree_register (DBusObjectTree *tree,
00394 dbus_bool_t fallback,
00395 const char **path,
00396 const DBusObjectPathVTable *vtable,
00397 void *user_data,
00398 DBusError *error)
00399 {
00400 DBusObjectSubtree *subtree;
00401
00402 _dbus_assert (tree != NULL);
00403 _dbus_assert (vtable->message_function != NULL);
00404 _dbus_assert (path != NULL);
00405
00406 subtree = ensure_subtree (tree, path);
00407 if (subtree == NULL)
00408 {
00409 _DBUS_SET_OOM (error);
00410 return FALSE;
00411 }
00412
00413 if (subtree->message_function != NULL)
00414 {
00415 if (error != NULL)
00416 {
00417 char *complete_path = flatten_path (path);
00418
00419 dbus_set_error (error, DBUS_ERROR_OBJECT_PATH_IN_USE,
00420 "A handler is already registered for %s",
00421 complete_path ? complete_path
00422 : "(cannot represent path: out of memory!)");
00423
00424 dbus_free (complete_path);
00425 }
00426
00427 return FALSE;
00428 }
00429
00430 subtree->message_function = vtable->message_function;
00431 subtree->unregister_function = vtable->unregister_function;
00432 subtree->user_data = user_data;
00433 subtree->invoke_as_fallback = fallback != FALSE;
00434
00435 return TRUE;
00436 }
00437
00449 static dbus_bool_t
00450 unregister_subtree (DBusObjectSubtree *subtree,
00451 DBusObjectPathUnregisterFunction *unregister_function_out,
00452 void **user_data_out)
00453 {
00454 _dbus_assert (subtree != NULL);
00455 _dbus_assert (unregister_function_out != NULL);
00456 _dbus_assert (user_data_out != NULL);
00457
00458
00459 if (subtree->message_function != NULL)
00460 {
00461 subtree->message_function = NULL;
00462
00463 *unregister_function_out = subtree->unregister_function;
00464 *user_data_out = subtree->user_data;
00465
00466 subtree->unregister_function = NULL;
00467 subtree->user_data = NULL;
00468
00469 return TRUE;
00470 }
00471 else
00472 {
00473
00474
00475
00476 _dbus_assert (subtree->parent == NULL || subtree->n_subtrees > 0);
00477
00478
00479 return FALSE;
00480 }
00481 }
00482
00494 static dbus_bool_t
00495 attempt_child_removal (DBusObjectSubtree *parent,
00496 int child_index)
00497 {
00498
00499 DBusObjectSubtree* candidate;
00500
00501 _dbus_assert (parent != NULL);
00502 _dbus_assert (child_index >= 0 && child_index < parent->n_subtrees);
00503
00504 candidate = parent->subtrees[child_index];
00505 _dbus_assert (candidate != NULL);
00506
00507 if (candidate->n_subtrees == 0 && candidate->message_function == NULL)
00508 {
00509
00510
00511
00512
00513
00514 memmove (&parent->subtrees[child_index],
00515 &parent->subtrees[child_index + 1],
00516 (parent->n_subtrees - child_index - 1)
00517 * sizeof (parent->subtrees[0]));
00518 parent->n_subtrees -= 1;
00519
00520
00521 candidate->parent = NULL;
00522 _dbus_object_subtree_unref (candidate);
00523
00524 return TRUE;
00525 }
00526 return FALSE;
00527 }
00528
00566 static dbus_bool_t
00567 unregister_and_free_path_recurse
00568 (DBusObjectSubtree *subtree,
00569 const char **path,
00570 dbus_bool_t *continue_removal_attempts,
00571 DBusObjectPathUnregisterFunction *unregister_function_out,
00572 void **user_data_out)
00573 {
00574 int i, j;
00575
00576 _dbus_assert (continue_removal_attempts != NULL);
00577 _dbus_assert (*continue_removal_attempts);
00578 _dbus_assert (unregister_function_out != NULL);
00579 _dbus_assert (user_data_out != NULL);
00580
00581 if (path[0] == NULL)
00582 return unregister_subtree (subtree, unregister_function_out, user_data_out);
00583
00584 i = 0;
00585 j = subtree->n_subtrees;
00586 while (i < j)
00587 {
00588 int k, v;
00589
00590 k = (i + j) / 2;
00591 v = strcmp (path[0], subtree->subtrees[k]->name);
00592
00593 if (v == 0)
00594 {
00595 dbus_bool_t freed;
00596 freed = unregister_and_free_path_recurse (subtree->subtrees[k],
00597 &path[1],
00598 continue_removal_attempts,
00599 unregister_function_out,
00600 user_data_out);
00601 if (freed && *continue_removal_attempts)
00602 *continue_removal_attempts = attempt_child_removal (subtree, k);
00603 return freed;
00604 }
00605 else if (v < 0)
00606 {
00607 j = k;
00608 }
00609 else
00610 {
00611 i = k + 1;
00612 }
00613 }
00614 return FALSE;
00615 }
00616
00624 void
00625 _dbus_object_tree_unregister_and_unlock (DBusObjectTree *tree,
00626 const char **path)
00627 {
00628 dbus_bool_t found_subtree;
00629 dbus_bool_t continue_removal_attempts;
00630 DBusObjectPathUnregisterFunction unregister_function;
00631 void *user_data;
00632 DBusConnection *connection;
00633
00634 _dbus_assert (tree != NULL);
00635 _dbus_assert (path != NULL);
00636
00637 continue_removal_attempts = TRUE;
00638 unregister_function = NULL;
00639 user_data = NULL;
00640
00641 found_subtree = unregister_and_free_path_recurse (tree->root,
00642 path,
00643 &continue_removal_attempts,
00644 &unregister_function,
00645 &user_data);
00646
00647 #ifndef DBUS_DISABLE_CHECKS
00648 if (found_subtree == FALSE)
00649 {
00650 _dbus_warn ("Attempted to unregister path (path[0] = %s path[1] = %s) which isn't registered\n",
00651 path[0] ? path[0] : "null",
00652 (path[0] && path[1]) ? path[1] : "null");
00653 goto unlock;
00654 }
00655 #else
00656 _dbus_assert (found_subtree == TRUE);
00657 #endif
00658
00659 unlock:
00660 connection = tree->connection;
00661
00662
00663 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00664 if (connection)
00665 #endif
00666 {
00667 _dbus_connection_ref_unlocked (connection);
00668 _dbus_verbose ("unlock\n");
00669 _dbus_connection_unlock (connection);
00670 }
00671
00672 if (unregister_function)
00673 (* unregister_function) (connection, user_data);
00674
00675 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00676 if (connection)
00677 #endif
00678 dbus_connection_unref (connection);
00679 }
00680
00681 static void
00682 free_subtree_recurse (DBusConnection *connection,
00683 DBusObjectSubtree *subtree)
00684 {
00685
00686
00687
00688 while (subtree->n_subtrees > 0)
00689 {
00690 DBusObjectSubtree *child;
00691
00692 child = subtree->subtrees[subtree->n_subtrees - 1];
00693 subtree->subtrees[subtree->n_subtrees - 1] = NULL;
00694 subtree->n_subtrees -= 1;
00695 child->parent = NULL;
00696
00697 free_subtree_recurse (connection, child);
00698 }
00699
00700
00701 if (subtree->unregister_function)
00702 (* subtree->unregister_function) (connection,
00703 subtree->user_data);
00704
00705 subtree->message_function = NULL;
00706 subtree->unregister_function = NULL;
00707 subtree->user_data = NULL;
00708
00709
00710 _dbus_object_subtree_unref (subtree);
00711 }
00712
00719 void
00720 _dbus_object_tree_free_all_unlocked (DBusObjectTree *tree)
00721 {
00722 if (tree->root)
00723 free_subtree_recurse (tree->connection,
00724 tree->root);
00725 tree->root = NULL;
00726 }
00727
00728 static dbus_bool_t
00729 _dbus_object_tree_list_registered_unlocked (DBusObjectTree *tree,
00730 const char **parent_path,
00731 char ***child_entries)
00732 {
00733 DBusObjectSubtree *subtree;
00734 char **retval;
00735
00736 _dbus_assert (parent_path != NULL);
00737 _dbus_assert (child_entries != NULL);
00738
00739 *child_entries = NULL;
00740
00741 subtree = lookup_subtree (tree, parent_path);
00742 if (subtree == NULL)
00743 {
00744 retval = dbus_new0 (char *, 1);
00745 }
00746 else
00747 {
00748 int i;
00749 retval = dbus_new0 (char*, subtree->n_subtrees + 1);
00750 if (retval == NULL)
00751 goto out;
00752 i = 0;
00753 while (i < subtree->n_subtrees)
00754 {
00755 retval[i] = _dbus_strdup (subtree->subtrees[i]->name);
00756 if (retval[i] == NULL)
00757 {
00758 dbus_free_string_array (retval);
00759 retval = NULL;
00760 goto out;
00761 }
00762 ++i;
00763 }
00764 }
00765
00766 out:
00767
00768 *child_entries = retval;
00769 return retval != NULL;
00770 }
00771
00772 static DBusHandlerResult
00773 handle_default_introspect_and_unlock (DBusObjectTree *tree,
00774 DBusMessage *message,
00775 const char **path)
00776 {
00777 DBusString xml;
00778 DBusHandlerResult result;
00779 char **children;
00780 int i;
00781 DBusMessage *reply;
00782 DBusMessageIter iter;
00783 const char *v_STRING;
00784 dbus_bool_t already_unlocked;
00785
00786
00787
00788 already_unlocked = FALSE;
00789
00790 _dbus_verbose (" considering default Introspect() handler...\n");
00791
00792 reply = NULL;
00793
00794 if (!dbus_message_is_method_call (message,
00795 DBUS_INTERFACE_INTROSPECTABLE,
00796 "Introspect"))
00797 {
00798 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00799 if (tree->connection)
00800 #endif
00801 {
00802 _dbus_verbose ("unlock\n");
00803 _dbus_connection_unlock (tree->connection);
00804 }
00805
00806 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00807 }
00808
00809 _dbus_verbose (" using default Introspect() handler!\n");
00810
00811 if (!_dbus_string_init (&xml))
00812 {
00813 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00814 if (tree->connection)
00815 #endif
00816 {
00817 _dbus_verbose ("unlock\n");
00818 _dbus_connection_unlock (tree->connection);
00819 }
00820
00821 return DBUS_HANDLER_RESULT_NEED_MEMORY;
00822 }
00823
00824 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
00825
00826 children = NULL;
00827 if (!_dbus_object_tree_list_registered_unlocked (tree, path, &children))
00828 goto out;
00829
00830 if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
00831 goto out;
00832
00833 if (!_dbus_string_append (&xml, "<node>\n"))
00834 goto out;
00835
00836 i = 0;
00837 while (children[i] != NULL)
00838 {
00839 if (!_dbus_string_append_printf (&xml, " <node name=\"%s\"/>\n",
00840 children[i]))
00841 goto out;
00842
00843 ++i;
00844 }
00845
00846 if (!_dbus_string_append (&xml, "</node>\n"))
00847 goto out;
00848
00849 reply = dbus_message_new_method_return (message);
00850 if (reply == NULL)
00851 goto out;
00852
00853 dbus_message_iter_init_append (reply, &iter);
00854 v_STRING = _dbus_string_get_const_data (&xml);
00855 if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &v_STRING))
00856 goto out;
00857
00858 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00859 if (tree->connection)
00860 #endif
00861 {
00862 already_unlocked = TRUE;
00863
00864 if (!_dbus_connection_send_and_unlock (tree->connection, reply, NULL))
00865 goto out;
00866 }
00867
00868 result = DBUS_HANDLER_RESULT_HANDLED;
00869
00870 out:
00871 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00872 if (tree->connection)
00873 #endif
00874 {
00875 if (!already_unlocked)
00876 {
00877 _dbus_verbose ("unlock\n");
00878 _dbus_connection_unlock (tree->connection);
00879 }
00880 }
00881
00882 _dbus_string_free (&xml);
00883 dbus_free_string_array (children);
00884 if (reply)
00885 dbus_message_unref (reply);
00886
00887 return result;
00888 }
00889
00904 DBusHandlerResult
00905 _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree,
00906 DBusMessage *message,
00907 dbus_bool_t *found_object)
00908 {
00909 char **path;
00910 dbus_bool_t exact_match;
00911 DBusList *list;
00912 DBusList *link;
00913 DBusHandlerResult result;
00914 DBusObjectSubtree *subtree;
00915
00916 #if 0
00917 _dbus_verbose ("Dispatch of message by object path\n");
00918 #endif
00919
00920 path = NULL;
00921 if (!dbus_message_get_path_decomposed (message, &path))
00922 {
00923 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00924 if (tree->connection)
00925 #endif
00926 {
00927 _dbus_verbose ("unlock\n");
00928 _dbus_connection_unlock (tree->connection);
00929 }
00930
00931 _dbus_verbose ("No memory to get decomposed path\n");
00932
00933 return DBUS_HANDLER_RESULT_NEED_MEMORY;
00934 }
00935
00936 if (path == NULL)
00937 {
00938 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00939 if (tree->connection)
00940 #endif
00941 {
00942 _dbus_verbose ("unlock\n");
00943 _dbus_connection_unlock (tree->connection);
00944 }
00945
00946 _dbus_verbose ("No path field in message\n");
00947 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00948 }
00949
00950
00951 subtree = find_handler (tree, (const char**) path, &exact_match);
00952
00953 if (found_object)
00954 *found_object = !!subtree;
00955
00956
00957
00958 list = NULL;
00959
00960 while (subtree != NULL)
00961 {
00962 if (subtree->message_function != NULL && (exact_match || subtree->invoke_as_fallback))
00963 {
00964 _dbus_object_subtree_ref (subtree);
00965
00966
00967 if (!_dbus_list_append (&list, subtree))
00968 {
00969 result = DBUS_HANDLER_RESULT_NEED_MEMORY;
00970 _dbus_object_subtree_unref (subtree);
00971 goto free_and_return;
00972 }
00973 }
00974
00975 exact_match = FALSE;
00976 subtree = subtree->parent;
00977 }
00978
00979 _dbus_verbose ("%d handlers in the path tree for this message\n",
00980 _dbus_list_get_length (&list));
00981
00982
00983
00984 result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
00985
00986 link = _dbus_list_get_first_link (&list);
00987 while (link != NULL)
00988 {
00989 DBusList *next = _dbus_list_get_next_link (&list, link);
00990 subtree = link->data;
00991
00992
00993
00994
00995 if (subtree->message_function)
00996 {
00997 DBusObjectPathMessageFunction message_function;
00998 void *user_data;
00999
01000 message_function = subtree->message_function;
01001 user_data = subtree->user_data;
01002
01003 #if 0
01004 _dbus_verbose (" (invoking a handler)\n");
01005 #endif
01006
01007 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01008 if (tree->connection)
01009 #endif
01010 {
01011 _dbus_verbose ("unlock\n");
01012 _dbus_connection_unlock (tree->connection);
01013 }
01014
01015
01016
01017
01018
01019
01020 result = (* message_function) (tree->connection,
01021 message,
01022 user_data);
01023
01024 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01025 if (tree->connection)
01026 #endif
01027 _dbus_connection_lock (tree->connection);
01028
01029 if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
01030 goto free_and_return;
01031 }
01032
01033 link = next;
01034 }
01035
01036 free_and_return:
01037
01038 if (result == DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
01039 {
01040
01041
01042 result = handle_default_introspect_and_unlock (tree, message,
01043 (const char**) path);
01044 }
01045 else
01046 {
01047 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01048 if (tree->connection)
01049 #endif
01050 {
01051 _dbus_verbose ("unlock\n");
01052 _dbus_connection_unlock (tree->connection);
01053 }
01054 }
01055
01056 while (list != NULL)
01057 {
01058 link = _dbus_list_get_first_link (&list);
01059 _dbus_object_subtree_unref (link->data);
01060 _dbus_list_remove_link (&list, link);
01061 }
01062
01063 dbus_free_string_array (path);
01064
01065 return result;
01066 }
01067
01076 void*
01077 _dbus_object_tree_get_user_data_unlocked (DBusObjectTree *tree,
01078 const char **path)
01079 {
01080 dbus_bool_t exact_match;
01081 DBusObjectSubtree *subtree;
01082
01083 _dbus_assert (tree != NULL);
01084 _dbus_assert (path != NULL);
01085
01086
01087 subtree = find_handler (tree, (const char**) path, &exact_match);
01088
01089 if ((subtree == NULL) || !exact_match)
01090 {
01091 _dbus_verbose ("No object at specified path found\n");
01092 return NULL;
01093 }
01094
01095 return subtree->user_data;
01096 }
01097
01104 static DBusObjectSubtree*
01105 allocate_subtree_object (const char *name)
01106 {
01107 int len;
01108 DBusObjectSubtree *subtree;
01109 const size_t front_padding = _DBUS_STRUCT_OFFSET (DBusObjectSubtree, name);
01110
01111 _dbus_assert (name != NULL);
01112
01113 len = strlen (name);
01114
01115 subtree = dbus_malloc0 (MAX (front_padding + (len + 1), sizeof (DBusObjectSubtree)));
01116
01117 if (subtree == NULL)
01118 return NULL;
01119
01120 memcpy (subtree->name, name, len + 1);
01121
01122 return subtree;
01123 }
01124
01125 static DBusObjectSubtree*
01126 _dbus_object_subtree_new (const char *name,
01127 const DBusObjectPathVTable *vtable,
01128 void *user_data)
01129 {
01130 DBusObjectSubtree *subtree;
01131
01132 subtree = allocate_subtree_object (name);
01133 if (subtree == NULL)
01134 goto oom;
01135
01136 _dbus_assert (name != NULL);
01137
01138 subtree->parent = NULL;
01139
01140 if (vtable)
01141 {
01142 subtree->message_function = vtable->message_function;
01143 subtree->unregister_function = vtable->unregister_function;
01144 }
01145 else
01146 {
01147 subtree->message_function = NULL;
01148 subtree->unregister_function = NULL;
01149 }
01150
01151 subtree->user_data = user_data;
01152 _dbus_atomic_inc (&subtree->refcount);
01153 subtree->subtrees = NULL;
01154 subtree->n_subtrees = 0;
01155 subtree->max_subtrees = 0;
01156 subtree->invoke_as_fallback = FALSE;
01157
01158 return subtree;
01159
01160 oom:
01161 return NULL;
01162 }
01163
01164 static DBusObjectSubtree *
01165 _dbus_object_subtree_ref (DBusObjectSubtree *subtree)
01166 {
01167 #ifdef DBUS_DISABLE_ASSERT
01168 _dbus_atomic_inc (&subtree->refcount);
01169 #else
01170 dbus_int32_t old_value;
01171
01172 old_value = _dbus_atomic_inc (&subtree->refcount);
01173 _dbus_assert (old_value > 0);
01174 #endif
01175
01176 return subtree;
01177 }
01178
01179 static void
01180 _dbus_object_subtree_unref (DBusObjectSubtree *subtree)
01181 {
01182 dbus_int32_t old_value;
01183
01184 old_value = _dbus_atomic_dec (&subtree->refcount);
01185 _dbus_assert (old_value > 0);
01186
01187 if (old_value == 1)
01188 {
01189 _dbus_assert (subtree->unregister_function == NULL);
01190 _dbus_assert (subtree->message_function == NULL);
01191
01192 dbus_free (subtree->subtrees);
01193 dbus_free (subtree);
01194 }
01195 }
01196
01207 dbus_bool_t
01208 _dbus_object_tree_list_registered_and_unlock (DBusObjectTree *tree,
01209 const char **parent_path,
01210 char ***child_entries)
01211 {
01212 dbus_bool_t result;
01213
01214 result = _dbus_object_tree_list_registered_unlocked (tree,
01215 parent_path,
01216 child_entries);
01217
01218 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01219 if (tree->connection)
01220 #endif
01221 {
01222 _dbus_verbose ("unlock\n");
01223 _dbus_connection_unlock (tree->connection);
01224 }
01225
01226 return result;
01227 }
01228
01229
01231 #define VERBOSE_DECOMPOSE 0
01232
01243 dbus_bool_t
01244 _dbus_decompose_path (const char* data,
01245 int len,
01246 char ***path,
01247 int *path_len)
01248 {
01249 char **retval;
01250 int n_components;
01251 int i, j, comp;
01252
01253 _dbus_assert (data != NULL);
01254 _dbus_assert (path != NULL);
01255
01256 #if VERBOSE_DECOMPOSE
01257 _dbus_verbose ("Decomposing path \"%s\"\n",
01258 data);
01259 #endif
01260
01261 n_components = 0;
01262 if (len > 1)
01263 {
01264 i = 0;
01265 while (i < len)
01266 {
01267 _dbus_assert (data[i] != '\0');
01268 if (data[i] == '/')
01269 n_components += 1;
01270 ++i;
01271 }
01272 }
01273
01274 retval = dbus_new0 (char*, n_components + 1);
01275
01276 if (retval == NULL)
01277 return FALSE;
01278
01279 comp = 0;
01280 if (n_components == 0)
01281 i = 1;
01282 else
01283 i = 0;
01284 while (comp < n_components)
01285 {
01286 _dbus_assert (i < len);
01287
01288 if (data[i] == '/')
01289 ++i;
01290 j = i;
01291
01292 while (j < len && data[j] != '/')
01293 ++j;
01294
01295
01296 _dbus_assert (i < j);
01297 _dbus_assert (data[i] != '/');
01298 _dbus_assert (j == len || data[j] == '/');
01299
01300 #if VERBOSE_DECOMPOSE
01301 _dbus_verbose (" (component in [%d,%d))\n",
01302 i, j);
01303 #endif
01304
01305 retval[comp] = _dbus_memdup (&data[i], j - i + 1);
01306 if (retval[comp] == NULL)
01307 {
01308 dbus_free_string_array (retval);
01309 return FALSE;
01310 }
01311 retval[comp][j-i] = '\0';
01312 #if VERBOSE_DECOMPOSE
01313 _dbus_verbose (" (component %d = \"%s\")\n",
01314 comp, retval[comp]);
01315 #endif
01316
01317 ++comp;
01318 i = j;
01319 }
01320 _dbus_assert (i == len);
01321
01322 *path = retval;
01323 if (path_len)
01324 *path_len = n_components;
01325
01326 return TRUE;
01327 }
01328
01331 static char*
01332 flatten_path (const char **path)
01333 {
01334 DBusString str;
01335 char *s;
01336
01337 if (!_dbus_string_init (&str))
01338 return NULL;
01339
01340 if (path[0] == NULL)
01341 {
01342 if (!_dbus_string_append_byte (&str, '/'))
01343 goto nomem;
01344 }
01345 else
01346 {
01347 int i;
01348
01349 i = 0;
01350 while (path[i])
01351 {
01352 if (!_dbus_string_append_byte (&str, '/'))
01353 goto nomem;
01354
01355 if (!_dbus_string_append (&str, path[i]))
01356 goto nomem;
01357
01358 ++i;
01359 }
01360 }
01361
01362 if (!_dbus_string_steal_data (&str, &s))
01363 goto nomem;
01364
01365 _dbus_string_free (&str);
01366
01367 return s;
01368
01369 nomem:
01370 _dbus_string_free (&str);
01371 return NULL;
01372 }
01373
01374
01375 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
01376
01377 #ifndef DOXYGEN_SHOULD_SKIP_THIS
01378
01379 #include "dbus-test.h"
01380 #include <stdio.h>
01381
01382 typedef enum
01383 {
01384 STR_EQUAL,
01385 STR_PREFIX,
01386 STR_DIFFERENT
01387 } StrComparison;
01388
01389
01390
01391 static StrComparison
01392 path_contains (const char **container,
01393 const char **child)
01394 {
01395 int i;
01396
01397 i = 0;
01398 while (child[i] != NULL)
01399 {
01400 int v;
01401
01402 if (container[i] == NULL)
01403 return STR_PREFIX;
01404
01405
01406
01407
01408 _dbus_assert (container[i] != NULL);
01409 _dbus_assert (child[i] != NULL);
01410
01411 v = strcmp (container[i], child[i]);
01412
01413 if (v != 0)
01414 return STR_DIFFERENT;
01415
01416
01417
01418 ++i;
01419 }
01420
01421
01422
01423
01424 if (container[i] == NULL)
01425 return STR_EQUAL;
01426 else
01427 return STR_DIFFERENT;
01428 }
01429
01430 #if 0
01431 static void
01432 spew_subtree_recurse (DBusObjectSubtree *subtree,
01433 int indent)
01434 {
01435 int i;
01436
01437 i = 0;
01438 while (i < indent)
01439 {
01440 _dbus_verbose (" ");
01441 ++i;
01442 }
01443
01444 _dbus_verbose ("%s (%d children)\n",
01445 subtree->name, subtree->n_subtrees);
01446
01447 i = 0;
01448 while (i < subtree->n_subtrees)
01449 {
01450 spew_subtree_recurse (subtree->subtrees[i], indent + 2);
01451
01452 ++i;
01453 }
01454 }
01455
01456 static void
01457 spew_tree (DBusObjectTree *tree)
01458 {
01459 spew_subtree_recurse (tree->root, 0);
01460 }
01461 #endif
01462
01466 typedef struct
01467 {
01468 const char **path;
01469 dbus_bool_t handler_fallback;
01470 dbus_bool_t message_handled;
01471 dbus_bool_t handler_unregistered;
01472 } TreeTestData;
01473
01474
01475 static void
01476 test_unregister_function (DBusConnection *connection,
01477 void *user_data)
01478 {
01479 TreeTestData *ttd = user_data;
01480
01481 ttd->handler_unregistered = TRUE;
01482 }
01483
01484 static DBusHandlerResult
01485 test_message_function (DBusConnection *connection,
01486 DBusMessage *message,
01487 void *user_data)
01488 {
01489 TreeTestData *ttd = user_data;
01490
01491 ttd->message_handled = TRUE;
01492
01493 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
01494 }
01495
01496 static dbus_bool_t
01497 do_register (DBusObjectTree *tree,
01498 const char **path,
01499 dbus_bool_t fallback,
01500 int i,
01501 TreeTestData *tree_test_data)
01502 {
01503 DBusObjectPathVTable vtable = { test_unregister_function,
01504 test_message_function, NULL };
01505
01506 tree_test_data[i].message_handled = FALSE;
01507 tree_test_data[i].handler_unregistered = FALSE;
01508 tree_test_data[i].handler_fallback = fallback;
01509 tree_test_data[i].path = path;
01510
01511 if (!_dbus_object_tree_register (tree, fallback, path,
01512 &vtable,
01513 &tree_test_data[i],
01514 NULL))
01515 return FALSE;
01516
01517 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path) ==
01518 &tree_test_data[i]);
01519
01520 return TRUE;
01521 }
01522
01523 static dbus_bool_t
01524 do_test_dispatch (DBusObjectTree *tree,
01525 const char **path,
01526 int i,
01527 TreeTestData *tree_test_data,
01528 int n_test_data)
01529 {
01530 DBusMessage *message;
01531 int j;
01532 DBusHandlerResult result;
01533 char *flat;
01534
01535 message = NULL;
01536
01537 flat = flatten_path (path);
01538 if (flat == NULL)
01539 goto oom;
01540
01541 message = dbus_message_new_method_call (NULL,
01542 flat,
01543 "org.freedesktop.TestInterface",
01544 "Foo");
01545 dbus_free (flat);
01546 if (message == NULL)
01547 goto oom;
01548
01549 j = 0;
01550 while (j < n_test_data)
01551 {
01552 tree_test_data[j].message_handled = FALSE;
01553 ++j;
01554 }
01555
01556 result = _dbus_object_tree_dispatch_and_unlock (tree, message, NULL);
01557 if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
01558 goto oom;
01559
01560 _dbus_assert (tree_test_data[i].message_handled);
01561
01562 j = 0;
01563 while (j < n_test_data)
01564 {
01565 if (tree_test_data[j].message_handled)
01566 {
01567 if (tree_test_data[j].handler_fallback)
01568 _dbus_assert (path_contains (tree_test_data[j].path,
01569 path) != STR_DIFFERENT);
01570 else
01571 _dbus_assert (path_contains (tree_test_data[j].path, path) == STR_EQUAL);
01572 }
01573 else
01574 {
01575 if (tree_test_data[j].handler_fallback)
01576 _dbus_assert (path_contains (tree_test_data[j].path,
01577 path) == STR_DIFFERENT);
01578 else
01579 _dbus_assert (path_contains (tree_test_data[j].path, path) != STR_EQUAL);
01580 }
01581
01582 ++j;
01583 }
01584
01585 dbus_message_unref (message);
01586
01587 return TRUE;
01588
01589 oom:
01590 if (message)
01591 dbus_message_unref (message);
01592 return FALSE;
01593 }
01594
01595 static size_t
01596 string_array_length (const char **array)
01597 {
01598 size_t i;
01599 for (i = 0; array[i]; i++) ;
01600 return i;
01601 }
01602
01603 typedef struct
01604 {
01605 const char *path;
01606 const char *result[20];
01607 } DecomposePathTest;
01608
01609 static DecomposePathTest decompose_tests[] = {
01610 { "/foo", { "foo", NULL } },
01611 { "/foo/bar", { "foo", "bar", NULL } },
01612 { "/", { NULL } },
01613 { "/a/b", { "a", "b", NULL } },
01614 { "/a/b/c", { "a", "b", "c", NULL } },
01615 { "/a/b/c/d", { "a", "b", "c", "d", NULL } },
01616 { "/foo/bar/q", { "foo", "bar", "q", NULL } },
01617 { "/foo/bar/this/is/longer", { "foo", "bar", "this", "is", "longer", NULL } }
01618 };
01619
01620 static dbus_bool_t
01621 run_decompose_tests (void)
01622 {
01623 int i;
01624
01625 i = 0;
01626 while (i < _DBUS_N_ELEMENTS (decompose_tests))
01627 {
01628 char **result;
01629 int result_len;
01630 int expected_len;
01631
01632 if (!_dbus_decompose_path (decompose_tests[i].path,
01633 strlen (decompose_tests[i].path),
01634 &result, &result_len))
01635 return FALSE;
01636
01637 expected_len = string_array_length (decompose_tests[i].result);
01638
01639 if (result_len != (int) string_array_length ((const char**)result) ||
01640 expected_len != result_len ||
01641 path_contains (decompose_tests[i].result,
01642 (const char**) result) != STR_EQUAL)
01643 {
01644 int real_len = string_array_length ((const char**)result);
01645 _dbus_warn ("Expected decompose of %s to have len %d, returned %d, appears to have %d\n",
01646 decompose_tests[i].path, expected_len, result_len,
01647 real_len);
01648 _dbus_warn ("Decompose resulted in elements: { ");
01649 i = 0;
01650 while (i < real_len)
01651 {
01652 _dbus_warn ("\"%s\"%s", result[i],
01653 (i + 1) == real_len ? "" : ", ");
01654 ++i;
01655 }
01656 _dbus_warn ("}\n");
01657 _dbus_assert_not_reached ("path decompose failed\n");
01658 }
01659
01660 dbus_free_string_array (result);
01661
01662 ++i;
01663 }
01664
01665 return TRUE;
01666 }
01667
01668 static DBusObjectSubtree*
01669 find_subtree_registered_or_unregistered (DBusObjectTree *tree,
01670 const char **path)
01671 {
01672 #if VERBOSE_FIND
01673 _dbus_verbose ("Looking for exact subtree, registered or unregistered\n");
01674 #endif
01675
01676 return find_subtree_recurse (tree->root, path, FALSE, NULL, NULL);
01677 }
01678
01679 static dbus_bool_t
01680 object_tree_test_iteration (void *data)
01681 {
01682 const char *path0[] = { NULL };
01683 const char *path1[] = { "foo", NULL };
01684 const char *path2[] = { "foo", "bar", NULL };
01685 const char *path3[] = { "foo", "bar", "baz", NULL };
01686 const char *path4[] = { "foo", "bar", "boo", NULL };
01687 const char *path5[] = { "blah", NULL };
01688 const char *path6[] = { "blah", "boof", NULL };
01689 const char *path7[] = { "blah", "boof", "this", "is", "really", "long", NULL };
01690 const char *path8[] = { "childless", NULL };
01691 const char *path9[] = { "blah", "a", NULL };
01692 const char *path10[] = { "blah", "b", NULL };
01693 const char *path11[] = { "blah", "c", NULL };
01694 const char *path12[] = { "blah", "a", "d", NULL };
01695 const char *path13[] = { "blah", "b", "d", NULL };
01696 const char *path14[] = { "blah", "c", "d", NULL };
01697 DBusObjectPathVTable test_vtable = { NULL, test_message_function, NULL };
01698 DBusObjectTree *tree;
01699 TreeTestData tree_test_data[9];
01700 int i;
01701 dbus_bool_t exact_match;
01702
01703 if (!run_decompose_tests ())
01704 return FALSE;
01705
01706 tree = NULL;
01707
01708 tree = _dbus_object_tree_new (NULL);
01709 if (tree == NULL)
01710 goto out;
01711
01712 if (!do_register (tree, path0, TRUE, 0, tree_test_data))
01713 goto out;
01714
01715 _dbus_assert (find_subtree (tree, path0, NULL));
01716 _dbus_assert (!find_subtree (tree, path1, NULL));
01717 _dbus_assert (!find_subtree (tree, path2, NULL));
01718 _dbus_assert (!find_subtree (tree, path3, NULL));
01719 _dbus_assert (!find_subtree (tree, path4, NULL));
01720 _dbus_assert (!find_subtree (tree, path5, NULL));
01721 _dbus_assert (!find_subtree (tree, path6, NULL));
01722 _dbus_assert (!find_subtree (tree, path7, NULL));
01723 _dbus_assert (!find_subtree (tree, path8, NULL));
01724
01725 _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match);
01726 _dbus_assert (find_handler (tree, path1, &exact_match) == tree->root && !exact_match);
01727 _dbus_assert (find_handler (tree, path2, &exact_match) == tree->root && !exact_match);
01728 _dbus_assert (find_handler (tree, path3, &exact_match) == tree->root && !exact_match);
01729 _dbus_assert (find_handler (tree, path4, &exact_match) == tree->root && !exact_match);
01730 _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match);
01731 _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match);
01732 _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match);
01733 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
01734
01735 if (!do_register (tree, path1, TRUE, 1, tree_test_data))
01736 goto out;
01737
01738 _dbus_assert (find_subtree (tree, path0, NULL));
01739 _dbus_assert (find_subtree (tree, path1, NULL));
01740 _dbus_assert (!find_subtree (tree, path2, NULL));
01741 _dbus_assert (!find_subtree (tree, path3, NULL));
01742 _dbus_assert (!find_subtree (tree, path4, NULL));
01743 _dbus_assert (!find_subtree (tree, path5, NULL));
01744 _dbus_assert (!find_subtree (tree, path6, NULL));
01745 _dbus_assert (!find_subtree (tree, path7, NULL));
01746 _dbus_assert (!find_subtree (tree, path8, NULL));
01747
01748 _dbus_assert (find_handler (tree, path0, &exact_match) && exact_match);
01749 _dbus_assert (find_handler (tree, path1, &exact_match) && exact_match);
01750 _dbus_assert (find_handler (tree, path2, &exact_match) && !exact_match);
01751 _dbus_assert (find_handler (tree, path3, &exact_match) && !exact_match);
01752 _dbus_assert (find_handler (tree, path4, &exact_match) && !exact_match);
01753 _dbus_assert (find_handler (tree, path5, &exact_match) == tree->root && !exact_match);
01754 _dbus_assert (find_handler (tree, path6, &exact_match) == tree->root && !exact_match);
01755 _dbus_assert (find_handler (tree, path7, &exact_match) == tree->root && !exact_match);
01756 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
01757
01758 if (!do_register (tree, path2, TRUE, 2, tree_test_data))
01759 goto out;
01760
01761 _dbus_assert (find_subtree (tree, path1, NULL));
01762 _dbus_assert (find_subtree (tree, path2, NULL));
01763 _dbus_assert (!find_subtree (tree, path3, NULL));
01764 _dbus_assert (!find_subtree (tree, path4, NULL));
01765 _dbus_assert (!find_subtree (tree, path5, NULL));
01766 _dbus_assert (!find_subtree (tree, path6, NULL));
01767 _dbus_assert (!find_subtree (tree, path7, NULL));
01768 _dbus_assert (!find_subtree (tree, path8, NULL));
01769
01770 if (!do_register (tree, path3, TRUE, 3, tree_test_data))
01771 goto out;
01772
01773 _dbus_assert (find_subtree (tree, path0, NULL));
01774 _dbus_assert (find_subtree (tree, path1, NULL));
01775 _dbus_assert (find_subtree (tree, path2, NULL));
01776 _dbus_assert (find_subtree (tree, path3, NULL));
01777 _dbus_assert (!find_subtree (tree, path4, NULL));
01778 _dbus_assert (!find_subtree (tree, path5, NULL));
01779 _dbus_assert (!find_subtree (tree, path6, NULL));
01780 _dbus_assert (!find_subtree (tree, path7, NULL));
01781 _dbus_assert (!find_subtree (tree, path8, NULL));
01782
01783 if (!do_register (tree, path4, TRUE, 4, tree_test_data))
01784 goto out;
01785
01786 _dbus_assert (find_subtree (tree, path0, NULL));
01787 _dbus_assert (find_subtree (tree, path1, NULL));
01788 _dbus_assert (find_subtree (tree, path2, NULL));
01789 _dbus_assert (find_subtree (tree, path3, NULL));
01790 _dbus_assert (find_subtree (tree, path4, NULL));
01791 _dbus_assert (!find_subtree (tree, path5, NULL));
01792 _dbus_assert (!find_subtree (tree, path6, NULL));
01793 _dbus_assert (!find_subtree (tree, path7, NULL));
01794 _dbus_assert (!find_subtree (tree, path8, NULL));
01795
01796 if (!do_register (tree, path5, TRUE, 5, tree_test_data))
01797 goto out;
01798
01799 _dbus_assert (find_subtree (tree, path0, NULL));
01800 _dbus_assert (find_subtree (tree, path1, NULL));
01801 _dbus_assert (find_subtree (tree, path2, NULL));
01802 _dbus_assert (find_subtree (tree, path3, NULL));
01803 _dbus_assert (find_subtree (tree, path4, NULL));
01804 _dbus_assert (find_subtree (tree, path5, NULL));
01805 _dbus_assert (!find_subtree (tree, path6, NULL));
01806 _dbus_assert (!find_subtree (tree, path7, NULL));
01807 _dbus_assert (!find_subtree (tree, path8, NULL));
01808
01809 _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root && exact_match);
01810 _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match);
01811 _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match);
01812 _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match);
01813 _dbus_assert (find_handler (tree, path4, &exact_match) != tree->root && exact_match);
01814 _dbus_assert (find_handler (tree, path5, &exact_match) != tree->root && exact_match);
01815 _dbus_assert (find_handler (tree, path6, &exact_match) != tree->root && !exact_match);
01816 _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && !exact_match);
01817 _dbus_assert (find_handler (tree, path8, &exact_match) == tree->root && !exact_match);
01818
01819 if (!do_register (tree, path6, TRUE, 6, tree_test_data))
01820 goto out;
01821
01822 _dbus_assert (find_subtree (tree, path0, NULL));
01823 _dbus_assert (find_subtree (tree, path1, NULL));
01824 _dbus_assert (find_subtree (tree, path2, NULL));
01825 _dbus_assert (find_subtree (tree, path3, NULL));
01826 _dbus_assert (find_subtree (tree, path4, NULL));
01827 _dbus_assert (find_subtree (tree, path5, NULL));
01828 _dbus_assert (find_subtree (tree, path6, NULL));
01829 _dbus_assert (!find_subtree (tree, path7, NULL));
01830 _dbus_assert (!find_subtree (tree, path8, NULL));
01831
01832 if (!do_register (tree, path7, TRUE, 7, tree_test_data))
01833 goto out;
01834
01835 _dbus_assert (find_subtree (tree, path0, NULL));
01836 _dbus_assert (find_subtree (tree, path1, NULL));
01837 _dbus_assert (find_subtree (tree, path2, NULL));
01838 _dbus_assert (find_subtree (tree, path3, NULL));
01839 _dbus_assert (find_subtree (tree, path4, NULL));
01840 _dbus_assert (find_subtree (tree, path5, NULL));
01841 _dbus_assert (find_subtree (tree, path6, NULL));
01842 _dbus_assert (find_subtree (tree, path7, NULL));
01843 _dbus_assert (!find_subtree (tree, path8, NULL));
01844
01845 if (!do_register (tree, path8, TRUE, 8, tree_test_data))
01846 goto out;
01847
01848 _dbus_assert (find_subtree (tree, path0, NULL));
01849 _dbus_assert (find_subtree (tree, path1, NULL));
01850 _dbus_assert (find_subtree (tree, path2, NULL));
01851 _dbus_assert (find_subtree (tree, path3, NULL));
01852 _dbus_assert (find_subtree (tree, path4, NULL));
01853 _dbus_assert (find_subtree (tree, path5, NULL));
01854 _dbus_assert (find_subtree (tree, path6, NULL));
01855 _dbus_assert (find_subtree (tree, path7, NULL));
01856 _dbus_assert (find_subtree (tree, path8, NULL));
01857
01858 _dbus_assert (find_handler (tree, path0, &exact_match) == tree->root && exact_match);
01859 _dbus_assert (find_handler (tree, path1, &exact_match) != tree->root && exact_match);
01860 _dbus_assert (find_handler (tree, path2, &exact_match) != tree->root && exact_match);
01861 _dbus_assert (find_handler (tree, path3, &exact_match) != tree->root && exact_match);
01862 _dbus_assert (find_handler (tree, path4, &exact_match) != tree->root && exact_match);
01863 _dbus_assert (find_handler (tree, path5, &exact_match) != tree->root && exact_match);
01864 _dbus_assert (find_handler (tree, path6, &exact_match) != tree->root && exact_match);
01865 _dbus_assert (find_handler (tree, path7, &exact_match) != tree->root && exact_match);
01866 _dbus_assert (find_handler (tree, path8, &exact_match) != tree->root && exact_match);
01867
01868
01869
01870 {
01871 const char *root[] = { NULL };
01872 char **child_entries;
01873 int nb;
01874
01875 _dbus_object_tree_list_registered_unlocked (tree, path1, &child_entries);
01876 if (child_entries != NULL)
01877 {
01878 nb = string_array_length ((const char**)child_entries);
01879 _dbus_assert (nb == 1);
01880 dbus_free_string_array (child_entries);
01881 }
01882
01883 _dbus_object_tree_list_registered_unlocked (tree, path2, &child_entries);
01884 if (child_entries != NULL)
01885 {
01886 nb = string_array_length ((const char**)child_entries);
01887 _dbus_assert (nb == 2);
01888 dbus_free_string_array (child_entries);
01889 }
01890
01891 _dbus_object_tree_list_registered_unlocked (tree, path8, &child_entries);
01892 if (child_entries != NULL)
01893 {
01894 nb = string_array_length ((const char**)child_entries);
01895 _dbus_assert (nb == 0);
01896 dbus_free_string_array (child_entries);
01897 }
01898
01899 _dbus_object_tree_list_registered_unlocked (tree, root, &child_entries);
01900 if (child_entries != NULL)
01901 {
01902 nb = string_array_length ((const char**)child_entries);
01903 _dbus_assert (nb == 3);
01904 dbus_free_string_array (child_entries);
01905 }
01906 }
01907
01908
01909 _dbus_object_tree_unref (tree);
01910
01911 i = 0;
01912 while (i < (int) _DBUS_N_ELEMENTS (tree_test_data))
01913 {
01914 _dbus_assert (tree_test_data[i].handler_unregistered);
01915 _dbus_assert (!tree_test_data[i].message_handled);
01916 ++i;
01917 }
01918
01919
01920 tree = _dbus_object_tree_new (NULL);
01921 if (tree == NULL)
01922 goto out;
01923
01924 if (!do_register (tree, path0, TRUE, 0, tree_test_data))
01925 goto out;
01926 if (!do_register (tree, path1, TRUE, 1, tree_test_data))
01927 goto out;
01928 if (!do_register (tree, path2, TRUE, 2, tree_test_data))
01929 goto out;
01930 if (!do_register (tree, path3, TRUE, 3, tree_test_data))
01931 goto out;
01932 if (!do_register (tree, path4, TRUE, 4, tree_test_data))
01933 goto out;
01934 if (!do_register (tree, path5, TRUE, 5, tree_test_data))
01935 goto out;
01936 if (!do_register (tree, path6, TRUE, 6, tree_test_data))
01937 goto out;
01938 if (!do_register (tree, path7, TRUE, 7, tree_test_data))
01939 goto out;
01940 if (!do_register (tree, path8, TRUE, 8, tree_test_data))
01941 goto out;
01942
01943 _dbus_object_tree_unregister_and_unlock (tree, path0);
01944 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path0) == NULL);
01945
01946 _dbus_assert (!find_subtree (tree, path0, NULL));
01947 _dbus_assert (find_subtree (tree, path1, NULL));
01948 _dbus_assert (find_subtree (tree, path2, NULL));
01949 _dbus_assert (find_subtree (tree, path3, NULL));
01950 _dbus_assert (find_subtree (tree, path4, NULL));
01951 _dbus_assert (find_subtree (tree, path5, NULL));
01952 _dbus_assert (find_subtree (tree, path6, NULL));
01953 _dbus_assert (find_subtree (tree, path7, NULL));
01954 _dbus_assert (find_subtree (tree, path8, NULL));
01955
01956 _dbus_object_tree_unregister_and_unlock (tree, path1);
01957 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path1) == NULL);
01958
01959 _dbus_assert (!find_subtree (tree, path0, NULL));
01960 _dbus_assert (!find_subtree (tree, path1, NULL));
01961 _dbus_assert (find_subtree (tree, path2, NULL));
01962 _dbus_assert (find_subtree (tree, path3, NULL));
01963 _dbus_assert (find_subtree (tree, path4, NULL));
01964 _dbus_assert (find_subtree (tree, path5, NULL));
01965 _dbus_assert (find_subtree (tree, path6, NULL));
01966 _dbus_assert (find_subtree (tree, path7, NULL));
01967 _dbus_assert (find_subtree (tree, path8, NULL));
01968
01969 _dbus_object_tree_unregister_and_unlock (tree, path2);
01970 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path2) == NULL);
01971
01972 _dbus_assert (!find_subtree (tree, path0, NULL));
01973 _dbus_assert (!find_subtree (tree, path1, NULL));
01974 _dbus_assert (!find_subtree (tree, path2, NULL));
01975 _dbus_assert (find_subtree (tree, path3, NULL));
01976 _dbus_assert (find_subtree (tree, path4, NULL));
01977 _dbus_assert (find_subtree (tree, path5, NULL));
01978 _dbus_assert (find_subtree (tree, path6, NULL));
01979 _dbus_assert (find_subtree (tree, path7, NULL));
01980 _dbus_assert (find_subtree (tree, path8, NULL));
01981
01982 _dbus_object_tree_unregister_and_unlock (tree, path3);
01983 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path3) == NULL);
01984
01985 _dbus_assert (!find_subtree (tree, path0, NULL));
01986 _dbus_assert (!find_subtree (tree, path1, NULL));
01987 _dbus_assert (!find_subtree (tree, path2, NULL));
01988 _dbus_assert (!find_subtree (tree, path3, NULL));
01989 _dbus_assert (find_subtree (tree, path4, NULL));
01990 _dbus_assert (find_subtree (tree, path5, NULL));
01991 _dbus_assert (find_subtree (tree, path6, NULL));
01992 _dbus_assert (find_subtree (tree, path7, NULL));
01993 _dbus_assert (find_subtree (tree, path8, NULL));
01994
01995 _dbus_object_tree_unregister_and_unlock (tree, path4);
01996 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path4) == NULL);
01997
01998 _dbus_assert (!find_subtree (tree, path0, NULL));
01999 _dbus_assert (!find_subtree (tree, path1, NULL));
02000 _dbus_assert (!find_subtree (tree, path2, NULL));
02001 _dbus_assert (!find_subtree (tree, path3, NULL));
02002 _dbus_assert (!find_subtree (tree, path4, NULL));
02003 _dbus_assert (find_subtree (tree, path5, NULL));
02004 _dbus_assert (find_subtree (tree, path6, NULL));
02005 _dbus_assert (find_subtree (tree, path7, NULL));
02006 _dbus_assert (find_subtree (tree, path8, NULL));
02007
02008 _dbus_object_tree_unregister_and_unlock (tree, path5);
02009 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path5) == NULL);
02010
02011 _dbus_assert (!find_subtree (tree, path0, NULL));
02012 _dbus_assert (!find_subtree (tree, path1, NULL));
02013 _dbus_assert (!find_subtree (tree, path2, NULL));
02014 _dbus_assert (!find_subtree (tree, path3, NULL));
02015 _dbus_assert (!find_subtree (tree, path4, NULL));
02016 _dbus_assert (!find_subtree (tree, path5, NULL));
02017 _dbus_assert (find_subtree (tree, path6, NULL));
02018 _dbus_assert (find_subtree (tree, path7, NULL));
02019 _dbus_assert (find_subtree (tree, path8, NULL));
02020
02021 _dbus_object_tree_unregister_and_unlock (tree, path6);
02022 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path6) == NULL);
02023
02024 _dbus_assert (!find_subtree (tree, path0, NULL));
02025 _dbus_assert (!find_subtree (tree, path1, NULL));
02026 _dbus_assert (!find_subtree (tree, path2, NULL));
02027 _dbus_assert (!find_subtree (tree, path3, NULL));
02028 _dbus_assert (!find_subtree (tree, path4, NULL));
02029 _dbus_assert (!find_subtree (tree, path5, NULL));
02030 _dbus_assert (!find_subtree (tree, path6, NULL));
02031 _dbus_assert (find_subtree (tree, path7, NULL));
02032 _dbus_assert (find_subtree (tree, path8, NULL));
02033
02034 _dbus_object_tree_unregister_and_unlock (tree, path7);
02035 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path7) == NULL);
02036
02037 _dbus_assert (!find_subtree (tree, path0, NULL));
02038 _dbus_assert (!find_subtree (tree, path1, NULL));
02039 _dbus_assert (!find_subtree (tree, path2, NULL));
02040 _dbus_assert (!find_subtree (tree, path3, NULL));
02041 _dbus_assert (!find_subtree (tree, path4, NULL));
02042 _dbus_assert (!find_subtree (tree, path5, NULL));
02043 _dbus_assert (!find_subtree (tree, path6, NULL));
02044 _dbus_assert (!find_subtree (tree, path7, NULL));
02045 _dbus_assert (find_subtree (tree, path8, NULL));
02046
02047 _dbus_object_tree_unregister_and_unlock (tree, path8);
02048 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path8) == NULL);
02049
02050 _dbus_assert (!find_subtree (tree, path0, NULL));
02051 _dbus_assert (!find_subtree (tree, path1, NULL));
02052 _dbus_assert (!find_subtree (tree, path2, NULL));
02053 _dbus_assert (!find_subtree (tree, path3, NULL));
02054 _dbus_assert (!find_subtree (tree, path4, NULL));
02055 _dbus_assert (!find_subtree (tree, path5, NULL));
02056 _dbus_assert (!find_subtree (tree, path6, NULL));
02057 _dbus_assert (!find_subtree (tree, path7, NULL));
02058 _dbus_assert (!find_subtree (tree, path8, NULL));
02059
02060 i = 0;
02061 while (i < (int) _DBUS_N_ELEMENTS (tree_test_data))
02062 {
02063 _dbus_assert (tree_test_data[i].handler_unregistered);
02064 _dbus_assert (!tree_test_data[i].message_handled);
02065 ++i;
02066 }
02067
02068
02069 if (!do_register (tree, path2, TRUE, 2, tree_test_data))
02070 goto out;
02071
02072 _dbus_object_tree_unregister_and_unlock (tree, path2);
02073 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
02074 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
02075 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
02076
02077
02078
02079 if (!do_register (tree, path2, TRUE, 2, tree_test_data))
02080 goto out;
02081
02082 _dbus_assert (!find_subtree (tree, path1, NULL));
02083 _dbus_assert (find_subtree_registered_or_unregistered (tree, path1));
02084 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
02085
02086 #if 0
02087
02088 _dbus_object_tree_unregister_and_unlock (tree, path1);
02089 #endif
02090 _dbus_assert (find_subtree (tree, path2, NULL));
02091 _dbus_assert (!find_subtree (tree, path1, NULL));
02092 _dbus_assert (find_subtree_registered_or_unregistered (tree, path1));
02093 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
02094
02095 _dbus_object_tree_unregister_and_unlock (tree, path2);
02096 _dbus_assert (!find_subtree (tree, path2, NULL));
02097 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
02098 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
02099 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
02100
02101
02102
02103
02104 if (!do_register (tree, path1, TRUE, 1, tree_test_data))
02105 goto out;
02106 if (!do_register (tree, path2, TRUE, 2, tree_test_data))
02107 goto out;
02108
02109 _dbus_assert (find_subtree (tree, path1, NULL));
02110 _dbus_assert (find_subtree (tree, path2, NULL));
02111
02112 _dbus_object_tree_unregister_and_unlock (tree, path1);
02113 _dbus_assert (!find_subtree (tree, path1, NULL));
02114 _dbus_assert (find_subtree (tree, path2, NULL));
02115 _dbus_assert (find_subtree_registered_or_unregistered (tree, path1));
02116 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
02117
02118 _dbus_object_tree_unregister_and_unlock (tree, path2);
02119 _dbus_assert (!find_subtree (tree, path1, NULL));
02120 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
02121 _dbus_assert (!find_subtree (tree, path2, NULL));
02122 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
02123 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
02124
02125
02126 if (!_dbus_object_tree_register (tree, TRUE, path2,
02127 &test_vtable,
02128 NULL,
02129 NULL))
02130 goto out;
02131
02132 _dbus_assert (_dbus_object_tree_get_user_data_unlocked (tree, path2) == NULL);
02133 _dbus_object_tree_unregister_and_unlock (tree, path2);
02134 _dbus_assert (!find_subtree (tree, path2, NULL));
02135 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
02136 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
02137 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
02138
02139
02140 if (!do_register (tree, path3, TRUE, 3, tree_test_data))
02141 goto out;
02142
02143 _dbus_object_tree_unregister_and_unlock (tree, path3);
02144 _dbus_assert (!find_subtree (tree, path3, NULL));
02145 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3));
02146 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
02147 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
02148 _dbus_assert (find_subtree_registered_or_unregistered (tree, path0));
02149
02150
02151 if (!do_register (tree, path3, TRUE, 3, tree_test_data))
02152 goto out;
02153 if (!do_register (tree, path4, TRUE, 4, tree_test_data))
02154 goto out;
02155
02156 _dbus_assert (find_subtree (tree, path3, NULL));
02157 _dbus_assert (find_subtree (tree, path4, NULL));
02158
02159 _dbus_object_tree_unregister_and_unlock (tree, path3);
02160 _dbus_assert (!find_subtree (tree, path3, NULL));
02161 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3));
02162 _dbus_assert (find_subtree (tree, path4, NULL));
02163 _dbus_assert (find_subtree_registered_or_unregistered (tree, path4));
02164 _dbus_assert (find_subtree_registered_or_unregistered (tree, path2));
02165 _dbus_assert (find_subtree_registered_or_unregistered (tree, path1));
02166
02167 _dbus_object_tree_unregister_and_unlock (tree, path4);
02168 _dbus_assert (!find_subtree (tree, path4, NULL));
02169 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path4));
02170 _dbus_assert (!find_subtree (tree, path3, NULL));
02171 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path3));
02172 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path2));
02173 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path1));
02174
02175
02176 if (!_dbus_object_tree_register (tree, TRUE, path12,
02177 &test_vtable,
02178 NULL,
02179 NULL))
02180 goto out;
02181
02182 _dbus_assert (find_subtree (tree, path12, NULL));
02183
02184 if (!_dbus_object_tree_register (tree, TRUE, path13,
02185 &test_vtable,
02186 NULL,
02187 NULL))
02188 goto out;
02189
02190 _dbus_assert (find_subtree (tree, path13, NULL));
02191
02192 if (!_dbus_object_tree_register (tree, TRUE, path14,
02193 &test_vtable,
02194 NULL,
02195 NULL))
02196 goto out;
02197
02198 _dbus_assert (find_subtree (tree, path14, NULL));
02199
02200 _dbus_object_tree_unregister_and_unlock (tree, path12);
02201
02202 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path12));
02203 _dbus_assert (find_subtree (tree, path13, NULL));
02204 _dbus_assert (find_subtree (tree, path14, NULL));
02205 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path9));
02206 _dbus_assert (find_subtree_registered_or_unregistered (tree, path5));
02207
02208 if (!_dbus_object_tree_register (tree, TRUE, path12,
02209 &test_vtable,
02210 NULL,
02211 NULL))
02212 goto out;
02213
02214 _dbus_assert (find_subtree (tree, path12, NULL));
02215
02216 _dbus_object_tree_unregister_and_unlock (tree, path13);
02217
02218 _dbus_assert (find_subtree (tree, path12, NULL));
02219 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path13));
02220 _dbus_assert (find_subtree (tree, path14, NULL));
02221 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path10));
02222 _dbus_assert (find_subtree_registered_or_unregistered (tree, path5));
02223
02224 if (!_dbus_object_tree_register (tree, TRUE, path13,
02225 &test_vtable,
02226 NULL,
02227 NULL))
02228 goto out;
02229
02230 _dbus_assert (find_subtree (tree, path13, NULL));
02231
02232 _dbus_object_tree_unregister_and_unlock (tree, path14);
02233
02234 _dbus_assert (find_subtree (tree, path12, NULL));
02235 _dbus_assert (find_subtree (tree, path13, NULL));
02236 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path14));
02237 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path11));
02238 _dbus_assert (find_subtree_registered_or_unregistered (tree, path5));
02239
02240 _dbus_object_tree_unregister_and_unlock (tree, path12);
02241
02242 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path12));
02243 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path9));
02244 _dbus_assert (find_subtree_registered_or_unregistered (tree, path5));
02245
02246 _dbus_object_tree_unregister_and_unlock (tree, path13);
02247
02248 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path13));
02249 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path10));
02250 _dbus_assert (!find_subtree_registered_or_unregistered (tree, path5));
02251
02252 #if 0
02253
02254
02255 _dbus_object_tree_unregister_and_unlock (tree, path0);
02256 _dbus_object_tree_unregister_and_unlock (tree, path1);
02257 _dbus_object_tree_unregister_and_unlock (tree, path2);
02258 _dbus_object_tree_unregister_and_unlock (tree, path3);
02259 _dbus_object_tree_unregister_and_unlock (tree, path4);
02260 #endif
02261
02262
02263
02264 if (!do_register (tree, path0, TRUE, 0, tree_test_data))
02265 goto out;
02266 if (!do_register (tree, path1, FALSE, 1, tree_test_data))
02267 goto out;
02268 if (!do_register (tree, path2, TRUE, 2, tree_test_data))
02269 goto out;
02270 if (!do_register (tree, path3, TRUE, 3, tree_test_data))
02271 goto out;
02272 if (!do_register (tree, path4, TRUE, 4, tree_test_data))
02273 goto out;
02274 if (!do_register (tree, path5, TRUE, 5, tree_test_data))
02275 goto out;
02276 if (!do_register (tree, path6, FALSE, 6, tree_test_data))
02277 goto out;
02278 if (!do_register (tree, path7, TRUE, 7, tree_test_data))
02279 goto out;
02280 if (!do_register (tree, path8, TRUE, 8, tree_test_data))
02281 goto out;
02282
02283 #if 0
02284 spew_tree (tree);
02285 #endif
02286
02287 if (!do_test_dispatch (tree, path0, 0, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
02288 goto out;
02289 if (!do_test_dispatch (tree, path1, 1, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
02290 goto out;
02291 if (!do_test_dispatch (tree, path2, 2, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
02292 goto out;
02293 if (!do_test_dispatch (tree, path3, 3, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
02294 goto out;
02295 if (!do_test_dispatch (tree, path4, 4, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
02296 goto out;
02297 if (!do_test_dispatch (tree, path5, 5, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
02298 goto out;
02299 if (!do_test_dispatch (tree, path6, 6, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
02300 goto out;
02301 if (!do_test_dispatch (tree, path7, 7, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
02302 goto out;
02303 if (!do_test_dispatch (tree, path8, 8, tree_test_data, _DBUS_N_ELEMENTS (tree_test_data)))
02304 goto out;
02305
02306 out:
02307 if (tree)
02308 {
02309
02310 _dbus_object_tree_ref (tree);
02311 _dbus_object_tree_unref (tree);
02312 _dbus_object_tree_unref (tree);
02313 }
02314
02315 return TRUE;
02316 }
02317
02323 dbus_bool_t
02324 _dbus_object_tree_test (void)
02325 {
02326 _dbus_test_oom_handling ("object tree",
02327 object_tree_test_iteration,
02328 NULL);
02329
02330 return TRUE;
02331 }
02332
02333 #endif
02334
02335 #endif