intel: XMM7360: add xmmrpc protocol test infrastructure

Signed-off-by: Dan Williams <dan@ioncontrol.co>
This commit is contained in:
Dan Williams
2026-05-24 08:33:48 -05:00
parent 64d8053413
commit d6fe0722c9
4 changed files with 380 additions and 7 deletions
@@ -21,6 +21,9 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <ModemManager.h>
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
#include "mm-xmmrpc-xmm7360-protocol.h" #include "mm-xmmrpc-xmm7360-protocol.h"
#include "mm-intel-enums-types.h" #include "mm-intel-enums-types.h"
@@ -50,7 +53,7 @@ xmm7360_rpc_response_free (Xmm7360RpcResponse *response)
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, fmt, __VA_ARGS__); \ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, fmt, __VA_ARGS__); \
} }
static gint gint
xmm7360_byte_array_read_asn_int (GByteArray *buf, xmm7360_byte_array_read_asn_int (GByteArray *buf,
gsize offset, gsize offset,
gint *out_val, gint *out_val,
@@ -64,7 +67,7 @@ xmm7360_byte_array_read_asn_int (GByteArray *buf,
if (buf->len <= offset + 2) { if (buf->len <= offset + 2) {
PARSE_ERROR ("initial buffer size %u too small (need %zu)", PARSE_ERROR ("initial buffer size %u too small (need %zu)",
buf->len, offset + 2); buf->len, offset + 2 + 1);
return -1; return -1;
} }
@@ -116,7 +119,7 @@ xmm7360_byte_array_read_asn_int (GByteArray *buf,
return offset - orig_offset; return offset - orig_offset;
} }
static gint gint
xmm7360_byte_array_read_string (GByteArray *buf, xmm7360_byte_array_read_string (GByteArray *buf,
gsize offset, gsize offset,
Xmm7360RpcMsgArg *out_arg, Xmm7360RpcMsgArg *out_arg,
@@ -217,14 +220,14 @@ xmm7360_byte_array_append_asn_int4 (GByteArray *buf, gint32 value)
g_byte_array_append (buf, (const guint8 *) &value_be, 4); g_byte_array_append (buf, (const guint8 *) &value_be, 4);
} }
static void void
xmm7360_byte_array_append_uint8 (GByteArray *buf, gulong val) xmm7360_byte_array_append_uint8 (GByteArray *buf, gulong val)
{ {
guint8 _val = (guint8) val; guint8 _val = (guint8) val;
g_byte_array_append (buf, &_val, 1); g_byte_array_append (buf, &_val, 1);
} }
static void void
xmm7360_byte_array_append_string (GByteArray *buf, xmm7360_byte_array_append_string (GByteArray *buf,
const guint8 *data, const guint8 *data,
gsize data_len, gsize data_len,
@@ -413,7 +416,7 @@ xmm7360_command_to_byte_array (Xmm7360RpcCallId callid,
return buf; return buf;
} }
static gboolean gboolean
xmm7360_rpc_msg_body_unpack (GByteArray *buf, GPtrArray *args, GError **error) xmm7360_rpc_msg_body_unpack (GByteArray *buf, GPtrArray *args, GError **error)
{ {
gsize offset; gsize offset;
@@ -526,9 +526,28 @@ typedef struct {
/*****************************************************************************/ /*****************************************************************************/
gint xmm7360_byte_array_read_asn_int (GByteArray *buf,
gsize offset,
gint *out_val,
Xmm7360RpcMsgArg *out_arg,
GError **error);
gint xmm7360_byte_array_read_string (GByteArray *buf,
gsize offset,
Xmm7360RpcMsgArg *out_arg,
GError **error);
void xmm7360_byte_array_append_asn_int4 (GByteArray *array, void xmm7360_byte_array_append_asn_int4 (GByteArray *array,
gint32 value); gint32 value);
void xmm7360_byte_array_append_uint8 (GByteArray *buf,
gulong val);
void xmm7360_byte_array_append_string (GByteArray *buf,
const guint8 *data,
gsize data_len,
guint data_len_padded);
void xmm7360_rpc_response_free (Xmm7360RpcResponse *msg); void xmm7360_rpc_response_free (Xmm7360RpcResponse *msg);
GByteArray * xmm7360_rpc_args_to_byte_array (const Xmm7360RpcMsgArg *args); GByteArray * xmm7360_rpc_args_to_byte_array (const Xmm7360RpcMsgArg *args);
@@ -544,6 +563,10 @@ GString * xmm7360_rpc_args_to_string (GPtrArray
GString * xmm7360_byte_array_hexlify (GByteArray *buf); GString * xmm7360_byte_array_hexlify (GByteArray *buf);
gboolean xmm7360_rpc_msg_body_unpack (GByteArray *buf,
GPtrArray *args,
GError **error);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (Xmm7360RpcResponse, xmm7360_rpc_response_free); G_DEFINE_AUTOPTR_CLEANUP_FUNC (Xmm7360RpcResponse, xmm7360_rpc_response_free);
#endif /* MM_XMMRPC_XMM7360_PROTOCOL_H */ #endif /* MM_XMMRPC_XMM7360_PROTOCOL_H */
@@ -0,0 +1,341 @@
/* -*- 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) 2018 Aleksander Morgado <aleksander@aleksander.es>
*/
#include <glib.h>
#include <glib-object.h>
#include <locale.h>
#include <ModemManager.h>
#define _LIBMM_INSIDE_MM
#include <libmm-glib.h>
#include "mm-log-test.h"
#include "mm-modem-helpers.h"
#include "mm-xmmrpc-xmm7360-protocol.h"
#define XMM_BUFFER(...) \
.buffer = { __VA_ARGS__ }, \
.buffer_size = sizeof((guint8[]){ __VA_ARGS__ }),
#define XMM_STRING_BUFFER(str_type, str_len, ...) \
.buffer = { str_type, \
str_len, \
0x02, /* len_padded: ASN int start marker */ \
0x01, /* len_padded: ASN int size 1 */ \
str_len * (str_type == 0x55 ? 1 : str_type == 0x56 ? 2 : str_type == 0x57 ? 4 : 0), /* len_padded: ASN int val <str_len> */ \
0x02, /* pad_len: ASN int start marker */ \
0x01, /* pad_len: ASN int size 1 */ \
0x00, /* pad_len: ASN int val 0 */ \
__VA_ARGS__ /* string data */ \
}, \
.buffer_size = sizeof((guint8[]){ __VA_ARGS__ }) + 8,
#define XMM_EXPECTED_ARG_BUFFER(...) \
.expected_arg_buf = { __VA_ARGS__ }, \
.expected_arg_size = sizeof((guint8[]){ __VA_ARGS__ }),
/*****************************************************************************/
typedef struct {
const gchar *detail;
const gsize offset;
const gint expected_consumed;
const gint expected_error;
const gchar *expected_error_string;
const guint8 buffer[255];
const guint buffer_size;
const guint8 expected_arg_buf[255];
const gsize expected_arg_size;
} ReadStrTest;
static const ReadStrTest read_str_tests[] = {
{
.detail = "zero_buffer",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "initial buffer size 0 too small (need 2)",
},
{
.detail = "1b_buffer",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "initial buffer size 1 too small (need 2)",
XMM_BUFFER( 0x02 )
},
{
.detail = "bad_string_type",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "unhandled string type 0x02",
XMM_BUFFER( 0x02, 0x04 )
},
{
.detail = "small_buffer_big_message",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "initial buffer size 3 too small (need 5)",
XMM_BUFFER( 0x55, 0x04, 0x02 )
},
{
.detail = "1b_string_2chars",
.expected_consumed = 10,
XMM_STRING_BUFFER( 0x55, 0x02, 'H', 'i' )
XMM_EXPECTED_ARG_BUFFER( 'H', 'i' )
},
{
.detail = "1b_string_5chars",
.expected_consumed = 13,
XMM_STRING_BUFFER( 0x55, 0x05, 'H', 'e', 'l', 'l', 'o' )
XMM_EXPECTED_ARG_BUFFER( 'H', 'e', 'l', 'l', 'o' )
},
{
.detail = "2b_string_2chars",
.expected_consumed = 12,
XMM_STRING_BUFFER( 0x56, 0x02, 0x00, 'H', 0x00, 'i' )
XMM_EXPECTED_ARG_BUFFER( 0x00, 'H', 0x00, 'i' )
},
{
.detail = "4b_string_2chars",
.expected_consumed = 16,
XMM_STRING_BUFFER( 0x57, 0x02, 0x00, 0x01, 0x02, 'H', 0x00, 0x01, 0x02, 'i' )
XMM_EXPECTED_ARG_BUFFER( 0x00, 0x01, 0x02, 'H', 0x00, 0x01, 0x02, 'i' )
},
{
.detail = "1b_string_zero_length",
.expected_consumed = 8,
XMM_STRING_BUFFER( 0x55, 0x00 )
},
{
.detail = "2b_string_zero_length",
.expected_consumed = 8,
XMM_STRING_BUFFER( 0x56, 0x00 )
},
{
.detail = "4b_string_zero_length",
.expected_consumed = 8,
XMM_STRING_BUFFER( 0x57, 0x00 )
},
};
static void
test_read_str (gconstpointer data)
{
const ReadStrTest *test = data;
g_autoptr(GError) error = NULL;
gint consumed;
g_autoptr(GByteArray) buffer = NULL;
Xmm7360RpcMsgArg arg = { 0 };
buffer = g_byte_array_sized_new (sizeof (test->buffer_size));
if (sizeof (test->buffer))
g_byte_array_append (buffer, test->buffer, test->buffer_size);
consumed = xmm7360_byte_array_read_string (buffer, test->offset, &arg, &error);
if (error) {
g_assert_error (error, MM_CORE_ERROR, test->expected_error);
g_assert_cmpstr (error->message, ==, test->expected_error_string);
g_assert_cmpint (consumed, <, 0);
g_assert_cmpint (test->expected_arg_size, ==, 0);
g_assert_cmpint (arg.size, ==, 0);
} else {
g_assert_no_error (error);
g_assert_cmpint (test->expected_error, ==, 0);
g_assert_false (!!test->expected_error_string);
g_assert_cmpint (consumed, ==, test->expected_consumed);
g_assert_cmpint (arg.type, ==, XMM7360_RPC_MSG_ARG_TYPE_STRING);
g_assert_cmpint (arg.size, ==, test->expected_arg_size);
g_assert_cmpmem (arg.value.string, arg.size, test->expected_arg_buf, test->expected_arg_size);
}
}
/*****************************************************************************/
typedef struct {
const gchar *detail;
const gsize offset;
const gint expected_consumed;
const gint expected_error;
const gchar *expected_error_string;
const gint expected_val;
const guint8 buffer[255];
const guint buffer_size;
const Xmm7360RpcMsgArg expected_arg;
} ReadAsnIntTest;
static const ReadAsnIntTest read_asn_int_tests[] = {
{
.detail = "zero_buffer",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "initial buffer size 0 too small (need 3)",
},
{
.detail = "1b_buffer",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "initial buffer size 1 too small (need 3)",
XMM_BUFFER( 0x02 )
},
{
.detail = "2b_buffer",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "initial buffer size 2 too small (need 3)",
XMM_BUFFER( 0x02, 0x01 )
},
{
.detail = "small_buffer_big_message",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "buffer size 3 too small (need 6)",
XMM_BUFFER( 0x02, 0x04, 0x02 )
},
{
.detail = "bad_start",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "unexpected ASN start byte 0x00 (expected 0x02)",
XMM_BUFFER( 0x00, 0x01, 0x01 )
},
{
.detail = "no_data",
.expected_consumed = 2,
.expected_val = 0,
XMM_BUFFER( 0x02, 0x00, 0x00 )
.expected_arg = {
.type = XMM7360_RPC_MSG_ARG_TYPE_UNKNOWN,
},
},
{
.detail = "u8",
.expected_consumed = 3,
.expected_val = 1,
XMM_BUFFER( 0x02, 0x01, 0x01 )
.expected_arg = {
.type = XMM7360_RPC_MSG_ARG_TYPE_BYTE,
.value.b = 0x01,
},
},
{
.detail = "u16",
.expected_consumed = 4,
.expected_val = 0x102,
XMM_BUFFER( 0x02, 0x02, 0x01, 0x02 )
.expected_arg = {
.type = XMM7360_RPC_MSG_ARG_TYPE_SHORT,
.value.s = 0x102,
},
},
{
.detail = "u24_is_bad",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "unhandled int size 3",
XMM_BUFFER( 0x02, 0x03, 0x01, 0x02, 0x03 )
},
{
.detail = "u32",
.expected_consumed = 6,
.expected_val = 0x1020304,
XMM_BUFFER( 0x02, 0x04, 0x01, 0x02, 0x03, 0x04 )
.expected_arg = {
.type = XMM7360_RPC_MSG_ARG_TYPE_LONG,
.value.l = 0x1020304,
},
},
{
.detail = "ubad",
.expected_consumed = -1,
.expected_error = MM_CORE_ERROR_FAILED,
.expected_error_string = "unhandled int size 6",
XMM_BUFFER( 0x02, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 )
},
};
static void
test_read_asn_int (gconstpointer data)
{
const ReadAsnIntTest *test = data;
g_autoptr(GError) error = NULL;
gint consumed;
g_autoptr(GByteArray) buffer = NULL;
gint val = 0;
Xmm7360RpcMsgArg arg = { 0 };
buffer = g_byte_array_sized_new (sizeof (test->buffer_size));
if (sizeof (test->buffer))
g_byte_array_append (buffer, test->buffer, test->buffer_size);
consumed = xmm7360_byte_array_read_asn_int (buffer, test->offset, &val, &arg, &error);
if (error) {
g_assert_error (error, MM_CORE_ERROR, test->expected_error);
g_assert_cmpstr (error->message, ==, test->expected_error_string);
g_assert_cmpint (consumed, <, 0);
g_assert_cmpint (test->expected_arg.type, ==, 0);
} else {
g_assert_no_error (error);
g_assert_cmpint (test->expected_error, ==, 0);
g_assert_false (!!test->expected_error_string);
g_assert_cmpint (consumed, ==, test->expected_consumed);
g_assert_cmpint (val, ==, test->expected_val);
if (test->expected_arg.type != XMM7360_RPC_MSG_ARG_TYPE_UNKNOWN) {
g_assert_cmpint (arg.type, ==, test->expected_arg.type);
switch (arg.type) {
case XMM7360_RPC_MSG_ARG_TYPE_BYTE:
g_assert_cmpint (arg.value.b, ==, test->expected_arg.value.b);
break;
case XMM7360_RPC_MSG_ARG_TYPE_SHORT:
g_assert_cmpint (arg.value.s, ==, test->expected_arg.value.s);
break;
case XMM7360_RPC_MSG_ARG_TYPE_LONG:
g_assert_cmpint (arg.value.l, ==, test->expected_arg.value.l);
break;
case XMM7360_RPC_MSG_ARG_TYPE_STRING:
g_assert_cmpmem (arg.value.string, arg.size, test->expected_arg.value.string, test->expected_arg.size);
break;
case XMM7360_RPC_MSG_ARG_TYPE_UNKNOWN:
default:
g_assert_not_reached ();
}
}
}
}
/*****************************************************************************/
int main (int argc, char **argv)
{
guint i;
setlocale (LC_ALL, "");
g_test_init (&argc, &argv, NULL);
for (i = 0; i < G_N_ELEMENTS (read_asn_int_tests); i++) {
g_autofree gchar *path;
path = g_strdup_printf ("/MM/xmmrpc/read_asn_int/%s", read_asn_int_tests[i].detail);
g_test_add_data_func (path, &read_asn_int_tests[i], test_read_asn_int);
}
for (i = 0; i < G_N_ELEMENTS (read_str_tests); i++) {
g_autofree gchar *path;
path = g_strdup_printf ("/MM/xmmrpc/read_str/%s", read_str_tests[i].detail);
g_test_add_data_func (path, &read_str_tests[i], test_read_str);
}
return g_test_run ();
}
+7 -1
View File
@@ -635,16 +635,22 @@ if plugins_options['intel']
command: [ command: [
python, python,
mm_mkenums, mm_mkenums,
'--fhead', '#include "mm-port-serial-xmmrpc-xmm7360.h"\n#ifndef __MM_XMM7360_ENUMS_TYPES_H__\n#define __MM_XMM7360_ENUMS_TYPES_H__\n', '--fhead', '#include "mm-xmmrpc-xmm7360-protocol.h"\n#ifndef __MM_XMM7360_ENUMS_TYPES_H__\n#define __MM_XMM7360_ENUMS_TYPES_H__\n',
'--template', files(templates_dir / enums_types + '.h.template'), '--template', files(templates_dir / enums_types + '.h.template'),
'--ftail', '#endif /* __MM_XMM7360_ENUMS_TYPES_H__ */\n', '--ftail', '#endif /* __MM_XMM7360_ENUMS_TYPES_H__ */\n',
'@INPUT@'], '@INPUT@'],
capture: true, capture: true,
) )
test_sources = files(
'intel/mm-xmmrpc-xmm7360-protocol.c',
'intel/tests/test-xmmrpc-xmm7360-protocol.c',
)
plugins += {'plugin-intel': { plugins += {'plugin-intel': {
'plugin': true, 'plugin': true,
'module': {'sources': sources, 'include_directories': plugins_incs + [xmm_inc, intel_inc], 'c_args': common_c_args}, 'module': {'sources': sources, 'include_directories': plugins_incs + [xmm_inc, intel_inc], 'c_args': common_c_args},
'test': {'sources': test_sources, 'include_directories': intel_inc, 'dependencies': libhelpers_dep},
}} }}
endif endif