1
0
Fork 0
mirror of https://gitlab.gnome.org/GNOME/calls.git synced 2024-09-17 17:05:26 +00:00
Purism-Calls/tests/test-ringer.c
Evangelos Ribeiro Tzaras 6d122b066f test-ringer: Remove cancellable test
This will get removed soon while refactoring the ringer as cancelling
the async methods would not guarantee that the requested operation would
not be performed.

It could actually already be started (e.g. starting or stopping the
feedback), but we have not yet received the reply, so it was always a
bit flaky.
2022-12-03 20:54:55 +01:00

537 lines
14 KiB
C

/*
* Copyright (C) 2021 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Author: Evangelos Ribeiro Tzaras <devrtz@fortysixandtwo.eu>
*
*/
#include "calls-manager.h"
#include "calls-ringer.h"
#include "calls-ui-call-data.h"
#include "mock-call.h"
#include "mock-libfeedback.h"
#include "mock-contacts-provider.h"
#include <cmocka.h>
#include <setjmp.h>
/* mock libfeedback functions */
static gboolean
on_mock_timeout (gpointer user_data)
{
GTask *task;
GCancellable *cancellable;
if (!G_IS_TASK (user_data))
return G_SOURCE_REMOVE;
task = G_TASK (user_data);
cancellable = g_task_get_cancellable (task);
if (!g_cancellable_is_cancelled (cancellable))
g_task_return_boolean (task, TRUE);
return G_SOURCE_REMOVE;
}
static gboolean
on_check_task_cancelled (gpointer user_data)
{
GTask *task;
if (!G_IS_TASK (user_data))
return G_SOURCE_REMOVE;
task = G_TASK (user_data);
if (g_task_get_completed (task) || g_task_return_error_if_cancelled (task))
return G_SOURCE_REMOVE;
return G_SOURCE_CONTINUE;
}
gboolean
__wrap_lfb_init (const char *app_id,
GError **error)
{
return TRUE;
}
void
__wrap_lfb_uninit (void)
{
return;
}
void
__wrap_lfb_event_set_feedback_profile (LfbEvent *self,
const char *profile)
{
return;
}
void
__wrap_lfb_event_trigger_feedback_async (LfbEvent *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *trigger_task = g_task_new (self, cancellable, callback, user_data);
int mock_time_ms = mock_type (int);
g_timeout_add (mock_time_ms, on_mock_timeout, trigger_task);
g_idle_add (G_SOURCE_FUNC (on_check_task_cancelled), trigger_task);
}
gboolean
__wrap_lfb_event_trigger_feedback_finish (LfbEvent *self,
GAsyncResult *res,
GError **error)
{
GTask *task = G_TASK (res);
gboolean ret;
ret = g_task_propagate_boolean (task, error);
g_object_unref (task);
return ret;
}
void
__wrap_lfb_event_end_feedback_async (LfbEvent *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *trigger_task = g_task_new (self, cancellable, callback, user_data);
int mock_time_ms = mock_type (int);
g_timeout_add (mock_time_ms, on_mock_timeout, trigger_task);
}
gboolean
__wrap_lfb_event_end_feedback_finish (LfbEvent *self,
GAsyncResult *res,
GError **error)
{
GTask *task = G_TASK (res);
gboolean ret;
ret = g_task_propagate_boolean (G_TASK (res), error);
g_object_unref (task);
return ret;
}
CallsContactsProvider *
__wrap_calls_contacts_provider_new (void)
{
return NULL;
}
/* add or remove calls */
static void
add_call (CallsManager *manager,
CallsUiCallData *call)
{
g_assert (CALLS_IS_MANAGER (manager));
g_assert (CALLS_IS_UI_CALL_DATA (call));
g_signal_emit_by_name (manager, "ui-call-added", call, NULL);
}
static void
remove_call (CallsManager *manager,
CallsUiCallData *call)
{
g_assert (CALLS_IS_MANAGER (manager));
g_assert (CALLS_IS_UI_CALL_DATA (call));
g_signal_emit_by_name (manager, "ui-call-removed", call, NULL);
}
/* TestData setup and tear down */
typedef struct {
CallsManager *manager;
CallsRinger *ringer;
CallsMockCall *call_one;
CallsUiCallData *ui_call_one;
CallsMockCall *call_two;
CallsUiCallData *ui_call_two;
GMainLoop *loop;
} TestData;
static int
setup_test_data (void **state)
{
TestData *data = g_new0 (TestData, 1);
if (data == NULL)
return -1;
data->manager = calls_manager_get_default ();
data->ringer = calls_ringer_new ();
data->call_one = calls_mock_call_new ();
data->ui_call_one = calls_ui_call_data_new (CALLS_CALL (data->call_one), NULL);
data->call_two = calls_mock_call_new ();
data->ui_call_two = calls_ui_call_data_new (CALLS_CALL (data->call_two), NULL);
data->loop = g_main_loop_new (NULL, FALSE);
*state = data;
return 0;
}
static int
tear_down_test_data (void **state)
{
TestData *data = *state;
g_object_unref (data->call_one);
g_object_unref (data->ui_call_one);
g_object_unref (data->call_two);
g_object_unref (data->ui_call_two);
g_object_unref (data->ringer);
g_main_loop_unref (data->loop);
g_free (data);
return 0;
}
/* t1: test_ringing_incoming_call */
static void
t1_on_ringer_call_accepted (CallsRinger *ringer,
GParamSpec *pspec,
gpointer user_data)
{
static guint test_phase = 0;
TestData *data = user_data;
switch (test_phase++) {
case 0: /* incoming call */
assert_true (calls_ringer_get_is_ringing (ringer));
calls_call_answer (CALLS_CALL (data->call_one));
break;
case 1: /* incoming call accepted */
assert_false (calls_ringer_get_is_ringing (ringer));
g_main_loop_quit ((GMainLoop *) data->loop);
break;
default:
g_assert_not_reached (); /* did not find equivalent cmocka assertion */
}
}
static void
test_ringing_accept_call (void **state)
{
TestData *data = *state;
assert_false (calls_ringer_get_is_ringing (data->ringer));
g_signal_connect (data->ringer,
"notify::ringing",
G_CALLBACK (t1_on_ringer_call_accepted),
data);
/* delay before completion of __wrap_lfb_event_trigger_feedback_async() */
will_return (__wrap_lfb_event_trigger_feedback_async, 10);
/* delay before completion of __wrap_lfb_event_end_feedback_async() */
will_return (__wrap_lfb_event_end_feedback_async, 10);
calls_call_set_state (CALLS_CALL (data->call_one), CALLS_CALL_STATE_INCOMING);
add_call (data->manager, data->ui_call_one);
/* main loop will quit in callback of notify::ring */
g_main_loop_run (data->loop);
remove_call (data->manager, data->ui_call_one);
assert_false (calls_ringer_get_is_ringing (data->ringer));
}
/* t2: test_ringing_hang_up_call */
static void
t2_on_ringer_call_hang_up (CallsRinger *ringer,
GParamSpec *pspec,
gpointer user_data)
{
static guint test_phase = 0;
TestData *data = user_data;
switch (test_phase++) {
case 0: /* incoming call */
assert_true (calls_ringer_get_is_ringing (ringer));
calls_call_hang_up (CALLS_CALL (data->call_one));
break;
case 1: /* incoming call hung up */
assert_false (calls_ringer_get_is_ringing (ringer));
g_main_loop_quit ((GMainLoop *) data->loop);
break;
default:
g_assert_not_reached (); /* did not find equivalent cmocka assertion */
}
}
static void
test_ringing_hang_up_call (void **state)
{
TestData *data = *state;
assert_false (calls_ringer_get_is_ringing (data->ringer));
g_signal_connect (data->ringer,
"notify::ringing",
G_CALLBACK (t2_on_ringer_call_hang_up),
data);
/* delay before completion of __wrap_lfb_event_trigger_feedback_async() */
will_return (__wrap_lfb_event_trigger_feedback_async, 10);
/* delay before completion of __wrap_lfb_event_end_feedback_async() */
will_return (__wrap_lfb_event_end_feedback_async, 10);
calls_call_set_state (CALLS_CALL (data->call_one), CALLS_CALL_STATE_INCOMING);
add_call (data->manager, data->ui_call_one);
/* main loop will quit in callback of notify::ring */
g_main_loop_run (data->loop);
remove_call (data->manager, data->ui_call_one);
assert_false (calls_ringer_get_is_ringing (data->ringer));
}
/* t4: test_ringing_silence_call */
static void
t4_on_ringer_call_silence (CallsRinger *ringer,
GParamSpec *pspec,
gpointer user_data)
{
static guint test_phase = 0;
TestData *data = user_data;
switch (test_phase++) {
case 0: /* incoming call */
assert_true (calls_ringer_get_is_ringing (ringer));
calls_ui_call_data_silence_ring (data->ui_call_one);
assert_true (calls_ui_call_data_get_silenced (data->ui_call_one));
break;
case 1: /* incoming call hung up */
assert_false (calls_ringer_get_is_ringing (ringer));
g_main_loop_quit ((GMainLoop *) data->loop);
break;
default:
g_assert_not_reached (); /* did not find equivalent cmocka assertion */
}
}
static void
test_ringing_silence_call (void **state)
{
TestData *data = *state;
assert_false (calls_ringer_get_is_ringing (data->ringer));
g_signal_connect (data->ringer,
"notify::ringing",
G_CALLBACK (t4_on_ringer_call_silence),
data);
/* delay before completion of __wrap_lfb_event_trigger_feedback_async() */
will_return (__wrap_lfb_event_trigger_feedback_async, 10);
/* delay before completion of __wrap_lfb_event_end_feedback_async() */
will_return (__wrap_lfb_event_end_feedback_async, 10);
calls_call_set_state (CALLS_CALL (data->call_one), CALLS_CALL_STATE_INCOMING);
add_call (data->manager, data->ui_call_one);
/* main loop will quit in callback of notify::ring */
g_main_loop_run (data->loop);
remove_call (data->manager, data->ui_call_one);
assert_false (calls_ringer_get_is_ringing (data->ringer));
}
/* t5: test_ringing_multiple_call */
static gboolean
t5_remove_calls (gpointer user_data)
{
static guint test_phase = 0;
TestData *data = user_data;
if (test_phase == 0) {
remove_call (data->manager, data->ui_call_one);
test_phase++;
return G_SOURCE_CONTINUE;
}
assert_true (calls_ringer_get_is_ringing (data->ringer));
remove_call (data->manager, data->ui_call_two);
return G_SOURCE_REMOVE;
}
static void
t5_on_ringer_multiple_calls (CallsRinger *ringer,
GParamSpec *pspec,
gpointer user_data)
{
static guint test_phase = 0;
TestData *data = user_data;
switch (test_phase++) {
case 0: /* add second call, and schedule call removal */
assert_true (calls_ringer_get_is_ringing (ringer));
add_call (data->manager, data->ui_call_two);
g_timeout_add (25, t5_remove_calls, data);
break;
case 1: /* both calls should be removed now */
assert_false (calls_ringer_get_is_ringing (ringer));
g_main_loop_quit ((GMainLoop *) data->loop);
break;
default:
g_assert_not_reached (); /* did not find equivalent cmocka assertion */
}
}
static void
test_ringing_multiple_calls (void **state)
{
TestData *data = *state;
assert_false (calls_ringer_get_is_ringing (data->ringer));
g_signal_connect (data->ringer,
"notify::ringing",
G_CALLBACK (t5_on_ringer_multiple_calls),
data);
/* delay before completion of __wrap_lfb_event_trigger_feedback_async() */
will_return (__wrap_lfb_event_trigger_feedback_async, 10);
/* delay before completion of __wrap_lfb_event_end_feedback_async() */
will_return (__wrap_lfb_event_end_feedback_async, 10);
calls_call_set_state (CALLS_CALL (data->call_one), CALLS_CALL_STATE_INCOMING);
add_call (data->manager, data->ui_call_one);
/* main loop will quit in callback of notify::ring */
g_main_loop_run (data->loop);
assert_false (calls_ringer_get_is_ringing (data->ringer));
}
static void
t6_on_ringer_multiple_calls_with_restart (CallsRinger *ringer,
GParamSpec *pspec,
gpointer user_data)
{
static guint test_phase = 0;
TestData *data = user_data;
switch (test_phase++) {
case 0:
assert_true (calls_ringer_get_is_ringing (ringer));
assert_false (calls_ringer_get_ring_is_quiet (ringer));
calls_call_answer (CALLS_CALL (data->call_one));
break;
case 1:
assert_true (calls_ringer_get_is_ringing (ringer));
assert_true (calls_ringer_get_ring_is_quiet (ringer));
calls_call_hang_up (CALLS_CALL (data->call_one));
break;
case 2:
assert_true (calls_ringer_get_is_ringing (ringer));
assert_false (calls_ringer_get_ring_is_quiet (ringer));
calls_call_hang_up (CALLS_CALL (data->call_two));
break;
case 3:
assert_false (calls_ringer_get_is_ringing (ringer));
assert_false (calls_ringer_get_ring_is_quiet (ringer));
g_main_loop_quit (data->loop);
break;
default:
g_assert_not_reached (); /* did not find equivalent cmocka assertion */
}
}
static void
test_ringing_multiple_calls_with_restart (void **state)
{
TestData *data = *state;
assert_false (calls_ringer_get_is_ringing (data->ringer));
g_signal_connect (data->ringer,
"notify::ringing",
G_CALLBACK (t6_on_ringer_multiple_calls_with_restart),
data);
/* delay before completion of __wrap_lfb_event_trigger_feedback_async() */
will_return_always (__wrap_lfb_event_trigger_feedback_async, 10);
/* delay before completion of __wrap_lfb_event_end_feedback_async() */
will_return_always (__wrap_lfb_event_end_feedback_async, 10);
calls_call_set_state (CALLS_CALL (data->call_one), CALLS_CALL_STATE_INCOMING);
add_call (data->manager, data->ui_call_one);
calls_call_set_state (CALLS_CALL (data->call_two), CALLS_CALL_STATE_INCOMING);
add_call (data->manager, data->ui_call_two);
/* main loop will quit in callback of notify::ring */
g_main_loop_run (data->loop);
assert_false (calls_ringer_get_is_ringing (data->ringer));
}
int
main (int argc,
char *argv[])
{
const struct CMUnitTest tests[] = {
cmocka_unit_test_setup_teardown (test_ringing_accept_call,
setup_test_data,
tear_down_test_data),
cmocka_unit_test_setup_teardown (test_ringing_hang_up_call,
setup_test_data,
tear_down_test_data),
cmocka_unit_test_setup_teardown (test_ringing_silence_call,
setup_test_data,
tear_down_test_data),
cmocka_unit_test_setup_teardown (test_ringing_multiple_calls,
setup_test_data,
tear_down_test_data),
cmocka_unit_test_setup_teardown (test_ringing_multiple_calls_with_restart,
setup_test_data,
tear_down_test_data)
};
return cmocka_run_group_tests (tests, NULL, NULL);
}