mirror of
https://github.com/physwizz/a155-U-u1.git
synced 2024-11-19 13:27:49 +00:00
337 lines
8.5 KiB
C
337 lines
8.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
#define TMEM_UT_TEST_FMT
|
|
#define PR_FMT_HEADER_MUST_BE_INCLUDED_BEFORE_ALL_HDRS
|
|
#include "private/tmem_pr_fmt.h" PR_FMT_HEADER_MUST_BE_INCLUDED_BEFORE_ALL_HDRS
|
|
|
|
#include <linux/errno.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/init.h>
|
|
#include <linux/io.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/kthread.h>
|
|
#include <linux/module.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/string.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/unistd.h>
|
|
#include <linux/types.h>
|
|
#include <linux/mutex.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/time.h>
|
|
#include <linux/slab.h>
|
|
|
|
#include "private/tmem_error.h"
|
|
#include "private/tmem_device.h"
|
|
#include "private/tmem_utils.h"
|
|
#include "private/ut_cmd.h"
|
|
#include "tests/ut_api.h"
|
|
|
|
#define KERN_UT_RUN_ALL_STOP_ONCE_FAILED (1)
|
|
|
|
struct ut_test_case_statistics {
|
|
enum UT_RET_STATE ret;
|
|
u32 pass_cnt;
|
|
u32 fail_cnt;
|
|
u32 spend_sec;
|
|
u32 spend_msec;
|
|
};
|
|
|
|
struct ut_test_case {
|
|
u64 cmd;
|
|
u64 param1;
|
|
u64 param2;
|
|
u64 param3;
|
|
struct ut_test_case_statistics statistics;
|
|
char *test_description;
|
|
enum UT_RET_STATE (*test_case_cb)(struct ut_params *params,
|
|
char *test_desc);
|
|
};
|
|
|
|
struct UT_TEST_CASE {
|
|
struct ut_test_case item;
|
|
struct list_head list;
|
|
};
|
|
|
|
static u32 ut_case_pass_count;
|
|
static u32 ut_case_fail_count;
|
|
static bool ut_case_halt;
|
|
static u64 ut_case_command;
|
|
static struct timespec64 ut_case_start_time;
|
|
static struct timespec64 ut_case_end_time;
|
|
void ut_set_halt(void)
|
|
{
|
|
ut_case_halt = true;
|
|
}
|
|
|
|
bool ut_is_halt(void)
|
|
{
|
|
return ut_case_halt;
|
|
}
|
|
|
|
void ut_increase_pass_cnt(void)
|
|
{
|
|
ut_case_pass_count++;
|
|
}
|
|
|
|
void ut_increase_fail_cnt(void)
|
|
{
|
|
ut_case_fail_count++;
|
|
}
|
|
|
|
static u32 ut_get_pass_cnt(void)
|
|
{
|
|
return ut_case_pass_count;
|
|
}
|
|
|
|
static u32 ut_get_fail_cnt(void)
|
|
{
|
|
return ut_case_fail_count;
|
|
}
|
|
|
|
static u32 ut_get_spend_sec(void)
|
|
{
|
|
struct timespec64 *start_time = &ut_case_start_time;
|
|
struct timespec64 *end_time = &ut_case_end_time;
|
|
|
|
return GET_TIME_DIFF_SEC_P(start_time, end_time);
|
|
}
|
|
|
|
static u32 ut_get_spend_msec(void)
|
|
{
|
|
struct timespec64 *start_time = &ut_case_start_time;
|
|
struct timespec64 *end_time = &ut_case_end_time;
|
|
|
|
return GET_TIME_DIFF_NSEC_P(start_time, end_time);
|
|
}
|
|
|
|
static void tmem_do_gettimeofday(struct timespec64 *tv)
|
|
{
|
|
struct timespec64 now;
|
|
|
|
ktime_get_real_ts64(&now);
|
|
tv->tv_sec = now.tv_sec;
|
|
tv->tv_nsec = now.tv_nsec;
|
|
}
|
|
|
|
static void ut_status_reset(u64 ut_cmd)
|
|
{
|
|
ut_case_pass_count = 0;
|
|
ut_case_fail_count = 0;
|
|
ut_case_halt = false;
|
|
ut_case_command = ut_cmd;
|
|
|
|
tmem_do_gettimeofday(&ut_case_start_time);
|
|
}
|
|
|
|
static void ut_status_dump(void)
|
|
{
|
|
tmem_do_gettimeofday(&ut_case_end_time);
|
|
|
|
pr_info("[UT_CASE]================================================\n");
|
|
pr_info("[UT_CASE]Executing UT command: %lld\n", ut_case_command);
|
|
pr_info("[UT_CASE] TOTAL TEST ITEMS: %d\n",
|
|
ut_case_pass_count + ut_case_fail_count);
|
|
pr_info("[UT_CASE] PASS TEST ITEMS: %d\n", ut_case_pass_count);
|
|
pr_info("[UT_CASE] FAIL TEST ITEMS: %d\n", ut_case_fail_count);
|
|
if (ut_case_fail_count == 0)
|
|
pr_info("[UT_CASE]all UT test items are passed!!!\n");
|
|
else
|
|
pr_info("[UT_CASE]some items are failed, please check!!!\n");
|
|
pr_info("[UT_CASE] Spend time: %d.%d seconds\n", ut_get_spend_sec(),
|
|
ut_get_spend_msec());
|
|
pr_info("[UT_CASE]================================================\n");
|
|
}
|
|
|
|
static struct UT_TEST_CASE g_test_case_list;
|
|
static void reset_all_cases_status(void)
|
|
{
|
|
struct UT_TEST_CASE *t_case, *tmp;
|
|
struct ut_test_case_statistics *t_statistics;
|
|
|
|
/* clang-format off */
|
|
list_for_each_entry_safe(t_case, tmp, &g_test_case_list.list, list) {
|
|
/* clang-format on */
|
|
t_statistics = &t_case->item.statistics;
|
|
t_statistics->ret = UT_STATE_UNSUPPORTED_CMD;
|
|
t_statistics->pass_cnt = 0;
|
|
t_statistics->fail_cnt = 0;
|
|
t_statistics->spend_sec = 0;
|
|
t_statistics->spend_msec = 0;
|
|
}
|
|
}
|
|
|
|
static int run_one_test_case(struct UT_TEST_CASE *t_case, u64 cmd, u64 param1,
|
|
u64 param2, u64 param3)
|
|
{
|
|
enum UT_RET_STATE case_ret;
|
|
struct ut_params params;
|
|
struct ut_test_case_statistics *statistics = &t_case->item.statistics;
|
|
|
|
pr_info("[UT_SUITE] UT case:%lld .....\n", cmd);
|
|
|
|
ut_status_reset(cmd);
|
|
|
|
params.cmd = cmd;
|
|
params.param1 = param1;
|
|
params.param2 = param2;
|
|
params.param3 = param3;
|
|
case_ret = t_case->item.test_case_cb(¶ms,
|
|
t_case->item.test_description);
|
|
|
|
if (case_ret == UT_STATE_PASS)
|
|
pr_debug(" UT case:%lld passed!\n", cmd);
|
|
else if (case_ret == UT_STATE_FAIL)
|
|
pr_debug(" UT case:%lld failed!\n", cmd);
|
|
else
|
|
pr_debug(" UT case:%lld unsupported!\n", cmd);
|
|
|
|
ut_status_dump();
|
|
|
|
statistics->pass_cnt = ut_get_pass_cnt();
|
|
statistics->fail_cnt = ut_get_fail_cnt();
|
|
statistics->spend_sec = ut_get_spend_sec();
|
|
statistics->spend_msec = ut_get_spend_msec();
|
|
statistics->ret = case_ret;
|
|
return case_ret;
|
|
}
|
|
|
|
static void dump_run_cases_results(u64 cmd, bool run_all_cases)
|
|
{
|
|
struct UT_TEST_CASE *t_case, *tmp;
|
|
u32 all_pass_cnt = 0;
|
|
u32 all_fail_cnt = 0;
|
|
u32 all_spend_sec = 0;
|
|
u32 all_spend_msec = 0;
|
|
struct ut_test_case_statistics *t_statistics;
|
|
|
|
pr_info("[UT_SUITE]Test Results: RUN %s\n",
|
|
(run_all_cases ? "ALL" : "ONE"));
|
|
pr_info("[UT_SUITE] CASE PASS FAIL TIME\n");
|
|
|
|
/* clang-format off */
|
|
list_for_each_entry_safe(t_case, tmp, &g_test_case_list.list, list) {
|
|
/* clang-format on */
|
|
t_statistics = &t_case->item.statistics;
|
|
if (t_statistics->ret != UT_STATE_UNSUPPORTED_CMD) {
|
|
if (cmd == t_case->item.cmd || run_all_cases)
|
|
pr_info("[UT_SUITE]%5lld %-9d %-7d %05d.%06d sec\n",
|
|
t_case->item.cmd,
|
|
t_statistics->pass_cnt,
|
|
t_statistics->fail_cnt,
|
|
t_statistics->spend_sec,
|
|
t_statistics->spend_msec);
|
|
all_pass_cnt += t_statistics->pass_cnt;
|
|
all_fail_cnt += t_statistics->fail_cnt;
|
|
all_spend_sec += t_statistics->spend_sec;
|
|
all_spend_msec += t_statistics->spend_msec;
|
|
}
|
|
}
|
|
|
|
if (run_all_cases) {
|
|
all_spend_sec += (all_spend_msec / 1000000);
|
|
all_spend_msec = (all_spend_msec % 1000000);
|
|
pr_info("[UT_SUITE] Summary:\n");
|
|
pr_info("[UT_SUITE] ALL %-9d %-7d %05d.%06d sec\n",
|
|
all_pass_cnt, all_fail_cnt, all_spend_sec,
|
|
all_spend_msec);
|
|
}
|
|
}
|
|
|
|
int invoke_ut_test_case(u64 cmd)
|
|
{
|
|
struct UT_TEST_CASE *t_case, *tmp;
|
|
enum UT_RET_STATE case_ret = UT_STATE_UNSUPPORTED_CMD;
|
|
bool run_all_cases = (cmd == TMEM_RUN_ALL_SUITES);
|
|
|
|
reset_all_cases_status();
|
|
|
|
/* clang-format off */
|
|
list_for_each_entry_safe(t_case, tmp, &g_test_case_list.list, list) {
|
|
/* clang-format on */
|
|
if (run_all_cases) {
|
|
pr_info("[UT_SUITE]Running UT Suites: %s\n",
|
|
t_case->item.test_description);
|
|
case_ret = run_one_test_case(
|
|
t_case, t_case->item.cmd, t_case->item.param1,
|
|
t_case->item.param2, t_case->item.param3);
|
|
if ((case_ret == UT_STATE_FAIL)
|
|
&& KERN_UT_RUN_ALL_STOP_ONCE_FAILED) {
|
|
dump_run_cases_results(cmd, run_all_cases);
|
|
return TMEM_GENERAL_ERROR;
|
|
}
|
|
} else if (t_case->item.cmd == cmd) {
|
|
pr_info("[UT_SUITE]Running UT Suites: %s\n",
|
|
t_case->item.test_description);
|
|
case_ret = run_one_test_case(
|
|
t_case, t_case->item.cmd, t_case->item.param1,
|
|
t_case->item.param2, t_case->item.param3);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (case_ret == UT_STATE_UNSUPPORTED_CMD) {
|
|
pr_info("[UT_SUITE]No UT Suite is Founded!\n");
|
|
pr_info("[UT_SUITE]UT case:%lld is unsupported!\n", cmd);
|
|
return TMEM_OPERATION_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
dump_run_cases_results(cmd, run_all_cases);
|
|
return TMEM_OK;
|
|
}
|
|
|
|
void register_ut_test_case(char *test_description, u64 cmd, u64 param1,
|
|
u64 param2, u64 param3,
|
|
int (*tc)(struct ut_params *params, char *test_desc))
|
|
{
|
|
struct UT_TEST_CASE *t_case;
|
|
|
|
t_case = kmalloc(sizeof(struct UT_TEST_CASE), GFP_KERNEL);
|
|
if (INVALID(t_case)) {
|
|
pr_err("malloc test case '%s' failed!\n", test_description);
|
|
return;
|
|
}
|
|
memset(t_case, 0x0, sizeof(struct UT_TEST_CASE));
|
|
|
|
t_case->item.cmd = cmd;
|
|
t_case->item.param1 = param1;
|
|
t_case->item.param2 = param2;
|
|
t_case->item.param3 = param3;
|
|
t_case->item.test_case_cb = tc;
|
|
t_case->item.test_description = test_description;
|
|
list_add_tail(&(t_case->list), &g_test_case_list.list);
|
|
}
|
|
|
|
int invoke_ut_cases(u64 cmd, u64 param1, u64 param2, u64 param3)
|
|
{
|
|
UNUSED(param1);
|
|
UNUSED(param2);
|
|
UNUSED(param3);
|
|
|
|
pr_info("%s:%d cmd=%lld\n", __func__, __LINE__, cmd);
|
|
return invoke_ut_test_case(cmd);
|
|
}
|
|
|
|
int tmem_ut_server_init(void)
|
|
{
|
|
pr_info("%s:%d\n", __func__, __LINE__);
|
|
|
|
INIT_LIST_HEAD(&g_test_case_list.list);
|
|
return TMEM_OK;
|
|
}
|
|
|
|
void tmem_ut_server_exit(void)
|
|
{
|
|
struct UT_TEST_CASE *t_case, *tmp;
|
|
|
|
/* clang-format off */
|
|
list_for_each_entry_safe(t_case, tmp, &g_test_case_list.list, list) {
|
|
/* clang-format on */
|
|
list_del(&t_case->list);
|
|
kfree(t_case);
|
|
}
|
|
}
|