LCOV - code coverage report
Current view: top level - tests - sbus_tests.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 101 138 73.2 %
Date: 2015-10-19 Functions: 8 11 72.7 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    sbus_codegen tests.
       5             : 
       6             :    Authors:
       7             :         Stef Walter <stefw@redhat.com>
       8             : 
       9             :    Copyright (C) Red Hat, Inc 2014
      10             : 
      11             :    This program is free software; you can redistribute it and/or modify
      12             :    it under the terms of the GNU General Public License as published by
      13             :    the Free Software Foundation; either version 3 of the License, or
      14             :    (at your option) any later version.
      15             : 
      16             :    This program is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :    GNU General Public License for more details.
      20             : 
      21             :    You should have received a copy of the GNU General Public License
      22             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include <stdlib.h>
      26             : #include <check.h>
      27             : #include <talloc.h>
      28             : #include <tevent.h>
      29             : #include <popt.h>
      30             : 
      31             : #include "common.h"
      32             : 
      33             : #include "sbus/sssd_dbus.h"
      34             : #include "sbus/sssd_dbus_meta.h"
      35             : #include "util/util_errors.h"
      36             : 
      37             : /*
      38             :  * Although one would normally rely on the codegen to generate these
      39             :  * structures, we want to test this functionality *before* we test
      40             :  * the codegen in sbus_codegen_tests ... so these are hand rolled.
      41             :  */
      42             : 
      43             : #define PILOT_IFACE "test.Pilot"
      44             : #define PILOT_BLINK "Blink"
      45             : #define PILOT_EAT "Eat"
      46             : 
      47             : #define PILOT_IFACE_INTROSPECT \
      48             :         "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" \
      49             :         " \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" \
      50             :         "<node name=\"/test/leela\">\n" \
      51             :         "  <interface name=\"org.freedesktop.DBus.Introspectable\">\n" \
      52             :         "    <method name=\"Introspect\">\n" \
      53             :         "      <arg type=\"s\" name=\"data\" direction=\"out\" />\n" \
      54             :         "    </method>\n" \
      55             :         "  </interface>\n" \
      56             :         "  <interface name=\"org.freedesktop.DBus.Properties\">\n" \
      57             :         "    <method name=\"Get\">\n" \
      58             :         "      <arg type=\"s\" name=\"interface_name\" direction=\"in\" />\n" \
      59             :         "      <arg type=\"s\" name=\"property_name\" direction=\"in\" />\n" \
      60             :         "      <arg type=\"v\" name=\"value\" direction=\"out\" />\n" \
      61             :         "    </method>\n" \
      62             :         "    <method name=\"Set\">\n" \
      63             :         "      <arg type=\"s\" name=\"interface_name\" direction=\"in\" />\n" \
      64             :         "      <arg type=\"s\" name=\"property_name\" direction=\"in\" />\n" \
      65             :         "      <arg type=\"v\" name=\"value\" direction=\"in\" />\n" \
      66             :         "    </method>\n" \
      67             :         "    <method name=\"GetAll\">\n" \
      68             :         "      <arg type=\"s\" name=\"interface_name\" direction=\"in\" />\n" \
      69             :         "      <arg type=\"a{sv}\" name=\"props\" direction=\"out\" />\n" \
      70             :         "    </method>\n" \
      71             :         "  </interface>\n" \
      72             :         "  <interface name=\"test.Pilot\">\n" \
      73             :         "    <method name=\"Blink\" />\n" \
      74             :         "    <method name=\"Eat\" />\n" \
      75             :         "  </interface>\n" \
      76             :         "</node>\n"
      77             : 
      78             : /* our vtable */
      79             : struct pilot_vtable {
      80             :     struct sbus_vtable vtable;
      81             :     sbus_msg_handler_fn Blink;
      82             :     sbus_msg_handler_fn Eat;
      83             : };
      84             : 
      85             : const struct sbus_method_meta pilot_methods[] = {
      86             :     {
      87             :         PILOT_BLINK, /* method name */
      88             :         NULL, /* in args: manually parsed */
      89             :         NULL, /* out args: manually parsed */
      90             :         offsetof(struct pilot_vtable, Blink),
      91             :         NULL
      92             :     },
      93             :     {
      94             :         PILOT_EAT, /* method name */
      95             :         NULL, /* in args: manually parsed */
      96             :         NULL, /* out args: manually parsed */
      97             :         offsetof(struct pilot_vtable, Eat),
      98             :         NULL
      99             :     },
     100             :     { NULL, }
     101             : };
     102             : 
     103             : const struct sbus_interface_meta pilot_meta = {
     104             :     PILOT_IFACE, /* name */
     105             :     pilot_methods,
     106             :     NULL, /* no signals */
     107             :     NULL, /* no properties */
     108             :     NULL, /* no GetAll invoker */
     109             : };
     110             : 
     111           0 : static int blink_handler(struct sbus_request *req, void *data)
     112             : {
     113           0 :     DBusError error = DBUS_ERROR_INIT;
     114           0 :     dbus_int32_t duration = 0;
     115             :     dbus_bool_t crashed;
     116             : 
     117           0 :     ck_assert(req->intf->vtable->meta == &pilot_meta);
     118           0 :     ck_assert(data != NULL);
     119           0 :     ck_assert(data == req->intf->handler_data);
     120             : 
     121           0 :     ck_assert_str_eq(req->intf->path, req->path);
     122             : 
     123           0 :     if (strcmp(req->path, "/test/fry") == 0) {
     124           0 :         ck_assert_str_eq(data, "Don't crash");
     125           0 :     } else if (strcmp(req->path, "/test/leela") == 0) {
     126           0 :         ck_assert_str_eq(data, "Crash into the billboard");
     127             :     } else {
     128           0 :         ck_abort();
     129             :     }
     130             : 
     131           0 :     if (!dbus_message_get_args (req->message, &error,
     132             :                                 DBUS_TYPE_INT32, &duration,
     133             :                                 DBUS_TYPE_INVALID)) {
     134           0 :         sbus_request_fail_and_finish(req, &error);
     135           0 :         dbus_error_free(&error);
     136           0 :         return EOK;
     137             :     }
     138             : 
     139             :     /* Pilot crashes when eyes closed too long */
     140           0 :     crashed = (duration > 5);
     141             : 
     142           0 :     return sbus_request_return_and_finish(req,
     143             :                                           DBUS_TYPE_BOOLEAN, &crashed,
     144             :                                           DBUS_TYPE_INVALID);
     145             : }
     146             : 
     147           0 : static int eat_handler(struct sbus_request *req, void *data)
     148             : {
     149             :     dbus_int32_t integer;
     150             :     dbus_bool_t boolean;
     151             :     const char **array;
     152             :     int count;
     153             : 
     154           0 :     if (!sbus_request_parse_or_finish (req,
     155             :                                        DBUS_TYPE_INT32, &integer,
     156             :                                        DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &array, &count,
     157             :                                        DBUS_TYPE_BOOLEAN, &boolean,
     158             :                                        DBUS_TYPE_INVALID)) {
     159           0 :         return EOK; /* handled */
     160             :     }
     161             : 
     162           0 :     ck_assert_int_eq(integer, 5);
     163           0 :     ck_assert(boolean == TRUE);
     164           0 :     ck_assert_int_eq(count, 3);
     165           0 :     ck_assert_str_eq(array[0], "one");
     166           0 :     ck_assert_str_eq(array[1], "two");
     167           0 :     ck_assert_str_eq(array[2], "three");
     168             : 
     169           0 :     return sbus_request_return_and_finish(req, DBUS_TYPE_INVALID);
     170             : }
     171             : 
     172             : struct pilot_vtable pilot_impl = {
     173             :     { &pilot_meta, 0 },
     174             :     .Blink = blink_handler,
     175             :     .Eat = eat_handler,
     176             : };
     177             : 
     178           0 : static int pilot_test_server_init(struct sbus_connection *server, void *unused)
     179             : {
     180             :     int ret;
     181             : 
     182           0 :     ret = sbus_conn_register_iface(server, &pilot_impl.vtable, "/test/leela",
     183             :                                    "Crash into the billboard");
     184           0 :     ck_assert_int_eq(ret, EOK);
     185             : 
     186             : 
     187           0 :     ret = sbus_conn_register_iface(server, &pilot_impl.vtable, "/test/fry",
     188             :                                    "Don't crash");
     189           0 :     ck_assert_int_eq(ret, EOK);
     190             : 
     191           0 :     return EOK;
     192             : }
     193             : 
     194           1 : START_TEST(test_raw_handler)
     195             : {
     196             :     TALLOC_CTX *ctx;
     197             :     DBusConnection *client;
     198           1 :     DBusError error = DBUS_ERROR_INIT;
     199             :     DBusMessage *reply;
     200             :     dbus_bool_t crashed;
     201             :     dbus_int32_t duration;
     202             : 
     203           1 :     ctx = talloc_new(NULL);
     204           1 :     client = test_dbus_setup_mock(ctx, NULL, pilot_test_server_init, NULL);
     205             : 
     206             :     /* Leela crashes with a duration higher than 5 */
     207           1 :     duration = 10;
     208           1 :     reply = test_dbus_call_sync(client,
     209             :                                 "/test/leela",
     210             :                                 PILOT_IFACE,
     211             :                                 PILOT_BLINK,
     212             :                                 &error,
     213             :                                 DBUS_TYPE_INT32, &duration,
     214             :                                 DBUS_TYPE_INVALID);
     215           1 :     ck_assert(reply != NULL);
     216           1 :     ck_assert(!dbus_error_is_set(&error));
     217           1 :     ck_assert(dbus_message_get_args(reply, NULL,
     218             :                                     DBUS_TYPE_BOOLEAN, &crashed,
     219             :                                     DBUS_TYPE_INVALID));
     220           1 :     dbus_message_unref (reply);
     221           1 :     ck_assert(crashed == true);
     222             : 
     223             :     /* Fry daesn't crash with a duration lower than 5 */
     224           1 :     duration = 1;
     225           1 :     reply = test_dbus_call_sync(client,
     226             :                                 "/test/fry",
     227             :                                 PILOT_IFACE,
     228             :                                 PILOT_BLINK,
     229             :                                 &error,
     230             :                                 DBUS_TYPE_INT32, &duration,
     231             :                                 DBUS_TYPE_INVALID);
     232           1 :     ck_assert(reply != NULL);
     233           1 :     ck_assert(!dbus_error_is_set(&error));
     234           1 :     ck_assert(dbus_message_get_args(reply, NULL,
     235             :                                     DBUS_TYPE_BOOLEAN, &crashed,
     236             :                                     DBUS_TYPE_INVALID));
     237           1 :     dbus_message_unref (reply);
     238           1 :     ck_assert(crashed == FALSE);
     239             : 
     240           1 :     talloc_free(ctx);
     241             : }
     242           1 : END_TEST
     243             : 
     244           1 : START_TEST(test_request_parse_ok)
     245             : {
     246           1 :     const char *args[] = { "one", "two", "three" };
     247             :     const char **array;
     248             :     TALLOC_CTX *ctx;
     249             :     DBusConnection *client;
     250           1 :     DBusError error = DBUS_ERROR_INIT;
     251             :     DBusMessage *reply;
     252             :     dbus_bool_t boolean;
     253             :     dbus_int32_t integer;
     254             :     int count;
     255             : 
     256           1 :     ctx = talloc_new(NULL);
     257           1 :     client = test_dbus_setup_mock(ctx, NULL, pilot_test_server_init, NULL);
     258             : 
     259           1 :     boolean = TRUE;
     260           1 :     integer = 5;
     261           1 :     count = 3;
     262           1 :     array = args;
     263           1 :     reply = test_dbus_call_sync(client,
     264             :                                 "/test/leela",
     265             :                                 PILOT_IFACE,
     266             :                                 PILOT_EAT,
     267             :                                 &error,
     268             :                                 DBUS_TYPE_INT32, &integer,
     269             :                                 DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &array, count,
     270             :                                 DBUS_TYPE_BOOLEAN, &boolean,
     271             :                                 DBUS_TYPE_INVALID);
     272           1 :     ck_assert(reply != NULL);
     273           1 :     ck_assert(!dbus_error_is_set(&error));
     274           1 :     ck_assert(dbus_message_get_args(reply, NULL,
     275             :                                     DBUS_TYPE_INVALID));
     276           1 :     dbus_message_unref (reply);
     277             : 
     278           1 :     talloc_free(ctx);
     279             : }
     280           1 : END_TEST
     281             : 
     282           1 : START_TEST(test_request_parse_bad_args)
     283             : {
     284             :     TALLOC_CTX *ctx;
     285             :     DBusConnection *client;
     286           1 :     DBusError error = DBUS_ERROR_INIT;
     287             :     DBusMessage *reply;
     288             : 
     289           1 :     ctx = talloc_new(NULL);
     290           1 :     client = test_dbus_setup_mock(ctx, NULL, pilot_test_server_init, NULL);
     291             : 
     292           1 :     reply = test_dbus_call_sync(client,
     293             :                                 "/test/leela",
     294             :                                 PILOT_IFACE,
     295             :                                 PILOT_EAT,
     296             :                                 &error,
     297             :                                 DBUS_TYPE_INVALID); /* bad agruments */
     298           1 :     ck_assert(reply == NULL);
     299           1 :     ck_assert(dbus_error_is_set(&error));
     300           1 :     ck_assert(dbus_error_has_name(&error, DBUS_ERROR_INVALID_ARGS));
     301           1 :     dbus_error_free(&error);
     302             : 
     303           1 :     talloc_free(ctx);
     304             : }
     305           1 : END_TEST
     306             : 
     307           1 : START_TEST(test_introspection)
     308             : {
     309             :     TALLOC_CTX *ctx;
     310             :     DBusConnection *client;
     311           1 :     DBusError error = DBUS_ERROR_INIT;
     312             :     DBusMessage *reply;
     313             :     char *xml;
     314             : 
     315           1 :     ctx = talloc_new(NULL);
     316           1 :     client = test_dbus_setup_mock(ctx, NULL, pilot_test_server_init, NULL);
     317             : 
     318           1 :     reply = test_dbus_call_sync(client,
     319             :                                 "/test/leela",
     320             :                                 DBUS_INTROSPECT_INTERFACE,
     321             :                                 DBUS_INTROSPECT_METHOD,
     322             :                                 &error,
     323             :                                 DBUS_TYPE_INVALID); /* bad agruments */
     324             : 
     325           1 :     ck_assert(reply != NULL);
     326           1 :     ck_assert(!dbus_error_is_set(&error));
     327           1 :     ck_assert(dbus_message_get_args(reply, NULL,
     328             :                                     DBUS_TYPE_STRING, &xml,
     329             :                                     DBUS_TYPE_INVALID));
     330           1 :     ck_assert_str_eq(PILOT_IFACE_INTROSPECT, xml);
     331             : 
     332           1 :     dbus_message_unref(reply);
     333             : 
     334           1 :     talloc_free(ctx);
     335             : }
     336           1 : END_TEST
     337             : 
     338           1 : START_TEST(test_sbus_new_error)
     339             : {
     340             :     TALLOC_CTX *ctx;
     341             :     DBusError *error;
     342             : 
     343           1 :     ctx = talloc_new(NULL);
     344             : 
     345           1 :     error = sbus_error_new(ctx, DBUS_ERROR_IO_ERROR, "Input-output error");
     346           1 :     ck_assert(error != NULL);
     347           1 :     ck_assert(dbus_error_is_set(error));
     348           1 :     ck_assert(dbus_error_has_name(error, DBUS_ERROR_IO_ERROR));
     349           1 :     talloc_free(error);
     350             : 
     351           1 :     error = sbus_error_new(ctx, DBUS_ERROR_IO_ERROR,
     352             :                            "The answer should have been %d", 42);
     353           1 :     ck_assert(error != NULL);
     354           1 :     ck_assert(dbus_error_is_set(error));
     355           1 :     ck_assert(dbus_error_has_name(error, DBUS_ERROR_IO_ERROR));
     356           1 :     talloc_free(error);
     357             : 
     358             :     /* NULL message must also work */
     359           1 :     error = sbus_error_new(ctx, DBUS_ERROR_IO_ERROR, NULL);
     360           1 :     ck_assert(error != NULL);
     361           1 :     ck_assert(dbus_error_is_set(error));
     362           1 :     ck_assert(dbus_error_has_name(error, DBUS_ERROR_IO_ERROR));
     363           1 :     talloc_free(error);
     364             : 
     365           1 :     talloc_free(ctx);
     366             : }
     367           1 : END_TEST
     368             : 
     369           1 : TCase *create_sbus_tests(void)
     370             : {
     371           1 :     TCase *tc = tcase_create("tests");
     372             : 
     373           1 :     tcase_add_test(tc, test_raw_handler);
     374           1 :     tcase_add_test(tc, test_request_parse_ok);
     375           1 :     tcase_add_test(tc, test_request_parse_bad_args);
     376           1 :     tcase_add_test(tc, test_introspection);
     377           1 :     tcase_add_test(tc, test_sbus_new_error);
     378             : 
     379           1 :     return tc;
     380             : }
     381             : 
     382           1 : Suite *create_suite(void)
     383             : {
     384           1 :     Suite *s = suite_create("sbus");
     385           1 :     suite_add_tcase(s, create_sbus_tests());
     386           1 :     return s;
     387             : }
     388             : 
     389           1 : int main(int argc, const char *argv[])
     390             : {
     391             :     int opt;
     392             :     poptContext pc;
     393             :     int failure_count;
     394             :     Suite *suite;
     395             :     SRunner *sr;
     396             : 
     397           1 :     struct poptOption long_options[] = {
     398             :         POPT_AUTOHELP
     399             :         POPT_TABLEEND
     400             :     };
     401             : 
     402           1 :     pc = poptGetContext(argv[0], argc, argv, long_options, 0);
     403           1 :     while ((opt = poptGetNextOpt(pc)) != -1) {
     404             :         switch (opt) {
     405             :         default:
     406           0 :             fprintf(stderr, "\nInvalid option %s: %s\n\n",
     407             :                     poptBadOption(pc, 0), poptStrerror(opt));
     408           0 :             poptPrintUsage(pc, stderr, 0);
     409           0 :             return 1;
     410             :         }
     411             :     }
     412           1 :     poptFreeContext(pc);
     413             : 
     414           1 :     suite = create_suite();
     415           1 :     sr = srunner_create(suite);
     416             :     /* If CK_VERBOSITY is set, use that, otherwise it defaults to CK_NORMAL */
     417           1 :     srunner_run_all(sr, CK_ENV);
     418           1 :     failure_count = srunner_ntests_failed(sr);
     419           1 :     srunner_free(sr);
     420           1 :     return (failure_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
     421             : }

Generated by: LCOV version 1.10