blob: fd8789a89c749a85aac1c7400e182caacb2a68f3 [file] [log] [blame]
/*
* Copyright (c) 2022 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "cmdline.h" /* native_posix command line options header */
#include "soc.h"
#include <zephyr/tc_util.h>
#include <zephyr/ztest_test_new.h>
static const char *test_args;
static bool list_tests;
static void add_test_filter_option(void)
{
static struct args_struct_t test_filter_s[] = {
/*
* Fields:
* manual, mandatory, switch,
* option_name, var_name ,type,
* destination, callback,
* description
*/
{ false, false, true, "list", NULL, 'b', (void *)&list_tests, NULL,
"List all suite and test cases" },
{ false, false, false, "test", "suite::test", 's', (void *)&test_args, NULL,
"Name of tests to run. Comma separated list formatted as "
"\'suiteA::test1,suiteA::test2,suiteB::*\'. An * can be used "
"as a wildcard to run all tests within a suite." },
ARG_TABLE_ENDMARKER
};
native_add_command_line_opts(test_filter_s);
}
NATIVE_TASK(add_test_filter_option, PRE_BOOT_1, 10);
/**
* @brief Try to shorten a filename by removing the current directory
*
* This helps to reduce the very long filenames in assertion failures. It
* removes the current directory from the filename and returns the rest.
* This makes assertions a lot more readable, and sometimes they fit on one
* line.
*
* Overrides implementation in ztest_new.c
*
* @param file Filename to check
* @returns Shortened filename, or @file if it could not be shortened
*/
const char *ztest_relative_filename(const char *file)
{
const char *cwd;
char buf[200];
cwd = getcwd(buf, sizeof(buf));
if (cwd && strlen(file) > strlen(cwd) && !strncmp(file, cwd, strlen(cwd))) {
return file + strlen(cwd) + 1; /* move past the trailing '/' */
}
return file;
}
/**
* @brief Helper function to set list_tests
*
* @param value - Sets list_tests to value
*/
void ztest_set_list_test(bool value)
{
list_tests = value;
}
/**
* @brief Helper function to get command line argument for listing tests
*
* @return true
* @return false
*/
bool z_ztest_get_list_test(void)
{
return list_tests;
}
/**
* @brief Helper function to get command line test arguments
*
* @return const char*
*/
const char *ztest_get_test_args(void)
{
return test_args;
}
/**
* @brief Lists registered unit tests in this binary, one per line
*
* @return int Number of tests in binary
*/
int z_ztest_list_tests(void)
{
struct ztest_suite_node *ptr;
struct ztest_unit_test *test = NULL;
int test_count = 0;
static bool list_once = true;
if (list_once) {
for (ptr = _ztest_suite_node_list_start; ptr < _ztest_suite_node_list_end; ++ptr) {
test = NULL;
while ((test = z_ztest_get_next_test(ptr->name, test)) != NULL) {
TC_PRINT("%s::%s\n", test->test_suite_name, test->name);
test_count++;
}
}
list_once = false;
}
return test_count;
}
/**
* Default entry point for running or listing registered unit tests.
*
* @param state The current state of the machine as it relates to the test executable.
*/
void z_ztest_run_all(const void *state)
{
if (z_ztest_get_list_test()) {
z_ztest_list_tests();
} else {
ztest_run_test_suites(state);
}
}
/**
* @brief Checks if the test_args contains the suite/test name.
*
* @param suite_name
* @param test_name
* @return true
* @return false
*/
static bool z_ztest_testargs_contains(const char *suite_name, const char *test_name)
{
bool found = false;
char *test_args_local = strdup(test_args);
char *suite_test_pair;
char *last_suite_test_pair;
char *suite_arg;
char *test_arg;
char *last_arg;
suite_test_pair = strtok_r(test_args_local, ",", &last_suite_test_pair);
while (suite_test_pair && !found) {
suite_arg = strtok_r(suite_test_pair, ":", &last_arg);
test_arg = strtok_r(NULL, ":", &last_arg);
found = !strcmp(suite_arg, suite_name);
if (test_name) {
found &= !strcmp(test_arg, "*") ||
!strcmp(test_arg, test_name);
}
suite_test_pair = strtok_r(NULL, ",", &last_suite_test_pair);
}
free(test_args_local);
return found;
}
/**
* @brief Determines if the test case should run based on test cases listed
* in the command line argument.
*
* Overrides implementation in ztest_new.c
*
* @param suite - name of test suite
* @param test - name of unit test
* @return true
* @return false
*/
bool z_ztest_should_test_run(const char *suite, const char *test)
{
bool run_test = false;
run_test = (test_args == NULL ||
z_ztest_testargs_contains(suite, test));
return run_test;
}
/**
* @brief Determines if the test suite should run based on test cases listed
* in the command line argument.
*
* Overrides implementation in ztest_new.c
*
* @param state The current state of the machine as it relates to the test
* executable.
* @param suite Pointer to ztest_suite_node
* @return true
* @return false
*/
bool z_ztest_should_suite_run(const void *state, struct ztest_suite_node *suite)
{
bool run_suite = true;
if (test_args != NULL && !z_ztest_testargs_contains(suite->name, NULL)) {
run_suite = false;
suite->stats->run_count++;
} else if (suite->predicate != NULL) {
run_suite = suite->predicate(state);
}
return run_suite;
}
ZTEST_DMEM const struct ztest_arch_api ztest_api = {
.run_all = z_ztest_run_all,
.should_suite_run = z_ztest_should_suite_run,
.should_test_run = z_ztest_should_test_run
};