diff options
Diffstat (limited to 'server/tests')
-rw-r--r-- | server/tests/infopipe-tests.c | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/server/tests/infopipe-tests.c b/server/tests/infopipe-tests.c new file mode 100644 index 00000000..2aaa653a --- /dev/null +++ b/server/tests/infopipe-tests.c @@ -0,0 +1,320 @@ +/* + SSSD + + InfoPipe + + Copyright (C) Stephen Gallagher <sgallagh@redhat.com> 2009 + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <check.h> +#include <talloc.h> +#include <tevent.h> +#include <popt.h> +#include <dbus/dbus.h> +#include "util/util.h" +#include "confdb/confdb.h" +#include "sbus/sssd_dbus.h" +#include "infopipe/infopipe.h" + +#define INFP_TEST_DBUS_NAME "org.freeipa.sssd.infopipe1.test" +#define TEST_TIMEOUT 30000 /* 30 seconds */ + +static int setup_infp_tests(DBusConnection **bus) +{ + DBusError error; + int ret; + + /* Connect to the system bus */ + dbus_error_init(&error); + *bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (*bus == NULL) { + fail("Could not connect to the system bus. %s:%s", error.name, error.message); + dbus_error_free(&error); + return EIO; + } + + /* Abort the tests if disconnect occurs */ + dbus_connection_set_exit_on_disconnect(*bus, TRUE); + + ret = dbus_bus_request_name(*bus, + INFP_TEST_DBUS_NAME, + /* We want exclusive access */ + DBUS_NAME_FLAG_DO_NOT_QUEUE, + &error); + if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + /* We were unable to register on the system bus */ + fail("Unable to request name on the system bus. Error: %s:%s\n", error.name, error.message); + dbus_error_free(&error); + return EIO; + } + return EOK; +} + +static int teardown_infp_tests(DBusConnection *bus) +{ + dbus_connection_unref(bus); + return EOK; +} + +#define INTROSPECT_CHUNK_SIZE 4096 +START_TEST(test_infp_introspect) +{ + TALLOC_CTX *tmp_ctx; + DBusConnection *bus; + DBusError error; + DBusMessage *introspect_req; + DBusMessage *reply; + FILE *xml_stream; + char *chunk; + char *introspect_xml; + char *returned_xml; + unsigned long xml_size; + size_t chunk_size; + int type; + + if (setup_infp_tests(&bus) != EOK) { + fail("Could not set up the tests"); + return; + } + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + fail("Could not create temporary talloc context"); + goto done; + } + + /* Create introspection method call */ + introspect_req = dbus_message_new_method_call(INFOPIPE_DBUS_NAME, + INFOPIPE_PATH, + DBUS_INTROSPECT_INTERFACE, + DBUS_INTROSPECT_METHOD); + if(!introspect_req) { + fail("Could not create new method call message"); + goto done; + } + + /* Send the message */ + dbus_error_init(&error); + reply = dbus_connection_send_with_reply_and_block(bus, + introspect_req, + TEST_TIMEOUT, + &error); + if(!reply) { + fail("Could not send message. Error: %s:%s", error.name, error.message); + dbus_error_free(&error); + goto done; + } + + type = dbus_message_get_type(reply); + switch (type) { + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + /* Read in the reference Introspection XML */ + xml_stream = fopen("introspect.ref", "r"); + if(xml_stream == NULL) { + DEBUG(0, ("Could not open the introspection XML for reading: [%d].\n", errno)); + return; + } + + chunk = talloc_size(tmp_ctx, INTROSPECT_CHUNK_SIZE); + if (chunk == NULL) goto done; + + xml_size = 0; + introspect_xml = NULL; + do { + chunk_size = fread(chunk, 1, INTROSPECT_CHUNK_SIZE, xml_stream); + introspect_xml = talloc_realloc_size(tmp_ctx, introspect_xml, xml_size+chunk_size+1); + if (introspect_xml == NULL) goto done; + + memcpy(introspect_xml+xml_size, chunk, chunk_size); + xml_size += chunk_size; + } while(chunk_size == INTROSPECT_CHUNK_SIZE); + introspect_xml[xml_size] = '\0'; + talloc_free(chunk); + + /* Get the XML from the message */ + dbus_message_get_args(reply, &error, + DBUS_TYPE_STRING, &returned_xml, + DBUS_TYPE_INVALID); + + /* Verify that the reply matches the reference file */ + if (strcmp(introspect_xml, returned_xml) != 0) { + fail("Verify Introspection XML: FAILED"); + } + break; + case DBUS_MESSAGE_TYPE_ERROR: + fail("Error: %s\n", dbus_message_get_error_name(reply)); + goto done; + } + +done: + talloc_free(tmp_ctx); + teardown_infp_tests(bus); +} +END_TEST + +START_TEST(test_infp_check_permissions) +{ + TALLOC_CTX *tmp_ctx; + DBusConnection *bus; + DBusError error; + DBusMessage *permission_req; + DBusMessage *reply; + DBusMessageIter msg_iter; + DBusMessageIter array_iter; + DBusMessageIter struct_iter; + dbus_bool_t *permission_array; + int permission_count; + char *domain; + char *object; + char *instance; + char *action; + char *attribute; + int type, i; + + if (setup_infp_tests(&bus) != EOK) { + fail("Could not set up the tests"); + return; + } + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + fail("Could not create temporary talloc context"); + goto done; + } + + /* Create permission request message */ + permission_req = dbus_message_new_method_call(INFOPIPE_DBUS_NAME, + INFOPIPE_PATH, + INFOPIPE_INTERFACE, + INFP_CHECK_PERMISSIONS); + if(!permission_req) { + fail("Could not create new method call message"); + goto done; + } + + /* Add arguments */ + domain = talloc_strdup(tmp_ctx, "LOCAL"); + object = talloc_strdup(tmp_ctx, "user"); + instance = talloc_strdup(tmp_ctx, "testuser1"); + action = talloc_strdup(tmp_ctx, "modify"); + attribute = talloc_strdup(tmp_ctx, "userpic"); + + dbus_message_append_args(permission_req, + DBUS_TYPE_STRING, &domain, + DBUS_TYPE_STRING, &object, + DBUS_TYPE_STRING, &instance, + DBUS_TYPE_INVALID); + + dbus_message_iter_init_append(permission_req, &msg_iter); + dbus_message_iter_open_container(&msg_iter, + DBUS_TYPE_ARRAY, "(ss)", /* Array of structs */ + &array_iter); + dbus_message_iter_open_container(&array_iter, + DBUS_TYPE_STRUCT, NULL, + &struct_iter); + dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &action); + dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &attribute); + dbus_message_iter_close_container(&array_iter, &struct_iter); + dbus_message_iter_close_container(&msg_iter, &array_iter); + + + /* Send the message */ + dbus_error_init(&error); + reply = dbus_connection_send_with_reply_and_block(bus, + permission_req, + TEST_TIMEOUT, + &error); + if(!reply) { + fail("Could not send message. Error: %s:%s", error.name, error.message); + dbus_error_free(&error); + goto done; + } + + type = dbus_message_get_type(reply); + switch (type) { + case DBUS_MESSAGE_TYPE_ERROR: + fail("Error: %s\n", dbus_message_get_error_name(reply)); + goto done; + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + dbus_message_get_args(reply, &error, + DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &permission_array, &permission_count, + DBUS_TYPE_INVALID); + } + + i = 0; + while(i < permission_count) { + if (permission_array[i] == true) { + fail("User was granted permission unexpectedly"); + goto done; + } + i++; + } + +done: + talloc_free(tmp_ctx); + teardown_infp_tests(bus); +} +END_TEST + +Suite *create_infopipe_suite(void) +{ + Suite *s = suite_create("infopipe"); + + TCase *tc_infp = tcase_create("InfoPipe Tests"); + + /* Test the Introspection XML */ + tcase_add_test(tc_infp, test_infp_introspect); + tcase_add_test(tc_infp, test_infp_check_permissions); + +/* Add all test cases to the test suite */ + suite_add_tcase(s, tc_infp); + + return s; +} + +int main(int argc, const char *argv[]) { + int opt; + poptContext pc; + int failure_count; + Suite *infopipe_suite; + SRunner *sr; + + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_MAIN_OPTS + { NULL } + }; + + 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); + + infopipe_suite = create_infopipe_suite(); + sr = srunner_create(infopipe_suite); + srunner_run_all(sr, CK_VERBOSE); + failure_count = srunner_ntests_failed(sr); + srunner_free(sr); + return (failure_count==0 ? EXIT_SUCCESS : EXIT_FAILURE); +} |