tests: drivers: gnss: Add GNSS API test suite

Add GNSS API test suite validating the behavior of a GNSS
device adheres to the GNSS API.

Signed-off-by: Bjarki Arge Andreasen <bjarki@arge-andreasen.me>
This commit is contained in:
Bjarki Arge Andreasen 2024-05-03 09:49:48 +02:00 committed by Carles Cufí
commit fdda93fd99
8 changed files with 364 additions and 0 deletions

View file

@ -0,0 +1,15 @@
# Copyright (c) 2024 Trackunit Corporation
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(gnss_api)
target_sources(app PRIVATE
src/test_enabled_systems.c
src/test_fix_rate.c
src/test_navigation_mode.c
src/test_suite.c
)

View file

@ -0,0 +1,32 @@
# Copyright (c) 2024 Trackunit Corporation
# SPDX-License-Identifier: Apache-2.0
source "Kconfig.zephyr"
config TEST_ENABLED_SYSTEMS_0
int "Enabled systems configuration 0"
range 0 255
default 0
config TEST_ENABLED_SYSTEMS_1
int "Enabled systems configuration 1"
range 0 255
default 0
config TEST_ENABLED_SYSTEMS_2
int "Enabled systems configuration 2"
range 0 255
default 0
config TEST_ENABLED_SYSTEMS_3
int "Enabled systems configuration 3"
range 0 255
default 0
config TEST_SEARCH_PERIOD
int "Search period for satellites in seconds"
default 60
config TEST_FIX_TIMEOUT
int "Timeout waiting for a fix in seconds"
default 60

View file

@ -0,0 +1,6 @@
# Copyright (c) 2024 Trackunit Corporation
# SPDX-License-Identifier: Apache-2.0
CONFIG_GNSS=y
CONFIG_ZTEST=y
CONFIG_ZTEST_STACK_SIZE=4096

View file

@ -0,0 +1,147 @@
/*
* Copyright 2024 Trackunit Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/gnss.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/ztest.h>
#define TEST_SEARCH_PERIOD K_SECONDS(CONFIG_TEST_SEARCH_PERIOD)
static const struct device *dev = DEVICE_DT_GET(DT_ALIAS(gnss));
static const gnss_systems_t enabled_systems_array[] = {
CONFIG_TEST_ENABLED_SYSTEMS_0,
CONFIG_TEST_ENABLED_SYSTEMS_1,
CONFIG_TEST_ENABLED_SYSTEMS_2,
CONFIG_TEST_ENABLED_SYSTEMS_3,
};
static bool test_reported_are_expected(gnss_systems_t reported, gnss_systems_t expected)
{
return ((~expected) & reported) == 0;
}
static void test_set_enabled_systems(gnss_systems_t enabled_systems)
{
int ret;
ret = gnss_set_enabled_systems(dev, enabled_systems);
zassert_ok(ret, "failed to set enabled systems (%i)", ret);
}
static void test_get_system_enabled(gnss_systems_t expected_systems)
{
int ret;
gnss_systems_t enabled_systems;
ret = gnss_get_enabled_systems(dev, &enabled_systems);
if (ret == -ENOSYS) {
return;
}
zassert_ok(ret, "failed to get enabled systems (%i)", ret);
zassert_equal(enabled_systems, expected_systems,
"invalid enabled systems (%u != %u)",
enabled_systems, expected_systems);
}
#ifdef CONFIG_GNSS_SATELLITES
static atomic_t reported_systems_atom = ATOMIC_INIT(0);
static void gnss_satellites_cb(const struct device *dev,
const struct gnss_satellite *satellites,
uint16_t size)
{
for (uint16_t i = 0; i < size; i++) {
atomic_or(&reported_systems_atom, satellites[i].system);
}
}
GNSS_SATELLITES_CALLBACK_DEFINE(DEVICE_DT_GET(DT_ALIAS(gnss)), gnss_satellites_cb);
static void test_validate_satellites(gnss_systems_t expected_systems)
{
gnss_systems_t reported_systems;
bool expected;
atomic_set(&reported_systems_atom, 0);
PRINT("searching with enabled system %u\n", expected_systems);
k_sleep(TEST_SEARCH_PERIOD);
reported_systems = atomic_get(&reported_systems_atom);
if (reported_systems == 0) {
PRINT("found no satellites\n");
} else {
PRINT("found satellites\n");
}
expected = test_reported_are_expected(reported_systems, expected_systems);
zassert_true(expected, "unexpected systems reported (%u != %u)",
reported_systems, expected_systems);
}
#endif
static void test_validate_enabled_systems(void)
{
gnss_systems_t enabled_systems;
for (uint8_t i = 0; i < ARRAY_SIZE(enabled_systems_array); i++) {
enabled_systems = enabled_systems_array[i];
if (enabled_systems == 0) {
continue;
}
test_set_enabled_systems(enabled_systems);
test_get_system_enabled(enabled_systems);
#ifdef CONFIG_GNSS_SATELLITES
test_validate_satellites(enabled_systems);
#endif
}
}
static bool test_all_enabled_systems_are_disabled(void)
{
gnss_systems_t enabled_systems;
for (uint8_t i = 0; i < ARRAY_SIZE(enabled_systems_array); i++) {
enabled_systems = enabled_systems_array[i];
if (enabled_systems != 0) {
return false;
}
}
return true;
}
static void test_validate_supported_systems(void)
{
gnss_systems_t supported_systems;
int ret;
gnss_systems_t enabled_systems;
bool supported;
ret = gnss_get_supported_systems(dev, &supported_systems);
if (ret == -ENOSYS) {
return;
}
zassert_ok(ret, "failed to get supported systems (%i)", ret);
for (uint8_t i = 0; i < ARRAY_SIZE(enabled_systems_array); i++) {
enabled_systems = enabled_systems_array[0];
supported = test_reported_are_expected(enabled_systems, supported_systems);
zassert_true(supported, "enabled systems %u is not supported", i);
}
}
ZTEST(gnss_api, test_enabled_systems)
{
if (test_all_enabled_systems_are_disabled()) {
ztest_test_skip();
}
test_validate_supported_systems();
test_validate_enabled_systems();
}

View file

@ -0,0 +1,88 @@
/*
* Copyright 2024 Trackunit Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/gnss.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/ztest.h>
#define TEST_VALIDATE_PERIOD_MS 10000
#define TEST_VALIDATE_PERIOD K_MSEC(TEST_VALIDATE_PERIOD_MS)
#define TEST_MIN_CALLBACK_COUNT(_fix_interval) \
(((TEST_VALIDATE_PERIOD_MS / _fix_interval) / 5) * 4)
#define TEST_MAX_CALLBACK_COUNT(_fix_interval) \
(((TEST_VALIDATE_PERIOD_MS / _fix_interval) / 5) * 6)
#define TEST_CONFIG_DEFINE(_fix_interval) \
{ \
.fix_interval = _fix_interval, \
.min_callback_count = TEST_MIN_CALLBACK_COUNT(_fix_interval), \
.max_callback_count = TEST_MAX_CALLBACK_COUNT(_fix_interval), \
}
static const struct device *dev = DEVICE_DT_GET(DT_ALIAS(gnss));
struct test_config {
uint32_t fix_interval;
uint32_t min_callback_count;
uint32_t max_callback_count;
};
static const struct test_config configs[] = {
TEST_CONFIG_DEFINE(100),
TEST_CONFIG_DEFINE(500),
TEST_CONFIG_DEFINE(1000),
TEST_CONFIG_DEFINE(2000),
};
static atomic_t callback_count_atom = ATOMIC_INIT(0);
static void gnss_data_cb(const struct device *dev, const struct gnss_data *data)
{
atomic_inc(&callback_count_atom);
}
GNSS_DATA_CALLBACK_DEFINE(DEVICE_DT_GET(DT_ALIAS(gnss)), gnss_data_cb);
static bool test_set_fix_rate(const struct test_config *config)
{
int ret;
ret = gnss_set_fix_rate(dev, config->fix_interval);
if (ret == -ENOSYS) {
ztest_test_skip();
}
if (ret == -EINVAL) {
return false;
}
zassert_ok(ret, "failed to set fix rate %u", config->fix_interval);
return true;
}
static void test_validate_fix_rate(const struct test_config *config)
{
bool valid;
uint32_t callback_count;
atomic_set(&callback_count_atom, 0);
k_sleep(TEST_VALIDATE_PERIOD);
callback_count = atomic_get(&callback_count_atom);
valid = (callback_count >= config->min_callback_count) &&
(callback_count <= config->max_callback_count);
zassert_true(valid, "callback count %u invalid", callback_count);
}
ZTEST(gnss_api, test_fix_rate)
{
for (uint32_t i = 0; i < ARRAY_SIZE(configs); i++) {
if (!test_set_fix_rate(&configs[i])) {
continue;
}
test_validate_fix_rate(&configs[i]);
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright 2024 Trackunit Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/gnss.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/ztest.h>
static const struct device *dev = DEVICE_DT_GET(DT_ALIAS(gnss));
static const enum gnss_navigation_mode nav_modes[] = {
GNSS_NAVIGATION_MODE_ZERO_DYNAMICS,
GNSS_NAVIGATION_MODE_LOW_DYNAMICS,
GNSS_NAVIGATION_MODE_BALANCED_DYNAMICS,
GNSS_NAVIGATION_MODE_HIGH_DYNAMICS,
};
static bool test_set_nav_mode(enum gnss_navigation_mode nav_mode)
{
int ret;
ret = gnss_set_navigation_mode(dev, nav_mode);
if (ret == -ENOSYS) {
ztest_test_skip();
}
if (ret == -EINVAL) {
return false;
}
zassert_ok(ret, "failed to set navigation mode %u", nav_mode);
return true;
}
static void test_validate_nav_mode(enum gnss_navigation_mode nav_mode)
{
int ret;
enum gnss_navigation_mode set_nav_mode;
ret = gnss_get_navigation_mode(dev, &set_nav_mode);
if (ret == -ENOSYS) {
return;
}
zassert_ok(ret, "failed to get navigation mode %u", nav_mode);
}
ZTEST(gnss_api, test_navigation_mode)
{
enum gnss_navigation_mode nav_mode;
for (uint8_t i = 0; i < ARRAY_SIZE(nav_modes); i++) {
nav_mode = nav_modes[i];
if (!test_set_nav_mode(nav_mode)) {
continue;
}
test_validate_nav_mode(nav_mode);
}
}

View file

@ -0,0 +1,9 @@
/*
* Copyright 2024 Trackunit Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
ZTEST_SUITE(gnss_api, NULL, NULL, NULL, NULL, NULL);

View file

@ -0,0 +1,7 @@
# Copyright (c) 2024 Trackunit Corporation
# SPDX-License-Identifier: Apache-2.0
tests:
drivers.gnss.gnss_api:
filter: dt_alias_exists("gnss")
timeout: 300