/* * Copyright (C) 2023 Purism SPC * * SPDX-License-Identifier: GPL-3.0-or-later * * Author: Evangelos Ribeiro Tzaras */ #include "calls-dbus-config.h" #include "calls-call-dbus.h" #include "calls-emergency-call-dbus.h" #include "cui-call.h" #include /* returns the PID of the process owning the given name on the session bus, or -1 if not found */ static int find_pid_by_bus_name (const char *name) { g_autoptr (GError) error = NULL; g_autoptr (GDBusProxy) proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.freedesktop.DBus", "/org/freesktop/DBus", "org.freedesktop.DBus", NULL, &error); g_autoptr (GVariant) ret = NULL; guint32 pid; g_assert_no_error (error); g_assert_nonnull (proxy); ret = g_dbus_proxy_call_sync (proxy, "GetConnectionUnixProcessID", g_variant_new ("(s)", name), G_DBUS_CALL_FLAGS_NONE, 5000, NULL, &error); g_assert_no_error (error); g_variant_get (ret, "(u)", &pid); return pid; } typedef struct { GTestDBus *dbus; GDBusObjectManager *calls_manager; CallsDBusEmergencyCalls *ec_manager; GMainLoop *loop; guint32 pid_server; int test_phase; const char *object_path; CallsDBusCallsCall *call; } DBusTestFixture; static void fixture_setup (DBusTestFixture *fixture, gconstpointer unused) { g_autoptr (GError) error = NULL; g_setenv ("GSETTINGS_BACKEND", "memory", TRUE); fixture->test_phase = 0; fixture->loop = g_main_loop_new (NULL, FALSE); fixture->dbus = g_test_dbus_new (G_TEST_DBUS_NONE); g_test_dbus_add_service_dir (fixture->dbus, CALLS_BUILD_DIR_STR "/tests/services"); g_test_dbus_up (fixture->dbus); fixture->calls_manager = calls_dbus_object_manager_client_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, CALLS_DBUS_NAME, CALLS_DBUS_OBJECT_PATH, NULL, &error); if (fixture->calls_manager == NULL) g_error ("Error getting object manager client: %s", error->message); fixture->ec_manager = calls_dbus_emergency_calls_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, CALLS_DBUS_NAME, CALLS_DBUS_OBJECT_PATH, NULL, &error); g_assert_no_error (error); fixture->pid_server = find_pid_by_bus_name (CALLS_DBUS_NAME); } static void fixture_teardown (DBusTestFixture *fixture, gconstpointer unused) { g_assert_finalize_object (fixture->calls_manager); g_assert_finalize_object (fixture->ec_manager); g_test_dbus_down (fixture->dbus); g_clear_object (&fixture->dbus); g_clear_pointer (&fixture->loop, g_main_loop_unref); } static void on_call_state_changed (GObject *object, GParamSpec *pspec, gpointer user_data) { g_autoptr (GError) error = NULL; CallsDBusCallsCall *call = CALLS_DBUS_CALLS_CALL (object); DBusTestFixture *fixture = user_data; const char *object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (object)); g_assert_cmpstr (object_path, ==, fixture->object_path); switch (fixture->test_phase) { case 0: g_assert_cmpint (calls_dbus_calls_call_get_state (call), ==, CUI_CALL_STATE_ACTIVE); g_assert_true (calls_dbus_calls_call_call_hangup_sync (call, NULL, &error)); g_assert_no_error (error); break; case 1: g_assert_cmpint (calls_dbus_calls_call_get_state (call), ==, CUI_CALL_STATE_DISCONNECTED); break; default: g_assert_not_reached (); } fixture->test_phase++; } static void on_call_added (GDBusObjectManager *manager, GDBusObject *object, gpointer user_data) { g_autoptr (GError) error = NULL; CallsDBusCallsCall *call; DBusTestFixture *fixture = user_data; fixture->object_path = g_dbus_object_get_object_path (object); call = calls_dbus_calls_call_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, CALLS_DBUS_NAME, fixture->object_path, NULL, &error); g_assert_nonnull (call); g_assert_no_error (error); fixture->call = call; g_assert_cmpint (calls_dbus_calls_call_get_state (call), ==, CUI_CALL_STATE_INCOMING); g_signal_connect (call, "notify::state", G_CALLBACK (on_call_state_changed), user_data); g_assert_true (calls_dbus_calls_call_call_accept_sync (call, NULL, &error)); g_assert_no_error (error); } static void on_call_removed (GDBusObjectManager *manager, GDBusObject *object, gpointer user_data) { DBusTestFixture *fixture = user_data; g_assert_cmpstr (g_dbus_object_get_object_path (object), ==, fixture->object_path); g_clear_object (&fixture->call); g_main_loop_quit (fixture->loop); } static void test_no_calls (DBusTestFixture *fixture, gconstpointer unused) { GList *objects; g_assert_cmpint (fixture->pid_server, >, 0); objects = g_dbus_object_manager_get_objects (fixture->calls_manager); g_assert_cmpint (g_list_length (objects), ==, 0); g_clear_list (&objects, g_object_unref); } static void test_interact_call (DBusTestFixture *fixture, gconstpointer unused) { GList *objects; g_assert_cmpint (fixture->pid_server, >, 0); objects = g_dbus_object_manager_get_objects (fixture->calls_manager); g_assert_cmpint (g_list_length (objects), ==, 0); g_clear_list (&objects, g_object_unref); g_signal_connect (fixture->calls_manager, "object-added", G_CALLBACK (on_call_added), fixture); g_signal_connect (fixture->calls_manager, "object-added", G_CALLBACK (on_call_removed), fixture); /* Sending USR1 will trigger an incoming call on the dummy provider running on the server*/ kill (fixture->pid_server, SIGUSR1); g_main_loop_run (fixture->loop); } static void test_emergency_calls_numbers (DBusTestFixture *fixture, gconstpointer unused) { gboolean success; gsize count; GVariantIter iter; const char *id = NULL; const char *name = NULL; gint32 source; g_autoptr (GError) error = NULL; g_autoptr (GVariant) contacts = NULL; success = calls_dbus_emergency_calls_call_get_emergency_contacts_sync (fixture->ec_manager, &contacts, NULL, &error); g_assert_no_error (error); g_assert_true (success); count = g_variant_n_children (contacts); g_assert_cmpint (count, ==, 2); #define CONTACT_FORMAT "(&s&si@a{sv})" g_variant_iter_init (&iter, contacts); g_variant_iter_next (&iter, CONTACT_FORMAT, &id, &name, &source, NULL); g_assert_cmpstr (id, ==, "123"); g_assert_cmpstr (name, ==, "123"); g_assert_cmpint (source, ==, 0); g_variant_iter_next (&iter, CONTACT_FORMAT, &id, &name, &source, NULL); g_assert_cmpstr (id, ==, "456"); g_assert_cmpstr (name, ==, "456"); g_assert_cmpint (source, ==, 0); } int main (int argc, char *argv[]) { g_test_init (&argc, &argv, NULL); g_test_add ("/Calls/DBus/no_calls", DBusTestFixture, NULL, fixture_setup, test_no_calls, fixture_teardown); g_test_add ("/Calls/DBus/call_interaction", DBusTestFixture, NULL, fixture_setup, test_interact_call, fixture_teardown); g_test_add ("/Calls/DBus/emergency-calls/numbers", DBusTestFixture, NULL, fixture_setup, test_emergency_calls_numbers, fixture_teardown); g_test_run (); }