LCOV - code coverage report
Current view: top level - src/plugins/dbusrecv - testmod_dbusrecv.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 163 0.0 %
Date: 2019-09-12 12:28:41 Functions: 0 9 0.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include "dbusrecv.h"
      10             : 
      11             : #include <stdio.h> // printf() & co
      12             : 
      13             : #include <kdbio/uv.h>
      14             : #include <kdbioplugin.h>
      15             : 
      16             : #include <uv.h>
      17             : 
      18             : #include <tests.h>
      19             : #include <tests_plugin.h>
      20             : 
      21             : #define TEST_TIMEOUT 1000
      22             : 
      23             : Key * test_callbackKey;
      24             : uv_loop_t * test_callbackLoop;
      25             : 
      26             : /** D-Bus bus type used by tests  */
      27             : DBusBusType testBusType;
      28             : 
      29             : /**
      30             :  * @internal
      31             :  * Get and setup D-Bus connection
      32             :  *
      33             :  * @param  type D-Bus bus type
      34             :  * @return      D-Bus connection or NULL on error
      35             :  */
      36           0 : static DBusConnection * getDbusConnection (DBusBusType type)
      37             : {
      38             :         DBusError error;
      39           0 :         dbus_error_init (&error);
      40             : 
      41           0 :         DBusConnection * connection = dbus_bus_get (type, &error);
      42           0 :         if (connection == NULL)
      43             :         {
      44           0 :                 printf ("connect: Failed to open connection to %s message bus: %s\n", (type == DBUS_BUS_SYSTEM) ? "system" : "session",
      45             :                         error.message);
      46           0 :                 dbus_error_free (&error);
      47           0 :                 return NULL;
      48             :         }
      49           0 :         dbus_error_free (&error);
      50             : 
      51           0 :         dbus_connection_set_exit_on_disconnect (connection, FALSE);
      52             : 
      53           0 :         return connection;
      54             : }
      55             : 
      56             : /**
      57             :  * @internal
      58             :  * Send Elektra's D-Bus message.
      59             :  *
      60             :  * @param signalName signal name
      61             :  * @param keyName    key name
      62             :  */
      63           0 : static void dbusSendMessage (const char * signalName, const char * keyName)
      64             : {
      65             :         DBusMessage * message;
      66           0 :         const char * interface = "org.libelektra";
      67           0 :         const char * path = "/org/libelektra/configuration";
      68             : 
      69           0 :         DBusConnection * connection = getDbusConnection (testBusType);
      70           0 :         exit_if_fail (connection != NULL, "could not get bus connection");
      71             : 
      72           0 :         message = dbus_message_new_signal (path, interface, signalName);
      73           0 :         exit_if_fail (message, "could not allocate dbus message");
      74             : 
      75           0 :         exit_if_fail (dbus_message_append_args (message, DBUS_TYPE_STRING, &keyName, DBUS_TYPE_INVALID), "could not add message arguments");
      76             : 
      77           0 :         dbus_connection_send (connection, message, NULL);
      78             : 
      79           0 :         dbus_message_unref (message);
      80           0 :         dbus_connection_unref (connection);
      81             : 
      82           0 :         return;
      83             : }
      84             : 
      85             : /**
      86             :  * Timeout for tests.
      87             :  *
      88             :  * Creates a failure and stops the event loop
      89             :  *
      90             :  * @param timerOp timer operation
      91             :  */
      92           0 : static void test_timerCallback (ElektraIoTimerOperation * timerOp ELEKTRA_UNUSED)
      93             : {
      94           0 :         succeed_if (0, "timeout exceeded; test failed");
      95           0 :         uv_stop (test_callbackLoop);
      96           0 : }
      97             : 
      98             : /**
      99             :  * @internal
     100             :  * Called by plugin when a notification was received.
     101             :  * The key is saved to be evaluated by the current test and the event loop is
     102             :  * stopped.
     103             :  *
     104             :  * @see ElektraNotificationCallback (kdbnotificationinternal.h)
     105             :  *
     106             :  * @param key     changed key
     107             :  * @param context notification callback context
     108             :  */
     109           0 : static void test_notificationCallback (Key * key, ElektraNotificationCallbackContext * context ELEKTRA_UNUSED)
     110             : {
     111           0 :         test_callbackKey = key;
     112           0 :         uv_stop (test_callbackLoop);
     113           0 : }
     114             : 
     115           0 : static int test_prerequisites (void)
     116             : {
     117           0 :         printf ("testing prerequisites\n");
     118           0 :         printf ("detecting available bus types - please ignore single error messages prefixed with \"connect:\"\n");
     119             : 
     120           0 :         DBusConnection * systemBus = getDbusConnection (DBUS_BUS_SYSTEM);
     121           0 :         DBusConnection * sessionBus = getDbusConnection (DBUS_BUS_SESSION);
     122             : 
     123           0 :         int success = 0;
     124           0 :         if (systemBus != NULL || sessionBus != NULL)
     125             :         {
     126             :                 // Set bus type for tests
     127             :                 // NOTE brew dbus on MacOs supports session by out of the box while session
     128             :                 // bus is not available without further configuration on Linux
     129           0 :                 if (systemBus)
     130             :                 {
     131           0 :                         testBusType = DBUS_BUS_SYSTEM;
     132             :                 }
     133           0 :                 else if (sessionBus)
     134             :                 {
     135           0 :                         testBusType = DBUS_BUS_SESSION;
     136             :                 }
     137             :                 success = 1;
     138             :         }
     139             : 
     140           0 :         if (systemBus) dbus_connection_unref (systemBus);
     141           0 :         if (sessionBus) dbus_connection_unref (sessionBus);
     142             : 
     143           0 :         return success;
     144             : }
     145             : 
     146           0 : static void test_commit (uv_loop_t * loop, ElektraIoInterface * binding)
     147             : {
     148           0 :         printf ("test commit\n");
     149             : 
     150           0 :         KeySet * conf = ksNew (1, keyNew ("user/announce", KEY_VALUE, "once", KEY_END), KS_END);
     151           0 :         PLUGIN_OPEN ("dbusrecv");
     152             : 
     153             :         // io binding is required for dispatching
     154           0 :         size_t func = elektraPluginGetFunction (plugin, "setIoBinding");
     155           0 :         exit_if_fail (func, "could not get function setIoBinding");
     156           0 :         KeySet * setIoBindingParams =
     157           0 :                 ksNew (1, keyNew ("/ioBinding", KEY_BINARY, KEY_SIZE, sizeof (binding), KEY_VALUE, &binding, KEY_END), KS_END);
     158           0 :         ElektraIoPluginSetBinding setIoBinding = (ElektraIoPluginSetBinding) func;
     159           0 :         setIoBinding (plugin, setIoBindingParams);
     160           0 :         ksDel (setIoBindingParams);
     161             : 
     162             :         // open notification
     163           0 :         func = elektraPluginGetFunction (plugin, "openNotification");
     164           0 :         exit_if_fail (func, "could not get function openNotification");
     165           0 :         ElektraNotificationOpenNotification openNotification = (ElektraNotificationOpenNotification) func;
     166           0 :         KeySet * openNotificationParams = ksNew (2, keyNew ("/callback", KEY_FUNC, test_notificationCallback, KEY_END), KS_END);
     167           0 :         openNotification (plugin, openNotificationParams);
     168           0 :         ksDel (openNotificationParams);
     169             : 
     170           0 :         char * expectedKeyName = "system/tests/testmod_dbusrecv/changed";
     171           0 :         dbusSendMessage ("Commit", expectedKeyName);
     172             : 
     173           0 :         ElektraIoTimerOperation * timerOp = elektraIoNewTimerOperation (TEST_TIMEOUT, 1, test_timerCallback, NULL);
     174           0 :         elektraIoBindingAddTimer (binding, timerOp);
     175             : 
     176           0 :         test_callbackKey = NULL;
     177           0 :         test_callbackLoop = loop;
     178           0 :         uv_run (loop, UV_RUN_DEFAULT);
     179             : 
     180           0 :         succeed_if_same_string (expectedKeyName, keyName (test_callbackKey));
     181             : 
     182             :         // close notification
     183           0 :         func = elektraPluginGetFunction (plugin, "closeNotification");
     184           0 :         exit_if_fail (func, "could not get function closeNotification");
     185           0 :         ElektraNotificationCloseNotification closeNotification = (ElektraNotificationCloseNotification) func;
     186           0 :         closeNotification (plugin, NULL);
     187             : 
     188           0 :         elektraIoBindingRemoveTimer (timerOp);
     189           0 :         elektraFree (timerOp);
     190           0 :         keyDel (test_callbackKey);
     191           0 :         PLUGIN_CLOSE ();
     192           0 : }
     193             : 
     194           0 : static void test_keyAdded (uv_loop_t * loop, ElektraIoInterface * binding)
     195             : {
     196           0 :         printf ("test adding keys\n");
     197             : 
     198           0 :         KeySet * conf = ksNew (0, KS_END);
     199           0 :         PLUGIN_OPEN ("dbusrecv");
     200             : 
     201             :         // io binding is required for dispatching
     202           0 :         size_t func = elektraPluginGetFunction (plugin, "setIoBinding");
     203           0 :         exit_if_fail (func, "could not get function setIoBinding");
     204           0 :         KeySet * setIoBindingParams =
     205           0 :                 ksNew (1, keyNew ("/ioBinding", KEY_BINARY, KEY_SIZE, sizeof (binding), KEY_VALUE, &binding, KEY_END), KS_END);
     206           0 :         ElektraIoPluginSetBinding setIoBinding = (ElektraIoPluginSetBinding) func;
     207           0 :         setIoBinding (plugin, setIoBindingParams);
     208           0 :         ksDel (setIoBindingParams);
     209             : 
     210             :         // open notification
     211           0 :         func = elektraPluginGetFunction (plugin, "openNotification");
     212           0 :         exit_if_fail (func, "could not get function openNotification");
     213           0 :         KeySet * openNotificationParams = ksNew (2, keyNew ("/callback", KEY_FUNC, test_notificationCallback, KEY_END), KS_END);
     214           0 :         ElektraNotificationOpenNotification openNotification = (ElektraNotificationOpenNotification) func;
     215           0 :         openNotification (plugin, openNotificationParams);
     216           0 :         ksDel (openNotificationParams);
     217             : 
     218           0 :         char * expectedKeyName = "system/tests/testmod_dbusrecv/added";
     219           0 :         dbusSendMessage ("KeyAdded", expectedKeyName);
     220             : 
     221           0 :         ElektraIoTimerOperation * timerOp = elektraIoNewTimerOperation (TEST_TIMEOUT, 1, test_timerCallback, NULL);
     222           0 :         elektraIoBindingAddTimer (binding, timerOp);
     223             : 
     224           0 :         test_callbackKey = NULL;
     225           0 :         test_callbackLoop = loop;
     226           0 :         uv_run (loop, UV_RUN_DEFAULT);
     227             : 
     228           0 :         succeed_if_same_string (expectedKeyName, keyName (test_callbackKey));
     229             : 
     230             :         // close notification
     231           0 :         func = elektraPluginGetFunction (plugin, "closeNotification");
     232           0 :         exit_if_fail (func, "could not get function closeNotification");
     233           0 :         ElektraNotificationCloseNotification closeNotification = (ElektraNotificationCloseNotification) func;
     234           0 :         closeNotification (plugin, NULL);
     235             : 
     236           0 :         elektraIoBindingRemoveTimer (timerOp);
     237           0 :         elektraFree (timerOp);
     238           0 :         keyDel (test_callbackKey);
     239           0 :         PLUGIN_CLOSE ();
     240           0 : }
     241             : 
     242           0 : static void test_keyChanged (uv_loop_t * loop, ElektraIoInterface * binding)
     243             : {
     244           0 :         printf ("test adding keys\n");
     245             : 
     246           0 :         KeySet * conf = ksNew (0, KS_END);
     247           0 :         PLUGIN_OPEN ("dbusrecv");
     248             : 
     249             :         // io binding is required for dispatching
     250           0 :         size_t func = elektraPluginGetFunction (plugin, "setIoBinding");
     251           0 :         exit_if_fail (func, "could not get function setIoBinding");
     252           0 :         KeySet * setIoBindingParams =
     253           0 :                 ksNew (1, keyNew ("/ioBinding", KEY_BINARY, KEY_SIZE, sizeof (binding), KEY_VALUE, &binding, KEY_END), KS_END);
     254           0 :         ElektraIoPluginSetBinding setIoBinding = (ElektraIoPluginSetBinding) func;
     255           0 :         setIoBinding (plugin, setIoBindingParams);
     256           0 :         ksDel (setIoBindingParams);
     257             : 
     258             :         // open notification
     259           0 :         func = elektraPluginGetFunction (plugin, "openNotification");
     260           0 :         exit_if_fail (func, "could not get function openNotification");
     261           0 :         KeySet * openNotificationParams = ksNew (2, keyNew ("/callback", KEY_FUNC, test_notificationCallback, KEY_END), KS_END);
     262           0 :         ElektraNotificationOpenNotification openNotification = (ElektraNotificationOpenNotification) func;
     263           0 :         openNotification (plugin, openNotificationParams);
     264           0 :         ksDel (openNotificationParams);
     265             : 
     266           0 :         char * expectedKeyName = "system/tests/testmod_dbusrecv/changed";
     267           0 :         dbusSendMessage ("KeyChanged", expectedKeyName);
     268             : 
     269           0 :         ElektraIoTimerOperation * timerOp = elektraIoNewTimerOperation (TEST_TIMEOUT, 1, test_timerCallback, NULL);
     270           0 :         elektraIoBindingAddTimer (binding, timerOp);
     271             : 
     272           0 :         test_callbackKey = NULL;
     273           0 :         test_callbackLoop = loop;
     274           0 :         uv_run (loop, UV_RUN_DEFAULT);
     275             : 
     276           0 :         succeed_if_same_string (expectedKeyName, keyName (test_callbackKey));
     277             : 
     278             :         // close notification
     279           0 :         func = elektraPluginGetFunction (plugin, "closeNotification");
     280           0 :         exit_if_fail (func, "could not get function closeNotification");
     281           0 :         ElektraNotificationCloseNotification closeNotification = (ElektraNotificationCloseNotification) func;
     282           0 :         closeNotification (plugin, NULL);
     283             : 
     284           0 :         elektraIoBindingRemoveTimer (timerOp);
     285           0 :         elektraFree (timerOp);
     286           0 :         keyDel (test_callbackKey);
     287           0 :         PLUGIN_CLOSE ();
     288           0 : }
     289             : 
     290           0 : int main (int argc, char ** argv)
     291             : {
     292           0 :         printf ("DBUSRECV TESTS\n");
     293           0 :         printf ("==============\n\n");
     294             : 
     295           0 :         init (argc, argv);
     296             : 
     297             :         // Test if dbus is available
     298           0 :         if (test_prerequisites ())
     299             :         {
     300             : 
     301           0 :                 uv_loop_t * loop = uv_default_loop ();
     302           0 :                 ElektraIoInterface * binding = elektraIoUvNew (loop);
     303             : 
     304             :                 // Test change types
     305           0 :                 test_commit (loop, binding);
     306           0 :                 test_keyAdded (loop, binding);
     307           0 :                 test_keyChanged (loop, binding);
     308             : 
     309           0 :                 elektraIoBindingCleanup (binding);
     310           0 :                 uv_run (loop, UV_RUN_ONCE);
     311             : #ifdef HAVE_LIBUV1
     312           0 :                 uv_loop_close (loop);
     313             : #elif HAVE_LIBUV0
     314             :                 uv_loop_delete (loop);
     315             : #endif
     316             :         }
     317             :         else
     318             :         {
     319           0 :                 printf ("warning: no dbus daemon available; skipping tests that require dbus\n");
     320             :         }
     321             : 
     322           0 :         print_result ("testmod_dbusrecv");
     323             : 
     324           0 :         dbus_shutdown ();
     325             : 
     326           0 :         return nbError;
     327             : }

Generated by: LCOV version 1.13