dunst/test/dbus.c
2018-12-29 14:31:31 +01:00

316 lines
9.0 KiB
C

#define wake_up wake_up_void
#include "../src/dbus.c"
#include "greatest.h"
#include <assert.h>
#include <gio/gio.h>
#include "queues.h"
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 < 2000) {
usleep(500);
waiting++;
}
ASSERTm("After 1s, there is still no dbus connection available.",
dbus_conn);
PASS();
}
TEST test_dbus_teardown(void)
{
dbus_teardown(owner_id);
PASS();
}
TEST test_invalid_notification(void)
{
GVariant *faulty = g_variant_new_boolean(true);
ASSERT(NULL == dbus_message_to_notification(":123", faulty));
ASSERT(NULL == dbus_invoke("Notify", faulty));
g_variant_unref(faulty);
PASS();
}
TEST test_empty_notification(void)
{
struct dbus_notification *n = dbus_notification_new();
gsize len = queues_length_waiting();
guint id;
ASSERT(dbus_notification_fire(n, &id));
ASSERT(id != 0);
ASSERT_EQ(queues_length_waiting(), len+1);
dbus_notification_free(n);
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();
}
TEST test_dbus_notify_colors(void)
{
const char *color_frame = "I allow all string values for frame!";
const char *color_bg = "I allow all string values for background!";
const char *color_fg = "I allow all string values for foreground!";
struct notification *n;
struct dbus_notification *n_dbus;
gsize len = queues_length_waiting();
n_dbus = dbus_notification_new();
n_dbus->app_name = "dunstteststack";
n_dbus->app_icon = "NONE";
n_dbus->summary = "test_dbus_notify_colors";
n_dbus->body = "Summary of it";
g_hash_table_insert(n_dbus->hints,
g_strdup("frcolor"),
g_variant_ref_sink(g_variant_new_string(color_frame)));
g_hash_table_insert(n_dbus->hints,
g_strdup("bgcolor"),
g_variant_ref_sink(g_variant_new_string(color_bg)));
g_hash_table_insert(n_dbus->hints,
g_strdup("fgcolor"),
g_variant_ref_sink(g_variant_new_string(color_fg)));
guint id;
ASSERT(dbus_notification_fire(n_dbus, &id));
ASSERT(id != 0);
ASSERT_EQ(queues_length_waiting(), len+1);
n = queues_debug_find_notification_by_id(id);
ASSERT_STR_EQ(n->colors.frame, color_frame);
ASSERT_STR_EQ(n->colors.fg, color_fg);
ASSERT_STR_EQ(n->colors.bg, color_bg);
dbus_notification_free(n_dbus);
PASS();
}
TEST test_server_caps(enum markup_mode markup)
{
GVariant *reply;
GVariant *caps = NULL;
const char **capsarray;
settings.markup = markup;
reply = dbus_invoke("GetCapabilities", NULL);
caps = g_variant_get_child_value(reply, 0);
capsarray = g_variant_get_strv(caps, NULL);
ASSERT(capsarray);
ASSERT(g_strv_contains(capsarray, "actions"));
ASSERT(g_strv_contains(capsarray, "body"));
ASSERT(g_strv_contains(capsarray, "body-hyperlinks"));
ASSERT(g_strv_contains(capsarray, "x-dunst-stack-tag"));
if (settings.markup != MARKUP_NO)
ASSERT(g_strv_contains(capsarray, "body-markup"));
else
ASSERT_FALSE(g_strv_contains(capsarray, "body-markup"));
g_free(capsarray);
g_variant_unref(caps);
g_variant_unref(reply);
PASS();
}
// TESTS END
GMainLoop *loop;
GThread *thread_tests;
gpointer run_threaded_tests(gpointer data)
{
RUN_TEST(test_dbus_init);
RUN_TEST(test_empty_notification);
RUN_TEST(test_basic_notification);
RUN_TEST(test_invalid_notification);
RUN_TEST(test_dbus_notify_colors);
RUN_TESTp(test_server_caps, MARKUP_FULL);
RUN_TESTp(test_server_caps, MARKUP_STRIP);
RUN_TESTp(test_server_caps, MARKUP_NO);
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: */