175 lines
4.3 KiB
C
175 lines
4.3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2021 Google LLC
|
|
*/
|
|
|
|
#ifndef _TEST_FRAMEWORK_H
|
|
#define _TEST_FRAMEWORK_H
|
|
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
|
|
#ifdef __ANDROID__
|
|
static int test_case_pass;
|
|
static int test_case_fail;
|
|
#define ksft_print_msg printf
|
|
#define ksft_test_result_pass(...) ({test_case_pass++; printf(__VA_ARGS__); })
|
|
#define ksft_test_result_fail(...) ({test_case_fail++; printf(__VA_ARGS__); })
|
|
#define ksft_exit_fail_msg(...) printf(__VA_ARGS__)
|
|
#define ksft_print_header()
|
|
#define ksft_set_plan(cnt)
|
|
#define ksft_get_fail_cnt() test_case_fail
|
|
#define ksft_exit_pass() 0
|
|
#define ksft_exit_fail() 1
|
|
#else
|
|
#include <kselftest.h>
|
|
#endif
|
|
|
|
#define TEST_FAILURE 1
|
|
#define TEST_SUCCESS 0
|
|
|
|
#define ptr_to_u64(p) ((__u64)p)
|
|
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
#define le16_to_cpu(x) (x)
|
|
#define le32_to_cpu(x) (x)
|
|
#define le64_to_cpu(x) (x)
|
|
#else
|
|
#error Big endian not supported!
|
|
#endif
|
|
|
|
struct _test_options {
|
|
int file;
|
|
bool verbose;
|
|
};
|
|
|
|
extern struct _test_options test_options;
|
|
|
|
#define TESTCOND(condition) \
|
|
do { \
|
|
if (!(condition)) { \
|
|
ksft_print_msg("%s failed %d\n", \
|
|
__func__, __LINE__); \
|
|
goto out; \
|
|
} else if (test_options.verbose) \
|
|
ksft_print_msg("%s succeeded %d\n", \
|
|
__func__, __LINE__); \
|
|
} while (false)
|
|
|
|
#define TESTCONDERR(condition) \
|
|
do { \
|
|
if (!(condition)) { \
|
|
ksft_print_msg("%s failed %d\n", \
|
|
__func__, __LINE__); \
|
|
ksft_print_msg("Error %d (\"%s\")\n", \
|
|
errno, strerror(errno)); \
|
|
goto out; \
|
|
} else if (test_options.verbose) \
|
|
ksft_print_msg("%s succeeded %d\n", \
|
|
__func__, __LINE__); \
|
|
} while (false)
|
|
|
|
#define TEST(statement, condition) \
|
|
do { \
|
|
statement; \
|
|
TESTCOND(condition); \
|
|
} while (false)
|
|
|
|
#define TESTERR(statement, condition) \
|
|
do { \
|
|
statement; \
|
|
TESTCONDERR(condition); \
|
|
} while (false)
|
|
|
|
enum _operator {
|
|
_eq,
|
|
_ne,
|
|
_ge,
|
|
};
|
|
|
|
static const char * const _operator_name[] = {
|
|
"==",
|
|
"!=",
|
|
">=",
|
|
};
|
|
|
|
#define _TEST_OPERATOR(name, _type, format_specifier) \
|
|
static inline int _test_operator_##name(const char *func, int line, \
|
|
_type a, _type b, enum _operator o) \
|
|
{ \
|
|
bool pass; \
|
|
switch (o) { \
|
|
case _eq: pass = a == b; break; \
|
|
case _ne: pass = a != b; break; \
|
|
case _ge: pass = a >= b; break; \
|
|
} \
|
|
\
|
|
if (!pass) \
|
|
ksft_print_msg("Failed: %s at line %d, " \
|
|
format_specifier " %s " \
|
|
format_specifier "\n", \
|
|
func, line, a, _operator_name[o], b); \
|
|
else if (test_options.verbose) \
|
|
ksft_print_msg("Passed: %s at line %d, " \
|
|
format_specifier " %s " \
|
|
format_specifier "\n", \
|
|
func, line, a, _operator_name[o], b); \
|
|
\
|
|
return pass ? TEST_SUCCESS : TEST_FAILURE; \
|
|
}
|
|
|
|
_TEST_OPERATOR(i, int, "%d")
|
|
_TEST_OPERATOR(ui, unsigned int, "%u")
|
|
_TEST_OPERATOR(lui, unsigned long, "%lu")
|
|
_TEST_OPERATOR(ss, ssize_t, "%zd")
|
|
_TEST_OPERATOR(vp, void *, "%px")
|
|
_TEST_OPERATOR(cp, char *, "%px")
|
|
|
|
#define _CALL_TO(_type, name, a, b, o) \
|
|
_type:_test_operator_##name(__func__, __LINE__, \
|
|
(_type) (long long) (a), \
|
|
(_type) (long long) (b), o)
|
|
|
|
#define TESTOPERATOR(a, b, o) \
|
|
do { \
|
|
if (_Generic((a), \
|
|
_CALL_TO(int, i, a, b, o), \
|
|
_CALL_TO(unsigned int, ui, a, b, o), \
|
|
_CALL_TO(unsigned long, lui, a, b, o), \
|
|
_CALL_TO(ssize_t, ss, a, b, o), \
|
|
_CALL_TO(void *, vp, a, b, o), \
|
|
_CALL_TO(char *, cp, a, b, o) \
|
|
)) \
|
|
goto out; \
|
|
} while (false)
|
|
|
|
#define TESTEQUAL(a, b) TESTOPERATOR(a, b, _eq)
|
|
#define TESTNE(a, b) TESTOPERATOR(a, b, _ne)
|
|
#define TESTGE(a, b) TESTOPERATOR(a, b, _ge)
|
|
|
|
/* For testing a syscall that returns 0 on success and sets errno otherwise */
|
|
#define TESTSYSCALL(statement) TESTCONDERR((statement) == 0)
|
|
|
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
|
|
|
|
static inline void print_bytes(const void *data, size_t size)
|
|
{
|
|
const char *bytes = data;
|
|
int i;
|
|
|
|
for (i = 0; i < size; ++i) {
|
|
if (i % 0x10 == 0)
|
|
printf("%08x:", i);
|
|
printf("%02x ", (unsigned int) (unsigned char) bytes[i]);
|
|
if (i % 0x10 == 0x0f)
|
|
printf("\n");
|
|
}
|
|
|
|
if (i % 0x10 != 0)
|
|
printf("\n");
|
|
}
|
|
|
|
|
|
|
|
#endif
|