1
0
Fork 0
mirror of https://gitlab.gnome.org/GNOME/calls.git synced 2024-12-13 16:07:36 +00:00
Purism-Calls/tests/test-ringer.c
Chris Talbot e91d6258ad calls-ui-call-data: change DELAY_UI_MS to 100 ms
15 ms does not seem to be enough time for phosh-antispam to be able
to hang up before the incoming call screen shows up. In my experiement,
90 looks to be the minimum time needed for the incoming call to not show up.

I put it to 100 ms just to be safe.
2022-06-11 18:56:46 -04:00

588 lines
16 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));
}
/* t3: test_ringing_hang_up_call_ringer_cancelled */
static gboolean
t3_on_ringer_timeout (gpointer user_data)
{
TestData *data = user_data;
static guint test_phase = 0;
assert_false (calls_ringer_get_is_ringing (data->ringer));
if (test_phase == 0) {
calls_call_hang_up (CALLS_CALL (data->call_one));
test_phase++;
return G_SOURCE_CONTINUE;
}
g_main_loop_quit ((GMainLoop *) data->loop);
return G_SOURCE_REMOVE;
}
/** this test should use cancellable code path by hanging up before
* event triggering completes
*/
static void
test_ringing_hang_up_call_ringer_cancelled (void **state)
{
TestData *data = *state;
assert_false (calls_ringer_get_is_ringing (data->ringer));
/* delay before completion of __wrap_lfb_event_trigger_feedback_async() */
will_return (__wrap_lfb_event_trigger_feedback_async, 50);
calls_call_set_state (CALLS_CALL (data->call_one), CALLS_CALL_STATE_INCOMING);
add_call (data->manager, data->ui_call_one);
/** this timeout needs to be longer than the delay for activating the UI/ringer,
* see DELAY_UI_MS in calls-ui-call-data.c
*/
g_timeout_add (105, G_SOURCE_FUNC (t3_on_ringer_timeout), data);
/* main loop will quit in t3_on_ringer_timeout() */
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_hang_up_call_ringer_cancelled,
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);
}