tests/subsys/modem: Added unit tests for modem modules
The tests test each module independently using the mock pipe, which implements the modem_pipe API, making it compatible with the modem modules. The modem_ppp module is slightly different from the others since it also interacts with the network stack. To acheive this, a mock implementation of the PPP L2 net iface has been implemented in the test suite for the modem_ppp. Signed-off-by: Bjarki Arge Andreasen <baa@trackunit.com>
This commit is contained in:
parent
b4cf54b8c3
commit
10ac828776
18 changed files with 2185 additions and 0 deletions
8
tests/subsys/modem/backends/tty/CMakeLists.txt
Normal file
8
tests/subsys/modem/backends/tty/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.20.0)
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
project(modem_backend_tty_test)
|
||||||
|
|
||||||
|
target_sources(app PRIVATE src/main.c)
|
12
tests/subsys/modem/backends/tty/prj.conf
Normal file
12
tests/subsys/modem/backends/tty/prj.conf
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
CONFIG_NO_OPTIMIZATIONS=y
|
||||||
|
|
||||||
|
CONFIG_MODEM_MODULES=y
|
||||||
|
CONFIG_MODEM_BACKEND_TTY=y
|
||||||
|
|
||||||
|
CONFIG_ZTEST=y
|
||||||
|
CONFIG_ZTEST_NEW_API=y
|
||||||
|
|
||||||
|
CONFIG_LOG=y
|
188
tests/subsys/modem/backends/tty/src/main.c
Normal file
188
tests/subsys/modem/backends/tty/src/main.c
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Trackunit Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Dependencies */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/sys/atomic.h>
|
||||||
|
|
||||||
|
#include <zephyr/modem/backend/tty.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
|
#define TEST_MODEM_BACKEND_TTY_PIPE_EVENT_OPENED_BIT (0)
|
||||||
|
#define TEST_MODEM_BACKEND_TTY_PIPE_EVENT_RRDY_BIT (1)
|
||||||
|
#define TEST_MODEM_BACKEND_TTY_PIPE_EVENT_CLOSED_BIT (2)
|
||||||
|
|
||||||
|
#define TEST_MODEM_BACKEND_TTY_OP_DELAY (K_MSEC(1000))
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Mock pipe */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static struct modem_backend_tty tty_backend;
|
||||||
|
static struct modem_pipe *tty_pipe;
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Mock PTY */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static int primary_fd;
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Buffers */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t buffer1[1024];
|
||||||
|
K_KERNEL_STACK_DEFINE(tty_stack, 4096);
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Helpers */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static void test_modem_backend_tty_cfmakeraw(struct termios *termios_p)
|
||||||
|
{
|
||||||
|
termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
|
||||||
|
termios_p->c_oflag &= ~OPOST;
|
||||||
|
termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
|
||||||
|
termios_p->c_cflag &= ~(CSIZE | PARENB);
|
||||||
|
termios_p->c_cflag |= CS8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Modem pipe callback */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static atomic_t tty_pipe_events;
|
||||||
|
|
||||||
|
static void modem_pipe_callback_handler(struct modem_pipe *pipe, enum modem_pipe_event event,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case MODEM_PIPE_EVENT_OPENED:
|
||||||
|
atomic_set_bit(&tty_pipe_events, TEST_MODEM_BACKEND_TTY_PIPE_EVENT_OPENED_BIT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MODEM_PIPE_EVENT_RECEIVE_READY:
|
||||||
|
atomic_set_bit(&tty_pipe_events, TEST_MODEM_BACKEND_TTY_PIPE_EVENT_RRDY_BIT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MODEM_PIPE_EVENT_CLOSED:
|
||||||
|
atomic_set_bit(&tty_pipe_events, TEST_MODEM_BACKEND_TTY_PIPE_EVENT_CLOSED_BIT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Test setup */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static void *test_modem_backend_tty_setup(void)
|
||||||
|
{
|
||||||
|
const char *secondary_name;
|
||||||
|
struct termios tio;
|
||||||
|
|
||||||
|
primary_fd = posix_openpt(O_RDWR | O_NOCTTY);
|
||||||
|
__ASSERT_NO_MSG(primary_fd > -1);
|
||||||
|
__ASSERT_NO_MSG(grantpt(primary_fd) > -1);
|
||||||
|
__ASSERT_NO_MSG(unlockpt(primary_fd) > -1);
|
||||||
|
__ASSERT_NO_MSG(tcgetattr(primary_fd, &tio) > -1);
|
||||||
|
test_modem_backend_tty_cfmakeraw(&tio);
|
||||||
|
__ASSERT_NO_MSG(tcsetattr(primary_fd, TCSAFLUSH, &tio) > -1);
|
||||||
|
secondary_name = ptsname(primary_fd);
|
||||||
|
|
||||||
|
struct modem_backend_tty_config config = {
|
||||||
|
.tty_path = secondary_name,
|
||||||
|
.stack = tty_stack,
|
||||||
|
.stack_size = K_KERNEL_STACK_SIZEOF(tty_stack),
|
||||||
|
};
|
||||||
|
|
||||||
|
tty_pipe = modem_backend_tty_init(&tty_backend, &config);
|
||||||
|
modem_pipe_attach(tty_pipe, modem_pipe_callback_handler, NULL);
|
||||||
|
__ASSERT_NO_MSG(modem_pipe_open(tty_pipe) == 0);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_modem_backend_tty_before(void *f)
|
||||||
|
{
|
||||||
|
atomic_set(&tty_pipe_events, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_modem_backend_tty_teardown(void *f)
|
||||||
|
{
|
||||||
|
modem_pipe_close(tty_pipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Tests */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
ZTEST(modem_backend_tty_suite, test_close_open)
|
||||||
|
{
|
||||||
|
zassert_true(modem_pipe_close(tty_pipe) == 0, "Failed to close pipe");
|
||||||
|
zassert_true(modem_pipe_close(tty_pipe) == -EALREADY, "Pipe should already be closed");
|
||||||
|
zassert_true(modem_pipe_open(tty_pipe) == 0, "Failed to open pipe");
|
||||||
|
zassert_true(modem_pipe_open(tty_pipe) == -EALREADY, "Pipe should already be open");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_backend_tty_suite, test_receive_ready_event_not_raised)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
k_sleep(TEST_MODEM_BACKEND_TTY_OP_DELAY);
|
||||||
|
|
||||||
|
result = atomic_test_bit(&tty_pipe_events, TEST_MODEM_BACKEND_TTY_PIPE_EVENT_RRDY_BIT);
|
||||||
|
zassert_false(result, "Receive ready event should not be set");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_backend_tty_suite, test_receive_ready_event_raised)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
bool result;
|
||||||
|
char *msg = "Test me buddy";
|
||||||
|
|
||||||
|
ret = write(primary_fd, msg, sizeof(msg));
|
||||||
|
zassert_true(ret == sizeof(msg), "Failed to write to primary FD");
|
||||||
|
|
||||||
|
k_sleep(TEST_MODEM_BACKEND_TTY_OP_DELAY);
|
||||||
|
|
||||||
|
result = atomic_test_bit(&tty_pipe_events, TEST_MODEM_BACKEND_TTY_PIPE_EVENT_RRDY_BIT);
|
||||||
|
zassert_true(result == true, "Receive ready evennt not set");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_backend_tty_suite, test_receive)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char msg[] = "Test me buddy";
|
||||||
|
|
||||||
|
ret = write(primary_fd, msg, sizeof(msg));
|
||||||
|
zassert_true(ret == sizeof(msg), "Failed to write to primary FD");
|
||||||
|
k_sleep(TEST_MODEM_BACKEND_TTY_OP_DELAY);
|
||||||
|
|
||||||
|
ret = modem_pipe_receive(tty_pipe, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(msg), "Received incorrect number of bytes");
|
||||||
|
ret = memcmp(msg, buffer1, sizeof(msg));
|
||||||
|
zassert_true(ret == 0, "Received incorrect bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_backend_tty_suite, test_transmit)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char msg[] = "Test me buddy 2";
|
||||||
|
|
||||||
|
ret = modem_pipe_transmit(tty_pipe, msg, sizeof(msg));
|
||||||
|
zassert_true(ret == sizeof(msg), "Failed to transmit using pipe");
|
||||||
|
|
||||||
|
k_sleep(TEST_MODEM_BACKEND_TTY_OP_DELAY);
|
||||||
|
|
||||||
|
ret = read(primary_fd, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(msg), "Read incorrect number of bytes");
|
||||||
|
ret = memcmp(msg, buffer1, sizeof(msg));
|
||||||
|
zassert_true(ret == 0, "Read incorrect bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST_SUITE(modem_backend_tty_suite, NULL, test_modem_backend_tty_setup,
|
||||||
|
test_modem_backend_tty_before, NULL, test_modem_backend_tty_teardown);
|
8
tests/subsys/modem/backends/tty/testcase.yaml
Normal file
8
tests/subsys/modem/backends/tty/testcase.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
tests:
|
||||||
|
modem.backends.tty:
|
||||||
|
tags: modem_backend_tty
|
||||||
|
harness: ztest
|
||||||
|
platform_allow: native_posix
|
132
tests/subsys/modem/mock/modem_backend_mock.c
Normal file
132
tests/subsys/modem/mock/modem_backend_mock.c
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Trackunit Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "modem_backend_mock.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int modem_backend_mock_open(void *data)
|
||||||
|
{
|
||||||
|
struct modem_backend_mock *mock = (struct modem_backend_mock *)data;
|
||||||
|
|
||||||
|
modem_pipe_notify_opened(&mock->pipe);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool modem_backend_mock_update(struct modem_backend_mock *mock, const uint8_t *buf,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
if (mock->transaction == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
__ASSERT(buf[i] == mock->transaction->get[mock->transaction_match_cnt],
|
||||||
|
"Unexpected transmit data");
|
||||||
|
|
||||||
|
mock->transaction_match_cnt++;
|
||||||
|
if (mock->transaction_match_cnt == mock->transaction->get_size) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int modem_backend_mock_transmit(void *data, const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
struct modem_backend_mock *mock = (struct modem_backend_mock *)data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
size = (mock->limit < size) ? mock->limit : size;
|
||||||
|
ret = ring_buf_put(&mock->tx_rb, buf, size);
|
||||||
|
if (modem_backend_mock_update(mock, buf, size)) {
|
||||||
|
modem_backend_mock_put(mock, mock->transaction->put,
|
||||||
|
mock->transaction->put_size);
|
||||||
|
|
||||||
|
mock->transaction = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int modem_backend_mock_receive(void *data, uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
struct modem_backend_mock *mock = (struct modem_backend_mock *)data;
|
||||||
|
|
||||||
|
size = (mock->limit < size) ? mock->limit : size;
|
||||||
|
return ring_buf_get(&mock->rx_rb, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int modem_backend_mock_close(void *data)
|
||||||
|
{
|
||||||
|
struct modem_backend_mock *mock = (struct modem_backend_mock *)data;
|
||||||
|
|
||||||
|
modem_pipe_notify_closed(&mock->pipe);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct modem_pipe_api modem_backend_mock_api = {
|
||||||
|
.open = modem_backend_mock_open,
|
||||||
|
.transmit = modem_backend_mock_transmit,
|
||||||
|
.receive = modem_backend_mock_receive,
|
||||||
|
.close = modem_backend_mock_close,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void modem_backend_mock_received_handler(struct k_work *item)
|
||||||
|
{
|
||||||
|
struct modem_backend_mock_work *mock_work_item = (struct modem_backend_mock_work *)item;
|
||||||
|
struct modem_backend_mock *mock = mock_work_item->mock;
|
||||||
|
|
||||||
|
modem_pipe_notify_receive_ready(&mock->pipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct modem_pipe *modem_backend_mock_init(struct modem_backend_mock *mock,
|
||||||
|
const struct modem_backend_mock_config *config)
|
||||||
|
{
|
||||||
|
memset(mock, 0, sizeof(*mock));
|
||||||
|
|
||||||
|
ring_buf_init(&mock->rx_rb, config->rx_buf_size, config->rx_buf);
|
||||||
|
ring_buf_init(&mock->tx_rb, config->tx_buf_size, config->tx_buf);
|
||||||
|
mock->received_work_item.mock = mock;
|
||||||
|
k_work_init(&mock->received_work_item.work, modem_backend_mock_received_handler);
|
||||||
|
mock->limit = config->limit;
|
||||||
|
modem_pipe_init(&mock->pipe, mock, &modem_backend_mock_api);
|
||||||
|
return &mock->pipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct modem_pipe *modem_backend_mock_get_pipe(struct modem_backend_mock *mock)
|
||||||
|
{
|
||||||
|
return &mock->pipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
void modem_backend_mock_reset(struct modem_backend_mock *mock)
|
||||||
|
{
|
||||||
|
ring_buf_reset(&mock->rx_rb);
|
||||||
|
ring_buf_reset(&mock->tx_rb);
|
||||||
|
mock->transaction = NULL;
|
||||||
|
mock->transaction_match_cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int modem_backend_mock_get(struct modem_backend_mock *mock, uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
return ring_buf_get(&mock->tx_rb, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void modem_backend_mock_put(struct modem_backend_mock *mock, const uint8_t *buf, size_t size)
|
||||||
|
{
|
||||||
|
__ASSERT(ring_buf_put(&mock->rx_rb, buf, size) == size,
|
||||||
|
"Mock buffer capacity exceeded");
|
||||||
|
|
||||||
|
k_work_submit(&mock->received_work_item.work);
|
||||||
|
}
|
||||||
|
|
||||||
|
void modem_backend_mock_prime(struct modem_backend_mock *mock,
|
||||||
|
const struct modem_backend_mock_transaction *transaction)
|
||||||
|
{
|
||||||
|
mock->transaction = transaction;
|
||||||
|
mock->transaction_match_cnt = 0;
|
||||||
|
}
|
66
tests/subsys/modem/mock/modem_backend_mock.h
Normal file
66
tests/subsys/modem/mock/modem_backend_mock.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Trackunit Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/modem/pipe.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/sys/ring_buffer.h>
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_DRIVERS_MODEM_MODEM_PIPE_MOCK
|
||||||
|
#define ZEPHYR_DRIVERS_MODEM_MODEM_PIPE_MOCK
|
||||||
|
|
||||||
|
struct modem_backend_mock;
|
||||||
|
|
||||||
|
struct modem_backend_mock_work {
|
||||||
|
struct k_work work;
|
||||||
|
struct modem_backend_mock *mock;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct modem_backend_mock_transaction {
|
||||||
|
/* Get data which will trigger put */
|
||||||
|
const uint8_t *get;
|
||||||
|
size_t get_size;
|
||||||
|
|
||||||
|
/* Data which will be put in response to get data */
|
||||||
|
const uint8_t *put;
|
||||||
|
size_t put_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct modem_backend_mock {
|
||||||
|
struct modem_pipe pipe;
|
||||||
|
|
||||||
|
struct ring_buf rx_rb;
|
||||||
|
struct ring_buf tx_rb;
|
||||||
|
|
||||||
|
struct modem_backend_mock_work received_work_item;
|
||||||
|
|
||||||
|
const struct modem_backend_mock_transaction *transaction;
|
||||||
|
size_t transaction_match_cnt;
|
||||||
|
|
||||||
|
/* Max allowed read/write size */
|
||||||
|
size_t limit;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct modem_backend_mock_config {
|
||||||
|
uint8_t *rx_buf;
|
||||||
|
size_t rx_buf_size;
|
||||||
|
uint8_t *tx_buf;
|
||||||
|
size_t tx_buf_size;
|
||||||
|
size_t limit;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct modem_pipe *modem_backend_mock_init(struct modem_backend_mock *mock,
|
||||||
|
const struct modem_backend_mock_config *config);
|
||||||
|
|
||||||
|
void modem_backend_mock_reset(struct modem_backend_mock *mock);
|
||||||
|
|
||||||
|
int modem_backend_mock_get(struct modem_backend_mock *mock, uint8_t *buf, size_t size);
|
||||||
|
|
||||||
|
void modem_backend_mock_put(struct modem_backend_mock *mock, const uint8_t *buf, size_t size);
|
||||||
|
|
||||||
|
void modem_backend_mock_prime(struct modem_backend_mock *mock,
|
||||||
|
const struct modem_backend_mock_transaction *transaction);
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_DRIVERS_MODEM_MODEM_PIPE_MOCK */
|
9
tests/subsys/modem/modem_chat/CMakeLists.txt
Normal file
9
tests/subsys/modem/modem_chat/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.20.0)
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
project(modem_cmux_test)
|
||||||
|
|
||||||
|
target_sources(app PRIVATE src/main.c ../mock/modem_backend_mock.c)
|
||||||
|
target_include_directories(app PRIVATE ../mock)
|
10
tests/subsys/modem/modem_chat/prj.conf
Normal file
10
tests/subsys/modem/modem_chat/prj.conf
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
CONFIG_NO_OPTIMIZATIONS=y
|
||||||
|
|
||||||
|
CONFIG_MODEM_MODULES=y
|
||||||
|
CONFIG_MODEM_CHAT=y
|
||||||
|
|
||||||
|
CONFIG_ZTEST=y
|
||||||
|
CONFIG_ZTEST_NEW_API=y
|
423
tests/subsys/modem/modem_chat/src/main.c
Normal file
423
tests/subsys/modem/modem_chat/src/main.c
Normal file
|
@ -0,0 +1,423 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Trackunit Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Dependencies */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/sys/atomic.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <zephyr/modem/chat.h>
|
||||||
|
#include <modem_backend_mock.h>
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Instances */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static struct modem_chat cmd;
|
||||||
|
static uint8_t cmd_delimiter[] = {'\r', '\n'};
|
||||||
|
static uint8_t cmd_receive_buf[128];
|
||||||
|
static uint8_t *cmd_argv[32];
|
||||||
|
static uint32_t cmd_user_data = 0x145212;
|
||||||
|
|
||||||
|
static struct modem_backend_mock mock;
|
||||||
|
static uint8_t mock_rx_buf[128];
|
||||||
|
static uint8_t mock_tx_buf[128];
|
||||||
|
static struct modem_pipe *mock_pipe;
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Track callbacks */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
#define MODEM_CHAT_UTEST_ON_IMEI_CALLED_BIT (0)
|
||||||
|
#define MODEM_CHAT_UTEST_ON_CREG_CALLED_BIT (1)
|
||||||
|
#define MODEM_CHAT_UTEST_ON_CGREG_CALLED_BIT (2)
|
||||||
|
#define MODEM_CHAT_UTEST_ON_QENG_SERVINGCELL_CALLED_BIT (3)
|
||||||
|
#define MODEM_CHAT_UTEST_ON_NO_CARRIER_CALLED_BIT (4)
|
||||||
|
#define MODEM_CHAT_UTEST_ON_ERROR_CALLED_BIT (5)
|
||||||
|
#define MODEM_CHAT_UTEST_ON_RDY_CALLED_BIT (6)
|
||||||
|
#define MODEM_CHAT_UTEST_ON_APP_RDY_CALLED_BIT (7)
|
||||||
|
#define MODEM_CHAT_UTEST_ON_NORMAL_POWER_DOWN_CALLED_BIT (8)
|
||||||
|
#define MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT (9)
|
||||||
|
|
||||||
|
static atomic_t callback_called;
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Script callbacks args copy */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t argv_buffers[32][128];
|
||||||
|
static uint16_t argc_buffers;
|
||||||
|
|
||||||
|
static void clone_args(char **argv, uint16_t argc)
|
||||||
|
{
|
||||||
|
argc_buffers = argc;
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < argc; i++) {
|
||||||
|
memcpy(argv_buffers[i], argv[i], strlen(argv[i]) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Script match callbacks */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static void on_imei(struct modem_chat *cmd, char **argv, uint16_t argc, void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_IMEI_CALLED_BIT);
|
||||||
|
clone_args(argv, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_creg(struct modem_chat *cmd, char **argv, uint16_t argc, void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_CREG_CALLED_BIT);
|
||||||
|
clone_args(argv, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_cgreg(struct modem_chat *cmd, char **argv, uint16_t argc, void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_CGREG_CALLED_BIT);
|
||||||
|
clone_args(argv, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_qeng_serving_cell(struct modem_chat *cmd, char **argv, uint16_t argc,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_QENG_SERVINGCELL_CALLED_BIT);
|
||||||
|
clone_args(argv, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_no_carrier(struct modem_chat *cmd, char **argv, uint16_t argc, void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_NO_CARRIER_CALLED_BIT);
|
||||||
|
clone_args(argv, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_error(struct modem_chat *cmd, char **argv, uint16_t argc, void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_ERROR_CALLED_BIT);
|
||||||
|
clone_args(argv, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_rdy(struct modem_chat *cmd, char **argv, uint16_t argc, void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_RDY_CALLED_BIT);
|
||||||
|
clone_args(argv, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_app_rdy(struct modem_chat *cmd, char **argv, uint16_t argc, void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_APP_RDY_CALLED_BIT);
|
||||||
|
clone_args(argv, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_normal_power_down(struct modem_chat *cmd, char **argv, uint16_t argc,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_NORMAL_POWER_DOWN_CALLED_BIT);
|
||||||
|
clone_args(argv, argc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Script callback */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static enum modem_chat_script_result script_result;
|
||||||
|
static void *script_result_user_data;
|
||||||
|
|
||||||
|
static void on_script_result(struct modem_chat *cmd, enum modem_chat_script_result result,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
atomic_set_bit(&callback_called, MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT);
|
||||||
|
script_result = result;
|
||||||
|
script_result_user_data = user_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Script */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
MODEM_CHAT_MATCH_DEFINE(ok_match, "OK", "", NULL);
|
||||||
|
MODEM_CHAT_MATCH_DEFINE(imei_match, "", "", on_imei);
|
||||||
|
MODEM_CHAT_MATCH_DEFINE(creg_match, "CREG: ", ",", on_creg);
|
||||||
|
MODEM_CHAT_MATCH_DEFINE(cgreg_match, "CGREG: ", ",", on_cgreg);
|
||||||
|
MODEM_CHAT_MATCH_DEFINE(qeng_servinc_cell_match, "+QENG: \"servingcell\",", ",",
|
||||||
|
on_qeng_serving_cell);
|
||||||
|
|
||||||
|
MODEM_CHAT_MATCHES_DEFINE(unsol_matches, MODEM_CHAT_MATCH("RDY", "", on_rdy),
|
||||||
|
MODEM_CHAT_MATCH("APP RDY", "", on_app_rdy),
|
||||||
|
MODEM_CHAT_MATCH("NORMAL POWER DOWN", "", on_normal_power_down));
|
||||||
|
|
||||||
|
MODEM_CHAT_SCRIPT_CMDS_DEFINE(
|
||||||
|
script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP("AT", ok_match),
|
||||||
|
MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match),
|
||||||
|
MODEM_CHAT_SCRIPT_CMD_RESP("IMEI?", imei_match), MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
|
||||||
|
MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?;+CGREG?", creg_match),
|
||||||
|
MODEM_CHAT_SCRIPT_CMD_RESP("", cgreg_match), MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match),
|
||||||
|
MODEM_CHAT_SCRIPT_CMD_RESP("AT+QENG=\"servingcell\"", qeng_servinc_cell_match),
|
||||||
|
MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match));
|
||||||
|
|
||||||
|
MODEM_CHAT_MATCHES_DEFINE(abort_matches, MODEM_CHAT_MATCH("NO CARRIER", "", on_no_carrier),
|
||||||
|
MODEM_CHAT_MATCH("ERROR ", ",:", on_error));
|
||||||
|
|
||||||
|
MODEM_CHAT_SCRIPT_DEFINE(script, script_cmds, abort_matches, on_script_result, 4);
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Script responses */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static const char at_response[] = "AT\r\n";
|
||||||
|
static const char ok_response[] = "OK\r\n";
|
||||||
|
static const char imei_response[] = "23412354123123\r\n";
|
||||||
|
static const char creg_response[] = "CREG: 1,2\r\n";
|
||||||
|
static const char cgreg_response[] = "CGREG: 10,43\r\n";
|
||||||
|
|
||||||
|
static const char qeng_servinc_cell_response[] = "+QENG: \"servingcell\",\"NOCONN\",\"GSM\",260"
|
||||||
|
",03,E182,AEAD,52,32,2,-68,255,255,0,38,38,1,,"
|
||||||
|
",,,,,,,,\r\n";
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Test setup */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static void *test_modem_chat_setup(void)
|
||||||
|
{
|
||||||
|
const struct modem_chat_config cmd_config = {
|
||||||
|
.user_data = &cmd_user_data,
|
||||||
|
.receive_buf = cmd_receive_buf,
|
||||||
|
.receive_buf_size = ARRAY_SIZE(cmd_receive_buf),
|
||||||
|
.delimiter = cmd_delimiter,
|
||||||
|
.delimiter_size = ARRAY_SIZE(cmd_delimiter),
|
||||||
|
.filter = NULL,
|
||||||
|
.filter_size = 0,
|
||||||
|
.argv = cmd_argv,
|
||||||
|
.argv_size = ARRAY_SIZE(cmd_argv),
|
||||||
|
.unsol_matches = unsol_matches,
|
||||||
|
.unsol_matches_size = ARRAY_SIZE(unsol_matches),
|
||||||
|
.process_timeout = K_MSEC(2),
|
||||||
|
};
|
||||||
|
|
||||||
|
zassert(modem_chat_init(&cmd, &cmd_config) == 0, "Failed to init modem CMD");
|
||||||
|
|
||||||
|
const struct modem_backend_mock_config mock_config = {
|
||||||
|
.rx_buf = mock_rx_buf,
|
||||||
|
.rx_buf_size = ARRAY_SIZE(mock_rx_buf),
|
||||||
|
.tx_buf = mock_tx_buf,
|
||||||
|
.tx_buf_size = ARRAY_SIZE(mock_tx_buf),
|
||||||
|
.limit = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
mock_pipe = modem_backend_mock_init(&mock, &mock_config);
|
||||||
|
zassert(modem_pipe_open(mock_pipe) == 0, "Failed to open mock pipe");
|
||||||
|
zassert(modem_chat_attach(&cmd, mock_pipe) == 0, "Failed to attach pipe mock to modem CMD");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_modem_chat_before(void *f)
|
||||||
|
{
|
||||||
|
/* Reset callback called */
|
||||||
|
atomic_set(&callback_called, 0);
|
||||||
|
|
||||||
|
/* Reset mock pipe */
|
||||||
|
modem_backend_mock_reset(&mock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_modem_chat_after(void *f)
|
||||||
|
{
|
||||||
|
/* Abort script */
|
||||||
|
modem_chat_script_abort(&cmd);
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Buffers */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t buffer[4096];
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Tests */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
ZTEST(modem_chat, test_script_no_error)
|
||||||
|
{
|
||||||
|
bool called;
|
||||||
|
|
||||||
|
zassert_true(modem_chat_script_run(&cmd, &script) == 0, "Failed to start script");
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Script sends "AT\r\n"
|
||||||
|
* Modem responds "AT\r\n"
|
||||||
|
* Modem responds "OK\r\n"
|
||||||
|
*/
|
||||||
|
|
||||||
|
modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer));
|
||||||
|
zassert_true(memcmp(buffer, "AT\r", sizeof("AT\r") - 1) == 0,
|
||||||
|
"Request not sent as expected");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&mock, at_response, sizeof(at_response) - 1);
|
||||||
|
modem_backend_mock_put(&mock, ok_response, sizeof(ok_response) - 1);
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Script sends "ATE0\r\n"
|
||||||
|
* Modem responds "OK\r\n"
|
||||||
|
*/
|
||||||
|
|
||||||
|
modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer));
|
||||||
|
zassert_true(memcmp(buffer, "ATE0\r\n", sizeof("ATE0\r\n") - 1) == 0,
|
||||||
|
"Request not sent as expected");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&mock, ok_response, sizeof(ok_response) - 1);
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Script sends "IMEI?\r\n"
|
||||||
|
* Modem responds "23412354123123\r\n"
|
||||||
|
* Modem responds "OK\r\n"
|
||||||
|
*/
|
||||||
|
|
||||||
|
modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer));
|
||||||
|
zassert_true(memcmp(buffer, "IMEI?\r\n", sizeof("IMEI?\r\n") - 1) == 0,
|
||||||
|
"Request not sent as expected");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&mock, imei_response, sizeof(imei_response) - 1);
|
||||||
|
modem_backend_mock_put(&mock, ok_response, sizeof(ok_response) - 1);
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
zassert_true(atomic_test_bit(&callback_called, MODEM_CHAT_UTEST_ON_IMEI_CALLED_BIT) == true,
|
||||||
|
"Expected IMEI callback called");
|
||||||
|
|
||||||
|
zassert_true(argv_buffers[0][0] == '\0', "Unexpected argv");
|
||||||
|
zassert_true(memcmp(argv_buffers[1], "23412354123123", sizeof("23412354123123")) == 0,
|
||||||
|
"Unexpected argv");
|
||||||
|
|
||||||
|
zassert_true(argc_buffers == 2, "Unexpected argc");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Script sends "AT+CREG?;+CGREG?\r\n"
|
||||||
|
* Modem responds "CREG: 1,2\r\n"
|
||||||
|
* Modem responds "CGREG: 1,2\r\n"
|
||||||
|
* Modem responds "OK\r\n"
|
||||||
|
*/
|
||||||
|
|
||||||
|
modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer));
|
||||||
|
zassert_true(memcmp(buffer, "AT+CREG?;+CGREG?\r\n", sizeof("AT+CREG?;+CGREG?\r\n") - 1) ==
|
||||||
|
0,
|
||||||
|
"Request not sent as expected");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&mock, creg_response, sizeof(creg_response) - 1);
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
zassert_true(memcmp(argv_buffers[0], "CREG: ", sizeof("CREG: ")) == 0, "Unexpected argv");
|
||||||
|
zassert_true(memcmp(argv_buffers[1], "1", sizeof("1")) == 0, "Unexpected argv");
|
||||||
|
zassert_true(memcmp(argv_buffers[2], "2", sizeof("2")) == 0, "Unexpected argv");
|
||||||
|
zassert_true(argc_buffers == 3, "Unexpected argc");
|
||||||
|
modem_backend_mock_put(&mock, cgreg_response, sizeof(cgreg_response) - 1);
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
zassert_true(memcmp(argv_buffers[0], "CGREG: ", sizeof("CGREG: ")) == 0, "Unexpected argv");
|
||||||
|
zassert_true(memcmp(argv_buffers[1], "10", sizeof("10")) == 0, "Unexpected argv");
|
||||||
|
zassert_true(memcmp(argv_buffers[2], "43", sizeof("43")) == 0, "Unexpected argv");
|
||||||
|
zassert_true(argc_buffers == 3, "Unexpected argc");
|
||||||
|
modem_backend_mock_put(&mock, ok_response, sizeof(ok_response) - 1);
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Script sends "AT+QENG=\"servingcell\"\r\n"
|
||||||
|
* Modem responds qeng_servinc_cell_response (long string)
|
||||||
|
* Modem responds "OK\r\n"
|
||||||
|
*/
|
||||||
|
|
||||||
|
modem_backend_mock_get(&mock, buffer, ARRAY_SIZE(buffer));
|
||||||
|
zassert_true(memcmp(buffer, "AT+QENG=\"servingcell\"\r\n",
|
||||||
|
sizeof("AT+QENG=\"servingcell\"\r\n") - 1) == 0,
|
||||||
|
"Request not sent as expected");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&mock, qeng_servinc_cell_response,
|
||||||
|
sizeof(qeng_servinc_cell_response) - 1);
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
zassert_true(memcmp(argv_buffers[0], "+QENG: \"servingcell\",",
|
||||||
|
sizeof("+QENG: \"servingcell\",")) == 0,
|
||||||
|
"Unexpected argv");
|
||||||
|
|
||||||
|
zassert_true(memcmp(argv_buffers[1], "\"NOCONN\"", sizeof("\"NOCONN\"")) == 0,
|
||||||
|
"Unexpected argv");
|
||||||
|
|
||||||
|
zassert_true(memcmp(argv_buffers[10], "-68", sizeof("-68")) == 0, "Unexpected argv");
|
||||||
|
zassert_true(argv_buffers[25][0] == '\0', "Unexpected argv");
|
||||||
|
zassert_true(argc_buffers == 26, "Unexpected argc");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Script ends after modem responds OK
|
||||||
|
*/
|
||||||
|
|
||||||
|
called = atomic_test_bit(&callback_called, MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT);
|
||||||
|
zassert_true(called == false, "Script callback should not have been called yet");
|
||||||
|
modem_backend_mock_put(&mock, ok_response, sizeof(ok_response) - 1);
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
called = atomic_test_bit(&callback_called, MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT);
|
||||||
|
zassert_true(called == true, "Script callback should have been called");
|
||||||
|
zassert_true(script_result == MODEM_CHAT_SCRIPT_RESULT_SUCCESS,
|
||||||
|
"Script result should be SUCCESS");
|
||||||
|
zassert_true(script_result_user_data == &cmd_user_data,
|
||||||
|
"Script result callback user data is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_chat, test_start_script_twice_then_abort)
|
||||||
|
{
|
||||||
|
bool called;
|
||||||
|
|
||||||
|
zassert_true(modem_chat_script_run(&cmd, &script) == 0, "Failed to start script");
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
zassert_true(modem_chat_script_run(&cmd, &script) == -EBUSY,
|
||||||
|
"Started new script while script is running");
|
||||||
|
|
||||||
|
called = atomic_test_bit(&callback_called, MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT);
|
||||||
|
zassert_true(called == false, "Script callback should not have been called yet");
|
||||||
|
modem_chat_script_abort(&cmd);
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
called = atomic_test_bit(&callback_called, MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT);
|
||||||
|
zassert_true(called == true, "Script callback should have been called");
|
||||||
|
zassert_true(script_result == MODEM_CHAT_SCRIPT_RESULT_ABORT,
|
||||||
|
"Script result should be ABORT");
|
||||||
|
zassert_true(script_result_user_data == &cmd_user_data,
|
||||||
|
"Script result callback user data is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_chat, test_start_script_then_time_out)
|
||||||
|
{
|
||||||
|
bool called;
|
||||||
|
|
||||||
|
zassert_true(modem_chat_script_run(&cmd, &script) == 0, "Failed to start script");
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
called = atomic_test_bit(&callback_called, MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT);
|
||||||
|
zassert_true(called == false, "Script callback should not have been called yet");
|
||||||
|
|
||||||
|
k_msleep(5900);
|
||||||
|
|
||||||
|
called = atomic_test_bit(&callback_called, MODEM_CHAT_UTEST_ON_SCRIPT_CALLBACK_BIT);
|
||||||
|
zassert_true(called == true, "Script callback should have been called");
|
||||||
|
zassert_true(script_result == MODEM_CHAT_SCRIPT_RESULT_TIMEOUT,
|
||||||
|
"Script result should be TIMEOUT");
|
||||||
|
zassert_true(script_result_user_data == &cmd_user_data,
|
||||||
|
"Script result callback user data is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Test suite */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
ZTEST_SUITE(modem_chat, NULL, test_modem_chat_setup, test_modem_chat_before, test_modem_chat_after,
|
||||||
|
NULL);
|
8
tests/subsys/modem/modem_chat/testcase.yaml
Normal file
8
tests/subsys/modem/modem_chat/testcase.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
tests:
|
||||||
|
modem.modem_chat:
|
||||||
|
tags: modem_chat
|
||||||
|
harness: ztest
|
||||||
|
platform_allow: native_posix
|
9
tests/subsys/modem/modem_cmux/CMakeLists.txt
Normal file
9
tests/subsys/modem/modem_cmux/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.20.0)
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
project(modem_cmux_test)
|
||||||
|
|
||||||
|
target_sources(app PRIVATE src/main.c ../mock/modem_backend_mock.c)
|
||||||
|
target_include_directories(app PRIVATE ../mock)
|
10
tests/subsys/modem/modem_cmux/prj.conf
Normal file
10
tests/subsys/modem/modem_cmux/prj.conf
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
CONFIG_NO_OPTIMIZATIONS=y
|
||||||
|
|
||||||
|
CONFIG_MODEM_MODULES=y
|
||||||
|
CONFIG_MODEM_CMUX=y
|
||||||
|
|
||||||
|
CONFIG_ZTEST=y
|
||||||
|
CONFIG_ZTEST_NEW_API=y
|
739
tests/subsys/modem/modem_cmux/src/main.c
Normal file
739
tests/subsys/modem/modem_cmux/src/main.c
Normal file
|
@ -0,0 +1,739 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Trackunit Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Dependencies */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <zephyr/modem/cmux.h>
|
||||||
|
#include <modem_backend_mock.h>
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Definitions */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
#define EVENT_CMUX_CONNECTED BIT(0)
|
||||||
|
#define EVENT_CMUX_DLCI1_OPEN BIT(1)
|
||||||
|
#define EVENT_CMUX_DLCI2_OPEN BIT(2)
|
||||||
|
#define EVENT_CMUX_DLCI1_CLOSED BIT(3)
|
||||||
|
#define EVENT_CMUX_DLCI2_CLOSED BIT(4)
|
||||||
|
#define EVENT_CMUX_DISCONNECTED BIT(5)
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Instances */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static struct modem_cmux cmux;
|
||||||
|
static uint8_t cmux_receive_buf[127];
|
||||||
|
static uint8_t cmux_transmit_buf[149];
|
||||||
|
static struct modem_cmux_dlci dlci1;
|
||||||
|
static struct modem_cmux_dlci dlci2;
|
||||||
|
static struct modem_pipe *dlci1_pipe;
|
||||||
|
static struct modem_pipe *dlci2_pipe;
|
||||||
|
|
||||||
|
static struct k_event cmux_event;
|
||||||
|
|
||||||
|
static struct modem_backend_mock bus_mock;
|
||||||
|
static uint8_t bus_mock_rx_buf[4096];
|
||||||
|
static uint8_t bus_mock_tx_buf[4096];
|
||||||
|
static struct modem_pipe *bus_mock_pipe;
|
||||||
|
|
||||||
|
static uint8_t dlci1_receive_buf[127];
|
||||||
|
static uint8_t dlci2_receive_buf[127];
|
||||||
|
|
||||||
|
static uint8_t buffer1[4096];
|
||||||
|
static uint8_t buffer2[4096];
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Callbacks */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static void test_modem_dlci1_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_event event,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case MODEM_PIPE_EVENT_OPENED:
|
||||||
|
k_event_post(&cmux_event, EVENT_CMUX_DLCI1_OPEN);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MODEM_PIPE_EVENT_CLOSED:
|
||||||
|
k_event_post(&cmux_event, EVENT_CMUX_DLCI1_CLOSED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_modem_dlci2_pipe_callback(struct modem_pipe *pipe, enum modem_pipe_event event,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
switch (event) {
|
||||||
|
case MODEM_PIPE_EVENT_OPENED:
|
||||||
|
k_event_post(&cmux_event, EVENT_CMUX_DLCI2_OPEN);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MODEM_PIPE_EVENT_CLOSED:
|
||||||
|
k_event_post(&cmux_event, EVENT_CMUX_DLCI2_CLOSED);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* CMUX frames */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t cmux_frame_control_sabm_cmd[] = {0xF9, 0x03, 0x3F, 0x01, 0x1C, 0xF9};
|
||||||
|
static uint8_t cmux_frame_control_sabm_ack[] = {0xF9, 0x03, 0x73, 0x01, 0xD7, 0xF9};
|
||||||
|
static uint8_t cmux_frame_control_cld_cmd[] = {0xF9, 0x03, 0xEF, 0x05, 0xC3, 0x01, 0xF2, 0xF9};
|
||||||
|
static uint8_t cmux_frame_control_cld_ack[] = {0xF9, 0x03, 0xEF, 0x05, 0xC1, 0x01, 0xF2, 0xF9};
|
||||||
|
static uint8_t cmux_frame_dlci1_sabm_cmd[] = {0xF9, 0x07, 0x3F, 0x01, 0xDE, 0xF9};
|
||||||
|
static uint8_t cmux_frame_dlci1_sabm_ack[] = {0xF9, 0x07, 0x73, 0x01, 0x15, 0xF9};
|
||||||
|
static uint8_t cmux_frame_dlci1_disc_cmd[] = {0xF9, 0x07, 0x53, 0x01, 0x3F, 0xF9};
|
||||||
|
static uint8_t cmux_frame_dlci1_ua_ack[] = {0xF9, 0x07, 0x73, 0x01, 0x15, 0xF9};
|
||||||
|
static uint8_t cmux_frame_dlci2_sabm_cmd[] = {0xF9, 0x0B, 0x3F, 0x01, 0x59, 0xF9};
|
||||||
|
static uint8_t cmux_frame_dlci2_sabm_ack[] = {0xF9, 0x0B, 0x73, 0x01, 0x92, 0xF9};
|
||||||
|
static uint8_t cmux_frame_dlci2_disc_cmd[] = {0xF9, 0x0B, 0x53, 0x01, 0xB8, 0xF9};
|
||||||
|
static uint8_t cmux_frame_dlci2_ua_ack[] = {0xF9, 0x0B, 0x73, 0x01, 0x92, 0xF9};
|
||||||
|
static uint8_t cmux_frame_control_msc_cmd[] = {0xF9, 0x01, 0xFF, 0x09, 0xE3,
|
||||||
|
0x05, 0x0B, 0x09, 0x8F, 0xF9};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_control_msc_ack[] = {0xF9, 0x01, 0xFF, 0x09, 0xE1,
|
||||||
|
0x05, 0x0B, 0x09, 0x8F, 0xF9};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_control_fcon_cmd[] = {0xF9, 0x01, 0xFF, 0x05, 0xA3, 0x01, 0x86, 0xF9};
|
||||||
|
static uint8_t cmux_frame_control_fcon_ack[] = {0xF9, 0x01, 0xFF, 0x05, 0xA1, 0x01, 0x86, 0xF9};
|
||||||
|
static uint8_t cmux_frame_control_fcoff_cmd[] = {0xF9, 0x01, 0xFF, 0x05, 0x63, 0x01, 0x86, 0xF9};
|
||||||
|
static uint8_t cmux_frame_control_fcoff_ack[] = {0xF9, 0x01, 0xFF, 0x05, 0x61, 0x01, 0x86, 0xF9};
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* DLCI2 AT CMUX frames */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t cmux_frame_dlci2_at_cgdcont[] = {
|
||||||
|
0xF9, 0x0B, 0xEF, 0x43, 0x41, 0x54, 0x2B, 0x43, 0x47, 0x44, 0x43, 0x4F, 0x4E,
|
||||||
|
0x54, 0x3D, 0x31, 0x2C, 0x22, 0x49, 0x50, 0x22, 0x2C, 0x22, 0x74, 0x72, 0x61,
|
||||||
|
0x63, 0x6B, 0x75, 0x6E, 0x69, 0x74, 0x2E, 0x6D, 0x32, 0x6D, 0x22, 0x23, 0xF9};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_data_dlci2_at_cgdcont[] = {
|
||||||
|
0x41, 0x54, 0x2B, 0x43, 0x47, 0x44, 0x43, 0x4F, 0x4E, 0x54, 0x3D,
|
||||||
|
0x31, 0x2C, 0x22, 0x49, 0x50, 0x22, 0x2C, 0x22, 0x74, 0x72, 0x61,
|
||||||
|
0x63, 0x6B, 0x75, 0x6E, 0x69, 0x74, 0x2E, 0x6D, 0x32, 0x6D, 0x22};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_dlci2_at_newline[] = {0xF9, 0x0B, 0xEF, 0x05, 0x0D, 0x0A, 0xB7, 0xF9};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_data_dlci2_at_newline[] = {0x0D, 0x0A};
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* DLCI1 AT CMUX frames */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t cmux_frame_dlci1_at_at[] = {0xF9, 0x07, 0xEF, 0x05, 0x41, 0x54, 0x30, 0xF9};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_data_dlci1_at_at[] = {0x41, 0x54};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_dlci1_at_newline[] = {0xF9, 0x07, 0xEF, 0x05, 0x0D, 0x0A, 0x30, 0xF9};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_data_dlci1_at_newline[] = {0x0D, 0x0A};
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* DLCI1 AT CMUX Desync frames */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t cmux_frame_dlci1_at_at_desync[] = {0x41, 0x54, 0x30, 0xF9};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_resync[] = {0xF9, 0xF9, 0xF9};
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* DLCI2 PPP CMUX frames */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t cmux_frame_dlci2_ppp_52[] = {
|
||||||
|
0xF9, 0x09, 0xEF, 0x69, 0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21, 0x7D, 0x21, 0x7D, 0x20, 0x7D,
|
||||||
|
0x20, 0x7D, 0x38, 0x7D, 0x22, 0x7D, 0x26, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x20,
|
||||||
|
0x7D, 0x23, 0x7D, 0x24, 0xC0, 0x23, 0x7D, 0x25, 0x7D, 0x26, 0x53, 0x96, 0x7D, 0x38, 0xAA,
|
||||||
|
0x7D, 0x27, 0x7D, 0x22, 0x7D, 0x28, 0x7D, 0x22, 0xD5, 0xA8, 0x7E, 0x97, 0xF9};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_data_dlci2_ppp_52[] = {
|
||||||
|
0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21, 0x7D, 0x21, 0x7D, 0x20, 0x7D, 0x20, 0x7D,
|
||||||
|
0x38, 0x7D, 0x22, 0x7D, 0x26, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x20, 0x7D, 0x20,
|
||||||
|
0x7D, 0x23, 0x7D, 0x24, 0xC0, 0x23, 0x7D, 0x25, 0x7D, 0x26, 0x53, 0x96, 0x7D,
|
||||||
|
0x38, 0xAA, 0x7D, 0x27, 0x7D, 0x22, 0x7D, 0x28, 0x7D, 0x22, 0xD5, 0xA8, 0x7E};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_dlci2_ppp_18[] = {0xF9, 0x09, 0xEF, 0x25, 0x7E, 0xFF, 0x7D, 0x23,
|
||||||
|
0xC0, 0x21, 0x7D, 0x22, 0x7D, 0x21, 0x7D, 0x20,
|
||||||
|
0x7D, 0x24, 0x7D, 0x3C, 0x90, 0x7E, 0xEE, 0xF9};
|
||||||
|
|
||||||
|
static uint8_t cmux_frame_data_dlci2_ppp_18[] = {0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21,
|
||||||
|
0x7D, 0x22, 0x7D, 0x21, 0x7D, 0x20,
|
||||||
|
0x7D, 0x24, 0x7D, 0x3C, 0x90, 0x7E};
|
||||||
|
|
||||||
|
const static struct modem_backend_mock_transaction transaction_control_cld = {
|
||||||
|
.get = cmux_frame_control_cld_cmd,
|
||||||
|
.get_size = sizeof(cmux_frame_control_cld_cmd),
|
||||||
|
.put = cmux_frame_control_cld_ack,
|
||||||
|
.put_size = sizeof(cmux_frame_control_cld_ack)
|
||||||
|
};
|
||||||
|
|
||||||
|
const static struct modem_backend_mock_transaction transaction_control_sabm = {
|
||||||
|
.get = cmux_frame_control_sabm_cmd,
|
||||||
|
.get_size = sizeof(cmux_frame_control_sabm_cmd),
|
||||||
|
.put = cmux_frame_control_sabm_ack,
|
||||||
|
.put_size = sizeof(cmux_frame_control_sabm_ack)
|
||||||
|
};
|
||||||
|
|
||||||
|
const static struct modem_backend_mock_transaction transaction_dlci1_disc = {
|
||||||
|
.get = cmux_frame_dlci1_disc_cmd,
|
||||||
|
.get_size = sizeof(cmux_frame_dlci1_disc_cmd),
|
||||||
|
.put = cmux_frame_dlci1_ua_ack,
|
||||||
|
.put_size = sizeof(cmux_frame_dlci1_ua_ack)
|
||||||
|
};
|
||||||
|
|
||||||
|
const static struct modem_backend_mock_transaction transaction_dlci2_disc = {
|
||||||
|
.get = cmux_frame_dlci2_disc_cmd,
|
||||||
|
.get_size = sizeof(cmux_frame_dlci2_disc_cmd),
|
||||||
|
.put = cmux_frame_dlci2_ua_ack,
|
||||||
|
.put_size = sizeof(cmux_frame_dlci2_ua_ack)
|
||||||
|
};
|
||||||
|
|
||||||
|
const static struct modem_backend_mock_transaction transaction_dlci1_sabm = {
|
||||||
|
.get = cmux_frame_dlci1_sabm_cmd,
|
||||||
|
.get_size = sizeof(cmux_frame_dlci1_sabm_cmd),
|
||||||
|
.put = cmux_frame_dlci1_ua_ack,
|
||||||
|
.put_size = sizeof(cmux_frame_dlci1_ua_ack)
|
||||||
|
};
|
||||||
|
|
||||||
|
const static struct modem_backend_mock_transaction transaction_dlci2_sabm = {
|
||||||
|
.get = cmux_frame_dlci2_sabm_cmd,
|
||||||
|
.get_size = sizeof(cmux_frame_dlci2_sabm_cmd),
|
||||||
|
.put = cmux_frame_dlci2_ua_ack,
|
||||||
|
.put_size = sizeof(cmux_frame_dlci2_ua_ack)
|
||||||
|
};
|
||||||
|
|
||||||
|
static void test_modem_cmux_callback(struct modem_cmux *cmux, enum modem_cmux_event event,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
if (event == MODEM_CMUX_EVENT_CONNECTED) {
|
||||||
|
k_event_post(&cmux_event, EVENT_CMUX_CONNECTED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == MODEM_CMUX_EVENT_DISCONNECTED) {
|
||||||
|
k_event_post(&cmux_event, EVENT_CMUX_DISCONNECTED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *test_modem_cmux_setup(void)
|
||||||
|
{
|
||||||
|
uint32_t events;
|
||||||
|
|
||||||
|
struct modem_cmux_dlci_config dlci1_config = {
|
||||||
|
.dlci_address = 1,
|
||||||
|
.receive_buf = dlci1_receive_buf,
|
||||||
|
.receive_buf_size = sizeof(dlci1_receive_buf),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct modem_cmux_dlci_config dlci2_config = {
|
||||||
|
.dlci_address = 2,
|
||||||
|
.receive_buf = dlci2_receive_buf,
|
||||||
|
.receive_buf_size = sizeof(dlci2_receive_buf),
|
||||||
|
};
|
||||||
|
|
||||||
|
k_event_init(&cmux_event);
|
||||||
|
|
||||||
|
struct modem_cmux_config cmux_config = {
|
||||||
|
.callback = test_modem_cmux_callback,
|
||||||
|
.user_data = NULL,
|
||||||
|
.receive_buf = cmux_receive_buf,
|
||||||
|
.receive_buf_size = sizeof(cmux_receive_buf),
|
||||||
|
.transmit_buf = cmux_transmit_buf,
|
||||||
|
.transmit_buf_size = ARRAY_SIZE(cmux_transmit_buf),
|
||||||
|
};
|
||||||
|
|
||||||
|
modem_cmux_init(&cmux, &cmux_config);
|
||||||
|
dlci1_pipe = modem_cmux_dlci_init(&cmux, &dlci1, &dlci1_config);
|
||||||
|
dlci2_pipe = modem_cmux_dlci_init(&cmux, &dlci2, &dlci2_config);
|
||||||
|
|
||||||
|
const struct modem_backend_mock_config bus_mock_config = {
|
||||||
|
.rx_buf = bus_mock_rx_buf,
|
||||||
|
.rx_buf_size = sizeof(bus_mock_rx_buf),
|
||||||
|
.tx_buf = bus_mock_tx_buf,
|
||||||
|
.tx_buf_size = sizeof(bus_mock_tx_buf),
|
||||||
|
.limit = 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
bus_mock_pipe = modem_backend_mock_init(&bus_mock, &bus_mock_config);
|
||||||
|
__ASSERT_NO_MSG(modem_pipe_open_async(bus_mock_pipe) == 0);
|
||||||
|
|
||||||
|
/* Connect CMUX */
|
||||||
|
__ASSERT_NO_MSG(modem_cmux_attach(&cmux, bus_mock_pipe) == 0);
|
||||||
|
__ASSERT_NO_MSG(modem_cmux_connect_async(&cmux) == 0);
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_control_sabm_ack,
|
||||||
|
sizeof(cmux_frame_control_sabm_ack));
|
||||||
|
|
||||||
|
events = k_event_wait(&cmux_event, EVENT_CMUX_CONNECTED, false, K_MSEC(100));
|
||||||
|
__ASSERT_NO_MSG(events == EVENT_CMUX_CONNECTED);
|
||||||
|
|
||||||
|
/* Open DLCI channels */
|
||||||
|
modem_pipe_attach(dlci1_pipe, test_modem_dlci1_pipe_callback, NULL);
|
||||||
|
modem_pipe_attach(dlci2_pipe, test_modem_dlci2_pipe_callback, NULL);
|
||||||
|
__ASSERT_NO_MSG(modem_pipe_open_async(dlci1_pipe) == 0);
|
||||||
|
__ASSERT_NO_MSG(modem_pipe_open_async(dlci2_pipe) == 0);
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_sabm_ack,
|
||||||
|
sizeof(cmux_frame_dlci1_sabm_ack));
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_sabm_ack,
|
||||||
|
sizeof(cmux_frame_dlci2_sabm_ack));
|
||||||
|
|
||||||
|
events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_OPEN | EVENT_CMUX_DLCI2_OPEN),
|
||||||
|
false, K_MSEC(100));
|
||||||
|
|
||||||
|
__ASSERT_NO_MSG((events & EVENT_CMUX_DLCI1_OPEN));
|
||||||
|
__ASSERT_NO_MSG((events & EVENT_CMUX_DLCI2_OPEN));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_modem_cmux_before(void *f)
|
||||||
|
{
|
||||||
|
/* Reset events */
|
||||||
|
k_event_clear(&cmux_event, UINT32_MAX);
|
||||||
|
|
||||||
|
/* Reset mock pipes */
|
||||||
|
modem_backend_mock_reset(&bus_mock);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_receive_dlci2_at)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_at_cgdcont,
|
||||||
|
sizeof(cmux_frame_dlci2_at_cgdcont));
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_at_newline,
|
||||||
|
sizeof(cmux_frame_dlci2_at_newline));
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_pipe_receive(dlci2_pipe, buffer2, sizeof(buffer2));
|
||||||
|
zassert_true(ret == (sizeof(cmux_frame_data_dlci2_at_cgdcont) +
|
||||||
|
sizeof(cmux_frame_data_dlci2_at_newline)),
|
||||||
|
"Incorrect number of bytes received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer2, cmux_frame_data_dlci2_at_cgdcont,
|
||||||
|
sizeof(cmux_frame_data_dlci2_at_cgdcont)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(&buffer2[sizeof(cmux_frame_data_dlci2_at_cgdcont)],
|
||||||
|
cmux_frame_data_dlci2_at_newline,
|
||||||
|
sizeof(cmux_frame_data_dlci2_at_newline)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_receive_dlci1_at)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_at_at, sizeof(cmux_frame_dlci1_at_at));
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_at_newline,
|
||||||
|
sizeof(cmux_frame_dlci1_at_newline));
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_pipe_receive(dlci1_pipe, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == (sizeof(cmux_frame_data_dlci1_at_at) +
|
||||||
|
sizeof(cmux_frame_data_dlci1_at_newline)),
|
||||||
|
"Incorrect number of bytes received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_data_dlci1_at_at,
|
||||||
|
sizeof(cmux_frame_data_dlci1_at_at)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(&buffer1[sizeof(cmux_frame_data_dlci1_at_at)],
|
||||||
|
cmux_frame_data_dlci1_at_newline,
|
||||||
|
sizeof(cmux_frame_data_dlci1_at_newline)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_receive_dlci2_ppp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_ppp_52, sizeof(cmux_frame_dlci2_ppp_52));
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_ppp_18, sizeof(cmux_frame_dlci2_ppp_18));
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_pipe_receive(dlci2_pipe, buffer2, sizeof(buffer2));
|
||||||
|
zassert_true(ret == (sizeof(cmux_frame_data_dlci2_ppp_52) +
|
||||||
|
sizeof(cmux_frame_data_dlci2_ppp_18)),
|
||||||
|
"Incorrect number of bytes received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer2, cmux_frame_data_dlci2_ppp_52,
|
||||||
|
sizeof(cmux_frame_data_dlci2_ppp_52)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(&buffer2[sizeof(cmux_frame_data_dlci2_ppp_52)],
|
||||||
|
cmux_frame_data_dlci2_ppp_18,
|
||||||
|
sizeof(cmux_frame_data_dlci2_ppp_18)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_transmit_dlci2_ppp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = modem_pipe_transmit(dlci2_pipe, cmux_frame_data_dlci2_ppp_52,
|
||||||
|
sizeof(cmux_frame_data_dlci2_ppp_52));
|
||||||
|
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_data_dlci2_ppp_52), "Failed to send DLCI2 PPP 52");
|
||||||
|
ret = modem_pipe_transmit(dlci2_pipe, cmux_frame_data_dlci2_ppp_18,
|
||||||
|
sizeof(cmux_frame_data_dlci2_ppp_18));
|
||||||
|
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_data_dlci2_ppp_18), "Failed to send DLCI2 PPP 18");
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer2, sizeof(buffer2));
|
||||||
|
zassert_true(ret == (sizeof(cmux_frame_dlci2_ppp_52) + sizeof(cmux_frame_dlci2_ppp_18)),
|
||||||
|
"Incorrect number of bytes transmitted");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_resync)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_at_at_desync,
|
||||||
|
sizeof(cmux_frame_dlci1_at_at_desync));
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_resync), "Expected resync flags to be sent to bus");
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_resync, sizeof(cmux_frame_resync)) == 0,
|
||||||
|
"Expected resync flags to be sent to bus");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_resync, sizeof(cmux_frame_resync));
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_at_at, sizeof(cmux_frame_dlci1_at_at));
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_at_newline,
|
||||||
|
sizeof(cmux_frame_dlci1_at_newline));
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_pipe_receive(dlci1_pipe, buffer1, sizeof(buffer1));
|
||||||
|
|
||||||
|
zassert_true(ret == (sizeof(cmux_frame_data_dlci1_at_at) +
|
||||||
|
sizeof(cmux_frame_data_dlci1_at_newline)),
|
||||||
|
"Incorrect number of bytes received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_data_dlci1_at_at,
|
||||||
|
sizeof(cmux_frame_data_dlci1_at_at)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(&buffer1[sizeof(cmux_frame_data_dlci1_at_at)],
|
||||||
|
cmux_frame_data_dlci1_at_newline,
|
||||||
|
sizeof(cmux_frame_data_dlci1_at_newline)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_flow_control_dlci2)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_control_fcoff_cmd,
|
||||||
|
sizeof(cmux_frame_control_fcoff_cmd));
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_control_fcoff_ack),
|
||||||
|
"Incorrect number of bytes received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_control_fcoff_ack,
|
||||||
|
sizeof(cmux_frame_control_fcoff_ack)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
|
||||||
|
ret = modem_pipe_transmit(dlci2_pipe, cmux_frame_data_dlci2_ppp_52,
|
||||||
|
sizeof(cmux_frame_data_dlci2_ppp_52));
|
||||||
|
|
||||||
|
zassert_true(ret == 0, "Failed to block transmit while flow control is off");
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == 0, "FCOFF failed to prevent transmission of data");
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_control_fcon_cmd,
|
||||||
|
sizeof(cmux_frame_control_fcon_cmd));
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_control_fcon_ack),
|
||||||
|
"Incorrect number of bytes received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_control_fcon_ack,
|
||||||
|
sizeof(cmux_frame_control_fcon_ack)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
|
||||||
|
ret = modem_pipe_transmit(dlci2_pipe, cmux_frame_data_dlci2_ppp_52,
|
||||||
|
sizeof(cmux_frame_data_dlci2_ppp_52));
|
||||||
|
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_data_dlci2_ppp_52),
|
||||||
|
"Transmit failed after flow control is enabled");
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_dlci2_ppp_52),
|
||||||
|
"Transmit failed after flow control is enabled");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_dlci2_ppp_52,
|
||||||
|
sizeof(cmux_frame_dlci2_ppp_52)) == 0,
|
||||||
|
"Incorrect data received");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_msc_cmd_ack)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_control_msc_cmd,
|
||||||
|
sizeof(cmux_frame_control_msc_cmd));
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_control_msc_ack),
|
||||||
|
"Incorrect number of bytes received");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_control_msc_ack,
|
||||||
|
sizeof(cmux_frame_control_msc_ack)) == 0,
|
||||||
|
"Incorrect MSC ACK received");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_dlci1_close_open)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint32_t events;
|
||||||
|
|
||||||
|
/* Close DLCI1 */
|
||||||
|
zassert_true(modem_pipe_close_async(dlci1_pipe) == 0, "Failed to close DLCI1 pipe");
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_dlci1_disc_cmd),
|
||||||
|
"Incorrect number of bytes received for DLCI1 close cmd");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_dlci1_disc_cmd,
|
||||||
|
sizeof(cmux_frame_dlci1_disc_cmd)) == 0,
|
||||||
|
"Incorrect DLCI1 close cmd received");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_ua_ack,
|
||||||
|
sizeof(cmux_frame_dlci1_ua_ack));
|
||||||
|
|
||||||
|
events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_CLOSED),
|
||||||
|
false, K_MSEC(100));
|
||||||
|
|
||||||
|
zassert_true((events & EVENT_CMUX_DLCI1_CLOSED),
|
||||||
|
"DLCI1 not closed as expected");
|
||||||
|
|
||||||
|
/* Wait for potential T1 timeout */
|
||||||
|
k_msleep(500);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == 0, "Received unexpected data");
|
||||||
|
|
||||||
|
/* Open DLCI1 */
|
||||||
|
zassert_true(modem_pipe_open_async(dlci1_pipe) == 0, "Failed to open DLCI1 pipe");
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_dlci1_sabm_cmd),
|
||||||
|
"Incorrect number of bytes received for DLCI1 open cmd");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_dlci1_sabm_cmd,
|
||||||
|
sizeof(cmux_frame_dlci1_sabm_cmd)) == 0,
|
||||||
|
"Incorrect DLCI1 open cmd received");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_sabm_ack,
|
||||||
|
sizeof(cmux_frame_dlci1_sabm_ack));
|
||||||
|
|
||||||
|
events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_OPEN),
|
||||||
|
false, K_MSEC(100));
|
||||||
|
|
||||||
|
zassert_true((events & EVENT_CMUX_DLCI1_OPEN),
|
||||||
|
"DLCI1 not opened as expected");
|
||||||
|
|
||||||
|
/* Wait for potential T1 timeout */
|
||||||
|
k_msleep(500);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == 0, "Received unexpected data");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_disconnect_connect)
|
||||||
|
{
|
||||||
|
uint32_t events;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Disconnect CMUX */
|
||||||
|
zassert_true(modem_pipe_close_async(dlci1_pipe) == 0, "Failed to close DLCI1");
|
||||||
|
zassert_true(modem_pipe_close_async(dlci2_pipe) == 0, "Failed to close DLCI2");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_ua_ack,
|
||||||
|
sizeof(cmux_frame_dlci1_ua_ack));
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_ua_ack,
|
||||||
|
sizeof(cmux_frame_dlci2_ua_ack));
|
||||||
|
|
||||||
|
events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_CLOSED | EVENT_CMUX_DLCI2_CLOSED),
|
||||||
|
false, K_MSEC(100));
|
||||||
|
|
||||||
|
zassert_true((events & EVENT_CMUX_DLCI1_CLOSED), "Failed to close DLCI1");
|
||||||
|
zassert_true((events & EVENT_CMUX_DLCI2_CLOSED), "Failed to close DLCI2");
|
||||||
|
|
||||||
|
/* Discard CMUX DLCI DISC commands */
|
||||||
|
modem_backend_mock_reset(&bus_mock);
|
||||||
|
zassert_true(modem_cmux_disconnect_async(&cmux) == 0, "Failed to disconnect CMUX");
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_control_cld_cmd),
|
||||||
|
"Incorrect number of bytes received for CLD cmd");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_control_cld_cmd,
|
||||||
|
sizeof(cmux_frame_control_cld_cmd)) == 0,
|
||||||
|
"Incorrect DLC cmd received");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_control_cld_ack,
|
||||||
|
sizeof(cmux_frame_control_cld_ack));
|
||||||
|
|
||||||
|
events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DISCONNECTED), false, K_MSEC(100));
|
||||||
|
zassert_true((events & EVENT_CMUX_DISCONNECTED), "Failed to disconnect CMUX");
|
||||||
|
|
||||||
|
/* Wait for potential T1 timeout */
|
||||||
|
k_msleep(500);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == 0, "Received unexpected data");
|
||||||
|
|
||||||
|
/* Reconnect CMUX */
|
||||||
|
zassert_true(modem_cmux_connect_async(&cmux) == 0, "Failed to connect CMUX");
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_control_sabm_cmd),
|
||||||
|
"Incorrect number of bytes received for SABM cmd");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_control_sabm_cmd,
|
||||||
|
sizeof(cmux_frame_control_sabm_cmd)) == 0,
|
||||||
|
"Incorrect SABM cmd received");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_control_sabm_ack,
|
||||||
|
sizeof(cmux_frame_control_sabm_ack));
|
||||||
|
|
||||||
|
events = k_event_wait_all(&cmux_event, (EVENT_CMUX_CONNECTED), false, K_MSEC(100));
|
||||||
|
zassert_true((events & EVENT_CMUX_CONNECTED), "Failed to connect CMUX");
|
||||||
|
|
||||||
|
/* Wait for potential T1 timeout */
|
||||||
|
k_msleep(500);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == 0, "Received unexpected data");
|
||||||
|
|
||||||
|
/* Open DLCI1 */
|
||||||
|
zassert_true(modem_pipe_open_async(dlci1_pipe) == 0, "Failed to open DLCI1 pipe");
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_dlci1_sabm_cmd),
|
||||||
|
"Incorrect number of bytes received for DLCI1 open cmd");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_dlci1_sabm_cmd,
|
||||||
|
sizeof(cmux_frame_dlci1_sabm_cmd)) == 0,
|
||||||
|
"Incorrect DLCI1 open cmd received");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci1_sabm_ack,
|
||||||
|
sizeof(cmux_frame_dlci1_sabm_ack));
|
||||||
|
|
||||||
|
events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI1_OPEN),
|
||||||
|
false, K_MSEC(100));
|
||||||
|
|
||||||
|
zassert_true((events & EVENT_CMUX_DLCI1_OPEN),
|
||||||
|
"DLCI1 not opened as expected");
|
||||||
|
|
||||||
|
/* Wait for potential T1 timeout */
|
||||||
|
k_msleep(500);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == 0, "Received unexpected data");
|
||||||
|
|
||||||
|
/* Open DLCI2 */
|
||||||
|
zassert_true(modem_pipe_open_async(dlci2_pipe) == 0, "Failed to open DLCI2 pipe");
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == sizeof(cmux_frame_dlci2_sabm_cmd),
|
||||||
|
"Incorrect number of bytes received for DLCI1 open cmd");
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer1, cmux_frame_dlci2_sabm_cmd,
|
||||||
|
sizeof(cmux_frame_dlci2_sabm_cmd)) == 0,
|
||||||
|
"Incorrect DLCI1 open cmd received");
|
||||||
|
|
||||||
|
modem_backend_mock_put(&bus_mock, cmux_frame_dlci2_sabm_ack,
|
||||||
|
sizeof(cmux_frame_dlci2_sabm_ack));
|
||||||
|
|
||||||
|
events = k_event_wait_all(&cmux_event, (EVENT_CMUX_DLCI2_OPEN),
|
||||||
|
false, K_MSEC(100));
|
||||||
|
|
||||||
|
zassert_true((events & EVENT_CMUX_DLCI2_OPEN),
|
||||||
|
"DLCI1 not opened as expected");
|
||||||
|
|
||||||
|
/* Wait for potential T1 timeout */
|
||||||
|
k_msleep(500);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&bus_mock, buffer1, sizeof(buffer1));
|
||||||
|
zassert_true(ret == 0, "Received unexpected data");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_disconnect_connect_sync)
|
||||||
|
{
|
||||||
|
modem_backend_mock_prime(&bus_mock, &transaction_dlci1_disc);
|
||||||
|
zassert_true(modem_pipe_close(dlci1_pipe) == 0, "Failed to close DLCI1");
|
||||||
|
modem_backend_mock_prime(&bus_mock, &transaction_dlci2_disc);
|
||||||
|
zassert_true(modem_pipe_close(dlci2_pipe) == 0, "Failed to close DLCI2");
|
||||||
|
modem_backend_mock_prime(&bus_mock, &transaction_control_cld);
|
||||||
|
zassert_true(modem_cmux_disconnect(&cmux) == 0, "Failed to disconnect CMUX");
|
||||||
|
zassert_true(modem_cmux_disconnect(&cmux) == -EALREADY,
|
||||||
|
"Should already be disconnected");
|
||||||
|
|
||||||
|
modem_backend_mock_prime(&bus_mock, &transaction_control_sabm);
|
||||||
|
zassert_true(modem_cmux_connect(&cmux) == 0, "Failed to connect CMUX");
|
||||||
|
zassert_true(modem_cmux_connect(&cmux) == -EALREADY,
|
||||||
|
"Should already be connected");
|
||||||
|
|
||||||
|
modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm);
|
||||||
|
zassert_true(modem_pipe_open(dlci1_pipe) == 0, "Failed to open DLCI1 pipe");
|
||||||
|
modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm);
|
||||||
|
zassert_true(modem_pipe_open(dlci2_pipe) == 0, "Failed to open DLCI2 pipe");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_cmux, test_modem_cmux_dlci_close_open_sync)
|
||||||
|
{
|
||||||
|
modem_backend_mock_prime(&bus_mock, &transaction_dlci1_disc);
|
||||||
|
zassert_true(modem_pipe_close(dlci1_pipe) == 0, "Failed to close DLCI1");
|
||||||
|
modem_backend_mock_prime(&bus_mock, &transaction_dlci2_disc);
|
||||||
|
zassert_true(modem_pipe_close(dlci2_pipe) == 0, "Failed to close DLCI2");
|
||||||
|
modem_backend_mock_prime(&bus_mock, &transaction_dlci1_sabm);
|
||||||
|
zassert_true(modem_pipe_open(dlci1_pipe) == 0, "Failed to open DLCI1 pipe");
|
||||||
|
modem_backend_mock_prime(&bus_mock, &transaction_dlci2_sabm);
|
||||||
|
zassert_true(modem_pipe_open(dlci2_pipe) == 0, "Failed to open DLCI2 pipe");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST_SUITE(modem_cmux, NULL, test_modem_cmux_setup, test_modem_cmux_before, NULL, NULL);
|
8
tests/subsys/modem/modem_cmux/testcase.yaml
Normal file
8
tests/subsys/modem/modem_cmux/testcase.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
tests:
|
||||||
|
modem.modem_cmux:
|
||||||
|
tags: modem_cmux
|
||||||
|
harness: ztest
|
||||||
|
platform_allow: native_posix
|
9
tests/subsys/modem/modem_ppp/CMakeLists.txt
Normal file
9
tests/subsys/modem/modem_ppp/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.20.0)
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
project(modem_ppp_test)
|
||||||
|
|
||||||
|
target_sources(app PRIVATE src/main.c ../mock/modem_backend_mock.c)
|
||||||
|
include_directories(../mock)
|
16
tests/subsys/modem/modem_ppp/prj.conf
Normal file
16
tests/subsys/modem/modem_ppp/prj.conf
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
CONFIG_NO_OPTIMIZATIONS=y
|
||||||
|
|
||||||
|
CONFIG_NETWORKING=y
|
||||||
|
CONFIG_MODEM_MODULES=y
|
||||||
|
CONFIG_MODEM_PPP=y
|
||||||
|
CONFIG_NET_L2_PPP=y
|
||||||
|
CONFIG_ETH_NATIVE_POSIX=n
|
||||||
|
|
||||||
|
CONFIG_ZTEST=y
|
||||||
|
CONFIG_ZTEST_NEW_API=y
|
||||||
|
|
||||||
|
CONFIG_LOG=y
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL=4
|
522
tests/subsys/modem/modem_ppp/src/main.c
Normal file
522
tests/subsys/modem/modem_ppp/src/main.c
Normal file
|
@ -0,0 +1,522 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Trackunit Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Dependencies */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/net/net_if.h>
|
||||||
|
#include <zephyr/net/net_pkt.h>
|
||||||
|
#include "zephyr/net/net_l2.h"
|
||||||
|
#include "zephyr/net/ppp.h"
|
||||||
|
#include <zephyr/sys/crc.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <zephyr/modem/ppp.h>
|
||||||
|
#include <modem_backend_mock.h>
|
||||||
|
|
||||||
|
#define TEST_MODEM_PPP_BUF_SIZE (16)
|
||||||
|
#define TEST_MODEM_PPP_TX_PKT_BUF_SIZE (5)
|
||||||
|
#define TEST_MODEM_PPP_MOCK_PIPE_RX_BUF_SIZE (4096)
|
||||||
|
#define TEST_MODEM_PPP_MOCK_PIPE_TX_BUF_SIZE (4096)
|
||||||
|
|
||||||
|
#define TEST_MODEM_PPP_IP_FRAME_SEND_MULT_N (5)
|
||||||
|
#define TEST_MODEM_PPP_IP_FRAME_SEND_LARGE_N (2048)
|
||||||
|
#define TEST_MODEM_PPP_IP_FRAME_RECEIVE_LARGE_N (2048)
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Mock pipe */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static struct modem_backend_mock mock;
|
||||||
|
static uint8_t mock_rx_buf[TEST_MODEM_PPP_MOCK_PIPE_RX_BUF_SIZE];
|
||||||
|
static uint8_t mock_tx_buf[TEST_MODEM_PPP_MOCK_PIPE_TX_BUF_SIZE];
|
||||||
|
static struct modem_pipe *mock_pipe;
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* PPP frames */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t ppp_frame_wrapped[] = {0x7E, 0xFF, 0x7D, 0x23, 0xC0, 0x21, 0x7D, 0x21, 0x7D,
|
||||||
|
0x21, 0x7D, 0x20, 0x7D, 0x24, 0xD1, 0xB5, 0x7E};
|
||||||
|
|
||||||
|
static uint8_t ppp_frame_unwrapped[] = {0xC0, 0x21, 0x01, 0x01, 0x00, 0x04};
|
||||||
|
|
||||||
|
static uint8_t ip_frame_wrapped[] = {
|
||||||
|
0x7E, 0xFF, 0x7D, 0x23, 0x7D, 0x20, 0x21, 0x45, 0x7D, 0x20, 0x7D, 0x20, 0x29, 0x87, 0x6E,
|
||||||
|
0x40, 0x7D, 0x20, 0xE8, 0x7D, 0x31, 0xC1, 0xE9, 0x7D, 0x23, 0xFB, 0x7D, 0x25, 0x20, 0x7D,
|
||||||
|
0x2A, 0x2B, 0x36, 0x26, 0x25, 0x7D, 0x32, 0x8C, 0x3E, 0x7D, 0x20, 0x7D, 0x35, 0xBD, 0xF3,
|
||||||
|
0x2D, 0x7D, 0x20, 0x7D, 0x2B, 0x7D, 0x20, 0x7D, 0x27, 0x7D, 0x20, 0x7D, 0x24, 0x7D, 0x20,
|
||||||
|
0x7D, 0x24, 0x7D, 0x2A, 0x7D, 0x20, 0x7D, 0x2A, 0x7D, 0x20, 0xD4, 0x31, 0x7E};
|
||||||
|
|
||||||
|
static uint8_t ip_frame_unwrapped[] = {
|
||||||
|
0x45, 0x00, 0x00, 0x29, 0x87, 0x6E, 0x40, 0x00, 0xE8, 0x11, 0xC1, 0xE9, 0x03, 0xFB,
|
||||||
|
0x05, 0x20, 0x0A, 0x2B, 0x36, 0x26, 0x25, 0x12, 0x8C, 0x3E, 0x00, 0x15, 0xBD, 0xF3,
|
||||||
|
0x2D, 0x00, 0x0B, 0x00, 0x07, 0x00, 0x04, 0x00, 0x04, 0x0A, 0x00, 0x0A, 0x00};
|
||||||
|
|
||||||
|
static uint8_t ip_frame_unwrapped_with_protocol[] = {
|
||||||
|
0x00, 0x21, 0x45, 0x00, 0x00, 0x29, 0x87, 0x6E, 0x40, 0x00, 0xE8, 0x11, 0xC1, 0xE9, 0x03,
|
||||||
|
0xFB, 0x05, 0x20, 0x0A, 0x2B, 0x36, 0x26, 0x25, 0x12, 0x8C, 0x3E, 0x00, 0x15, 0xBD, 0xF3,
|
||||||
|
0x2D, 0x00, 0x0B, 0x00, 0x07, 0x00, 0x04, 0x00, 0x04, 0x0A, 0x00, 0x0A, 0x00};
|
||||||
|
|
||||||
|
static uint8_t corrupt_start_end_ppp_frame_wrapped[] = {0x2A, 0x46, 0x7E, 0x7E, 0xFF, 0x7D, 0x23,
|
||||||
|
0xC0, 0x21, 0x7D, 0x21, 0x7D, 0x21, 0x7D,
|
||||||
|
0x20, 0x7D, 0x24, 0xD1, 0xB5, 0x7E};
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Buffers */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static struct net_pkt *received_packets[12];
|
||||||
|
static size_t received_packets_len;
|
||||||
|
static uint8_t buffer[4096];
|
||||||
|
static uint8_t unwrapped_buffer[4096];
|
||||||
|
static uint8_t wrapped_buffer[4096];
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Mock network interface */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t test_net_link_addr[] = {0x00, 0x00, 0x5E, 0x00, 0x53, 0x01};
|
||||||
|
|
||||||
|
static enum net_verdict test_net_l2_recv(struct net_if *iface, struct net_pkt *pkt)
|
||||||
|
{
|
||||||
|
/* Validate buffer not overflowing */
|
||||||
|
zassert_true(received_packets_len < ARRAY_SIZE(received_packets),
|
||||||
|
"Mock network interface receive buffer limit reached");
|
||||||
|
|
||||||
|
/* Store pointer to received packet */
|
||||||
|
received_packets[received_packets_len] = pkt;
|
||||||
|
received_packets_len++;
|
||||||
|
return NET_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This emulates the layer two API */
|
||||||
|
static struct net_l2 test_net_l2 = {
|
||||||
|
.recv = test_net_l2_recv,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This emulates the network interface device which will receive unwrapped network packets */
|
||||||
|
static struct net_if_dev test_net_if_dev = {
|
||||||
|
.l2 = &test_net_l2,
|
||||||
|
.link_addr.addr = test_net_link_addr,
|
||||||
|
.link_addr.len = sizeof(test_net_link_addr),
|
||||||
|
.link_addr.type = NET_LINK_DUMMY,
|
||||||
|
.mtu = 1500,
|
||||||
|
.oper_state = NET_IF_OPER_UP,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This emulates the network interface which contains the network interface device */
|
||||||
|
static struct net_if test_iface = {
|
||||||
|
.if_dev = &test_net_if_dev,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Modem PPP */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* The following initialization happens automatically when MODEM_PPP_DEFINE is used. However,
|
||||||
|
* since we are emulating the network interface, we can't use that macro, and have to initialize
|
||||||
|
* it manually here.
|
||||||
|
*/
|
||||||
|
static uint8_t ppp_receive_buf[TEST_MODEM_PPP_BUF_SIZE];
|
||||||
|
static uint8_t ppp_transmit_buf[TEST_MODEM_PPP_BUF_SIZE];
|
||||||
|
|
||||||
|
static struct modem_ppp ppp = {
|
||||||
|
.iface = &test_iface,
|
||||||
|
.receive_buf = ppp_receive_buf,
|
||||||
|
.transmit_buf = ppp_transmit_buf,
|
||||||
|
.buf_size = TEST_MODEM_PPP_BUF_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Modem PPP net device */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
extern const struct ppp_api modem_ppp_ppp_api;
|
||||||
|
static const struct device ppp_net_dev = {.data = &ppp};
|
||||||
|
static int test_net_send(struct net_pkt *pkt)
|
||||||
|
{
|
||||||
|
return modem_ppp_ppp_api.send(&ppp_net_dev, pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Helpers */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static uint8_t test_modem_ppp_prng_random(bool reset)
|
||||||
|
{
|
||||||
|
static uint32_t prng_state = 1234;
|
||||||
|
|
||||||
|
if (reset == true) {
|
||||||
|
prng_state = 1234;
|
||||||
|
}
|
||||||
|
|
||||||
|
prng_state = (1103515245 * prng_state + 12345) % (1 << 31);
|
||||||
|
return (uint8_t)(prng_state & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t test_modem_ppp_fill_net_pkt(struct net_pkt *pkt, size_t size)
|
||||||
|
{
|
||||||
|
test_modem_ppp_prng_random(true);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
if (net_pkt_write_u8(pkt, test_modem_ppp_prng_random(false)) < 0) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t test_modem_ppp_unwrap(uint8_t *unwrapped, const uint8_t *wrapped, size_t wrapped_size)
|
||||||
|
{
|
||||||
|
size_t wrapped_pos = 4;
|
||||||
|
size_t unwrapped_pos = 0;
|
||||||
|
|
||||||
|
while (wrapped_pos < (wrapped_size - 1)) {
|
||||||
|
/* Escape byte */
|
||||||
|
if (wrapped[wrapped_pos] == 0x7D) {
|
||||||
|
unwrapped[unwrapped_pos] = wrapped[wrapped_pos + 1] ^ 0x20;
|
||||||
|
wrapped_pos += 2;
|
||||||
|
unwrapped_pos += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normal byte */
|
||||||
|
unwrapped[unwrapped_pos] = wrapped[wrapped_pos];
|
||||||
|
wrapped_pos += 1;
|
||||||
|
unwrapped_pos += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove FCS */
|
||||||
|
unwrapped_pos -= 2;
|
||||||
|
return unwrapped_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool test_modem_ppp_validate_fill(const uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
test_modem_ppp_prng_random(true);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
if (data[i] != test_modem_ppp_prng_random(false)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_modem_ppp_generate_ppp_frame(uint8_t *frame, size_t size)
|
||||||
|
{
|
||||||
|
uint8_t byte;
|
||||||
|
uint16_t fcs;
|
||||||
|
|
||||||
|
test_modem_ppp_prng_random(true);
|
||||||
|
|
||||||
|
byte = 0x03;
|
||||||
|
fcs = crc16_ccitt(0xFFFF, &byte, 0x01);
|
||||||
|
|
||||||
|
frame[0] = 0x00;
|
||||||
|
frame[1] = 0x21;
|
||||||
|
|
||||||
|
for (size_t i = 2; i < (size - 2); i++) {
|
||||||
|
byte = test_modem_ppp_prng_random(false);
|
||||||
|
frame[i] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
fcs = crc16_ccitt(fcs, frame, size) ^ 0xFFFF;
|
||||||
|
|
||||||
|
frame[size - 2] = fcs >> 8;
|
||||||
|
frame[size - 1] = fcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t test_modem_ppp_wrap_ppp_frame(uint8_t *wrapped, const uint8_t *frame, size_t size)
|
||||||
|
{
|
||||||
|
size_t wrapped_pos = 4;
|
||||||
|
|
||||||
|
wrapped[0] = 0x7E;
|
||||||
|
wrapped[1] = 0xFF;
|
||||||
|
wrapped[2] = 0x7D;
|
||||||
|
wrapped[3] = 0x23;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
if ((frame[i] == 0x7E) || (frame[i] == 0x7D) || (frame[i] < 0x20)) {
|
||||||
|
wrapped[wrapped_pos] = 0x7D;
|
||||||
|
wrapped[wrapped_pos + 1] = frame[i] ^ 0x20;
|
||||||
|
wrapped_pos += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapped[wrapped_pos] = frame[i];
|
||||||
|
wrapped_pos += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapped[wrapped_pos] = 0x7E;
|
||||||
|
wrapped_pos += 1;
|
||||||
|
return wrapped_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Test setup */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
static void *test_modem_ppp_setup(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Manually run internal init function which would normally be performed by kernel as
|
||||||
|
* result of using the macro MODEM_PPP_DEFINE()
|
||||||
|
*/
|
||||||
|
zassert_true(modem_ppp_init_internal(&ppp_net_dev) == 0, "Failed to run internal init");
|
||||||
|
net_if_flag_set(modem_ppp_get_iface(&ppp), NET_IF_UP);
|
||||||
|
|
||||||
|
const struct modem_backend_mock_config mock_config = {
|
||||||
|
.rx_buf = mock_rx_buf,
|
||||||
|
.rx_buf_size = sizeof(mock_rx_buf),
|
||||||
|
.tx_buf = mock_tx_buf,
|
||||||
|
.tx_buf_size = sizeof(mock_tx_buf),
|
||||||
|
.limit = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
mock_pipe = modem_backend_mock_init(&mock, &mock_config);
|
||||||
|
zassert_true(modem_pipe_open(mock_pipe) == 0, "Failed to open mock pipe");
|
||||||
|
modem_ppp_attach(&ppp, mock_pipe);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_modem_ppp_before(void *f)
|
||||||
|
{
|
||||||
|
/* Unreference packets */
|
||||||
|
for (size_t i = 0; i < received_packets_len; i++) {
|
||||||
|
net_pkt_unref(received_packets[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset packets received buffer */
|
||||||
|
received_packets_len = 0;
|
||||||
|
|
||||||
|
/* Reset mock pipe */
|
||||||
|
modem_backend_mock_reset(&mock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************************************************************************/
|
||||||
|
/* Tests */
|
||||||
|
/*************************************************************************************************/
|
||||||
|
ZTEST(modem_ppp, test_ppp_frame_receive)
|
||||||
|
{
|
||||||
|
struct net_pkt *pkt;
|
||||||
|
size_t pkt_len;
|
||||||
|
|
||||||
|
/* Put wrapped frame */
|
||||||
|
modem_backend_mock_put(&mock, ppp_frame_wrapped, sizeof(ppp_frame_wrapped));
|
||||||
|
|
||||||
|
/* Give modem ppp time to process received frame */
|
||||||
|
k_msleep(1000);
|
||||||
|
|
||||||
|
/* Validate frame received on mock network interface */
|
||||||
|
zassert_true(received_packets_len == 1, "Expected to receive one network packet");
|
||||||
|
|
||||||
|
pkt = received_packets[0];
|
||||||
|
pkt_len = net_pkt_get_len(pkt);
|
||||||
|
|
||||||
|
/* Validate length of received frame */
|
||||||
|
zassert_true(pkt_len == sizeof(ppp_frame_unwrapped), "Received net pkt data len incorrect");
|
||||||
|
|
||||||
|
/* Validate data of received frame */
|
||||||
|
net_pkt_cursor_init(pkt);
|
||||||
|
net_pkt_read(pkt, buffer, pkt_len);
|
||||||
|
|
||||||
|
zassert_true(memcmp(buffer, ppp_frame_unwrapped, pkt_len) == 0,
|
||||||
|
"Recevied net pkt data incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_ppp, test_corrupt_start_end_ppp_frame_receive)
|
||||||
|
{
|
||||||
|
struct net_pkt *pkt;
|
||||||
|
size_t pkt_len;
|
||||||
|
|
||||||
|
/* Put wrapped frame */
|
||||||
|
modem_backend_mock_put(&mock, corrupt_start_end_ppp_frame_wrapped,
|
||||||
|
sizeof(corrupt_start_end_ppp_frame_wrapped));
|
||||||
|
|
||||||
|
/* Give modem ppp time to process received frame */
|
||||||
|
k_msleep(1000);
|
||||||
|
|
||||||
|
/* Validate frame received on mock network interface */
|
||||||
|
zassert_true(received_packets_len == 1, "Expected to receive one network packet");
|
||||||
|
|
||||||
|
/* Validate length of received frame */
|
||||||
|
pkt = received_packets[0];
|
||||||
|
pkt_len = net_pkt_get_len(pkt);
|
||||||
|
zassert_true(pkt_len == sizeof(ppp_frame_unwrapped), "Received net pkt data len incorrect");
|
||||||
|
|
||||||
|
/* Validate data of received frame */
|
||||||
|
net_pkt_cursor_init(pkt);
|
||||||
|
net_pkt_read(pkt, buffer, pkt_len);
|
||||||
|
zassert_true(memcmp(buffer, ppp_frame_unwrapped, pkt_len) == 0,
|
||||||
|
"Recevied net pkt data incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_ppp, test_ppp_frame_send)
|
||||||
|
{
|
||||||
|
struct net_pkt *pkt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Allocate net pkt */
|
||||||
|
pkt = net_pkt_alloc_with_buffer(&test_iface, 256, AF_UNSPEC, 0, K_NO_WAIT);
|
||||||
|
|
||||||
|
zassert_true(pkt != NULL, "Failed to allocate network packet");
|
||||||
|
|
||||||
|
/* Set network packet data */
|
||||||
|
net_pkt_cursor_init(pkt);
|
||||||
|
ret = net_pkt_write(pkt, ppp_frame_unwrapped, sizeof(ppp_frame_unwrapped));
|
||||||
|
zassert_true(ret == 0, "Failed to write data to allocated network packet");
|
||||||
|
net_pkt_set_ppp(pkt, true);
|
||||||
|
|
||||||
|
/* Send network packet */
|
||||||
|
zassert_true(test_net_send(pkt) == 0, "Failed to send PPP pkt");
|
||||||
|
|
||||||
|
/* Give modem ppp time to wrap and send frame */
|
||||||
|
k_msleep(1000);
|
||||||
|
|
||||||
|
/* Get any sent data */
|
||||||
|
ret = modem_backend_mock_get(&mock, buffer, sizeof(buffer));
|
||||||
|
zassert_true(ret == sizeof(ppp_frame_wrapped), "Wrapped frame length incorrect");
|
||||||
|
zassert_true(memcmp(buffer, ppp_frame_wrapped, ret) == 0,
|
||||||
|
"Wrapped frame content is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_ppp, test_ip_frame_receive)
|
||||||
|
{
|
||||||
|
struct net_pkt *pkt;
|
||||||
|
size_t pkt_len;
|
||||||
|
|
||||||
|
/* Put wrapped frame */
|
||||||
|
modem_backend_mock_put(&mock, ip_frame_wrapped, sizeof(ip_frame_wrapped));
|
||||||
|
|
||||||
|
/* Give modem ppp time to process received frame */
|
||||||
|
k_msleep(1000);
|
||||||
|
|
||||||
|
/* Validate frame received on mock network interface */
|
||||||
|
zassert_true(received_packets_len == 1, "Expected to receive one network packet");
|
||||||
|
pkt = received_packets[0];
|
||||||
|
pkt_len = net_pkt_get_len(pkt);
|
||||||
|
|
||||||
|
/* Validate length of received frame */
|
||||||
|
zassert_true(pkt_len == sizeof(ip_frame_unwrapped_with_protocol),
|
||||||
|
"Received net pkt data len incorrect");
|
||||||
|
|
||||||
|
/* Validate data of received frame */
|
||||||
|
net_pkt_cursor_init(pkt);
|
||||||
|
net_pkt_read(pkt, buffer, pkt_len);
|
||||||
|
zassert_true(memcmp(buffer, ip_frame_unwrapped_with_protocol, pkt_len) == 0,
|
||||||
|
"Recevied net pkt data incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_ppp, test_ip_frame_send)
|
||||||
|
{
|
||||||
|
struct net_pkt *pkt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Allocate net pkt */
|
||||||
|
pkt = net_pkt_alloc_with_buffer(&test_iface, 256, AF_UNSPEC, 0, K_NO_WAIT);
|
||||||
|
zassert_true(pkt != NULL, "Failed to allocate network packet");
|
||||||
|
|
||||||
|
/* Set network packet data */
|
||||||
|
net_pkt_cursor_init(pkt);
|
||||||
|
ret = net_pkt_write(pkt, ip_frame_unwrapped, sizeof(ip_frame_unwrapped));
|
||||||
|
zassert_true(ret == 0, "Failed to write data to allocated network packet");
|
||||||
|
net_pkt_set_family(pkt, AF_INET);
|
||||||
|
|
||||||
|
/* Send network packet */
|
||||||
|
test_net_send(pkt);
|
||||||
|
|
||||||
|
/* Give modem ppp time to wrap and send frame */
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
/* Get any sent data */
|
||||||
|
ret = modem_backend_mock_get(&mock, buffer, sizeof(buffer));
|
||||||
|
zassert_true(ret == sizeof(ip_frame_wrapped), "Wrapped frame length incorrect");
|
||||||
|
zassert_true(memcmp(buffer, ip_frame_wrapped, ret) == 0,
|
||||||
|
"Wrapped frame content is incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_ppp, test_ip_frame_send_multiple)
|
||||||
|
{
|
||||||
|
struct net_pkt *pkts[TEST_MODEM_PPP_IP_FRAME_SEND_MULT_N];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Allocate net pkts */
|
||||||
|
for (uint8_t i = 0; i < TEST_MODEM_PPP_IP_FRAME_SEND_MULT_N; i++) {
|
||||||
|
pkts[i] = net_pkt_alloc_with_buffer(&test_iface, 256, AF_UNSPEC, 0, K_NO_WAIT);
|
||||||
|
zassert_true(pkts[i] != NULL, "Failed to allocate network packet");
|
||||||
|
net_pkt_cursor_init(pkts[i]);
|
||||||
|
ret = net_pkt_write(pkts[i], ip_frame_unwrapped, sizeof(ip_frame_unwrapped));
|
||||||
|
zassert_true(ret == 0, "Failed to write data to allocated network packet");
|
||||||
|
net_pkt_set_family(pkts[i], AF_INET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send net pkts */
|
||||||
|
for (uint8_t i = 0; i < TEST_MODEM_PPP_IP_FRAME_SEND_MULT_N; i++) {
|
||||||
|
test_net_send(pkts[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
k_msleep(100);
|
||||||
|
|
||||||
|
ret = modem_backend_mock_get(&mock, buffer, TEST_MODEM_PPP_MOCK_PIPE_RX_BUF_SIZE);
|
||||||
|
zassert_true(ret == (sizeof(ip_frame_wrapped) * TEST_MODEM_PPP_IP_FRAME_SEND_MULT_N),
|
||||||
|
"Incorrect data amount received");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_ppp, test_ip_frame_send_large)
|
||||||
|
{
|
||||||
|
struct net_pkt *pkt;
|
||||||
|
size_t size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pkt = net_pkt_alloc_with_buffer(&test_iface, TEST_MODEM_PPP_IP_FRAME_SEND_LARGE_N,
|
||||||
|
AF_UNSPEC, 0, K_NO_WAIT);
|
||||||
|
|
||||||
|
net_pkt_cursor_init(pkt);
|
||||||
|
net_pkt_set_family(pkt, AF_INET);
|
||||||
|
size = test_modem_ppp_fill_net_pkt(pkt, TEST_MODEM_PPP_IP_FRAME_SEND_LARGE_N);
|
||||||
|
zassert_true(size == TEST_MODEM_PPP_IP_FRAME_SEND_LARGE_N, "Failed to fill net pkt");
|
||||||
|
test_net_send(pkt);
|
||||||
|
k_msleep(TEST_MODEM_PPP_IP_FRAME_SEND_LARGE_N * 2);
|
||||||
|
|
||||||
|
/* Data + protocol */
|
||||||
|
ret = modem_backend_mock_get(&mock, buffer, TEST_MODEM_PPP_MOCK_PIPE_RX_BUF_SIZE);
|
||||||
|
size = test_modem_ppp_unwrap(unwrapped_buffer, buffer, ret);
|
||||||
|
zassert_true(size == (TEST_MODEM_PPP_IP_FRAME_SEND_LARGE_N + 2),
|
||||||
|
"Incorrect data amount received");
|
||||||
|
|
||||||
|
/* Validate protocol */
|
||||||
|
zassert_true(unwrapped_buffer[0] == 0x00, "Incorrect protocol");
|
||||||
|
zassert_true(unwrapped_buffer[1] == 0x21, "Incorrect protocol");
|
||||||
|
|
||||||
|
/* Validate data */
|
||||||
|
zassert_true(test_modem_ppp_validate_fill(&unwrapped_buffer[2], (size - 2)) == true,
|
||||||
|
"Incorrect data received");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(modem_ppp, test_ip_frame_receive_large)
|
||||||
|
{
|
||||||
|
struct net_pkt *pkt;
|
||||||
|
size_t size;
|
||||||
|
size_t pkt_len;
|
||||||
|
|
||||||
|
test_modem_ppp_generate_ppp_frame(buffer, TEST_MODEM_PPP_IP_FRAME_RECEIVE_LARGE_N);
|
||||||
|
size = test_modem_ppp_wrap_ppp_frame(wrapped_buffer, buffer,
|
||||||
|
TEST_MODEM_PPP_IP_FRAME_RECEIVE_LARGE_N);
|
||||||
|
|
||||||
|
zassert_true(size > TEST_MODEM_PPP_IP_FRAME_RECEIVE_LARGE_N, "Failed to wrap data");
|
||||||
|
modem_backend_mock_put(&mock, wrapped_buffer, size);
|
||||||
|
|
||||||
|
k_msleep(TEST_MODEM_PPP_IP_FRAME_RECEIVE_LARGE_N * 2);
|
||||||
|
|
||||||
|
zassert_true(received_packets_len == 1, "Expected to receive one network packet");
|
||||||
|
pkt = received_packets[0];
|
||||||
|
pkt_len = net_pkt_get_len(pkt);
|
||||||
|
|
||||||
|
/* FCS is removed from packet data */
|
||||||
|
zassert_true(pkt_len == (TEST_MODEM_PPP_IP_FRAME_RECEIVE_LARGE_N - 2),
|
||||||
|
"Incorrect length of net packet received");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST_SUITE(modem_ppp, NULL, test_modem_ppp_setup, test_modem_ppp_before, NULL, NULL);
|
8
tests/subsys/modem/modem_ppp/testcase.yaml
Normal file
8
tests/subsys/modem/modem_ppp/testcase.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2023 Trackunit Corporation
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
tests:
|
||||||
|
modem.modem_ppp:
|
||||||
|
tags: modem_ppp
|
||||||
|
harness: ztest
|
||||||
|
platform_allow: native_posix
|
Loading…
Add table
Add a link
Reference in a new issue