247 lines
5.3 KiB
C
247 lines
5.3 KiB
C
/*
|
|
* Copyright (c) 2017-2018 Oticon A/S
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
#include <zephyr/init.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include "bs_types.h"
|
|
#include "bs_tracing.h"
|
|
#include "bstests.h"
|
|
#include "bs_oswrap.h"
|
|
|
|
/*
|
|
* Result of the testcase execution.
|
|
* Note that the executable will return the maximum of bst_result and
|
|
* {the HW model return code} to the shell and that
|
|
* {the HW model return code} will be 0 unless it fails or it is
|
|
* configured illegally
|
|
*/
|
|
enum bst_result_t bst_result;
|
|
|
|
static struct bst_test_instance *current_test;
|
|
static struct bst_test_list *test_list_top;
|
|
|
|
__attribute__((weak)) bst_test_install_t test_installers[] = { NULL };
|
|
|
|
struct bst_test_list *bst_add_tests(struct bst_test_list *tests,
|
|
const struct bst_test_instance *test_def)
|
|
{
|
|
int idx = 0;
|
|
struct bst_test_list *tail = tests;
|
|
struct bst_test_list *head = tests;
|
|
|
|
if (tail) {
|
|
/* First we 'run to end' */
|
|
while (tail->next) {
|
|
tail = tail->next;
|
|
}
|
|
} else {
|
|
if (test_def[idx].test_id != NULL) {
|
|
head = bs_malloc(sizeof(struct bst_test_list));
|
|
head->next = NULL;
|
|
head->test_instance = (struct bst_test_instance *)
|
|
&test_def[idx++];
|
|
tail = head;
|
|
}
|
|
}
|
|
|
|
while (test_def[idx].test_id != NULL) {
|
|
tail->next = bs_malloc(sizeof(struct bst_test_list));
|
|
tail = tail->next;
|
|
tail->test_instance = (struct bst_test_instance *)
|
|
&test_def[idx++];
|
|
tail->next = NULL;
|
|
}
|
|
|
|
return head;
|
|
}
|
|
|
|
static struct bst_test_instance *bst_test_find(struct bst_test_list *tests,
|
|
char *test_id)
|
|
{
|
|
struct bst_test_list *top = tests;
|
|
|
|
while (top != NULL) {
|
|
if (!strcmp(top->test_instance->test_id, test_id)) {
|
|
/* Match found */
|
|
return top->test_instance;
|
|
}
|
|
top = top->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void bst_install_tests(void)
|
|
{
|
|
int idx = 0;
|
|
|
|
if (test_list_top) {
|
|
/* Tests were already installed */
|
|
return;
|
|
}
|
|
|
|
/* First execute installers until first test was installed */
|
|
while (!test_list_top && test_installers[idx]) {
|
|
test_list_top = test_installers[idx++](test_list_top);
|
|
}
|
|
|
|
/* After that simply add remaining tests to list */
|
|
while (test_installers[idx]) {
|
|
test_installers[idx++](test_list_top);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Print the tests list displayed with the --testslist command
|
|
* line option
|
|
*/
|
|
void bst_print_testslist(void)
|
|
{
|
|
struct bst_test_list *top;
|
|
|
|
/* Install tests */
|
|
bst_install_tests();
|
|
|
|
top = test_list_top;
|
|
while (top) {
|
|
bs_trace_raw(0, "TestID: %-10s\t%s\n",
|
|
top->test_instance->test_id,
|
|
top->test_instance->test_descr);
|
|
top = top->next;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Select the testcase to be run from its id
|
|
*/
|
|
void bst_set_testapp_mode(char *test_id)
|
|
{
|
|
/* Install tests */
|
|
bst_install_tests();
|
|
|
|
/* By default all tests start as in progress */
|
|
bst_result = In_progress;
|
|
|
|
current_test = bst_test_find(test_list_top, test_id);
|
|
if (!current_test) {
|
|
bs_trace_error_line("test id %s doesn't exist\n", test_id);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pass to the testcase the command line arguments it may have
|
|
*
|
|
* This function is called after bst_set_testapp_mode
|
|
* and before *init_f
|
|
*/
|
|
void bst_pass_args(int argc, char **argv)
|
|
{
|
|
if (current_test && current_test->test_args_f) {
|
|
current_test->test_args_f(argc, argv);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Will be called before the CPU is booted
|
|
*/
|
|
void bst_pre_init(void)
|
|
{
|
|
if (current_test && current_test->test_pre_init_f) {
|
|
current_test->test_pre_init_f();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Will be called when the CPU has gone to sleep for the first time
|
|
*/
|
|
void bst_post_init(void)
|
|
{
|
|
if (current_test && current_test->test_post_init_f) {
|
|
current_test->test_post_init_f();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Will be called each time the bstest_ticker timer is triggered
|
|
*/
|
|
void bst_tick(bs_time_t time)
|
|
{
|
|
|
|
if (current_test == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (current_test->test_tick_f) {
|
|
current_test->test_tick_f(time);
|
|
} else if (current_test->test_id) {
|
|
bs_trace_error_line("the test id %s doesn't have a tick handler"
|
|
" (how come did we arrive here?)\n",
|
|
current_test->test_id);
|
|
}
|
|
|
|
}
|
|
|
|
bool bst_irq_sniffer(int irq_number)
|
|
{
|
|
if (current_test && current_test->test_irq_sniffer_f) {
|
|
return current_test->test_irq_sniffer_f(irq_number);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static int bst_fake_device_driver_pre2_init(void)
|
|
{
|
|
if (current_test && current_test->test_fake_ddriver_prekernel_f) {
|
|
current_test->test_fake_ddriver_prekernel_f();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int bst_fake_device_driver_post_init(void)
|
|
{
|
|
if (current_test && current_test->test_fake_ddriver_postkernel_f) {
|
|
current_test->test_fake_ddriver_postkernel_f();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
SYS_INIT(bst_fake_device_driver_pre2_init, PRE_KERNEL_1, 0);
|
|
SYS_INIT(bst_fake_device_driver_post_init, POST_KERNEL, 0);
|
|
|
|
void bst_main(void)
|
|
{
|
|
if (current_test && current_test->test_main_f) {
|
|
current_test->test_main_f();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Will be called when the device is being terminated
|
|
*/
|
|
uint8_t bst_delete(void)
|
|
{
|
|
if (current_test && current_test->test_delete_f) {
|
|
current_test->test_delete_f();
|
|
}
|
|
|
|
while (test_list_top) {
|
|
struct bst_test_list *tmp = test_list_top->next;
|
|
|
|
free(test_list_top);
|
|
test_list_top = tmp;
|
|
}
|
|
|
|
if (bst_result == In_progress) {
|
|
bs_trace_raw_time(2, "TESTCASE NOT PASSED at exit (test return "
|
|
"(%u) indicates it was still in progress)\n", bst_result);
|
|
} else if (bst_result != Passed) {
|
|
bs_trace_raw_time(2, "The TESTCASE FAILED (test return code %u)\n",
|
|
bst_result);
|
|
}
|
|
|
|
return bst_result;
|
|
}
|