From 0161a3c5637a0c0092bf54c436bb3d6508d7df26 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Fri, 9 May 2014 20:03:02 +0200 Subject: SBUS: Add an async request to retrieve the caller ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an async request sbus_get_sender_id_{send,recv} that allows retrieval of UID based on "sender" as returned by dbus_message_get_sender(). The UID is an int64_t to be able to use "-1" to as a fallback value for uknown or error cases. The unit test is added as a standalone one, not part of the sbus_tests because the request, and by extension the unit test relies on being connected to the system bus, which is very unlikely to work in a build system. Reviewed-by: Pavel Březina Reviewed-by: Stef Walter --- src/tests/cmocka/sbus_internal_tests.c | 268 +++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 src/tests/cmocka/sbus_internal_tests.c (limited to 'src/tests') diff --git a/src/tests/cmocka/sbus_internal_tests.c b/src/tests/cmocka/sbus_internal_tests.c new file mode 100644 index 000000000..6100037ea --- /dev/null +++ b/src/tests/cmocka/sbus_internal_tests.c @@ -0,0 +1,268 @@ +/* + Authors: + Jakub Hrozek + + Copyright (C) 2014 Red Hat + + SSSD tests: SBUS internals + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include + +#include "util/util.h" +#include "responder/common/responder.h" +#include "tests/cmocka/common_mock.h" +#include "sbus/sssd_dbus_private.h" + +struct sbus_get_id_ctx { + struct sss_test_ctx *stc; + struct sbus_connection *conn; + + DBusPendingCallNotifyFunction reply_handler; + void *reply_pvt; + int last_hash_lookup; + + int64_t expected; +}; + +struct sbus_get_id_ctx *global_test_ctx; + +DBusConnection * +__wrap_dbus_bus_get(DBusBusType type, + DBusError *error) +{ + /* just don't return NULL */ + return (DBusConnection *) 0x42; +} + +void +__wrap_dbus_connection_set_exit_on_disconnect(DBusConnection *connection, + dbus_bool_t exit_on_disconnect) +{ + return; +} + +void __wrap_dbus_pending_call_unref(DBusPendingCall *pending) +{ + return; +} + +void __wrap_dbus_message_unref(DBusMessage *message) +{ + return; +} + +void __wrap_dbus_connection_unref(DBusConnection *connection) +{ + return; +} + +DBusMessage* +__wrap_dbus_pending_call_steal_reply(DBusPendingCall *pending) +{ + return sss_mock_ptr_type(DBusMessage *); +} + +int __real_hash_lookup(hash_table_t *table, hash_key_t *key, hash_value_t *value); + +int __wrap_hash_lookup(hash_table_t *table, hash_key_t *key, hash_value_t *value) +{ + global_test_ctx->last_hash_lookup = __real_hash_lookup(table, key, value); + return global_test_ctx->last_hash_lookup; +} + +static void fake_sbus_msg_done(struct tevent_context *ev, + struct tevent_immediate *imm, + void *pvt) +{ + struct sbus_get_id_ctx *test_ctx = talloc_get_type(pvt, + struct sbus_get_id_ctx); + talloc_free(imm); + test_ctx->reply_handler(NULL, test_ctx->reply_pvt); +} + +int sss_dbus_conn_send(DBusConnection *dbus_conn, + DBusMessage *msg, + int timeout_ms, + DBusPendingCallNotifyFunction reply_handler, + void *pvt, + DBusPendingCall **pending) +{ + struct tevent_immediate *imm; + + global_test_ctx->reply_pvt = pvt; + global_test_ctx->reply_handler = reply_handler; + + imm = tevent_create_immediate(global_test_ctx->stc->ev); + assert_non_null(imm); + tevent_schedule_immediate(imm, global_test_ctx->stc->ev, fake_sbus_msg_done, global_test_ctx); + + return EOK; +} + +void sbus_get_id_test_setup(void **state) +{ + struct sbus_get_id_ctx *test_ctx; + int ret; + + test_ctx = talloc(global_talloc_context, struct sbus_get_id_ctx); + assert_non_null(test_ctx); + + test_ctx->conn = talloc(test_ctx, struct sbus_connection); + assert_non_null(test_ctx->conn); + test_ctx->conn->connection_type = SBUS_CONN_TYPE_SYSBUS; + ret = sss_hash_create(test_ctx->conn, 32, &test_ctx->conn->clients); + assert_int_equal(ret, EOK); + + test_ctx->stc = create_ev_test_ctx(test_ctx); + assert_non_null(test_ctx->stc); + + *state = test_ctx; + global_test_ctx = test_ctx; +} + +void sbus_int_test_get_uid_done(struct tevent_req *req) +{ + errno_t ret; + int64_t uid; + struct sbus_get_id_ctx *test_ctx = tevent_req_callback_data(req, + struct sbus_get_id_ctx); + + ret = sbus_get_sender_id_recv(req, &uid); + talloc_free(req); + assert_int_equal(ret, EOK); + + test_ctx->stc->done = true; + assert_int_equal(uid, test_ctx->expected); +} + +void sbus_int_test_get_uid(void **state) +{ + errno_t ret; + struct tevent_req *req; + DBusMessage *reply; + struct sbus_get_id_ctx *test_ctx = talloc_get_type(*state, + struct sbus_get_id_ctx); + + uint32_t uid; + + test_ctx->expected = 42; + uid = test_ctx->expected; + + reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL); + assert_non_null(reply); + dbus_message_append_args(reply, + DBUS_TYPE_UINT32, &uid, + DBUS_TYPE_INVALID); + will_return(__wrap_dbus_pending_call_steal_reply, reply); + + req = sbus_get_sender_id_send(test_ctx, test_ctx->stc->ev, + test_ctx->conn, __FILE__); + tevent_req_set_callback(req, sbus_int_test_get_uid_done, test_ctx); + + ret = test_ev_loop(test_ctx->stc); + assert_int_equal(ret, EOK); + assert_int_equal(test_ctx->last_hash_lookup, HASH_ERROR_KEY_NOT_FOUND); + + /* Now do the same lookup again, just make sure the result was cached */ + req = sbus_get_sender_id_send(test_ctx, test_ctx->stc->ev, + test_ctx->conn, __FILE__); + tevent_req_set_callback(req, sbus_int_test_get_uid_done, test_ctx); + + ret = test_ev_loop(test_ctx->stc); + assert_int_equal(ret, EOK); + assert_int_equal(test_ctx->last_hash_lookup, HASH_SUCCESS); +} + +void sbus_int_test_get_uid_no_sender_done(struct tevent_req *req) +{ + errno_t ret; + int64_t uid; + struct sbus_get_id_ctx *test_ctx = tevent_req_callback_data(req, + struct sbus_get_id_ctx); + + ret = sbus_get_sender_id_recv(req, &uid); + talloc_free(req); + assert_int_equal(ret, ERR_SBUS_NO_SENDER); + test_ctx->stc->done = true; +} + +void sbus_int_test_get_uid_no_sender(void **state) +{ + errno_t ret; + struct tevent_req *req; + struct sbus_get_id_ctx *test_ctx = talloc_get_type(*state, + struct sbus_get_id_ctx); + + uint32_t uid; + + test_ctx->expected = -1; + uid = test_ctx->expected; + + req = sbus_get_sender_id_send(test_ctx, test_ctx->stc->ev, + test_ctx->conn, NULL); + tevent_req_set_callback(req, sbus_int_test_get_uid_no_sender_done, test_ctx); + + ret = test_ev_loop(test_ctx->stc); + assert_int_equal(ret, EOK); +} + +void sbus_get_id_test_teardown(void **state) +{ + struct sbus_get_id_ctx *test_ctx = talloc_get_type(*state, + struct sbus_get_id_ctx); + talloc_free(test_ctx); +} + +int main(int argc, const char *argv[]) +{ + poptContext pc; + int opt; + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_DEBUG_OPTS + POPT_TABLEEND + }; + + const UnitTest tests[] = { + unit_test_setup_teardown(sbus_int_test_get_uid, + sbus_get_id_test_setup, + sbus_get_id_test_teardown), + unit_test_setup_teardown(sbus_int_test_get_uid_no_sender, + sbus_get_id_test_setup, + sbus_get_id_test_teardown), + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ + debug_level = SSSDBG_INVALID; + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + } + poptFreeContext(pc); + + DEBUG_INIT(debug_level); + tests_set_cwd(); + return run_tests(tests); +} -- cgit