Files
ModemManager/tools/tests/test-stub.c
Alyssa Ross a8f086bfb3 tools: fix signal type in service test
The signal definition is:

    <signal name="StateChanged">
      <arg name="old" type="i" />
      <arg name="new" type="i" />
      <arg name="reason" type="u" />
    </signal>

So the first two arguments need to be adjusted.

Without this change, the test was failing for me:

    (/build/source/tools/tests/.libs/lt-test-stub:77030): GLib-GObject-CRITICAL **: 15:05:35.276: ../gobject/gsignal.c:3167: value for 'gint' parameter 0 for signal "state-changed" is of type 'guint'
2021-06-18 08:34:06 +00:00

460 lines
16 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
* Copyright (C) 2020 Frederic Martinsons <frederic.martinsons@sigfox.com>
*/
#include <config.h>
#include <glib.h>
#include <gio/gio.h>
#include <libmm-glib.h>
#include <ModemManager-names.h>
#define MM_LOG_NO_OBJECT
#include <mm-log-test.h>
#define MM_TEST_IFACE_NAME "org.freedesktop.ModemManager1.LibmmGlibTest"
typedef struct {
GMainLoop *loop;
MMManager *mm_manager;
GDBusConnection *gdbus_connection;
GDBusProxy *mm_proxy;
GDBusProxy *mm_modem_prop_proxy;
GTestDBus *test_bus;
gchar *modem_object_path;
guint timeout_id;
MMSim *sim;
gboolean pin_error;
} TestData;
static void
setup (TestData **ptdata,
gconstpointer data)
{
GError *error = NULL;
TestData *tdata = NULL;
tdata = (TestData *)g_malloc0 (sizeof(TestData));
*ptdata = tdata;
tdata->loop = g_main_loop_new (NULL, FALSE);
g_assert_nonnull (tdata->loop);
tdata->test_bus = g_test_dbus_new (G_TEST_DBUS_NONE);
g_assert_nonnull (tdata->test_bus);
g_test_dbus_add_service_dir (tdata->test_bus, TEST_SERVICES);
g_test_dbus_up (tdata->test_bus);
/* Grab a proxy to the fake NM service to trigger tests */
tdata->mm_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
MM_DBUS_SERVICE,
MM_DBUS_PATH,
MM_TEST_IFACE_NAME,
NULL, &error);
g_assert_no_error (error);
tdata->gdbus_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
g_assert_no_error (error);
tdata->mm_manager = mm_manager_new_sync (tdata->gdbus_connection,
G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
NULL,
&error);
g_assert_no_error (error);
g_assert_nonnull (tdata->mm_manager);
}
static void
teardown (TestData **ptdata,
gconstpointer data)
{
TestData *tdata = NULL;
tdata = *ptdata;
g_clear_object (&tdata->mm_modem_prop_proxy);
g_clear_object (&tdata->mm_proxy);
g_clear_object (&tdata->mm_manager);
g_clear_object (&tdata->gdbus_connection);
g_test_dbus_down (tdata->test_bus);
g_clear_object (&tdata->test_bus);
g_main_loop_unref (tdata->loop);
g_free (tdata);
}
static gboolean
loop_timeout_cb (gpointer user_data)
{
mm_err ("Timeout has elapsed");
g_assert_not_reached ();
return G_SOURCE_REMOVE;
}
static void
run_loop_for_ms (TestData *tdata,
guint32 timeout)
{
mm_info ("Run loop for %u ms", timeout);
tdata->timeout_id = g_timeout_add (timeout, loop_timeout_cb, tdata);
g_main_loop_run (tdata->loop);
}
static void
stop_loop (TestData *tdata)
{
if (tdata->timeout_id) {
g_source_remove (tdata->timeout_id);
tdata->timeout_id = 0;
}
mm_info ("Stop the loop");
g_main_loop_quit (tdata->loop);
}
static void
add_modem_completion_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
GVariant *dbus_return = NULL;
GVariant *obj_path_variant = NULL;
TestData *tdata = NULL;
tdata = (TestData*)user_data;
mm_info ("AddModem DBus call completed");
dbus_return = g_dbus_proxy_call_finish (tdata->mm_proxy, res, &error);
g_assert_no_error (error);
g_assert_nonnull (dbus_return);
g_assert_cmpstr (g_variant_get_type_string (dbus_return), == , "(o)");
obj_path_variant = g_variant_get_child_value (dbus_return, 0);
tdata->modem_object_path = g_variant_dup_string (obj_path_variant, NULL);
g_assert_null (tdata->mm_modem_prop_proxy);
tdata->mm_modem_prop_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
NULL,
MM_DBUS_SERVICE,
tdata->modem_object_path,
"org.freedesktop.DBus.Properties",
NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (tdata->mm_modem_prop_proxy);
g_variant_unref (dbus_return);
g_variant_unref (obj_path_variant);
stop_loop (tdata);
}
static gchar*
add_modem (TestData *tdata,
gboolean add_sim,
const gchar *iccid)
{
g_dbus_proxy_call (tdata->mm_proxy,
"AddModem",
g_variant_new ("(bs)", add_sim, iccid),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
1000,
NULL,
add_modem_completion_cb,
tdata);
run_loop_for_ms (tdata, 1000);
return tdata->modem_object_path;
}
static void
emit_state_changed_completion_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
GVariant *dbus_return = NULL;
TestData *tdata = NULL;
tdata = (TestData*)user_data;
mm_info ("EmitStateChanged DBus call completed");
dbus_return = g_dbus_proxy_call_finish (tdata->mm_proxy, res, &error);
g_assert_no_error (error);
g_assert_nonnull (dbus_return);
g_variant_unref (dbus_return);
stop_loop (tdata);
}
static void
set_modem_state (TestData *tdata,
MMModemState state,
MMModemStateFailedReason reason)
{
GError *error = NULL;
GVariant *ret = NULL;
GVariant *old_state_variant = NULL;
gint old_state = 0;
g_assert_nonnull (tdata->mm_modem_prop_proxy);
/* Get current state */
ret = g_dbus_proxy_call_sync (tdata->mm_modem_prop_proxy,
"org.freedesktop.DBus.Properties.Get",
g_variant_new ("(ss)",
MM_DBUS_INTERFACE_MODEM,
MM_MODEM_PROPERTY_STATE),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1,
NULL,
&error);
g_assert_no_error (error);
g_variant_get (ret, "(v)", &old_state_variant);
old_state = g_variant_get_int32 (old_state_variant);
g_variant_unref (ret);
g_variant_unref (old_state_variant);
ret = g_dbus_proxy_call_sync (tdata->mm_modem_prop_proxy,
"org.freedesktop.DBus.Properties.Set",
g_variant_new ("(ssv)",
MM_DBUS_INTERFACE_MODEM,
MM_MODEM_PROPERTY_STATE,
g_variant_new_int32 (state)),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1,
NULL,
&error);
g_assert_no_error (error);
g_variant_unref (ret);
ret = g_dbus_proxy_call_sync (tdata->mm_modem_prop_proxy,
"org.freedesktop.DBus.Properties.Set",
g_variant_new ("(ssv)",
MM_DBUS_INTERFACE_MODEM,
MM_MODEM_PROPERTY_STATEFAILEDREASON,
g_variant_new_uint32 (reason)),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
-1,
NULL,
&error);
g_assert_no_error (error);
g_variant_unref (ret);
/* Emit state change signal */
g_dbus_proxy_call (tdata->mm_proxy,
"EmitStateChanged",
g_variant_new ("(iiu)", old_state, state, reason),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
1000,
NULL,
emit_state_changed_completion_cb,
tdata);
run_loop_for_ms (tdata, 1000);
}
static void
set_modem_unlock_completion_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
GVariant *dbus_return = NULL;
TestData *tdata = NULL;
tdata = (TestData*)user_data;
mm_info ("org.freedesktop.DBus.Properties.Set DBus call completed");
dbus_return = g_dbus_proxy_call_finish (tdata->mm_modem_prop_proxy, res, &error);
g_assert_no_error (error);
g_assert_nonnull (dbus_return);
g_variant_unref (dbus_return);
stop_loop (tdata);
}
static void
set_modem_unlock (TestData *tdata,
MMModemLock lock_state)
{
g_assert_nonnull (tdata->mm_modem_prop_proxy);
g_dbus_proxy_call (tdata->mm_modem_prop_proxy,
"org.freedesktop.DBus.Properties.Set",
g_variant_new ("(ssv)",
MM_DBUS_INTERFACE_MODEM,
MM_MODEM_PROPERTY_UNLOCKREQUIRED,
g_variant_new_uint32 (lock_state)),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
1000,
NULL,
set_modem_unlock_completion_cb,
tdata);
run_loop_for_ms (tdata, 1000);
}
static void
set_modem_equipment_error (TestData *tdata,
MMMobileEquipmentError equipmentError,
gboolean clear)
{
GError *error = NULL;
GVariant *ret = NULL;
ret = g_dbus_proxy_call_sync (tdata->mm_proxy,
"SetMobileEquipmentError",
g_variant_new ("(ub)", equipmentError, clear),
G_DBUS_CALL_FLAGS_NO_AUTO_START,
3000,
NULL,
&error);
g_assert_no_error (error);
g_variant_unref (ret);
}
static void
test_modem_interface (TestData **ptdata,
gconstpointer data)
{
TestData *tdata = NULL;
GDBusObject *modem_object = NULL;
MMModem *mm_modem = NULL;
g_autofree gchar *modem_path = NULL;
tdata = *ptdata;
/* Add a modem object (with no sim attached) */
modem_path = add_modem (tdata, FALSE, "");
modem_object = g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (tdata->mm_manager), modem_path);
g_assert_nonnull (modem_object);
mm_modem = mm_object_get_modem (MM_OBJECT (modem_object));
g_clear_object (&modem_object);
/* Check the modem states */
g_assert_cmpuint (mm_modem_get_state (mm_modem), ==, MM_MODEM_STATE_UNKNOWN);
g_assert_cmpuint (mm_modem_get_state_failed_reason (mm_modem), ==, MM_MODEM_STATE_FAILED_REASON_UNKNOWN);
/* Set new state and check that it is propagated */
set_modem_state (tdata, MM_MODEM_STATE_REGISTERED, MM_MODEM_STATE_FAILED_REASON_NONE);
g_assert_cmpuint (mm_modem_get_state (mm_modem), ==, MM_MODEM_STATE_REGISTERED);
g_assert_cmpuint (mm_modem_get_state_failed_reason (mm_modem), ==, MM_MODEM_STATE_FAILED_REASON_NONE);
g_clear_object (&mm_modem);
}
static void
mm_sim_send_pin_completion_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
gboolean ret = FALSE;
TestData *tdata = NULL;
tdata = (TestData*)user_data;
mm_info("SendPin DBus method call completed");
ret = mm_sim_send_pin_finish (tdata->sim, res, &error);
if (tdata->pin_error) {
g_assert_nonnull (error);
g_assert_false (ret);
g_clear_error (&error);
} else {
g_assert_no_error (error);
g_assert_true (ret);
}
stop_loop (tdata);
}
static void
test_sim_interface (TestData **ptdata,
gconstpointer data)
{
TestData *tdata = NULL;
GDBusObject *modem_object = NULL;
MMModem *mm_modem = NULL;
GError *error = NULL;
g_autofree gchar *modem_path = NULL;
tdata = *ptdata;
/* Add a modem with a sim object */
modem_path = add_modem (tdata, TRUE, "89330122503000800750");
modem_object = g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (tdata->mm_manager), modem_path);
g_assert_nonnull (modem_object);
mm_modem = mm_object_get_modem (MM_OBJECT (modem_object));
g_clear_object (&modem_object);
g_assert_cmpuint (mm_modem_get_unlock_required (mm_modem), ==, MM_MODEM_LOCK_NONE);
/* Lock the modem */
set_modem_unlock (tdata, MM_MODEM_LOCK_SIM_PIN);
g_assert_cmpuint (mm_modem_get_unlock_required (mm_modem), ==, MM_MODEM_LOCK_SIM_PIN);
tdata->sim = mm_modem_get_sim_sync (mm_modem, NULL, &error);
g_assert_no_error (error);
g_assert_nonnull (tdata->sim);
g_assert_cmpstr (mm_sim_get_identifier(tdata->sim), ==, "89330122503000800750");
/* Send a pin code */
tdata->pin_error = FALSE;
mm_sim_send_pin (tdata->sim, "1234", NULL, mm_sim_send_pin_completion_cb, tdata);
run_loop_for_ms (tdata, 1000);
/* Check that the modem has been unlocked */
g_assert_cmpuint (mm_modem_get_unlock_required (mm_modem), ==, MM_MODEM_LOCK_NONE);
/* Re lock it */
set_modem_unlock (tdata, MM_MODEM_LOCK_SIM_PIN);
g_assert_cmpuint (mm_modem_get_unlock_required (mm_modem), ==, MM_MODEM_LOCK_SIM_PIN);
/* Set an error that will simulate wrong pin code */
set_modem_equipment_error (tdata, MM_MOBILE_EQUIPMENT_ERROR_INCORRECT_PASSWORD, FALSE);
tdata->pin_error = TRUE;
mm_sim_send_pin (tdata->sim, "0000", NULL, mm_sim_send_pin_completion_cb, tdata);
run_loop_for_ms (tdata, 1000);
g_assert_cmpuint (mm_modem_get_unlock_required (mm_modem), ==, MM_MODEM_LOCK_SIM_PIN);
/* Clear the error and retry the pin code */
set_modem_equipment_error (tdata, 0, TRUE);
tdata->pin_error = FALSE;
mm_sim_send_pin (tdata->sim, "1234", NULL, mm_sim_send_pin_completion_cb, tdata);
run_loop_for_ms (tdata, 1000);
g_assert_cmpuint (mm_modem_get_unlock_required (mm_modem), ==, MM_MODEM_LOCK_NONE);
g_clear_object (&tdata->sim);
g_clear_object (&mm_modem);
}
int main (int argc,
char **argv)
{
g_test_init (&argc, &argv, NULL);
g_test_add ("/MM/stub/modem/interface",
TestData *, NULL, setup,
test_modem_interface,
teardown);
g_test_add ("/MM/stub/sim/interface",
TestData *, NULL, setup,
test_sim_interface,
teardown);
return g_test_run ();
}