858 lines
25 KiB
C
858 lines
25 KiB
C
#define wake_up wake_up_void
|
|
#include "../src/dbus.c"
|
|
#include "greatest.h"
|
|
|
|
#include <assert.h>
|
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
#include <gio/gio.h>
|
|
|
|
#include "queues.h"
|
|
|
|
extern const char *base;
|
|
|
|
void wake_up_void(void) { }
|
|
|
|
struct signal_actioninvoked {
|
|
guint id;
|
|
gchar *key;
|
|
guint subscription_id;
|
|
GDBusConnection *conn;
|
|
};
|
|
|
|
struct signal_closed {
|
|
guint32 id;
|
|
guint32 reason;
|
|
guint subscription_id;
|
|
GDBusConnection *conn;
|
|
};
|
|
|
|
void dbus_signal_cb_actioninvoked(GDBusConnection *connection,
|
|
const gchar *sender_name,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
g_return_if_fail(user_data);
|
|
|
|
guint32 id;
|
|
gchar *key;
|
|
|
|
struct signal_actioninvoked *sig = (struct signal_actioninvoked*) user_data;
|
|
|
|
g_variant_get(parameters, "(us)", &id, &key);
|
|
|
|
if (id == sig->id) {
|
|
sig->id = id;
|
|
sig->key = key;
|
|
}
|
|
}
|
|
|
|
void dbus_signal_subscribe_actioninvoked(struct signal_actioninvoked *actioninvoked)
|
|
{
|
|
assert(actioninvoked);
|
|
|
|
actioninvoked->conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
|
|
actioninvoked->subscription_id =
|
|
g_dbus_connection_signal_subscribe(
|
|
actioninvoked->conn,
|
|
FDN_NAME,
|
|
FDN_IFAC,
|
|
"ActionInvoked",
|
|
FDN_PATH,
|
|
NULL,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
dbus_signal_cb_actioninvoked,
|
|
actioninvoked,
|
|
NULL);
|
|
}
|
|
|
|
void dbus_signal_unsubscribe_actioninvoked(struct signal_actioninvoked *actioninvoked)
|
|
{
|
|
assert(actioninvoked);
|
|
|
|
g_dbus_connection_signal_unsubscribe(actioninvoked->conn, actioninvoked->subscription_id);
|
|
g_object_unref(actioninvoked->conn);
|
|
|
|
actioninvoked->conn = NULL;
|
|
actioninvoked->subscription_id = -1;
|
|
}
|
|
|
|
void dbus_signal_cb_closed(GDBusConnection *connection,
|
|
const gchar *sender_name,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *signal_name,
|
|
GVariant *parameters,
|
|
gpointer user_data)
|
|
{
|
|
g_return_if_fail(user_data);
|
|
|
|
guint32 id;
|
|
guint32 reason;
|
|
|
|
struct signal_closed *sig = (struct signal_closed*) user_data;
|
|
g_variant_get(parameters, "(uu)", &id, &reason);
|
|
|
|
if (id == sig->id) {
|
|
sig->id = id;
|
|
sig->reason = reason;
|
|
}
|
|
}
|
|
|
|
void dbus_signal_subscribe_closed(struct signal_closed *closed)
|
|
{
|
|
assert(closed);
|
|
|
|
closed->conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
|
|
closed->subscription_id =
|
|
g_dbus_connection_signal_subscribe(
|
|
closed->conn,
|
|
FDN_NAME,
|
|
FDN_IFAC,
|
|
"NotificationClosed",
|
|
FDN_PATH,
|
|
NULL,
|
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
dbus_signal_cb_closed,
|
|
closed,
|
|
NULL);
|
|
}
|
|
|
|
void dbus_signal_unsubscribe_closed(struct signal_closed *closed)
|
|
{
|
|
assert(closed);
|
|
|
|
g_dbus_connection_signal_unsubscribe(closed->conn, closed->subscription_id);
|
|
g_object_unref(closed->conn);
|
|
|
|
closed->conn = NULL;
|
|
closed->subscription_id = -1;
|
|
}
|
|
|
|
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);
|
|
}
|
|
// Add an invalid appendix to cover odd numbered action arrays
|
|
// Shouldn't interfere with normal testing
|
|
g_variant_builder_add(&b, "s", "invalid appendix");
|
|
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;
|
|
}
|
|
}
|
|
|
|
void dbus_notification_set_raw_image(struct dbus_notification *n_dbus, const char *path)
|
|
{
|
|
GdkPixbuf *pb = gdk_pixbuf_new_from_file(path, NULL);
|
|
|
|
if (!pb)
|
|
return;
|
|
|
|
GVariant *hint_data = g_variant_new_from_data(
|
|
G_VARIANT_TYPE("ay"),
|
|
gdk_pixbuf_read_pixels(pb),
|
|
gdk_pixbuf_get_byte_length(pb),
|
|
TRUE,
|
|
(GDestroyNotify) g_object_unref,
|
|
g_object_ref(pb));
|
|
|
|
GVariant *hint = g_variant_new(
|
|
"(iiibii@ay)",
|
|
gdk_pixbuf_get_width(pb),
|
|
gdk_pixbuf_get_height(pb),
|
|
gdk_pixbuf_get_rowstride(pb),
|
|
gdk_pixbuf_get_has_alpha(pb),
|
|
gdk_pixbuf_get_bits_per_sample(pb),
|
|
gdk_pixbuf_get_n_channels(pb),
|
|
hint_data);
|
|
|
|
g_hash_table_insert(n_dbus->hints,
|
|
g_strdup("image-data"),
|
|
g_variant_ref_sink(hint));
|
|
g_object_unref(pb);
|
|
}
|
|
|
|
/////// 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_hint_transient(void)
|
|
{
|
|
static char msg[50];
|
|
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_hint_transient";
|
|
n_dbus->body = "Summary of it";
|
|
|
|
bool values[] = { true, true, true, false, false, false, false };
|
|
GVariant *variants[] = {
|
|
g_variant_new_boolean(true),
|
|
g_variant_new_int32(1),
|
|
g_variant_new_uint32(1),
|
|
g_variant_new_boolean(false),
|
|
g_variant_new_int32(0),
|
|
g_variant_new_uint32(0),
|
|
g_variant_new_int32(-1),
|
|
};
|
|
for (size_t i = 0; i < G_N_ELEMENTS(variants); i++) {
|
|
g_hash_table_insert(n_dbus->hints,
|
|
g_strdup("transient"),
|
|
g_variant_ref_sink(variants[i]));
|
|
|
|
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);
|
|
|
|
snprintf(msg, sizeof(msg), "In round %ld", i);
|
|
ASSERT_EQm(msg, values[i], n->transient);
|
|
}
|
|
|
|
dbus_notification_free(n_dbus);
|
|
|
|
PASS();
|
|
}
|
|
|
|
TEST test_hint_progress(void)
|
|
{
|
|
static char msg[50];
|
|
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_hint_progress";
|
|
n_dbus->body = "Summary of it";
|
|
|
|
int values[] = { 99, 12, 123, 123, -1, -1 };
|
|
GVariant *variants[] = {
|
|
g_variant_new_int32(99),
|
|
g_variant_new_uint32(12),
|
|
g_variant_new_int32(123), // allow higher than 100
|
|
g_variant_new_uint32(123),
|
|
g_variant_new_int32(-192),
|
|
g_variant_new_uint32(-192),
|
|
};
|
|
for (size_t i = 0; i < G_N_ELEMENTS(variants); i++) {
|
|
g_hash_table_insert(n_dbus->hints,
|
|
g_strdup("value"),
|
|
g_variant_ref_sink(variants[i]));
|
|
|
|
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);
|
|
|
|
snprintf(msg, sizeof(msg), "In round %ld", i);
|
|
ASSERT_EQm(msg, values[i], n->progress);
|
|
}
|
|
|
|
dbus_notification_free(n_dbus);
|
|
|
|
PASS();
|
|
}
|
|
|
|
TEST test_hint_icons(void)
|
|
{
|
|
struct notification *n;
|
|
struct dbus_notification *n_dbus;
|
|
const char *iconname = "NEWICON";
|
|
|
|
gsize len = queues_length_waiting();
|
|
|
|
n_dbus = dbus_notification_new();
|
|
n_dbus->app_name = "dunstteststack";
|
|
n_dbus->app_icon = "NONE";
|
|
n_dbus->summary = "test_hint_icons";
|
|
n_dbus->body = "Summary of it";
|
|
|
|
g_hash_table_insert(n_dbus->hints,
|
|
g_strdup("image-path"),
|
|
g_variant_ref_sink(g_variant_new_string(iconname)));
|
|
|
|
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(iconname, n->iconname);
|
|
|
|
dbus_notification_free(n_dbus);
|
|
|
|
PASS();
|
|
}
|
|
|
|
TEST test_hint_category(void)
|
|
{
|
|
struct notification *n;
|
|
struct dbus_notification *n_dbus;
|
|
const char *category = "VOLUME";
|
|
|
|
gsize len = queues_length_waiting();
|
|
|
|
n_dbus = dbus_notification_new();
|
|
n_dbus->app_name = "dunstteststack";
|
|
n_dbus->app_icon = "NONE";
|
|
n_dbus->summary = "test_hint_category";
|
|
n_dbus->body = "Summary of it";
|
|
|
|
g_hash_table_insert(n_dbus->hints,
|
|
g_strdup("category"),
|
|
g_variant_ref_sink(g_variant_new_string(category)));
|
|
|
|
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(category, n->category);
|
|
|
|
dbus_notification_free(n_dbus);
|
|
|
|
PASS();
|
|
}
|
|
|
|
TEST test_hint_desktop_entry(void)
|
|
{
|
|
struct notification *n;
|
|
struct dbus_notification *n_dbus;
|
|
const char *desktop_entry = "org.dunst-project.dunst";
|
|
|
|
gsize len = queues_length_waiting();
|
|
|
|
n_dbus = dbus_notification_new();
|
|
n_dbus->app_name = "dunstteststack";
|
|
n_dbus->app_icon = "NONE";
|
|
n_dbus->summary = "test_hint_desktopentry";
|
|
n_dbus->body = "Summary of my desktop_entry";
|
|
|
|
g_hash_table_insert(n_dbus->hints,
|
|
g_strdup("desktop-entry"),
|
|
g_variant_ref_sink(g_variant_new_string(desktop_entry)));
|
|
|
|
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(desktop_entry, n->desktop_entry);
|
|
|
|
dbus_notification_free(n_dbus);
|
|
|
|
PASS();
|
|
}
|
|
|
|
TEST test_hint_urgency(void)
|
|
{
|
|
static char msg[50];
|
|
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_hint_urgency";
|
|
n_dbus->body = "Summary of it";
|
|
|
|
enum urgency values[] = { URG_MAX, URG_LOW, URG_NORM, URG_CRIT };
|
|
GVariant *variants[] = {
|
|
g_variant_new_byte(10),
|
|
g_variant_new_byte(0),
|
|
g_variant_new_byte(1),
|
|
g_variant_new_byte(2),
|
|
};
|
|
for (size_t i = 0; i < G_N_ELEMENTS(variants); i++) {
|
|
g_hash_table_insert(n_dbus->hints,
|
|
g_strdup("urgency"),
|
|
g_variant_ref_sink(variants[i]));
|
|
|
|
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);
|
|
|
|
snprintf(msg, sizeof(msg), "In round %ld", i);
|
|
ASSERT_EQm(msg, values[i], n->urgency);
|
|
|
|
queues_notification_close_id(id, REASON_UNDEF);
|
|
}
|
|
|
|
dbus_notification_free(n_dbus);
|
|
|
|
PASS();
|
|
}
|
|
|
|
TEST test_hint_raw_image(void)
|
|
{
|
|
guint id;
|
|
struct notification *n;
|
|
struct dbus_notification *n_dbus;
|
|
|
|
char *path = g_strconcat(base, "/data/icons/valid.png", NULL);
|
|
gsize len = queues_length_waiting();
|
|
|
|
n_dbus = dbus_notification_new();
|
|
dbus_notification_set_raw_image(n_dbus, path);
|
|
n_dbus->app_name = "dunstteststack";
|
|
n_dbus->app_icon = "NONE";
|
|
n_dbus->summary = "test_hint_raw_image";
|
|
n_dbus->body = "Summary of it";
|
|
|
|
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(n->icon);
|
|
ASSERT(!STR_EQ(n->icon_id, n_dbus->app_icon));
|
|
|
|
dbus_notification_free(n_dbus);
|
|
g_free(path);
|
|
|
|
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();
|
|
}
|
|
|
|
TEST test_signal_actioninvoked(void)
|
|
{
|
|
const struct notification *n;
|
|
struct dbus_notification *n_dbus;
|
|
struct signal_actioninvoked sig = {0, NULL, -1};
|
|
|
|
dbus_signal_subscribe_actioninvoked(&sig);
|
|
|
|
n_dbus = dbus_notification_new();
|
|
n_dbus->app_name = "dunstteststack";
|
|
n_dbus->app_icon = "NONE2";
|
|
n_dbus->summary = "Headline for New";
|
|
n_dbus->body = "Text";
|
|
g_hash_table_insert(n_dbus->actions, g_strdup("actionkey"), g_strdup("Print this text"));
|
|
|
|
dbus_notification_fire(n_dbus, &sig.id);
|
|
n = queues_debug_find_notification_by_id(sig.id);
|
|
|
|
signal_action_invoked(n, "actionkey");
|
|
|
|
uint waiting = 0;
|
|
while (!sig.key && waiting < 2000) {
|
|
usleep(500);
|
|
waiting++;
|
|
}
|
|
|
|
ASSERT_STR_EQ("actionkey", sig.key);
|
|
|
|
g_free(sig.key);
|
|
dbus_notification_free(n_dbus);
|
|
dbus_signal_unsubscribe_actioninvoked(&sig);
|
|
PASS();
|
|
}
|
|
|
|
TEST test_close_and_signal(void)
|
|
{
|
|
GVariant *data, *ret;
|
|
struct dbus_notification *n;
|
|
struct signal_closed sig = {0, REASON_MIN-1, -1};
|
|
|
|
dbus_signal_subscribe_closed(&sig);
|
|
|
|
n = dbus_notification_new();
|
|
n->app_name = "dunstteststack";
|
|
n->app_icon = "NONE2";
|
|
n->summary = "Headline for New";
|
|
n->body = "Text";
|
|
|
|
dbus_notification_fire(n, &sig.id);
|
|
|
|
data = g_variant_new("(u)", sig.id);
|
|
ret = dbus_invoke("CloseNotification", data);
|
|
|
|
ASSERT(ret);
|
|
|
|
uint waiting = 0;
|
|
while (sig.reason == REASON_MIN-1 && waiting < 2000) {
|
|
usleep(500);
|
|
waiting++;
|
|
}
|
|
|
|
ASSERT(sig.reason != REASON_MIN-1);
|
|
|
|
dbus_notification_free(n);
|
|
dbus_signal_unsubscribe_closed(&sig);
|
|
g_variant_unref(ret);
|
|
PASS();
|
|
}
|
|
|
|
TEST test_get_fdn_daemon_info(void)
|
|
{
|
|
unsigned int pid_is;
|
|
pid_t pid_should;
|
|
char *name, *vendor;
|
|
GDBusConnection *conn;
|
|
|
|
pid_should = getpid();
|
|
conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
|
|
|
|
ASSERT(dbus_get_fdn_daemon_info(conn, &pid_is, &name, &vendor));
|
|
|
|
ASSERT_EQ_FMT(pid_should, pid_is, "%d");
|
|
ASSERT_STR_EQ("dunst", name);
|
|
ASSERT_STR_EQ("knopwob", vendor);
|
|
|
|
g_free(name);
|
|
g_free(vendor);
|
|
|
|
g_object_unref(conn);
|
|
PASS();
|
|
}
|
|
|
|
TEST assert_methodlists_sorted(void)
|
|
{
|
|
for (size_t i = 0; i+1 < G_N_ELEMENTS(methods_fdn); i++) {
|
|
ASSERT(0 > strcmp(
|
|
methods_fdn[i].method_name,
|
|
methods_fdn[i+1].method_name));
|
|
}
|
|
|
|
PASS();
|
|
}
|
|
|
|
|
|
// TESTS END
|
|
|
|
GMainLoop *loop;
|
|
GThread *thread_tests;
|
|
|
|
gpointer run_threaded_tests(gpointer data)
|
|
{
|
|
RUN_TEST(test_dbus_init);
|
|
|
|
RUN_TEST(test_get_fdn_daemon_info);
|
|
|
|
RUN_TEST(test_empty_notification);
|
|
RUN_TEST(test_basic_notification);
|
|
RUN_TEST(test_invalid_notification);
|
|
RUN_TEST(test_hint_transient);
|
|
RUN_TEST(test_hint_progress);
|
|
RUN_TEST(test_hint_icons);
|
|
RUN_TEST(test_hint_category);
|
|
RUN_TEST(test_hint_desktop_entry);
|
|
RUN_TEST(test_hint_urgency);
|
|
RUN_TEST(test_hint_raw_image);
|
|
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_close_and_signal);
|
|
RUN_TEST(test_signal_actioninvoked);
|
|
|
|
RUN_TEST(assert_methodlists_sorted);
|
|
|
|
RUN_TEST(test_dbus_teardown);
|
|
g_main_loop_quit(loop);
|
|
return NULL;
|
|
}
|
|
|
|
SUITE(suite_dbus)
|
|
{
|
|
settings.icon_path = "";
|
|
|
|
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);
|
|
|
|
settings.icon_path = NULL;
|
|
}
|
|
|
|
/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */
|