LCOV - code coverage report
Current view: top level - tests - common_dbus.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 37 61 60.7 %
Date: 2015-10-19 Functions: 3 6 50.0 %

          Line data    Source code
       1             : /*
       2             :    SSSD
       3             : 
       4             :    Common utilities for dbus based 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 "config.h"
      26             : 
      27             : #include <stdio.h>
      28             : #include "tests/common.h"
      29             : 
      30             : struct mock_server {
      31             :     char *temp_dir;
      32             :     char *dbus_address;
      33             :     pid_t pid;
      34             :     DBusConnection *client;
      35             : 
      36             :     /* Used for synchronization */
      37             :     int sync_fds[2];
      38             : 
      39             :     /* Only used during init */
      40             :     sbus_server_conn_init_fn init_fn;
      41             :     void *init_pvt_data;
      42             : };
      43             : 
      44             : /*
      45             :  * If you think we're going to do full error propagation during tests ...
      46             :  * you're going to have a bad time (reading this code)
      47             :  */
      48             : #define verify_eq(x, y) \
      49             :     do { if ((x) != (y)) { fprintf(stderr, "failed: %s == %s\n", #x, #y); abort(); } } while (0)
      50             : #define verify_neq(x, y) \
      51             :     do { if ((x) == (y)) { fprintf(stderr, "failed: %s != %s\n", #x, #y); abort(); } } while (0)
      52             : 
      53             : static int
      54           9 : mock_server_cleanup(struct mock_server *mock)
      55             : {
      56             :     int child_status;
      57             :     const char *file;
      58             :     struct stat sb;
      59             : 
      60           9 :     dbus_connection_close(mock->client);
      61           9 :     dbus_connection_unref(mock->client);
      62             : 
      63             :     /* Tell the server thread to quit */
      64           9 :     verify_eq (write(mock->sync_fds[0], "X", 1), 1);
      65             : 
      66             :     /* Wait for the server child, it always returns mock */
      67           9 :     verify_eq (waitpid(mock->pid, &child_status, 0), mock->pid);
      68           9 :     verify_eq (child_status, 0);
      69             : 
      70           9 :     file = strchr(mock->dbus_address, '/');
      71           9 :     if (stat(file, &sb) == 0) {
      72           0 :         verify_eq (unlink(file), 0);
      73             :     }
      74           9 :     verify_eq (rmdir(mock->temp_dir), 0);
      75             : 
      76           9 :     return EOK;
      77             : }
      78             : 
      79             : static int
      80           0 : on_accept_connection(struct sbus_connection *conn,
      81             :                      void *data)
      82             : {
      83           0 :     struct mock_server *mock = data;
      84             : 
      85           0 :     verify_eq (mock->init_fn(conn, mock->init_pvt_data), EOK);
      86             : 
      87             :     /* Synchronization point: test_dbus_setup_mock() should return */
      88           0 :     verify_eq (write(mock->sync_fds[1], "X", 1), 1);
      89             : 
      90           0 :     return EOK;
      91             : }
      92             : 
      93             : static void
      94           0 : on_sync_fd_written(struct tevent_context *loop,
      95             :                    struct tevent_fd *fde,
      96             :                    uint16_t flags,
      97             :                    void *data)
      98             : {
      99           0 :     bool *stop_server = data;
     100           0 :     *stop_server = true;
     101           0 : }
     102             : 
     103             : static void
     104           0 : mock_server_child(void *data)
     105             : {
     106           0 :     struct mock_server *mock = data;
     107             :     struct tevent_context *loop;
     108             :     struct sbus_connection *server;
     109           0 :     bool stop_server = false;
     110             :     TALLOC_CTX *ctx;
     111             : 
     112           0 :     ctx = talloc_new(NULL);
     113           0 :     loop = tevent_context_init(ctx);
     114             : 
     115           0 :     verify_eq (sbus_new_server(ctx, loop, mock->dbus_address, geteuid(), getegid(),
     116             :                                false, &server, on_accept_connection, mock), EOK);
     117             : 
     118           0 :     tevent_add_fd(loop, ctx, mock->sync_fds[1], TEVENT_FD_READ,
     119             :                   on_sync_fd_written, &stop_server);
     120             : 
     121             :     /* Synchronization point: test_dbus_setup_mock() should connect */
     122           0 :     verify_eq (write(mock->sync_fds[1], "X", 1), 1);
     123             : 
     124             :     /* Do the loop */
     125           0 :     while(!stop_server) {
     126           0 :         verify_eq (tevent_loop_once(loop), 0);
     127             :     }
     128             : 
     129             :     /* TODO: sbus doesn't support cleanup of a server */
     130             : 
     131           0 :     talloc_free(ctx);
     132           0 : }
     133             : 
     134             : struct DBusConnection *
     135           9 : test_dbus_setup_mock(TALLOC_CTX *mem_ctx,
     136             :                      struct tevent_context *loop,
     137             :                      sbus_server_conn_init_fn init_fn,
     138             :                      void *init_pvt_data)
     139             : {
     140             :     struct mock_server *mock;
     141             :     char dummy;
     142             : 
     143           9 :     mock = talloc_zero(mem_ctx, struct mock_server);
     144           9 :     talloc_set_destructor(mock, mock_server_cleanup);
     145           9 :     mock->init_fn = init_fn;
     146           9 :     mock->init_pvt_data = init_pvt_data;
     147             : 
     148           9 :     mock->temp_dir = mkdtemp(talloc_strdup(mock, "/tmp/sssd-dbus-tests.XXXXXX"));
     149           9 :     verify_neq (mock->temp_dir, NULL);
     150           9 :     mock->dbus_address = talloc_asprintf(mock, "unix:path=%s/sbus", mock->temp_dir);
     151           9 :     verify_neq (mock->dbus_address, NULL);
     152             : 
     153             :     /* We use an fd pair as a synchronization device, integrates with tevent well */
     154           9 :     verify_eq (socketpair(PF_LOCAL, SOCK_STREAM, 0, mock->sync_fds), 0);
     155             : 
     156             :     /* Run the dbus server in a child process */
     157           9 :     mock->pid = fork();
     158           9 :     if (mock->pid == 0) {
     159           0 :         mock_server_child(mock);
     160           0 :         _exit(0);
     161             :     }
     162             : 
     163           9 :     verify_neq (mock->pid, -1);
     164             : 
     165             :     /* Synchronization point: wait for sync point in mock_server_child */
     166           9 :     verify_eq (read(mock->sync_fds[0], &dummy, 1), 1);
     167             : 
     168             :     /* Open a shared D-BUS connection to the address */
     169           9 :     mock->client = dbus_connection_open_private(mock->dbus_address, NULL);
     170           9 :     verify_neq (mock->client, NULL);
     171             : 
     172             :     /* Synchronization point: wait for sync point in on_accept_connection */
     173           9 :     verify_eq (read(mock->sync_fds[0], &dummy, 1), 1);
     174             : 
     175           9 :     return mock->client;
     176             : }
     177             : 
     178             : DBusMessage *
     179          33 : test_dbus_call_sync(DBusConnection *conn, const char *object_path,
     180             :                     const char *interface, const char *method,
     181             :                     DBusError *error, int first_arg_type, ...)
     182             : {
     183             :     DBusMessage *message;
     184             :     DBusMessage *reply;
     185             :     va_list va;
     186             : 
     187          33 :     message = dbus_message_new_method_call(NULL, object_path, interface, method);
     188          33 :     verify_neq(message, NULL);
     189             : 
     190          33 :     va_start(va, first_arg_type);
     191          33 :     verify_eq(dbus_message_append_args_valist(message, first_arg_type, va), TRUE);
     192          33 :     va_end(va);
     193             : 
     194          33 :     reply = dbus_connection_send_with_reply_and_block(conn, message, -1, error);
     195          33 :     dbus_message_unref(message);
     196             : 
     197          33 :     return reply;
     198             : }

Generated by: LCOV version 1.10