/* * * Embedded Linux library * * Copyright (C) 2011-2014 Intel Corporation. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifdef HAVE_CONFIG_H #include #endif #define _GNU_SOURCE #include #include #include #include #include #include #include "ell/dbus-private.h" #ifndef WAIT_ANY #define WAIT_ANY (-1) /* Any process */ #endif #define TEST_BUS_ADDRESS "unix:path=/tmp/ell-test-bus" #define ROOT_PATH "/ell/test" static pid_t dbus_daemon_pid = -1; static bool start_dbus_daemon(void) { char *prg_argv[5]; char *prg_envp[1]; pid_t pid; prg_argv[0] = "dbus-daemon"; prg_argv[1] = "--nopidfile"; prg_argv[2] = "--nofork"; prg_argv[3] = "--config-file=" UNITDIR "dbus.conf"; prg_argv[4] = NULL; prg_envp[0] = NULL; l_info("launching dbus-daemon"); pid = fork(); if (pid < 0) { l_error("failed to fork new process"); return false; } if (pid == 0) { execvpe(prg_argv[0], prg_argv, prg_envp); exit(EXIT_SUCCESS); } l_info("dbus-daemon process %d created", pid); dbus_daemon_pid = pid; return true; } static void signal_handler(uint32_t signo, void *user_data) { switch (signo) { case SIGINT: case SIGTERM: l_info("Terminate"); l_main_quit(); break; } } static void sigchld_handler(void *user_data) { while (1) { pid_t pid; int status; pid = waitpid(WAIT_ANY, &status, WNOHANG); if (pid < 0 || pid == 0) break; l_info("process %d terminated with status=%d\n", pid, status); if (pid == dbus_daemon_pid) { dbus_daemon_pid = -1; l_main_quit(); } } } static struct l_dbus *dbus; struct dbus_test { const char *name; void (*start)(struct l_dbus *dbus, void *); void *data; }; static bool success; static struct l_queue *tests; static const struct l_queue_entry *current; static void test_add(const char *name, void (*start)(struct l_dbus *dbus, void *), void *test_data) { struct dbus_test *test = l_new(struct dbus_test, 1); test->name = name; test->start = start; test->data = test_data; if (!tests) tests = l_queue_new(); l_queue_push_tail(tests, test); } static void test_next() { struct dbus_test *test; if (current) current = current->next; else current = l_queue_get_entries(tests); if (!current) { success = true; l_main_quit(); return; } test = current->data; l_info("TEST: %s", test->name); test->start(dbus, test->data); } #define test_assert(cond) \ do { \ if (!(cond)) { \ l_info("TEST FAILED in %s at %s:%i: %s", \ __func__, __FILE__, __LINE__, \ L_STRINGIFY(cond)); \ l_main_quit(); \ return; \ } \ } while (0) static void request_name_callback(struct l_dbus *dbus, bool success, bool queued, void *user_data) { l_info("request name result=%s", success ? (queued ? "queued" : "success") : "failed"); test_next(); } static void ready_callback(void *user_data) { l_info("ready"); l_dbus_name_acquire(dbus, "org.test", false, false, false, request_name_callback, NULL); } static void disconnect_callback(void *user_data) { l_info("Disconnected from DBus"); l_main_quit(); } static bool test_string_getter(struct l_dbus *dbus, struct l_dbus_message *message, struct l_dbus_message_builder *builder, void *user_data) { return l_dbus_message_builder_append_basic(builder, 's', "foo"); } static bool setter_called; static bool int_optional; static struct l_dbus_message *test_string_setter(struct l_dbus *dbus, struct l_dbus_message *message, struct l_dbus_message_iter *new_value, l_dbus_property_complete_cb_t complete, void *user_data) { const char *strvalue; if (!l_dbus_message_iter_get_variant(new_value, "s", &strvalue)) goto done; if (strcmp(strvalue, "bar")) goto done; setter_called = true; done: complete(dbus, message, NULL); return NULL; } static bool test_int_getter(struct l_dbus *dbus, struct l_dbus_message *message, struct l_dbus_message_builder *builder, void *user_data) { uint32_t u; if (int_optional) return false; u = 5; return l_dbus_message_builder_append_basic(builder, 'u', &u); } static struct l_dbus_message *test_int_setter(struct l_dbus *dbus, struct l_dbus_message *message, struct l_dbus_message_iter *new_value, l_dbus_property_complete_cb_t complete, void *user_data) { uint32_t u; if (!l_dbus_message_iter_get_variant(new_value, "u", &u)) goto done; if (u != 42) goto done; setter_called = true; done: return l_dbus_message_new_method_return(message); } static struct l_dbus_message *test_error_setter(struct l_dbus *dbus, struct l_dbus_message *message, struct l_dbus_message_iter *new_value, l_dbus_property_complete_cb_t complete, void *user_data) { setter_called = true; return l_dbus_message_new_error(message, "org.test.Error", "Error"); } static bool test_path_getter(struct l_dbus *dbus, struct l_dbus_message *message, struct l_dbus_message_builder *builder, void *user_data) { return l_dbus_message_builder_append_basic(builder, 'o', "/foo/bar"); } static void setup_test_interface(struct l_dbus_interface *interface) { l_dbus_interface_property(interface, "String", L_DBUS_PROPERTY_FLAG_AUTO_EMIT, "s", test_string_getter, test_string_setter); l_dbus_interface_property(interface, "Integer", L_DBUS_PROPERTY_FLAG_AUTO_EMIT, "u", test_int_getter, test_int_setter); l_dbus_interface_property(interface, "Readonly", 0, "s", test_string_getter, NULL); l_dbus_interface_property(interface, "SetError", 0, "s", test_string_getter, test_error_setter); l_dbus_interface_property(interface, "Path", 0, "o", test_path_getter, NULL); } static void validate_properties(struct l_dbus_message_iter *dict) { struct l_dbus_message_iter variant; const char *name, *strval; uint32_t intval; test_assert(l_dbus_message_iter_next_entry(dict, &name, &variant)); test_assert(!strcmp(name, "String")); test_assert(l_dbus_message_iter_get_variant(&variant, "s", &strval)); test_assert(!strcmp(strval, "foo")); if (!int_optional) { test_assert(l_dbus_message_iter_next_entry(dict, &name, &variant)); test_assert(!strcmp(name, "Integer")); test_assert(l_dbus_message_iter_get_variant(&variant, "u", &intval)); test_assert(intval == 5); } test_assert(l_dbus_message_iter_next_entry(dict, &name, &variant)); test_assert(!strcmp(name, "Readonly")); test_assert(l_dbus_message_iter_get_variant(&variant, "s", &strval)); test_assert(!strcmp(strval, "foo")); test_assert(l_dbus_message_iter_next_entry(dict, &name, &variant)); test_assert(!strcmp(name, "SetError")); test_assert(l_dbus_message_iter_get_variant(&variant, "s", &strval)); test_assert(!strcmp(strval, "foo")); test_assert(l_dbus_message_iter_next_entry(dict, &name, &variant)); test_assert(!strcmp(name, "Path")); test_assert(l_dbus_message_iter_get_variant(&variant, "o", &strval)); test_assert(!strcmp(strval, "/foo/bar")); test_assert(!l_dbus_message_iter_next_entry(dict, &name, &variant)); } static void get_properties_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message_iter dict; test_assert(!l_dbus_message_get_error(message, NULL, NULL)); test_assert(l_dbus_message_get_arguments(message, "a{sv}", &dict)); validate_properties(&dict); test_next(); } static void test_old_get(struct l_dbus *dbus, void *test_data) { struct l_dbus_message *call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.test", "GetProperties"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "")); test_assert(l_dbus_send_with_reply(dbus, call, get_properties_callback, NULL, NULL)); } static void test_old_optional_get(struct l_dbus *dbus, void *test_data) { struct l_dbus_message *call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.test", "GetProperties"); int_optional = true; test_assert(call); test_assert(l_dbus_message_set_arguments(call, "")); test_assert(l_dbus_send_with_reply(dbus, call, get_properties_callback, NULL, NULL)); } static void set_invalid_callback(struct l_dbus_message *message, void *user_data) { test_assert(l_dbus_message_get_error(message, NULL, NULL)); test_assert(!setter_called); test_next(); } static void old_set_error_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(l_dbus_message_get_error(message, NULL, NULL)); test_assert(setter_called); setter_called = false; call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.test", "SetProperty"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "sv", "Invalid", "s", "bar")); test_assert(l_dbus_send_with_reply(dbus, call, set_invalid_callback, NULL, NULL)); } static void old_set_ro_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(l_dbus_message_get_error(message, NULL, NULL)); test_assert(!setter_called); call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.test", "SetProperty"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "sv", "SetError", "s", "bar")); test_assert(l_dbus_send_with_reply(dbus, call, old_set_error_callback, NULL, NULL)); } static void old_set_int_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(!l_dbus_message_get_error(message, NULL, NULL)); test_assert(l_dbus_message_get_arguments(message, "")); test_assert(setter_called); setter_called = false; call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.test", "SetProperty"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "sv", "Readonly", "s", "bar")); test_assert(l_dbus_send_with_reply(dbus, call, old_set_ro_callback, NULL, NULL)); } static void old_set_string_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(!l_dbus_message_get_error(message, NULL, NULL)); test_assert(l_dbus_message_get_arguments(message, "")); test_assert(setter_called); setter_called = false; call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.test", "SetProperty"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "sv", "Integer", "u", 42)); test_assert(l_dbus_send_with_reply(dbus, call, old_set_int_callback, NULL, NULL)); } static void test_old_set(struct l_dbus *dbus, void *test_data) { struct l_dbus_message *call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.test", "SetProperty"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "sv", "String", "s", "bar")); test_assert(!setter_called); test_assert(l_dbus_send_with_reply(dbus, call, old_set_string_callback, NULL, NULL)); } static void new_get_invalid_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(l_dbus_message_get_error(message, NULL, NULL)); call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "GetAll"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "s", "org.test")); test_assert(l_dbus_send_with_reply(dbus, call, get_properties_callback, NULL, NULL)); } static void new_get_bad_if_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(l_dbus_message_get_error(message, NULL, NULL)); call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "Get"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "ss", "org.test", "Invalid")); test_assert(l_dbus_send_with_reply(dbus, call, new_get_invalid_callback, NULL, NULL)); } static void new_get_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message_iter variant; const char *strval; struct l_dbus_message *call; test_assert(!l_dbus_message_get_error(message, NULL, NULL)); test_assert(l_dbus_message_get_arguments(message, "v", &variant)); test_assert(l_dbus_message_iter_get_variant(&variant, "s", &strval)); test_assert(!strcmp(strval, "foo")); call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "Get"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "ss", "org.invalid", "String")); test_assert(l_dbus_send_with_reply(dbus, call, new_get_bad_if_callback, NULL, NULL)); } static void test_new_get(struct l_dbus *dbus, void *test_data) { struct l_dbus_message *call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "Get"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "ss", "org.test", "String")); test_assert(l_dbus_send_with_reply(dbus, call, new_get_callback, NULL, NULL)); } static void new_set_bad_if_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(l_dbus_message_get_error(message, NULL, NULL)); test_assert(!setter_called); call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "Set"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "ssv", "org.test", "Invalid", "s", "bar")); test_assert(l_dbus_send_with_reply(dbus, call, set_invalid_callback, NULL, NULL)); } static void new_set_error_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(l_dbus_message_get_error(message, NULL, NULL)); test_assert(setter_called); setter_called = false; call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "Set"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "ssv", "org.invalid", "String", "s", "bar")); test_assert(l_dbus_send_with_reply(dbus, call, new_set_bad_if_callback, NULL, NULL)); } static void new_set_ro_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(l_dbus_message_get_error(message, NULL, NULL)); test_assert(!setter_called); call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "Set"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "ssv", "org.test", "SetError", "s", "bar")); test_assert(l_dbus_send_with_reply(dbus, call, new_set_error_callback, NULL, NULL)); } static void new_set_int_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(!l_dbus_message_get_error(message, NULL, NULL)); test_assert(l_dbus_message_get_arguments(message, "")); test_assert(setter_called); setter_called = false; call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "Set"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "ssv", "org.test", "Readonly", "s", "bar")); test_assert(l_dbus_send_with_reply(dbus, call, new_set_ro_callback, NULL, NULL)); } static void new_set_string_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message *call; test_assert(!l_dbus_message_get_error(message, NULL, NULL)); test_assert(l_dbus_message_get_arguments(message, "")); test_assert(setter_called); setter_called = false; call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "Set"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "ssv", "org.test", "Integer", "u", 42)); test_assert(l_dbus_send_with_reply(dbus, call, new_set_int_callback, NULL, NULL)); } static void test_new_set(struct l_dbus *dbus, void *test_data) { struct l_dbus_message *call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "Set"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "ssv", "org.test", "String", "s", "bar")); test_assert(!setter_called); test_assert(l_dbus_send_with_reply(dbus, call, new_set_string_callback, NULL, NULL)); } static struct l_timeout *signal_timeout; static void signal_timeout_callback(struct l_timeout *timeout, void *user_data) { signal_timeout = NULL; test_assert(false); } static bool old_signal_received, new_signal_received; static bool signal_success; static void test_check_signal_success(void) { struct l_dbus_message *call; if (!old_signal_received || !new_signal_received) return; l_timeout_remove(signal_timeout); signal_timeout = NULL; if (!signal_success) { signal_success = true; /* Now repeat the test for the signal triggered by Set */ old_signal_received = false; new_signal_received = false; signal_timeout = l_timeout_create(1, signal_timeout_callback, NULL, NULL); test_assert(signal_timeout); call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "Set"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "ssv", "org.test", "String", "s", "bar")); test_assert(!setter_called); test_assert(l_dbus_send(dbus, call)); } else { test_assert(setter_called); setter_called = false; test_next(); } } static void test_old_signal_callback(struct l_dbus_message *message, void *user_data) { const char *property, *value; struct l_dbus_message_iter variant; if (!signal_timeout) return; test_assert(l_dbus_message_get_arguments(message, "sv", &property, &variant)); test_assert(!strcmp(property, "String")); test_assert(l_dbus_message_iter_get_variant(&variant, "s", &value)); test_assert(!strcmp(value, "foo")); test_assert(!old_signal_received); old_signal_received = true; test_check_signal_success(); } static void test_new_signal_callback(struct l_dbus_message *message, void *user_data) { const char *interface, *property, *value; struct l_dbus_message_iter variant, changed, invalidated; if (!signal_timeout) return; test_assert(l_dbus_message_get_arguments(message, "sa{sv}as", &interface, &changed, &invalidated)); test_assert(l_dbus_message_iter_next_entry(&changed, &property, &variant)); test_assert(!strcmp(property, "String")); test_assert(l_dbus_message_iter_get_variant(&variant, "s", &value)); test_assert(!strcmp(value, "foo")); test_assert(!l_dbus_message_iter_next_entry(&changed, &property, &variant)); test_assert(!l_dbus_message_iter_next_entry(&invalidated, &property)); test_assert(!new_signal_received); new_signal_received = true; test_check_signal_success(); } static void test_property_signals(struct l_dbus *dbus, void *test_data) { old_signal_received = false; new_signal_received = false; signal_timeout = l_timeout_create(1, signal_timeout_callback, NULL, NULL); test_assert(signal_timeout); test_assert(l_dbus_property_changed(dbus, ROOT_PATH"/test", "org.test", "String")); } static void object_manager_callback(struct l_dbus_message *message, void *user_data) { struct l_dbus_message_iter objects, interfaces, properties, variant; const char *path, *interface, *name; bool object_manager_found = false; bool test_found = false; bool properties_found = false; test_assert(!l_dbus_message_get_error(message, NULL, NULL)); test_assert(l_dbus_message_get_arguments(message, "a{oa{sa{sv}}}", &objects)); while (l_dbus_message_iter_next_entry(&objects, &path, &interfaces)) { while (l_dbus_message_iter_next_entry(&interfaces, &interface, &properties)) { if (!strcmp(path, ROOT_PATH) && !strcmp(interface, "org.freedesktop.DBus.ObjectManager")) { test_assert(!object_manager_found); object_manager_found = true; test_assert(!l_dbus_message_iter_next_entry( &properties, &name, &variant)); } if (!strcmp(path, ROOT_PATH"/test") && !strcmp(interface, "org.freedesktop.DBus.Properties")) { test_assert(!properties_found); properties_found = true; test_assert(!l_dbus_message_iter_next_entry( &properties, &name, &variant)); } if (!strcmp(path, ROOT_PATH"/test") && !strcmp(interface, "org.test")) { test_assert(!test_found); test_found = true; validate_properties(&properties); } } } test_assert(object_manager_found && test_found && properties_found); test_next(); } static void test_object_manager_get(struct l_dbus *dbus, void *test_data) { struct l_dbus_message *call = l_dbus_message_new_method_call(dbus, "org.test", ROOT_PATH, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); test_assert(call); test_assert(l_dbus_message_set_arguments(call, "")); test_assert(l_dbus_send_with_reply(dbus, call, object_manager_callback, NULL, NULL)); } static struct l_timeout *om_signal_timeout; static void om_signal_timeout_callback(struct l_timeout *timeout, void *user_data) { om_signal_timeout = NULL; test_assert(false); } static bool expect_interfaces_added; static void om_signal_callback(struct l_dbus_message *message, void *user_data) { const char *path, *interface, *member; struct l_dbus_message_iter interfaces, properties; if (!om_signal_timeout) return; member = l_dbus_message_get_member(message); if (!strcmp(member, "InterfacesAdded")) test_assert(expect_interfaces_added); else if (!strcmp(member, "InterfacesRemoved")) test_assert(!expect_interfaces_added); else return; if (!strcmp(member, "InterfacesAdded")) { test_assert(l_dbus_message_get_arguments(message, "oa{sa{sv}}", &path, &interfaces)); test_assert(!strcmp(path, ROOT_PATH"/test2")); test_assert(l_dbus_message_iter_next_entry(&interfaces, &interface, &properties)); test_assert(!strcmp(interface, "org.test")); validate_properties(&properties); test_assert(!l_dbus_message_iter_next_entry(&interfaces, &interface, &properties)); /* Now repeat the test for the InterfacesRemoved signal */ expect_interfaces_added = false; test_assert(l_dbus_unregister_object(dbus, ROOT_PATH"/test2")); } else { test_assert(l_dbus_message_get_arguments(message, "oas", &path, &interfaces)); test_assert(!strcmp(path, ROOT_PATH"/test2")); test_assert(l_dbus_message_iter_next_entry(&interfaces, &interface)); test_assert(!strcmp(interface, "org.test")); test_assert(!l_dbus_message_iter_next_entry(&interfaces, &interface)); l_timeout_remove(om_signal_timeout); om_signal_timeout = NULL; test_next(); } } static void test_object_manager_signals(struct l_dbus *dbus, void *test_data) { om_signal_timeout = l_timeout_create(1, om_signal_timeout_callback, NULL, NULL); test_assert(om_signal_timeout); expect_interfaces_added = true; test_assert(l_dbus_object_add_interface(dbus, ROOT_PATH"/test2", "org.test", NULL)); } static void test_run(void) { success = false; l_dbus_set_ready_handler(dbus, ready_callback, dbus, NULL); l_dbus_set_disconnect_handler(dbus, disconnect_callback, NULL, NULL); if (!l_dbus_register_interface(dbus, "org.test", setup_test_interface, NULL, true)) { l_info("Unable to register interface"); return; } if (!l_dbus_object_add_interface(dbus, ROOT_PATH"/test", "org.test", NULL)) { l_info("Unable to instantiate interface"); return; } if (!l_dbus_object_add_interface(dbus, ROOT_PATH"/test", "org.freedesktop.DBus.Properties", NULL)) { l_info("Unable to instantiate the properties interface"); return; } l_dbus_add_signal_watch(dbus, "org.test", ROOT_PATH"/test", "org.test", "PropertyChanged", L_DBUS_MATCH_NONE, test_old_signal_callback, NULL); l_dbus_add_signal_watch(dbus, "org.test", ROOT_PATH"/test", "org.freedesktop.DBus.Properties", "PropertiesChanged", L_DBUS_MATCH_ARGUMENT(0), "org.test", L_DBUS_MATCH_NONE, test_new_signal_callback, NULL); if (!l_dbus_object_manager_enable(dbus, ROOT_PATH)) { l_info("Unable to enable Object Manager"); return; } l_dbus_add_signal_watch(dbus, "org.test", ROOT_PATH, "org.freedesktop.DBus.ObjectManager", NULL, L_DBUS_MATCH_NONE, om_signal_callback, NULL); l_main_run_with_signal(signal_handler, NULL); } int main(int argc, char *argv[]) { struct l_signal *sigchld; int i; if (!l_main_init()) return -1; test_add("Legacy properties get", test_old_get, NULL); test_add("Legacy properties set", test_old_set, NULL); test_add("Legacy optional property", test_old_optional_get, NULL); test_add("org.freedesktop.DBus.Properties get", test_new_get, NULL); test_add("org.freedesktop.DBus.Properties set", test_new_set, NULL); test_add("Property changed signals", test_property_signals, NULL); test_add("org.freedesktop.DBus.ObjectManager get", test_object_manager_get, NULL); test_add("org.freedesktop.DBus.ObjectManager signals", test_object_manager_signals, NULL); sigchld = l_signal_create(SIGCHLD, sigchld_handler, NULL, NULL); l_log_set_stderr(); if (!start_dbus_daemon()) return -1; for (i = 0; i < 10; i++) { usleep(200 * 1000); dbus = l_dbus_new(TEST_BUS_ADDRESS); if (dbus) break; } if (!dbus) goto done; test_run(); l_dbus_destroy(dbus); done: if (dbus_daemon_pid > 0) kill(dbus_daemon_pid, SIGKILL); l_signal_remove(sigchld); l_queue_destroy(tests, l_free); l_main_exit(); if (!success) abort(); return 0; }