diff --git a/test/dbus.c b/test/dbus.c new file mode 100644 index 0000000..841b19e --- /dev/null +++ b/test/dbus.c @@ -0,0 +1,208 @@ +#define wake_up wake_up_void +#include "../src/dbus.c" +#include "greatest.h" + +#include +#include + +void wake_up_void(void) { } + +GVariant *dbus_invoke(const char *method, GVariant *params) +{ + GDBusConnection *connection_client; + GVariant *retdata; + GError *error = NULL; + + connection_client = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); + retdata = g_dbus_connection_call_sync( + connection_client, + FDN_NAME, + FDN_PATH, + FDN_IFAC, + method, + params, + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + &error); + if (error) { + printf("Error while calling GTestDBus instance: %s\n", error->message); + g_error_free(error); + } + + g_object_unref(connection_client); + + return retdata; +} + +struct dbus_notification { + const char* app_name; + guint replaces_id; + const char* app_icon; + const char* summary; + const char* body; + GHashTable *actions; + GHashTable *hints; + int expire_timeout; +}; + +void g_free_variant_value(gpointer tofree) +{ + g_variant_unref((GVariant*) tofree); +} + +struct dbus_notification *dbus_notification_new(void) +{ + struct dbus_notification *n = g_malloc0(sizeof(struct dbus_notification)); + n->expire_timeout = -1; + n->replaces_id = 0; + n->actions = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + n->hints = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free_variant_value); + return n; +} + +void dbus_notification_free(struct dbus_notification *n) +{ + g_hash_table_unref(n->hints); + g_hash_table_unref(n->actions); + g_free(n); +} + +bool dbus_notification_fire(struct dbus_notification *n, uint *id) +{ + assert(n); + assert(id); + GVariantBuilder b; + GVariantType *t; + + gpointer p_key; + gpointer p_value; + GHashTableIter iter; + + t = g_variant_type_new("(susssasa{sv}i)"); + g_variant_builder_init(&b, t); + g_variant_type_free(t); + + g_variant_builder_add(&b, "s", n->app_name); + g_variant_builder_add(&b, "u", n->replaces_id); + g_variant_builder_add(&b, "s", n->app_icon); + g_variant_builder_add(&b, "s", n->summary); + g_variant_builder_add(&b, "s", n->body); + + // Add the actions + t = g_variant_type_new("as"); + g_variant_builder_open(&b, t); + g_hash_table_iter_init(&iter, n->actions); + while (g_hash_table_iter_next(&iter, &p_key, &p_value)) { + g_variant_builder_add(&b, "s", (char*)p_key); + g_variant_builder_add(&b, "s", (char*)p_value); + } + g_variant_builder_close(&b); + g_variant_type_free(t); + + // Add the hints + t = g_variant_type_new("a{sv}"); + g_variant_builder_open(&b, t); + g_hash_table_iter_init(&iter, n->hints); + while (g_hash_table_iter_next(&iter, &p_key, &p_value)) { + g_variant_builder_add(&b, "{sv}", (char*)p_key, (GVariant*)p_value); + } + g_variant_builder_close(&b); + g_variant_type_free(t); + + g_variant_builder_add(&b, "i", n->expire_timeout); + + GVariant *reply = dbus_invoke("Notify", g_variant_builder_end(&b)); + if (reply) { + g_variant_get(reply, "(u)", id); + g_variant_unref(reply); + return true; + } else { + return false; + } +} + +/////// TESTS +gint owner_id; + +TEST test_dbus_init(void) +{ + owner_id = dbus_init(); + uint waiting = 0; + while (!dbus_conn && waiting < 20) { + usleep(500); + waiting++; + } + ASSERTm("After 10ms, there is still no dbus connection available.", + dbus_conn); + PASS(); +} + +TEST test_dbus_teardown(void) +{ + dbus_teardown(owner_id); + PASS(); +} + +TEST test_basic_notification(void) +{ + struct dbus_notification *n = dbus_notification_new(); + gsize len = queues_length_waiting(); + n->app_name = "dunstteststack"; + n->app_icon = "NONE"; + n->summary = "Headline"; + n->body = "Text"; + g_hash_table_insert(n->actions, g_strdup("actionid"), g_strdup("Print this text")); + g_hash_table_insert(n->hints, + g_strdup("x-dunst-stack-tag"), + g_variant_ref_sink(g_variant_new_string("volume"))); + + n->replaces_id = 10; + + guint id; + ASSERT(dbus_notification_fire(n, &id)); + ASSERT(id != 0); + + ASSERT_EQ(queues_length_waiting(), len+1); + dbus_notification_free(n); + PASS(); +} +// TESTS END + +GMainLoop *loop; +GThread *thread_tests; + +gpointer run_threaded_tests(gpointer data) +{ + RUN_TEST(test_dbus_init); + + RUN_TEST(test_basic_notification); + + RUN_TEST(test_dbus_teardown); + g_main_loop_quit(loop); + return NULL; +} + +SUITE(suite_dbus) +{ + GTestDBus *dbus_bus; + g_test_dbus_unset(); + queues_init(); + + loop = g_main_loop_new(NULL, false); + + dbus_bus = g_test_dbus_new(G_TEST_DBUS_NONE); + g_test_dbus_up(dbus_bus); + + thread_tests = g_thread_new("testexecutor", run_threaded_tests, loop); + g_main_loop_run(loop); + + queues_teardown(); + g_test_dbus_down(dbus_bus); + g_object_unref(dbus_bus); + g_thread_unref(thread_tests); + g_main_loop_unref(loop); +} + +/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */ diff --git a/test/test.c b/test/test.c index 1863070..d8f907a 100644 --- a/test/test.c +++ b/test/test.c @@ -19,6 +19,7 @@ SUITE_EXTERN(suite_queues); SUITE_EXTERN(suite_dunst); SUITE_EXTERN(suite_log); SUITE_EXTERN(suite_menu); +SUITE_EXTERN(suite_dbus); GREATEST_MAIN_DEFS(); @@ -44,6 +45,7 @@ int main(int argc, char *argv[]) { RUN_SUITE(suite_dunst); RUN_SUITE(suite_log); RUN_SUITE(suite_menu); + RUN_SUITE(suite_dbus); GREATEST_MAIN_END(); base = NULL;