tests: drivers: can: add test for the CAN shell module

Add test for the CAN shell module.

The tests execute a set of CAN shell module commands against a CAN
controller driver mock, verifies that the expected CAN controller driver
API functions are called, and that their arguments are as expected.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2022-08-26 13:34:06 +02:00 committed by Carles Cufí
commit 11ed7d62b7
9 changed files with 840 additions and 0 deletions

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(can_shell)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})

View file

@ -0,0 +1,13 @@
# Copyright (c) 2022 Vestas Wind Systems A/S
# SPDX-License-Identifier: Apache-2.0
config TEST_FAKE_CAN
bool
default y
depends on DT_HAS_TEST_FAKE_CAN_ENABLED
select CAN_HAS_RX_TIMESTAMP
select CAN_HAS_CANFD
help
Enable support for the fake CAN driver.
source "Kconfig.zephyr"

View file

@ -0,0 +1,19 @@
/*
* Copyright (c) 2022 Vestas Wind Systems A/S
*
* SPDX-License-Identifier: Apache-2.0
*/
/{
fake_can: fake_can {
compatible = "test-fake-can";
status = "okay";
sjw = <1>;
sample-point = <875>;
bus-speed = <125000>;
sample-point = <875>;
sjw-data = <1>;
bus-speed-data = <1000000>;
sample-point-data = <750>;
};
};

View file

@ -0,0 +1,10 @@
# Copyright (c) 2022 Vestas Wind Systems A/S
# SPDX-License-Identifier: Apache-2.0
description: |
This binding provides resources required to build and run the
tests/drivers/can/shell test in Zephyr.
compatible: "test-fake-can"
include: can-fd-controller.yaml

View file

@ -0,0 +1,9 @@
CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=n
CONFIG_SHELL_BACKEND_DUMMY=y
CONFIG_CAN=y
CONFIG_CAN_AUTO_BUS_OFF_RECOVERY=n
CONFIG_CAN_FD_MODE=y
CONFIG_CAN_SHELL=y
CONFIG_ZTEST=y
CONFIG_ZTEST_NEW_API=y

View file

@ -0,0 +1,146 @@
/*
* Copyright (c) 2022 Vestas Wind Systems A/S
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/device.h>
#include <zephyr/drivers/can.h>
#include <zephyr/fff.h>
#ifdef CONFIG_ZTEST_NEW_API
#include <zephyr/ztest.h>
#endif /* CONFIG_ZTEST_NEW_API */
#include "fake_can.h"
#define DT_DRV_COMPAT test_fake_can
DEFINE_FAKE_VALUE_FUNC(int, fake_can_set_timing, const struct device *, const struct can_timing *);
DEFINE_FAKE_VALUE_FUNC(int, fake_can_set_timing_data, const struct device *,
const struct can_timing *);
DEFINE_FAKE_VALUE_FUNC(int, fake_can_get_capabilities, const struct device *, can_mode_t *);
DEFINE_FAKE_VALUE_FUNC(int, fake_can_set_mode, const struct device *, can_mode_t);
DEFINE_FAKE_VALUE_FUNC(int, fake_can_send, const struct device *, const struct can_frame *,
k_timeout_t, can_tx_callback_t, void *);
DEFINE_FAKE_VALUE_FUNC(int, fake_can_add_rx_filter, const struct device *, can_rx_callback_t,
void *, const struct can_filter *);
DEFINE_FAKE_VOID_FUNC(fake_can_remove_rx_filter, const struct device *, int);
DEFINE_FAKE_VALUE_FUNC(int, fake_can_recover, const struct device *, k_timeout_t);
DEFINE_FAKE_VALUE_FUNC(int, fake_can_get_state, const struct device *, enum can_state *,
struct can_bus_err_cnt *);
DEFINE_FAKE_VOID_FUNC(fake_can_set_state_change_callback, const struct device *,
can_state_change_callback_t, void *);
DEFINE_FAKE_VALUE_FUNC(int, fake_can_get_max_filters, const struct device *, enum can_ide);
#ifdef CONFIG_ZTEST_NEW_API
static void fake_can_reset_rule_before(const struct ztest_unit_test *test, void *fixture)
{
ARG_UNUSED(test);
ARG_UNUSED(fixture);
RESET_FAKE(fake_can_get_capabilities);
RESET_FAKE(fake_can_set_mode);
RESET_FAKE(fake_can_set_timing);
RESET_FAKE(fake_can_set_timing_data);
RESET_FAKE(fake_can_send);
RESET_FAKE(fake_can_add_rx_filter);
RESET_FAKE(fake_can_remove_rx_filter);
RESET_FAKE(fake_can_get_state);
RESET_FAKE(fake_can_recover);
RESET_FAKE(fake_can_set_state_change_callback);
RESET_FAKE(fake_can_get_max_filters);
}
ZTEST_RULE(fake_can_reset_rule, fake_can_reset_rule_before, NULL);
#endif /* CONFIG_ZTEST_NEW_API */
static int fake_can_get_core_clock(const struct device *dev, uint32_t *rate)
{
ARG_UNUSED(dev);
*rate = 16000000;
return 0;
}
static int fake_can_get_max_bitrate(const struct device *dev, uint32_t *max_bitrate)
{
ARG_UNUSED(dev);
*max_bitrate = 5000000;
return 0;
}
static const struct can_driver_api fake_can_driver_api = {
.get_capabilities = fake_can_get_capabilities,
.set_mode = fake_can_set_mode,
.set_timing = fake_can_set_timing,
.send = fake_can_send,
.add_rx_filter = fake_can_add_rx_filter,
.remove_rx_filter = fake_can_remove_rx_filter,
.get_state = fake_can_get_state,
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
.recover = fake_can_recover,
#endif /* CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
.set_state_change_callback = fake_can_set_state_change_callback,
.get_core_clock = fake_can_get_core_clock,
.get_max_filters = fake_can_get_max_filters,
.get_max_bitrate = fake_can_get_max_bitrate,
.timing_min = {
.sjw = 0x01,
.prop_seg = 0x01,
.phase_seg1 = 0x01,
.phase_seg2 = 0x01,
.prescaler = 0x01
},
.timing_max = {
.sjw = 0x0f,
.prop_seg = 0x0f,
.phase_seg1 = 0x0f,
.phase_seg2 = 0x0f,
.prescaler = 0xffff
},
#ifdef CONFIG_CAN_FD_MODE
.set_timing_data = fake_can_set_timing_data,
.timing_data_min = {
.sjw = 0x01,
.prop_seg = 0x01,
.phase_seg1 = 0x01,
.phase_seg2 = 0x01,
.prescaler = 0x01
},
.timing_data_max = {
.sjw = 0x0f,
.prop_seg = 0x0f,
.phase_seg1 = 0x0f,
.phase_seg2 = 0x0f,
.prescaler = 0xffff
},
#endif /* CONFIG_CAN_FD_MODE */
};
static int fake_can_init(const struct device *dev)
{
ARG_UNUSED(dev);
return 0;
}
#define FAKE_CAN_INIT(inst) \
DEVICE_DT_INST_DEFINE(inst, &fake_can_init, NULL, NULL, NULL, \
POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \
&fake_can_driver_api);
DT_INST_FOREACH_STATUS_OKAY(FAKE_CAN_INIT)

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2022 Vestas Wind Systems A/S
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_TESTS_DRIVERS_CAN_SHELL_FAKE_CAN_H_
#define ZEPHYR_TESTS_DRIVERS_CAN_SHELL_FAKE_CAN_H_
#include <zephyr/drivers/can.h>
#include <zephyr/fff.h>
#ifdef __cplusplus
extern "C" {
#endif
DECLARE_FAKE_VALUE_FUNC(int, fake_can_set_timing, const struct device *, const struct can_timing *);
DECLARE_FAKE_VALUE_FUNC(int, fake_can_set_timing_data, const struct device *,
const struct can_timing *);
DECLARE_FAKE_VALUE_FUNC(int, fake_can_get_capabilities, const struct device *, can_mode_t *);
DECLARE_FAKE_VALUE_FUNC(int, fake_can_set_mode, const struct device *, can_mode_t);
DECLARE_FAKE_VALUE_FUNC(int, fake_can_send, const struct device *, const struct can_frame *,
k_timeout_t, can_tx_callback_t, void *);
DECLARE_FAKE_VALUE_FUNC(int, fake_can_add_rx_filter, const struct device *, can_rx_callback_t,
void *, const struct can_filter *);
DECLARE_FAKE_VOID_FUNC(fake_can_remove_rx_filter, const struct device *, int);
DECLARE_FAKE_VALUE_FUNC(int, fake_can_recover, const struct device *, k_timeout_t);
DECLARE_FAKE_VALUE_FUNC(int, fake_can_get_state, const struct device *, enum can_state *,
struct can_bus_err_cnt *);
DECLARE_FAKE_VOID_FUNC(fake_can_set_state_change_callback, const struct device *,
can_state_change_callback_t, void *);
DECLARE_FAKE_VALUE_FUNC(int, fake_can_get_max_filters, const struct device *, enum can_ide);
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_TESTS_DRIVERS_CAN_SHELL_FAKE_CAN_H_ */

View file

@ -0,0 +1,581 @@
/*
* Copyright (c) 2022 Vestas Wind Systems A/S
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "fake_can.h"
#include <string.h>
#include <zephyr/drivers/can.h>
#include <zephyr/fff.h>
#include <zephyr/shell/shell.h>
#include <zephyr/shell/shell_dummy.h>
#include <zephyr/ztest.h>
/**
* @addtogroup t_can_driver
* @{
* @defgroup t_can_api test_can_shell
* @}
*/
#define FAKE_CAN_NAME DEVICE_DT_NAME(DT_NODELABEL(fake_can))
/* Global variables */
static const struct device *const fake_can_dev = DEVICE_DT_GET(DT_NODELABEL(fake_can));
static struct can_timing timing_capture;
static struct can_filter filter_capture;
static struct can_frame frame_capture;
DEFINE_FFF_GLOBALS;
static void assert_can_timing_equal(const struct can_timing *t1, const struct can_timing *t2)
{
zassert_equal(t1->sjw, t2->sjw, "sjw mismatch");
zassert_equal(t1->prop_seg, t2->prop_seg, "prop_seg mismatch");
zassert_equal(t1->phase_seg1, t2->phase_seg1, "hase_seg1 mismatch");
zassert_equal(t1->phase_seg2, t2->phase_seg2, "phase_seg2 mismatch");
zassert_equal(t1->prescaler, t2->prescaler, "prescaler mismatch");
}
static void assert_can_filter_equal(const struct can_filter *f1, const struct can_filter *f2)
{
zassert_equal(f1->id_type, f2->id_type, "id_type mismatch");
zassert_equal(f1->id, f2->id, "id mismatch");
zassert_equal(f1->id_mask, f2->id_mask, "id_mask mismatch");
zassert_equal(f1->rtr, f2->rtr, "rtr mismatch");
zassert_equal(f1->rtr_mask, f2->rtr_mask, "rtr_mask mismatch");
}
static void assert_can_frame_equal(const struct can_frame *f1, const struct can_frame *f2)
{
zassert_equal(f1->id_type, f2->id_type, "id_type mismatch");
zassert_equal(f1->id, f2->id, "id mismatch");
zassert_equal(f1->rtr, f2->rtr, "rtr mismatch");
zassert_equal(f1->fd, f2->fd, "fd mismatch");
zassert_equal(f1->brs, f2->brs, "brs mismatch");
zassert_equal(f1->dlc, f2->dlc, "dlc mismatch");
zassert_mem_equal(f1->data, f2->data, can_dlc_to_bytes(f1->dlc), "data mismatch");
}
static int can_shell_test_capture_timing(const struct device *dev, const struct can_timing *timing)
{
ARG_UNUSED(dev);
memcpy(&timing_capture, timing, sizeof(timing_capture));
return 0;
}
static int can_shell_test_capture_filter(const struct device *dev, can_rx_callback_t callback,
void *user_data, const struct can_filter *filter)
{
ARG_UNUSED(dev);
ARG_UNUSED(callback);
ARG_UNUSED(user_data);
memcpy(&filter_capture, filter, sizeof(filter_capture));
return 0;
}
static int can_shell_test_capture_frame(const struct device *dev, const struct can_frame *frame,
k_timeout_t timeout, can_tx_callback_t callback,
void *user_data)
{
ARG_UNUSED(dev);
ARG_UNUSED(timeout);
ARG_UNUSED(callback);
ARG_UNUSED(user_data);
memcpy(&frame_capture, frame, sizeof(frame_capture));
return 0;
}
ZTEST(can_shell, test_can_show)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
err = shell_execute_cmd(sh, "can show " FAKE_CAN_NAME);
zassert_ok(err, "failed to execute shell command (err %d)", err);
zassert_equal(fake_can_get_max_filters_fake.call_count, 2,
"get_max_filters function not called twice");
zassert_equal(fake_can_get_capabilities_fake.call_count, 1,
"get_capabilities function not called");
zassert_equal(fake_can_get_state_fake.call_count, 1, "get_state function not called");
}
ZTEST(can_shell, test_can_bitrate_missing_value)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
err = shell_execute_cmd(sh, "can bitrate " FAKE_CAN_NAME);
zassert_not_equal(err, 0, " executed shell command without bitrate");
zassert_equal(fake_can_set_timing_fake.call_count, 0, "set_timing function called");
}
static void can_shell_test_bitrate(const char *cmd, uint32_t expected_bitrate,
uint16_t expected_sample_pnt)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
struct can_timing expected;
int err;
expected.sjw = CAN_SJW_NO_CHANGE;
err = can_calc_timing(fake_can_dev, &expected, expected_bitrate, expected_sample_pnt);
zassert_ok(err, "failed to calculate reference timing (err %d)", err);
fake_can_set_timing_fake.custom_fake = can_shell_test_capture_timing;
err = shell_execute_cmd(sh, cmd);
zassert_ok(err, "failed to execute shell command (err %d)", err);
zassert_equal(fake_can_set_timing_fake.call_count, 1, "set_timing function not called");
zassert_equal(fake_can_set_timing_fake.arg0_val, fake_can_dev, "wrong device pointer");
assert_can_timing_equal(&expected, &timing_capture);
}
ZTEST(can_shell, test_can_bitrate)
{
can_shell_test_bitrate("can bitrate " FAKE_CAN_NAME " 125000", 125000, 875);
}
ZTEST(can_shell, test_can_bitrate_sample_point)
{
can_shell_test_bitrate("can bitrate " FAKE_CAN_NAME " 125000 750", 125000, 750);
}
ZTEST(can_shell, test_can_dbitrate_missing_value)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
Z_TEST_SKIP_IFNDEF(CONFIG_CAN_FD_MODE);
err = shell_execute_cmd(sh, "can dbitrate " FAKE_CAN_NAME);
zassert_not_equal(err, 0, " executed shell command without dbitrate");
zassert_equal(fake_can_set_timing_data_fake.call_count, 0,
"set_timing_data function called");
}
static void can_shell_test_dbitrate(const char *cmd, uint32_t expected_bitrate,
uint16_t expected_sample_pnt)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
struct can_timing expected;
int err;
Z_TEST_SKIP_IFNDEF(CONFIG_CAN_FD_MODE);
expected.sjw = CAN_SJW_NO_CHANGE;
err = can_calc_timing_data(fake_can_dev, &expected, expected_bitrate, expected_sample_pnt);
zassert_ok(err, "failed to calculate reference timing (err %d)", err);
fake_can_set_timing_data_fake.custom_fake = can_shell_test_capture_timing;
err = shell_execute_cmd(sh, cmd);
zassert_ok(err, "failed to execute shell command (err %d)", err);
zassert_equal(fake_can_set_timing_data_fake.call_count, 1,
"set_timing_data function not called");
zassert_equal(fake_can_set_timing_data_fake.arg0_val, fake_can_dev, "wrong device pointer");
assert_can_timing_equal(&expected, &timing_capture);
}
ZTEST(can_shell, test_can_dbitrate)
{
can_shell_test_dbitrate("can dbitrate " FAKE_CAN_NAME " 1000000", 1000000, 750);
}
ZTEST(can_shell, test_can_dbitrate_sample_point)
{
can_shell_test_dbitrate("can dbitrate " FAKE_CAN_NAME " 1000000 875", 1000000, 875);
}
ZTEST(can_shell, test_can_mode_missing_value)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
err = shell_execute_cmd(sh, "can mode " FAKE_CAN_NAME);
zassert_not_equal(err, 0, " executed shell command without mode value");
zassert_equal(fake_can_set_mode_fake.call_count, 0, "set_mode function called");
}
ZTEST(can_shell, test_can_mode_unknown)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
err = shell_execute_cmd(sh, "can mode " FAKE_CAN_NAME " foobarbaz");
zassert_not_equal(err, 0, " executed shell command with unknown mode value");
zassert_equal(fake_can_set_mode_fake.call_count, 0, "set_mode function called");
}
static void can_shell_test_mode(const char *cmd, can_mode_t expected)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
err = shell_execute_cmd(sh, cmd);
zassert_ok(err, "failed to execute shell command (err %d)", err);
zassert_equal(fake_can_set_mode_fake.call_count, 1, "set_mode function not called");
zassert_equal(fake_can_set_mode_fake.arg0_val, fake_can_dev, "wrong device pointer");
zassert_equal(fake_can_set_mode_fake.arg1_val, expected, "wrong mode value");
}
ZTEST(can_shell, test_can_mode_raw_value)
{
can_shell_test_mode("can mode " FAKE_CAN_NAME " 0xaabbccdd", 0xaabbccdd);
}
ZTEST(can_shell, test_can_mode_fd)
{
can_shell_test_mode("can mode " FAKE_CAN_NAME " fd", CAN_MODE_FD);
}
ZTEST(can_shell, test_can_mode_listen_only)
{
can_shell_test_mode("can mode " FAKE_CAN_NAME " listen-only", CAN_MODE_LISTENONLY);
}
ZTEST(can_shell, test_can_mode_loopback)
{
can_shell_test_mode("can mode " FAKE_CAN_NAME " loopback", CAN_MODE_LOOPBACK);
}
ZTEST(can_shell, test_can_mode_normal)
{
can_shell_test_mode("can mode " FAKE_CAN_NAME " normal", CAN_MODE_NORMAL);
}
ZTEST(can_shell, test_can_mode_one_shot)
{
can_shell_test_mode("can mode " FAKE_CAN_NAME " one-shot", CAN_MODE_ONE_SHOT);
}
ZTEST(can_shell, test_can_mode_triple_sampling)
{
can_shell_test_mode("can mode " FAKE_CAN_NAME " triple-sampling", CAN_MODE_3_SAMPLES);
}
ZTEST(can_shell, test_can_mode_combined)
{
can_shell_test_mode("can mode " FAKE_CAN_NAME " listen-only loopback",
CAN_MODE_LISTENONLY | CAN_MODE_LOOPBACK);
}
ZTEST(can_shell, test_can_send_missing_id)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
err = shell_execute_cmd(sh, "can send " FAKE_CAN_NAME);
zassert_not_equal(err, 0, " executed shell command without CAN ID");
zassert_equal(fake_can_send_fake.call_count, 0,
"send function called");
}
static void can_shell_test_send(const char *cmd, const struct can_frame *expected)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
fake_can_send_fake.custom_fake = can_shell_test_capture_frame;
err = shell_execute_cmd(sh, cmd);
zassert_ok(err, "failed to execute shell command (err %d)", err);
zassert_equal(fake_can_send_fake.call_count, 1, "send function not called");
zassert_equal(fake_can_send_fake.arg0_val, fake_can_dev, "wrong device pointer");
assert_can_frame_equal(expected, &frame_capture);
}
ZTEST(can_shell, test_can_send_std_id)
{
const struct can_frame expected = {
.id_type = CAN_STANDARD_IDENTIFIER,
.id = 0x010,
.rtr = CAN_DATAFRAME,
.fd = 0,
.brs = 0,
.dlc = can_bytes_to_dlc(2),
.data = { 0xaa, 0x55 },
};
can_shell_test_send("can send " FAKE_CAN_NAME " 010 aa 55", &expected);
}
ZTEST(can_shell, test_can_send_ext_id)
{
const struct can_frame expected = {
.id_type = CAN_EXTENDED_IDENTIFIER,
.id = 0x1024,
.rtr = CAN_DATAFRAME,
.fd = 0,
.brs = 0,
.dlc = can_bytes_to_dlc(4),
.data = { 0xde, 0xad, 0xbe, 0xef },
};
can_shell_test_send("can send " FAKE_CAN_NAME " -e 1024 de ad be ef", &expected);
}
ZTEST(can_shell, test_can_send_no_data)
{
const struct can_frame expected = {
.id_type = CAN_STANDARD_IDENTIFIER,
.id = 0x133,
.rtr = CAN_DATAFRAME,
.fd = 0,
.brs = 0,
.dlc = can_bytes_to_dlc(0),
.data = { },
};
can_shell_test_send("can send " FAKE_CAN_NAME " 133", &expected);
}
ZTEST(can_shell, test_can_send_rtr)
{
const struct can_frame expected = {
.id_type = CAN_STANDARD_IDENTIFIER,
.id = 0x7ff,
.rtr = CAN_REMOTEREQUEST,
.fd = 0,
.brs = 0,
.dlc = can_bytes_to_dlc(0),
.data = { },
};
can_shell_test_send("can send " FAKE_CAN_NAME " -r 7ff", &expected);
}
ZTEST(can_shell, test_can_send_fd)
{
const struct can_frame expected = {
.id_type = CAN_STANDARD_IDENTIFIER,
.id = 0x123,
.rtr = CAN_DATAFRAME,
.fd = 1,
.brs = 0,
.dlc = can_bytes_to_dlc(8),
.data = { 0xaa, 0x55, 0xaa, 0x55, 0x11, 0x22, 0x33, 0x44 },
};
can_shell_test_send("can send " FAKE_CAN_NAME " -f 123 aa 55 aa 55 11 22 33 44", &expected);
}
ZTEST(can_shell, test_can_send_fd_brs)
{
const struct can_frame expected = {
.id_type = CAN_STANDARD_IDENTIFIER,
.id = 0x321,
.rtr = CAN_DATAFRAME,
.fd = 1,
.brs = 1,
.dlc = can_bytes_to_dlc(7),
.data = { 0xaa, 0x55, 0xaa, 0x55, 0x11, 0x22, 0x33 },
};
can_shell_test_send("can send " FAKE_CAN_NAME " -f -b 321 aa 55 aa 55 11 22 33", &expected);
}
ZTEST(can_shell, test_can_send_data_all_options)
{
const struct can_frame expected = {
.id_type = CAN_EXTENDED_IDENTIFIER,
.id = 0x1024,
.rtr = CAN_REMOTEREQUEST,
.fd = 1,
.brs = 1,
.dlc = can_bytes_to_dlc(0),
.data = { },
};
can_shell_test_send("can send " FAKE_CAN_NAME " -r -e -f -b 1024", &expected);
}
ZTEST(can_shell, test_can_filter_add_missing_id)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
err = shell_execute_cmd(sh, "can filter add " FAKE_CAN_NAME);
zassert_not_equal(err, 0, " executed shell command without CAN ID");
zassert_equal(fake_can_add_rx_filter_fake.call_count, 0,
"add_rx_filter function called");
}
static void can_shell_test_filter_add(const char *cmd, const struct can_filter *expected)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
fake_can_add_rx_filter_fake.custom_fake = can_shell_test_capture_filter;
err = shell_execute_cmd(sh, cmd);
zassert_ok(err, "failed to execute shell command (err %d)", err);
zassert_equal(fake_can_add_rx_filter_fake.call_count, 1,
"add_rx_filter function not called");
zassert_equal(fake_can_add_rx_filter_fake.arg0_val, fake_can_dev, "wrong device pointer");
assert_can_filter_equal(expected, &filter_capture);
}
ZTEST(can_shell, test_can_filter_add_std_id)
{
struct can_filter expected = {
.id_type = CAN_STANDARD_IDENTIFIER,
.id = 0x010,
.id_mask = CAN_STD_ID_MASK,
.rtr = CAN_DATAFRAME,
.rtr_mask = 0,
};
can_shell_test_filter_add("can filter add " FAKE_CAN_NAME " 010", &expected);
}
ZTEST(can_shell, test_can_filter_add_std_id_mask)
{
struct can_filter expected = {
.id_type = CAN_STANDARD_IDENTIFIER,
.id = 0x010,
.id_mask = 0x020,
.rtr = CAN_DATAFRAME,
.rtr_mask = 0,
};
can_shell_test_filter_add("can filter add " FAKE_CAN_NAME " 010 020", &expected);
}
ZTEST(can_shell, test_can_filter_add_ext_id)
{
struct can_filter expected = {
.id_type = CAN_EXTENDED_IDENTIFIER,
.id = 0x1024,
.id_mask = CAN_EXT_ID_MASK,
.rtr = CAN_DATAFRAME,
.rtr_mask = 0,
};
can_shell_test_filter_add("can filter add " FAKE_CAN_NAME " -e 1024", &expected);
}
ZTEST(can_shell, test_can_filter_add_ext_id_mask)
{
struct can_filter expected = {
.id_type = CAN_EXTENDED_IDENTIFIER,
.id = 0x1024,
.id_mask = 0x2048,
.rtr = CAN_DATAFRAME,
.rtr_mask = 0,
};
can_shell_test_filter_add("can filter add " FAKE_CAN_NAME " -e 1024 2048", &expected);
}
ZTEST(can_shell, test_can_filter_add_rtr)
{
struct can_filter expected = {
.id_type = CAN_STANDARD_IDENTIFIER,
.id = 0x022,
.id_mask = CAN_STD_ID_MASK,
.rtr = CAN_REMOTEREQUEST,
.rtr_mask = 0,
};
can_shell_test_filter_add("can filter add " FAKE_CAN_NAME " -r 022", &expected);
}
ZTEST(can_shell, test_can_filter_add_rtr_mask)
{
struct can_filter expected = {
.id_type = CAN_STANDARD_IDENTIFIER,
.id = 0x322,
.id_mask = CAN_STD_ID_MASK,
.rtr = CAN_DATAFRAME,
.rtr_mask = 1,
};
can_shell_test_filter_add("can filter add " FAKE_CAN_NAME " -R 322", &expected);
}
ZTEST(can_shell, test_can_filter_add_all_options)
{
struct can_filter expected = {
.id_type = CAN_EXTENDED_IDENTIFIER,
.id = 0x2048,
.id_mask = 0x4096,
.rtr = CAN_REMOTEREQUEST,
.rtr_mask = 1,
};
can_shell_test_filter_add("can filter add " FAKE_CAN_NAME " -e -r -R 2048 4096", &expected);
}
ZTEST(can_shell, test_can_filter_remove_missing_value)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
err = shell_execute_cmd(sh, "can filter remove " FAKE_CAN_NAME);
zassert_not_equal(err, 0, " executed shell command without filter ID");
zassert_equal(fake_can_remove_rx_filter_fake.call_count, 0,
"remove_rx_filter function called");
}
ZTEST(can_shell, test_can_filter_remove)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
err = shell_execute_cmd(sh, "can filter remove " FAKE_CAN_NAME " 1234");
zassert_ok(err, "failed to execute shell command (err %d)", err);
zassert_equal(fake_can_remove_rx_filter_fake.call_count, 1,
"remove_rx_filter function not called");
zassert_equal(fake_can_remove_rx_filter_fake.arg0_val, fake_can_dev,
"wrong device pointer");
zassert_equal(fake_can_remove_rx_filter_fake.arg1_val, 1234, "wrong filter ID");
}
static void can_shell_test_recover(const char *cmd, k_timeout_t expected)
{
const struct shell *sh = shell_backend_dummy_get_ptr();
int err;
Z_TEST_SKIP_IFDEF(CONFIG_CAN_AUTO_BUS_OFF_RECOVERY);
err = shell_execute_cmd(sh, cmd);
zassert_ok(err, "failed to execute shell command (err %d)", err);
zassert_equal(fake_can_recover_fake.call_count, 1, "recover function not called");
zassert_equal(fake_can_recover_fake.arg0_val, fake_can_dev, "wrong device pointer");
zassert_true(K_TIMEOUT_EQ(fake_can_recover_fake.arg1_val, expected),
"wrong timeout value");
}
ZTEST(can_shell, test_can_recover)
{
can_shell_test_recover("can recover " FAKE_CAN_NAME, K_FOREVER);
}
ZTEST(can_shell, test_can_recover_timeout)
{
can_shell_test_recover("can recover " FAKE_CAN_NAME " 100", K_MSEC(100));
}
static void can_shell_before(void *fixture)
{
ARG_UNUSED(fixture);
memset(&timing_capture, 0, sizeof(timing_capture));
memset(&filter_capture, 0, sizeof(filter_capture));
memset(&frame_capture, 0, sizeof(frame_capture));
}
ZTEST_SUITE(can_shell, NULL, NULL, can_shell_before, NULL, NULL);

View file

@ -0,0 +1,6 @@
tests:
drivers.can.shell:
integration_platforms:
- native_posix
- native_posix_64
tags: drivers can shell