fix(test): Improve and fix the unit self-test.
This commit is contained in:
@@ -29,8 +29,8 @@ extern "C" {
|
||||
#if defined(MR_USE_SPRINTF_STD)
|
||||
#define mr_vsnprintf(_b, _s, _f, _a) vsnprintf(_b, _s, _f, _a)
|
||||
#define mr_vsprintf(_b, _f, _a) vsprintf(_b, _f, _a)
|
||||
#define mr_snprintf(_b, _s, _f, ...) snprintf(_b, _s, _f, __VA_ARGS__)
|
||||
#define mr_sprintf(_b, _f, ...) sprintf(_b, _f, __VA_ARGS__)
|
||||
#define mr_snprintf(_b, _s, _f, ...) snprintf(_b, _s, _f, ##__VA_ARGS__)
|
||||
#define mr_sprintf(_b, _f, ...) sprintf(_b, _f, ##__VA_ARGS__)
|
||||
#else
|
||||
/**
|
||||
* @brief This function prints a formatted string to a buffer.
|
||||
|
||||
@@ -37,6 +37,7 @@ extern "C" {
|
||||
#define mr_strcpy(_d, _s) strcpy(_d, _s)
|
||||
#define mr_strerror(_e) strerror(_e)
|
||||
#define mr_strlen(_s) strlen(_s)
|
||||
#define mr_strnlen(_s, _sz) strnlen(_s, _sz)
|
||||
#define mr_strncmp(_s1, _s2, _sz) strncmp(_s1, _s2, _sz)
|
||||
#define mr_strncpy(_d, _s, _sz) strncpy(_d, _s, _sz)
|
||||
#define mr_strchr(_s, _c) strchr(_s, _c)
|
||||
|
||||
@@ -105,29 +105,6 @@ MR_INLINE void mr_list_replace(mr_list_t *new, mr_list_t *old) {
|
||||
old->next = old->prev = old;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function swaps two elements in the list.
|
||||
*
|
||||
* @param entry1 The first element.
|
||||
* @param entry2 The second element.
|
||||
*/
|
||||
MR_INLINE void mr_list_swap(mr_list_t *entry1, mr_list_t *entry2) {
|
||||
mr_list_t *tmp;
|
||||
|
||||
/* Remove from the list */
|
||||
tmp = entry2->prev;
|
||||
mr_list_del(entry2);
|
||||
|
||||
/* Replace in the list */
|
||||
mr_list_replace(entry1, entry2);
|
||||
if (tmp == entry1) {
|
||||
tmp = entry2;
|
||||
}
|
||||
|
||||
/* Add to the list */
|
||||
mr_list_add(tmp, entry1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function moves an element to the head of the list.
|
||||
*
|
||||
|
||||
@@ -31,28 +31,39 @@ extern mr_uint32_t __mr_test_status;
|
||||
/* Test pass magic number definition */
|
||||
#define __MR_TEST_MAGIC_PASS (0x70617373U)
|
||||
|
||||
/**
|
||||
* @brief This macro function checks if the condition is true.
|
||||
*
|
||||
* @param _a The first operand.
|
||||
* @param _cond The condition.
|
||||
* @param _b The second operand.
|
||||
* @param _type The operand type.
|
||||
* @param _fmt The format string for the operand.
|
||||
*/
|
||||
/* Test printf macro definition */
|
||||
#define __MR_TEST_PRINTF(_desc, _a_str, _a, _b_str, _b, _fmt) \
|
||||
do { \
|
||||
mr_printf("%s:%d\n", __FILE__, __LINE__); \
|
||||
mr_printf("Expectation failed: %s\n", _desc); \
|
||||
mr_printf(" %s = "_fmt \
|
||||
"\n", \
|
||||
(_a_str), (_a)); \
|
||||
mr_printf(" %s = "_fmt \
|
||||
"\n", \
|
||||
(_b_str), (_b)); \
|
||||
} while (0)
|
||||
|
||||
/* Test check macro definition */
|
||||
#define __MR_TEST_CHECK(_a, _cond, _b, _type, _fmt) \
|
||||
do { \
|
||||
_type __a = (_type)(_a); \
|
||||
_type __b = (_type)(_b); \
|
||||
if (!(__a _cond __b)) { \
|
||||
mr_printf("%s:%d: Test Failure\n", __FILE__, __LINE__); \
|
||||
mr_printf("Expectation failed: %s %s %s\n", #_a, #_cond, #_b); \
|
||||
mr_printf(" %s = "_fmt \
|
||||
"\n", \
|
||||
#_a, __a); \
|
||||
mr_printf(" %s = "_fmt \
|
||||
"\n", \
|
||||
#_b, __b); \
|
||||
__MR_TEST_PRINTF(#_a " " #_cond " " #_b, #_a, __a, #_b, __b, \
|
||||
_fmt); \
|
||||
__mr_test_status = ~__MR_TEST_MAGIC_PASS; \
|
||||
} \
|
||||
} while (0)
|
||||
#define __MR_TEST_CHECK_NEAR(_a, _b, _e, _type, _fmt) \
|
||||
do { \
|
||||
_type __a = (_type)(_a); \
|
||||
_type __b = (_type)(_b); \
|
||||
_type __e = (_type)(_e); \
|
||||
_type __c = (__a > __b) ? (__a - __b) : (__b - __a); \
|
||||
if (!(__c <= __e)) { \
|
||||
__MR_TEST_PRINTF("| " #_a " - " #_b " | <= " #_e, #_a, __a, #_b, \
|
||||
__b, _fmt); \
|
||||
__mr_test_status = ~__MR_TEST_MAGIC_PASS; \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -70,15 +81,34 @@ extern mr_uint32_t __mr_test_status;
|
||||
__MR_TEST_CHECK(_a, >, _b, _type, _fmt)
|
||||
#define __MR_TEST_GE(_a, _b, _type, _fmt) \
|
||||
__MR_TEST_CHECK(_a, >=, _b, _type, _fmt)
|
||||
#define __MR_TEST_NEAR(_a, _b, _e, _type, _fmt) \
|
||||
__MR_TEST_CHECK_NEAR(_a, _b, _e, _type, _fmt)
|
||||
|
||||
/* Test condition macros definition */
|
||||
#define __MR_TEST_COND_INT(_a, _cond, _b) \
|
||||
__MR_TEST_##_cond(_a, _b, mr_int64_t, "%lld")
|
||||
#define __MR_TEST_COND_UINT(_a, _cond, _b) \
|
||||
__MR_TEST_##_cond(_a, _b, mr_uint64_t, "%llu")
|
||||
#define __MR_TEST_COND_PTR(_a, _cond, _b) \
|
||||
__MR_TEST_##_cond(_a, _b, mr_ptr_t, "%p")
|
||||
#define __MR_TEST_COND_FLOAT(_a, _cond, _b) \
|
||||
__MR_TEST_##_cond(_a, _b, mr_f32_t, "%f")
|
||||
#define __MR_TEST_COND_DOUBLE(_a, _cond, _b) \
|
||||
__MR_TEST_##_cond(_a, _b, mr_f64_t, "%lf")
|
||||
#define __MR_TEST_COND_NEAR(_a, _b, _e) \
|
||||
__MR_TEST_NEAR(_a, _b, _e, mr_f64_t, "%lf")
|
||||
|
||||
/* Test expect and assert macros definition */
|
||||
#define __MR_TEST_EXPECT(_check) _check
|
||||
#define __MR_TEST_ASSERT(_check) \
|
||||
do { \
|
||||
mr_uint32_t __s = __mr_test_status; \
|
||||
__mr_test_status = __MR_TEST_MAGIC_PASS; \
|
||||
_check; \
|
||||
if (__mr_test_status == (~__MR_TEST_MAGIC_PASS)) { \
|
||||
return; \
|
||||
} \
|
||||
__mr_test_status = __s; \
|
||||
} while (0)
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
|
||||
|
||||
@@ -26,135 +26,141 @@ extern "C" {
|
||||
#if defined(MR_USE_TEST)
|
||||
/* Test expect and assert equality macros definition */
|
||||
#define MR_TEST_EXPECT_EQ_INT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_EQ(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_INT(_a, EQ, _b))
|
||||
#define MR_TEST_EXPECT_EQ_UINT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_EQ(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_UINT(_a, EQ, _b))
|
||||
#define MR_TEST_EXPECT_EQ_PTR(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_EQ(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_PTR(_a, EQ, _b))
|
||||
#define MR_TEST_EXPECT_EQ_FLOAT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_EQ(_a, _b, float, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_NEAR(_a, _b, 1e-6))
|
||||
#define MR_TEST_EXPECT_EQ_DOUBLE(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_EQ(_a, _b, double, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_NEAR(_a, _b, 1e-8))
|
||||
#define MR_TEST_ASSERT_EQ_INT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_EQ(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_INT(_a, EQ, _b))
|
||||
#define MR_TEST_ASSERT_EQ_UINT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_EQ(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_UINT(_a, EQ, _b))
|
||||
#define MR_TEST_ASSERT_EQ_PTR(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_EQ(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_PTR(_a, EQ, _b))
|
||||
#define MR_TEST_ASSERT_EQ_FLOAT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_EQ(_a, _b, float, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_NEAR(_a, _b, 1e-6))
|
||||
#define MR_TEST_ASSERT_EQ_DOUBLE(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_EQ(_a, _b, double, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_NEAR(_a, _b, 1e-8))
|
||||
|
||||
/* Test expect and assert inequality macros definition */
|
||||
#define MR_TEST_EXPECT_NE_INT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_NE(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_INT(_a, NE, _b))
|
||||
#define MR_TEST_EXPECT_NE_UINT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_NE(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_UINT(_a, NE, _b))
|
||||
#define MR_TEST_EXPECT_NE_PTR(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_NE(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_PTR(_a, NE, _b))
|
||||
#define MR_TEST_EXPECT_NE_FLOAT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_NE(_a, _b, float, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_FLOAT(_a, NE, _b))
|
||||
#define MR_TEST_EXPECT_NE_DOUBLE(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_NE(_a, _b, double, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_DOUBLE(_a, NE, _b))
|
||||
#define MR_TEST_ASSERT_NE_INT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_NE(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_INT(_a, NE, _b))
|
||||
#define MR_TEST_ASSERT_NE_UINT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_NE(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_UINT(_a, NE, _b))
|
||||
#define MR_TEST_ASSERT_NE_PTR(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_NE(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_PTR(_a, NE, _b))
|
||||
#define MR_TEST_ASSERT_NE_FLOAT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_NE(_a, _b, float, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_FLOAT(_a, NE, _b))
|
||||
#define MR_TEST_ASSERT_NE_DOUBLE(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_NE(_a, _b, double, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_DOUBLE(_a, NE, _b))
|
||||
|
||||
/* Test expect and assert less than macros definition */
|
||||
#define MR_TEST_EXPECT_LT_INT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_LT(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_INT(_a, LT, _b))
|
||||
#define MR_TEST_EXPECT_LT_UINT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_LT(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_UINT(_a, LT, _b))
|
||||
#define MR_TEST_EXPECT_LT_PTR(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_LT(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_PTR(_a, LT, _b))
|
||||
#define MR_TEST_EXPECT_LT_FLOAT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_LT(_a, _b, float, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_FLOAT(_a, LT, _b))
|
||||
#define MR_TEST_EXPECT_LT_DOUBLE(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_LT(_a, _b, double, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_DOUBLE(_a, LT, _b))
|
||||
#define MR_TEST_ASSERT_LT_INT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_LT(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_INT(_a, LT, _b))
|
||||
#define MR_TEST_ASSERT_LT_UINT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_LT(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_UINT(_a, LT, _b))
|
||||
#define MR_TEST_ASSERT_LT_PTR(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_LT(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_PTR(_a, LT, _b))
|
||||
#define MR_TEST_ASSERT_LT_FLOAT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_LT(_a, _b, float, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_FLOAT(_a, LT, _b))
|
||||
#define MR_TEST_ASSERT_LT_DOUBLE(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_LT(_a, _b, double, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_DOUBLE(_a, LT, _b))
|
||||
|
||||
/* Test expect and assert less than or equal macros definition */
|
||||
#define MR_TEST_EXPECT_LE_INT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_LE(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_INT(_a, LE, _b))
|
||||
#define MR_TEST_EXPECT_LE_UINT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_LE(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_UINT(_a, LE, _b))
|
||||
#define MR_TEST_EXPECT_LE_PTR(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_LE(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_PTR(_a, LE, _b))
|
||||
#define MR_TEST_EXPECT_LE_FLOAT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_LE(_a, _b, float, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_FLOAT(_a, LE, _b))
|
||||
#define MR_TEST_EXPECT_LE_DOUBLE(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_LE(_a, _b, double, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_DOUBLE(_a, LE, _b))
|
||||
#define MR_TEST_ASSERT_LE_INT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_LE(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_INT(_a, LE, _b))
|
||||
#define MR_TEST_ASSERT_LE_UINT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_LE(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_UINT(_a, LE, _b))
|
||||
#define MR_TEST_ASSERT_LE_PTR(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_LE(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_PTR(_a, LE, _b))
|
||||
#define MR_TEST_ASSERT_LE_FLOAT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_LE(_a, _b, float, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_FLOAT(_a, LE, _b))
|
||||
#define MR_TEST_ASSERT_LE_DOUBLE(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_LE(_a, _b, double, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_DOUBLE(_a, LE, _b))
|
||||
|
||||
/* Test expect and assert greater than macros definition */
|
||||
#define MR_TEST_EXPECT_GT_INT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_GT(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_INT(_a, GT, _b))
|
||||
#define MR_TEST_EXPECT_GT_UINT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_GT(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_UINT(_a, GT, _b))
|
||||
#define MR_TEST_EXPECT_GT_PTR(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_GT(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_PTR(_a, GT, _b))
|
||||
#define MR_TEST_EXPECT_GT_FLOAT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_GT(_a, _b, float, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_FLOAT(_a, GT, _b))
|
||||
#define MR_TEST_EXPECT_GT_DOUBLE(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_GT(_a, _b, double, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_DOUBLE(_a, GT, _b))
|
||||
#define MR_TEST_ASSERT_GT_INT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_GT(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_INT(_a, GT, _b))
|
||||
#define MR_TEST_ASSERT_GT_UINT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_GT(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_UINT(_a, GT, _b))
|
||||
#define MR_TEST_ASSERT_GT_PTR(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_GT(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_PTR(_a, GT, _b))
|
||||
#define MR_TEST_ASSERT_GT_FLOAT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_GT(_a, _b, float, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_FLOAT(_a, GT, _b))
|
||||
#define MR_TEST_ASSERT_GT_DOUBLE(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_GT(_a, _b, double, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_DOUBLE(_a, GT, _b))
|
||||
|
||||
/* Test expect and assert greater than or equal macros definition */
|
||||
#define MR_TEST_EXPECT_GE_INT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_GE(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_INT(_a, GE, _b))
|
||||
#define MR_TEST_EXPECT_GE_UINT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_GE(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_UINT(_a, GE, _b))
|
||||
#define MR_TEST_EXPECT_GE_PTR(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_GE(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_PTR(_a, GE, _b))
|
||||
#define MR_TEST_EXPECT_GE_FLOAT(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_GE(_a, _b, float, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_FLOAT(_a, GE, _b))
|
||||
#define MR_TEST_EXPECT_GE_DOUBLE(_a, _b) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_GE(_a, _b, double, "%f"))
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_DOUBLE(_a, GE, _b))
|
||||
#define MR_TEST_ASSERT_GE_INT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_GE(_a, _b, mr_int64_t, "%lld"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_INT(_a, GE, _b))
|
||||
#define MR_TEST_ASSERT_GE_UINT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_GE(_a, _b, mr_uint64_t, "%llu"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_UINT(_a, GE, _b))
|
||||
#define MR_TEST_ASSERT_GE_PTR(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_GE(_a, _b, mr_ptr_t, "%p"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_PTR(_a, GE, _b))
|
||||
#define MR_TEST_ASSERT_GE_FLOAT(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_GE(_a, _b, float, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_FLOAT(_a, GE, _b))
|
||||
#define MR_TEST_ASSERT_GE_DOUBLE(_a, _b) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_GE(_a, _b, double, "%f"))
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_DOUBLE(_a, GE, _b))
|
||||
|
||||
/* Test expect and assert near macros definition */
|
||||
#define MR_TEST_EXPECT_NEAR(_a, _b, _e) \
|
||||
__MR_TEST_EXPECT(__MR_TEST_COND_NEAR(_a, _b, _e))
|
||||
#define MR_TEST_ASSERT_NEAR(_a, _b, _e) \
|
||||
__MR_TEST_ASSERT(__MR_TEST_COND_NEAR(_a, _b, _e))
|
||||
|
||||
/* Testcase entry type */
|
||||
typedef void(mr_testcase_entry)(void);
|
||||
@@ -183,9 +189,26 @@ typedef struct MR_ALIGN(MR_ALIGN_SIZE) mr_testcase {
|
||||
__MR_TEST_EXPORT(_suite, _name, _entry, "1")
|
||||
|
||||
/**
|
||||
* @brief This function runs all testcases.
|
||||
* @brief This function runs a testcase.
|
||||
*
|
||||
* @param suite The testcase suite name.
|
||||
* @param name The testcase name.
|
||||
*/
|
||||
int mr_test_all_run(void);
|
||||
void mr_testcase_run(const char *suite, const char *name);
|
||||
|
||||
/**
|
||||
* @brief This function runs a testsuite.
|
||||
*
|
||||
* @param suite The testsuite name.
|
||||
*/
|
||||
void mr_testsuite_run(const char *suite);
|
||||
|
||||
/**
|
||||
* @brief This function runs all testcases.
|
||||
*
|
||||
* @return MR_TRUE on success, MR_FALSE on failure.
|
||||
*/
|
||||
mr_bool_t mr_test_run(void);
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -90,6 +90,11 @@ void *mr_malloc(mr_size_t size) {
|
||||
|
||||
/* Align the size */
|
||||
size = HEAP_ALIGN(size, MR_ALIGN_SIZE);
|
||||
if (size == 0) {
|
||||
/* Overflow */
|
||||
mem = MR_NULL;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
/* Search for and take blocks that match the criteria */
|
||||
for (blk = prev->next; blk->size < size; blk = blk->next) {
|
||||
|
||||
@@ -211,7 +211,7 @@ int mr_vsnprintf(char *buf, mr_size_t size, const char *fmt, mr_va_list args) {
|
||||
char eff;
|
||||
|
||||
/* Check parameter */
|
||||
if ((!fmt) || (fmt[0] == '\0')) {
|
||||
if (!fmt) {
|
||||
return 0;
|
||||
}
|
||||
if (!buf) {
|
||||
@@ -478,7 +478,7 @@ _default:
|
||||
|
||||
int mr_vsprintf(char *buf, const char *fmt, mr_va_list args) {
|
||||
/* Format string no limit */
|
||||
return mr_vsnprintf(buf, (mr_size_t)-1, fmt, args);
|
||||
return mr_vsnprintf(buf, MR_SIZE_MAX - (mr_size_t)buf, fmt, args);
|
||||
}
|
||||
|
||||
int mr_snprintf(char *buf, mr_size_t size, const char *fmt, ...) {
|
||||
|
||||
@@ -16,7 +16,7 @@ int mr_sscanf(const char *buf, const char *fmt, ...) {
|
||||
int ret;
|
||||
|
||||
/* Check parameter */
|
||||
if ((!buf) || (!fmt) || (fmt[0] == '\0')) {
|
||||
if ((!buf) || (!fmt)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <libc/mr_string.h>
|
||||
#if defined(MR_USE_STRING)
|
||||
#include <libc/mr_errno.h>
|
||||
#endif /* defined(MR_USE_STRING) */
|
||||
|
||||
/* DeBruijn ffs32 */
|
||||
const int __mr_ffs_debruijn32[32] = {
|
||||
@@ -24,6 +25,7 @@ const int __mr_ffs_debruijn64[64] = {
|
||||
55, 27, 41, 16, 35, 21, 32, 11, 26, 15, 20, 10, 14, 9, 8, 7,
|
||||
};
|
||||
|
||||
#if defined(MR_USE_STRING)
|
||||
void *mr_memccpy(void *dst, const void *src, int c, mr_size_t size) {
|
||||
const char *s;
|
||||
char *d;
|
||||
|
||||
188
test/kernel/list.c
Normal file
188
test/kernel/list.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* @copyright (c) 2024-2025, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <test/mr_test.h>
|
||||
#if defined(MR_USE_TEST)
|
||||
#include <mr-X/mr_list.h>
|
||||
|
||||
typedef struct test_node {
|
||||
mr_list_t link;
|
||||
int id;
|
||||
} test_node_t;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: static init */
|
||||
static void test_list_static_init(void) {
|
||||
static mr_list_t head = MR_LIST_INIT(&head);
|
||||
|
||||
MR_TEST_ASSERT_EQ_INT(mr_list_is_empty(&head), MR_TRUE);
|
||||
MR_TEST_ASSERT_EQ_PTR(head.next, &head);
|
||||
MR_TEST_ASSERT_EQ_PTR(head.prev, &head);
|
||||
}
|
||||
MR_TEST_EXPORT(list, static_init, test_list_static_init);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: init/empty */
|
||||
static void test_list_init_empty(void) {
|
||||
mr_list_t head;
|
||||
|
||||
mr_list_init(&head);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_list_is_empty(&head), MR_TRUE);
|
||||
}
|
||||
MR_TEST_EXPORT(list, init_empty, test_list_init_empty);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: add elements */
|
||||
static void test_list_add(void) {
|
||||
test_node_t n1, n2, n3;
|
||||
int ids[3], idx;
|
||||
test_node_t *n;
|
||||
mr_list_t *pos;
|
||||
mr_list_t head;
|
||||
|
||||
mr_list_init(&head);
|
||||
n1.id = 1;
|
||||
n2.id = 2;
|
||||
n3.id = 3;
|
||||
mr_list_add(&head, &n1.link);
|
||||
mr_list_add(&head, &n2.link);
|
||||
mr_list_add(&head, &n3.link);
|
||||
|
||||
idx = 0;
|
||||
MR_LIST_FOR_EACH(pos, &head) {
|
||||
n = MR_LIST_ENTRY(pos, test_node_t, link);
|
||||
ids[idx++] = n->id;
|
||||
}
|
||||
MR_TEST_ASSERT_EQ_INT(ids[0], 1);
|
||||
MR_TEST_ASSERT_EQ_INT(ids[1], 2);
|
||||
MR_TEST_ASSERT_EQ_INT(ids[2], 3);
|
||||
}
|
||||
MR_TEST_EXPORT(list, add, test_list_add);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: insert to head */
|
||||
static void test_list_insert(void) {
|
||||
test_node_t n1, n2;
|
||||
test_node_t *n;
|
||||
mr_list_t head;
|
||||
mr_list_t *pos;
|
||||
|
||||
mr_list_init(&head);
|
||||
n1.id = 1;
|
||||
n2.id = 2;
|
||||
mr_list_insert(&head, &n1.link);
|
||||
mr_list_insert(&head, &n2.link);
|
||||
|
||||
pos = head.next;
|
||||
n = MR_LIST_ENTRY(pos, test_node_t, link);
|
||||
MR_TEST_ASSERT_EQ_INT(n->id, 2);
|
||||
pos = pos->next;
|
||||
n = MR_LIST_ENTRY(pos, test_node_t, link);
|
||||
MR_TEST_ASSERT_EQ_INT(n->id, 1);
|
||||
}
|
||||
MR_TEST_EXPORT(list, insert, test_list_insert);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: remove element */
|
||||
static void test_list_del(void) {
|
||||
test_node_t n1, n2;
|
||||
test_node_t *n;
|
||||
mr_list_t head;
|
||||
|
||||
mr_list_init(&head);
|
||||
n1.id = 1;
|
||||
n2.id = 2;
|
||||
mr_list_add(&head, &n1.link);
|
||||
mr_list_add(&head, &n2.link);
|
||||
|
||||
mr_list_del(&n1.link);
|
||||
n = MR_LIST_ENTRY(head.next, test_node_t, link);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_list_is_empty(&head), 0);
|
||||
MR_TEST_ASSERT_EQ_INT(n->id, 2);
|
||||
}
|
||||
MR_TEST_EXPORT(list, del, test_list_del);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: replace element */
|
||||
static void test_list_replace(void) {
|
||||
test_node_t n1, n2, n3;
|
||||
test_node_t *n;
|
||||
mr_list_t head;
|
||||
mr_list_t *pos;
|
||||
|
||||
mr_list_init(&head);
|
||||
n1.id = 1;
|
||||
n2.id = 2;
|
||||
n3.id = 3;
|
||||
mr_list_add(&head, &n1.link);
|
||||
mr_list_add(&head, &n2.link);
|
||||
|
||||
mr_list_replace(&n3.link, &n1.link);
|
||||
|
||||
pos = head.next;
|
||||
n = MR_LIST_ENTRY(pos, test_node_t, link);
|
||||
MR_TEST_ASSERT_EQ_INT(n->id, 3);
|
||||
pos = pos->next;
|
||||
n = MR_LIST_ENTRY(pos, test_node_t, link);
|
||||
MR_TEST_ASSERT_EQ_INT(n->id, 2);
|
||||
}
|
||||
MR_TEST_EXPORT(list, replace, test_list_replace);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: move element */
|
||||
static void test_list_move(void) {
|
||||
mr_list_t head1, head2;
|
||||
test_node_t n1;
|
||||
test_node_t *n;
|
||||
|
||||
mr_list_init(&head1);
|
||||
mr_list_init(&head2);
|
||||
n1.id = 42;
|
||||
mr_list_add(&head1, &n1.link);
|
||||
|
||||
mr_list_move(&n1.link, &head2);
|
||||
n = MR_LIST_ENTRY(head2.next, test_node_t, link);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_list_is_empty(&head1), 1);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_list_is_empty(&head2), 0);
|
||||
MR_TEST_ASSERT_EQ_INT(n->id, 42);
|
||||
}
|
||||
MR_TEST_EXPORT(list, move, test_list_move);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: safe traversal and delete */
|
||||
static void test_list_safe_foreach_del(void) {
|
||||
test_node_t nodes[4];
|
||||
mr_list_t *pos, *l;
|
||||
int i, ids[2], idx;
|
||||
mr_list_t head;
|
||||
test_node_t *n;
|
||||
|
||||
mr_list_init(&head);
|
||||
for (i = 0; i < 4; ++i) {
|
||||
nodes[i].id = i;
|
||||
mr_list_add(&head, &nodes[i].link);
|
||||
}
|
||||
|
||||
MR_LIST_FOR_EACH_SAFE(pos, l, &head) {
|
||||
test_node_t *node = MR_LIST_ENTRY(pos, test_node_t, link);
|
||||
if ((node->id % 2) == 0) {
|
||||
mr_list_del(pos);
|
||||
}
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
MR_LIST_FOR_EACH(pos, &head) {
|
||||
n = MR_LIST_ENTRY(pos, test_node_t, link);
|
||||
ids[idx++] = n->id;
|
||||
}
|
||||
MR_TEST_ASSERT_EQ_INT(idx, 2);
|
||||
MR_TEST_ASSERT_EQ_INT(ids[0], 1);
|
||||
MR_TEST_ASSERT_EQ_INT(ids[1], 3);
|
||||
}
|
||||
MR_TEST_EXPORT(list, safe_foreach_del, test_list_safe_foreach_del);
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
95
test/kernel/object.c
Normal file
95
test/kernel/object.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* @copyright (c) 2024-2025, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <test/mr_test.h>
|
||||
#if defined(MR_USE_TEST)
|
||||
#include <mr-X/mr_object.h>
|
||||
|
||||
typedef struct test_obj {
|
||||
mr_object_t obj;
|
||||
int data;
|
||||
} test_obj_t;
|
||||
|
||||
static void test_obj_release(struct mr_object *obj) {
|
||||
test_obj_t *t = (test_obj_t *)obj;
|
||||
t->data = -1;
|
||||
}
|
||||
|
||||
static const mr_clazz_t test_clazz = MR_CLAZZ_INIT("test", test_obj_release);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: Static initializer */
|
||||
static void test_object_static_init(void) {
|
||||
static test_obj_t o
|
||||
= {.obj = MR_OBJECT_INIT(&o.o, &test_clazz), .data = 42};
|
||||
|
||||
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(&o.obj), MR_TRUE);
|
||||
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_CLAZZ_IS(&o.obj, &test_clazz), MR_TRUE);
|
||||
}
|
||||
MR_TEST_EXPORT(object, static_init, test_object_static_init);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: Dynamic init / del */
|
||||
static void test_object_init_del(void) {
|
||||
test_obj_t o;
|
||||
|
||||
MR_TEST_ASSERT_EQ_INT(mr_object_init(&o.obj, &test_clazz), 0);
|
||||
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_IS_INITED(&o.obj), MR_TRUE);
|
||||
|
||||
mr_object_del(&o.obj);
|
||||
MR_TEST_ASSERT_EQ_INT(o.data, -1);
|
||||
}
|
||||
MR_TEST_EXPORT(object, init_del, test_object_init_del);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: Get / put reference counting */
|
||||
static void test_object_refcount(void) {
|
||||
mr_object_t *p;
|
||||
test_obj_t o;
|
||||
|
||||
mr_object_init(&o.obj, &test_clazz);
|
||||
|
||||
p = mr_object_get(&o.obj);
|
||||
MR_TEST_ASSERT_EQ_PTR(p, &o.obj);
|
||||
|
||||
p = mr_object_get(&o.obj);
|
||||
MR_TEST_ASSERT_EQ_PTR(p, &o.obj);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_object_put(&o.obj), MR_FALSE);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_object_put(&o.obj), MR_FALSE);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_object_put(&o.obj), MR_TRUE);
|
||||
}
|
||||
MR_TEST_EXPORT(object, refcount, test_object_refcount);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: Null and double-init protection */
|
||||
static void test_object_invalid(void) {
|
||||
test_obj_t o;
|
||||
|
||||
MR_TEST_ASSERT_EQ_INT(mr_object_init(MR_NULL, &test_clazz), -MR_EINVAL);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_object_init(&o.obj, MR_NULL), 0);
|
||||
|
||||
mr_object_init(&o.obj, &test_clazz);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_object_init(&o.obj, &test_clazz), -MR_EINVAL);
|
||||
}
|
||||
MR_TEST_EXPORT(object, invalid, test_object_invalid);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: MR_OBJECT_CLAZZ_IS_OR */
|
||||
static void test_object_clazz_or(void) {
|
||||
test_obj_t o;
|
||||
|
||||
mr_object_init(&o.obj, &test_clazz);
|
||||
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_CLAZZ_IS_OR(&o.obj, &test_clazz, MR_NULL),
|
||||
MR_TRUE);
|
||||
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_CLAZZ_IS_OR(&o.obj, MR_NULL, &test_clazz),
|
||||
MR_TRUE);
|
||||
MR_TEST_ASSERT_EQ_INT(MR_OBJECT_CLAZZ_IS_OR(&o.obj, MR_NULL, MR_NULL),
|
||||
MR_FALSE);
|
||||
}
|
||||
MR_TEST_EXPORT(object, clazz_or, test_object_clazz_or);
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
74
test/kernel/ref.c
Normal file
74
test/kernel/ref.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @copyright (c) 2024-2025, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <test/mr_test.h>
|
||||
#if defined(MR_USE_TEST)
|
||||
#include <mr-X/mr_ref.h>
|
||||
|
||||
static void stub_release(mr_ref_t *ref) {
|
||||
*ref = 0xdeadbeef;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: static init */
|
||||
static void test_ref_static_init(void) {
|
||||
static mr_ref_t r = MR_REF_INIT();
|
||||
|
||||
MR_TEST_ASSERT_EQ_INT(MR_REF_IS_INITED(r), MR_TRUE);
|
||||
MR_TEST_ASSERT_EQ_INT(MR_REF_COUNT(r), 1);
|
||||
}
|
||||
MR_TEST_EXPORT(ref, static_init, test_ref_static_init);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: init/inited/count */
|
||||
static void test_ref_init(void) {
|
||||
mr_ref_t r;
|
||||
|
||||
mr_ref_init(&r);
|
||||
MR_TEST_ASSERT_EQ_INT(MR_REF_IS_INITED(r), MR_TRUE);
|
||||
MR_TEST_ASSERT_EQ_INT(MR_REF_COUNT(r), 1);
|
||||
}
|
||||
MR_TEST_EXPORT(ref, init, test_ref_init);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: get increments count */
|
||||
static void test_ref_get(void) {
|
||||
mr_ref_t r;
|
||||
|
||||
mr_ref_init(&r);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ref_get(&r), MR_TRUE);
|
||||
MR_TEST_ASSERT_EQ_INT(MR_REF_COUNT(r), 2);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ref_get(&r), MR_TRUE);
|
||||
MR_TEST_ASSERT_EQ_INT(MR_REF_COUNT(r), 3);
|
||||
}
|
||||
MR_TEST_EXPORT(ref, get, test_ref_get);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: put decrements and release */
|
||||
static void test_ref_put(void) {
|
||||
mr_ref_t r;
|
||||
|
||||
mr_ref_init(&r);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ref_put(&r, stub_release), MR_TRUE);
|
||||
MR_TEST_ASSERT_EQ_INT(r, 0xdeadbeef);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ref_put(&r, stub_release), MR_FALSE);
|
||||
MR_TEST_ASSERT_EQ_INT(r, 0xdeadbeef - 1);
|
||||
}
|
||||
MR_TEST_EXPORT(ref, put, test_ref_put);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: get after release fails */
|
||||
static void test_ref_get_fail(void) {
|
||||
mr_ref_t r;
|
||||
|
||||
mr_ref_init(&r);
|
||||
mr_ref_put(&r, stub_release);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ref_get(&r), MR_FALSE);
|
||||
}
|
||||
MR_TEST_EXPORT(ref, get_fail, test_ref_get_fail);
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
52
test/kernel/spinlock.c
Normal file
52
test/kernel/spinlock.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @copyright (c) 2024-2025, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <test/mr_test.h>
|
||||
#if defined(MR_USE_TEST)
|
||||
#include <mr-X/mr_spinlock.h>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: static initializer */
|
||||
static void test_spinlock_static_init(void) {
|
||||
static mr_spinlock_t lock = MR_SPINLOCK_INIT();
|
||||
|
||||
MR_TEST_ASSERT_EQ_INT(mr_spinlock_is_locked(&lock), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(spinlock, static_init, test_spinlock_static_init);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: init / lock / unlock */
|
||||
static void test_spinlock_lock_unlock(void) {
|
||||
mr_spinlock_t lock;
|
||||
|
||||
mr_spinlock_init(&lock);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_spinlock_is_locked(&lock), 0);
|
||||
|
||||
mr_spinlock_lock(&lock);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_spinlock_is_locked(&lock), 1);
|
||||
|
||||
mr_spinlock_unlock(&lock);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_spinlock_is_locked(&lock), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(spinlock, lock_unlock, test_spinlock_lock_unlock);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: lock_irqsave / unlock_irqrestore */
|
||||
static void test_spinlock_irq_save_restore(void) {
|
||||
mr_spinlock_t lock;
|
||||
int mask;
|
||||
|
||||
mr_spinlock_init(&lock);
|
||||
mask = mr_spinlock_lock_irqsave(&lock);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_spinlock_is_locked(&lock), 1);
|
||||
|
||||
mr_spinlock_unlock_irqrestore(&lock, mask);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_spinlock_is_locked(&lock), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(spinlock, irq_save_restore, test_spinlock_irq_save_restore);
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
99
test/libc/atomic.c
Normal file
99
test/libc/atomic.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @copyright (c) 2024-2025, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <test/mr_test.h>
|
||||
#if defined(MR_USE_TEST)
|
||||
#include <libc/mr_atomic.h>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: static init */
|
||||
static void test_atomic_static_init(void) {
|
||||
static mr_atomic_t v = MR_ATOMIC_INIT(12345);
|
||||
|
||||
MR_TEST_ASSERT_EQ_INT(mr_atomic_load(&v), 12345);
|
||||
}
|
||||
MR_TEST_EXPORT(atomic, static_init, test_atomic_static_init);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: load/store */
|
||||
static void test_atomic_load_store(void) {
|
||||
mr_atomic_t v;
|
||||
|
||||
mr_atomic_init(&v, 0);
|
||||
mr_atomic_store(&v, 42);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_atomic_load(&v), 42);
|
||||
}
|
||||
MR_TEST_EXPORT(atomic, load_store, test_atomic_load_store);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: exchange */
|
||||
static void test_atomic_exchange(void) {
|
||||
mr_atomic_t v, old;
|
||||
|
||||
mr_atomic_init(&v, 5);
|
||||
old = mr_atomic_exchange(&v, 7);
|
||||
MR_TEST_ASSERT_EQ_INT(old, 5);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_atomic_load(&v), 7);
|
||||
}
|
||||
MR_TEST_EXPORT(atomic, exchange, test_atomic_exchange);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: compare-exchange success/fail */
|
||||
static void test_atomic_compare_exchange(void) {
|
||||
mr_atomic_t v, expect;
|
||||
|
||||
mr_atomic_init(&v, 3);
|
||||
mr_atomic_store(&expect, 3);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_atomic_compare_exchange(&v, &expect, 9), MR_TRUE);
|
||||
MR_TEST_ASSERT_EQ_INT(v, 9);
|
||||
|
||||
expect = 3;
|
||||
MR_TEST_ASSERT_EQ_INT(mr_atomic_compare_exchange(&v, &expect, 1), MR_FALSE);
|
||||
MR_TEST_ASSERT_EQ_INT(expect, 9);
|
||||
}
|
||||
MR_TEST_EXPORT(atomic, compare_exchange, test_atomic_compare_exchange);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: fetch-add */
|
||||
static void test_atomic_fetch_add(void) {
|
||||
mr_atomic_t v;
|
||||
|
||||
mr_atomic_init(&v, 10);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_atomic_fetch_add(&v, 5), 10);
|
||||
MR_TEST_ASSERT_EQ_INT(v, 15);
|
||||
}
|
||||
MR_TEST_EXPORT(atomic, fetch_add, test_atomic_fetch_add);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: fetch-sub */
|
||||
static void test_atomic_fetch_sub(void) {
|
||||
mr_atomic_t v;
|
||||
|
||||
mr_atomic_init(&v, 20);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_atomic_fetch_sub(&v, 8), 20);
|
||||
MR_TEST_ASSERT_EQ_INT(v, 12);
|
||||
}
|
||||
MR_TEST_EXPORT(atomic, fetch_sub, test_atomic_fetch_sub);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: bitwise fetch-and/or/xor */
|
||||
static void test_atomic_bitwise(void) {
|
||||
mr_atomic_t v;
|
||||
|
||||
mr_atomic_init(&v, 0x0F);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_atomic_fetch_and(&v, 0x07), 0x0F);
|
||||
MR_TEST_ASSERT_EQ_INT(v, 0x07);
|
||||
|
||||
MR_TEST_ASSERT_EQ_INT(mr_atomic_fetch_or(&v, 0x08), 0x07);
|
||||
MR_TEST_ASSERT_EQ_INT(v, 0x0F);
|
||||
|
||||
MR_TEST_ASSERT_EQ_INT(mr_atomic_fetch_xor(&v, 0x0F), 0x0F);
|
||||
MR_TEST_ASSERT_EQ_INT(v, 0x00);
|
||||
}
|
||||
MR_TEST_EXPORT(atomic, bitwise, test_atomic_bitwise);
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
@@ -39,12 +39,22 @@ static void test_malloc_free_basic(void) {
|
||||
mr_size_t usable;
|
||||
void *p;
|
||||
|
||||
p = mr_malloc(0);
|
||||
MR_TEST_ASSERT_EQ_PTR(p, MR_NULL);
|
||||
mr_free(MR_NULL);
|
||||
|
||||
p = mr_malloc(128);
|
||||
MR_TEST_ASSERT_NE_PTR(p, MR_NULL);
|
||||
|
||||
usable = mr_malloc_usable_size(p);
|
||||
MR_TEST_ASSERT_GE_UINT(usable, 128);
|
||||
|
||||
usable = mr_malloc_usable_size(MR_NULL);
|
||||
MR_TEST_ASSERT_EQ_UINT(usable, 0);
|
||||
|
||||
usable = mr_malloc_usable_size(p + 32);
|
||||
MR_TEST_ASSERT_EQ_UINT(usable, 0);
|
||||
|
||||
canary_fill(p, usable);
|
||||
MR_TEST_ASSERT_EQ_INT(canary_verify(p, usable), 1);
|
||||
|
||||
@@ -56,9 +66,15 @@ MR_TEST_EXPORT(malloc, free_basic, test_malloc_free_basic);
|
||||
/* calloc test: memory must be zero-filled */
|
||||
static void test_calloc_zero(void) {
|
||||
const mr_size_t n = 16, sz = 32;
|
||||
mr_size_t usable;
|
||||
mr_size_t usable, i;
|
||||
void *p;
|
||||
|
||||
p = mr_calloc(0, 0);
|
||||
MR_TEST_ASSERT_EQ_PTR(p, MR_NULL);
|
||||
|
||||
p = mr_calloc(MR_SIZE_MAX / 2, 1);
|
||||
MR_TEST_ASSERT_EQ_PTR(p, MR_NULL);
|
||||
|
||||
p = mr_calloc(n, sz);
|
||||
MR_TEST_ASSERT_NE_PTR(p, MR_NULL);
|
||||
|
||||
@@ -66,7 +82,7 @@ static void test_calloc_zero(void) {
|
||||
MR_TEST_ASSERT_GE_UINT(usable, n * sz);
|
||||
|
||||
/* Verify all bytes are zero */
|
||||
for (mr_size_t i = 0; i < usable; ++i) {
|
||||
for (i = 0; i < usable; ++i) {
|
||||
MR_TEST_ASSERT_EQ_INT(((mr_uint8_t *)p)[i], 0);
|
||||
}
|
||||
|
||||
@@ -83,12 +99,13 @@ static void test_realloc_resize(void) {
|
||||
MR_TEST_ASSERT_NE_PTR(p1, MR_NULL);
|
||||
canary_fill(p1, 64);
|
||||
|
||||
/* Expand */
|
||||
p2 = mr_realloc(p1, MR_SIZE_MAX);
|
||||
MR_TEST_ASSERT_EQ_PTR(p2, MR_NULL);
|
||||
|
||||
p2 = mr_realloc(p1, 256);
|
||||
MR_TEST_ASSERT_NE_PTR(p2, MR_NULL);
|
||||
MR_TEST_ASSERT_EQ_INT(canary_verify(p2, 64), 1);
|
||||
|
||||
/* Shrink */
|
||||
p3 = mr_realloc(p2, 32);
|
||||
MR_TEST_ASSERT_NE_PTR(p3, MR_NULL);
|
||||
MR_TEST_ASSERT_EQ_INT(canary_verify(p3, 32), 1);
|
||||
@@ -146,7 +163,10 @@ MR_TEST_EXPORT(malloc, frag_merge, test_frag_merge);
|
||||
static void test_malloc_max(void) {
|
||||
const mr_size_t huge = 3 * 1024;
|
||||
mr_size_t usable;
|
||||
void *p;
|
||||
void *p, *n;
|
||||
|
||||
p = mr_malloc(MR_SIZE_MAX - 32);
|
||||
MR_TEST_ASSERT_EQ_PTR(p, MR_NULL);
|
||||
|
||||
p = mr_malloc(huge);
|
||||
if (p) {
|
||||
|
||||
106
test/libc/sprintf.c
Normal file
106
test/libc/sprintf.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @copyright (c) 2024-2025, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <test/mr_test.h>
|
||||
#if defined(MR_USE_TEST)
|
||||
#include <libc/mr_sprintf.h>
|
||||
#include <libc/mr_string.h>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: sprintf basic integer formatting */
|
||||
static void test_sprintf_basic_int(void) {
|
||||
char buf[64];
|
||||
int ret;
|
||||
|
||||
ret = mr_sprintf(buf, "%d", 123);
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 3);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_strcmp(buf, "123"), 0);
|
||||
|
||||
ret = mr_sprintf(buf, "%04d", 42);
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 4);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_strcmp(buf, "0042"), 0);
|
||||
|
||||
ret = mr_sprintf(buf, "%x", 0xAB);
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 2);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_strcmp(buf, "ab"), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(sprintf, basic_int, test_sprintf_basic_int);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: sprintf string formatting */
|
||||
static void test_sprintf_string(void) {
|
||||
char buf[64];
|
||||
int ret;
|
||||
|
||||
ret = mr_sprintf(buf, "%s", "hello");
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 5);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_strcmp(buf, "hello"), 0);
|
||||
|
||||
ret = mr_sprintf(buf, "%10s", "test");
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 10);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_strcmp(buf, " test"), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(sprintf, string, test_sprintf_string);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: sprintf mixed formatting */
|
||||
static void test_sprintf_mixed(void) {
|
||||
char buf[128];
|
||||
int ret;
|
||||
|
||||
ret = mr_sprintf(buf, "Val: %d, Str: %s, Hex: %x", 42, "world", 255);
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 28);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_strcmp(buf, "Val: 42, Str: world, Hex: ff"), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(sprintf, mixed, test_sprintf_mixed);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: snprintf with buffer size limit */
|
||||
static void test_snprintf_limit(void) {
|
||||
char buf[10];
|
||||
int ret;
|
||||
|
||||
ret = mr_snprintf(buf, sizeof(buf), "%s", "1234567890");
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 10);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_strcmp(buf, "123456789"), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(sprintf, snprintf_limit, test_snprintf_limit);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: sprintf pointer formatting */
|
||||
static void test_sprintf_pointer(void) {
|
||||
const void *ptr = (void *)0x12345678;
|
||||
char buf[32];
|
||||
int ret;
|
||||
|
||||
ret = mr_sprintf(buf, "%p", ptr);
|
||||
MR_TEST_ASSERT_GT_INT(ret, 0);
|
||||
MR_TEST_ASSERT_NE_PTR(mr_memchr(buf, '1', (mr_size_t)ret), MR_NULL);
|
||||
}
|
||||
MR_TEST_EXPORT(sprintf, pointer, test_sprintf_pointer);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: sprintf edge cases */
|
||||
static void test_sprintf_edge_cases(void) {
|
||||
char buf[64];
|
||||
int ret;
|
||||
|
||||
ret = mr_sprintf(buf, "");
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 0);
|
||||
MR_TEST_ASSERT_EQ_INT(buf[0], '\0');
|
||||
|
||||
ret = mr_sprintf(buf, "%05d", 7);
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 5);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_strcmp(buf, "00007"), 0);
|
||||
|
||||
ret = mr_sprintf(buf, "%-5d", 42);
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 5);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_strcmp(buf, "42 "), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(sprintf, edge_cases, test_sprintf_edge_cases);
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
46
test/libc/sscanf.c
Normal file
46
test/libc/sscanf.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @copyright (c) 2024-2025, MacRsh
|
||||
*
|
||||
* @license SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* @date 2024-09-06 MacRsh First version
|
||||
*/
|
||||
|
||||
#include <test/mr_test.h>
|
||||
#if defined(MR_USE_TEST)
|
||||
#include <libc/mr_sscanf.h>
|
||||
#include <libc/mr_string.h>
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: basic integer and string extraction */
|
||||
static void test_sscanf_basic(void) {
|
||||
int val, ret;
|
||||
char buf[8];
|
||||
|
||||
ret = mr_sscanf("42 hello", "%d %7s", &val, buf);
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 2);
|
||||
MR_TEST_ASSERT_EQ_INT(val, 42);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_strcmp(buf, "hello"), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(sscanf, basic, test_sscanf_basic);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: format mismatch */
|
||||
static void test_sscanf_mismatch(void) {
|
||||
int val, ret;
|
||||
|
||||
ret = mr_sscanf("abc", "%d", &val);
|
||||
MR_TEST_ASSERT_EQ_INT(ret, 0);
|
||||
}
|
||||
MR_TEST_EXPORT(sscanf, mismatch, test_sscanf_mismatch);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: null / empty input */
|
||||
static void test_sscanf_null_empty(void) {
|
||||
int val;
|
||||
|
||||
MR_TEST_ASSERT_EQ_INT(mr_sscanf("", "%d", &val), -1);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_sscanf("123", "", &val), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(sscanf, null_empty, test_sscanf_null_empty);
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
@@ -51,6 +51,18 @@ static void test_memcpy_basic(void) {
|
||||
mr_memcpy(dst, src, SZ);
|
||||
MR_TEST_ASSERT_EQ_INT(canary_verify(dst, SZ), 1);
|
||||
|
||||
canary_fill(src, SZ / 3);
|
||||
mr_memcpy(dst, src, SZ / 3);
|
||||
MR_TEST_ASSERT_EQ_INT(canary_verify(dst, SZ / 3), 1);
|
||||
|
||||
canary_fill(src + 1, SZ - 1);
|
||||
mr_memcpy(dst + 1, src + 1, SZ - 1);
|
||||
MR_TEST_ASSERT_EQ_INT(canary_verify(dst + 1, SZ - 1), 1);
|
||||
|
||||
canary_fill(src + 1, SZ - 1);
|
||||
mr_memcpy(dst, src + 1, SZ - 1);
|
||||
MR_TEST_ASSERT_EQ_INT(canary_verify(dst, SZ - 1), 1);
|
||||
|
||||
mr_free(src);
|
||||
mr_free(dst);
|
||||
}
|
||||
@@ -73,6 +85,11 @@ static void test_memset_basic(void) {
|
||||
MR_TEST_ASSERT_EQ_INT(buf[i], 0x5A);
|
||||
}
|
||||
|
||||
mr_memset(buf + 1, 0x5A, SZ - 1);
|
||||
for (i = 1; i < SZ - 1; ++i) {
|
||||
MR_TEST_ASSERT_EQ_INT(buf[i], 0x5A);
|
||||
}
|
||||
|
||||
mr_free(buf);
|
||||
}
|
||||
MR_TEST_EXPORT(string, memset_basic, test_memset_basic);
|
||||
@@ -103,9 +120,10 @@ MR_TEST_EXPORT(string, memchr_find, test_memchr_find);
|
||||
static void test_memccpy_stop(void) {
|
||||
const char src[16] = "Hello\0World";
|
||||
char dst[16];
|
||||
void *e;
|
||||
|
||||
mr_memset(dst, '\0', sizeof(dst));
|
||||
void *e = mr_memccpy(dst, src, 'o', sizeof(dst));
|
||||
e = mr_memccpy(dst, src, 'o', sizeof(dst));
|
||||
MR_TEST_ASSERT_NE_PTR(e, MR_NULL);
|
||||
MR_TEST_ASSERT_EQ_INT(dst[4], 'o');
|
||||
MR_TEST_ASSERT_EQ_INT(dst[5], '\0');
|
||||
@@ -129,15 +147,38 @@ static void test_strcpy_basic(void) {
|
||||
}
|
||||
MR_TEST_EXPORT(string, strcpy_basic, test_strcpy_basic);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: strerror copies C-string including terminator */
|
||||
static void test_strerror_basic(void) {
|
||||
mr_strerror(0);
|
||||
mr_strerror(MR_EPERM);
|
||||
mr_strerror(MR_ENOENT);
|
||||
mr_strerror(MR_EIO);
|
||||
mr_strerror(MR_EAGAIN);
|
||||
mr_strerror(MR_ENOMEM);
|
||||
mr_strerror(MR_EBUSY);
|
||||
mr_strerror(MR_EEXIST);
|
||||
mr_strerror(MR_EINVAL);
|
||||
mr_strerror(MR_ENOSYS);
|
||||
mr_strerror(MR_ETIMEDOUT);
|
||||
mr_strerror(-99999);
|
||||
}
|
||||
MR_TEST_EXPORT(string, strerror_basic, test_strerror_basic);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: strncpy copies at most n bytes */
|
||||
static void test_strncpy_trunc(void) {
|
||||
const char *src = "long_string";
|
||||
const char *long_src = "long_string";
|
||||
const char *short_src = "str";
|
||||
char buf[8];
|
||||
|
||||
mr_strncpy(buf, src, sizeof(buf));
|
||||
mr_strncpy(buf, long_src, sizeof(buf));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
MR_TEST_ASSERT_EQ_INT(mr_memcmp(buf, "long_st", sizeof(buf)), 0);
|
||||
|
||||
mr_strncpy(buf, short_src, sizeof(buf));
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
MR_TEST_ASSERT_EQ_INT(mr_memcmp(buf, "str", 4), 0);
|
||||
}
|
||||
MR_TEST_EXPORT(string, strncpy_trunc, test_strncpy_trunc);
|
||||
|
||||
@@ -174,4 +215,48 @@ static void test_strchr_find(void) {
|
||||
MR_TEST_ASSERT_EQ_PTR(mr_strchr(s, 'X'), MR_NULL);
|
||||
}
|
||||
MR_TEST_EXPORT(string, strchr_find, test_strchr_find);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: ffs32 basic cases */
|
||||
static void test_ffs32_basic(void) {
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ffs32(0), 0);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ffs32(1), 1);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ffs32(0x80000000U), 32);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ffs32(0x00010000U), 17);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ffs32(0x000000FFU), 1);
|
||||
}
|
||||
MR_TEST_EXPORT(string, ffs32_basic, test_ffs32_basic);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: ffs64 basic cases */
|
||||
static void test_ffs64_basic(void) {
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ffs64(0), 0);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ffs64(1ULL), 1);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ffs64(0x8000000000000000ULL), 64);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ffs64(0x0000000100000000ULL), 33);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_ffs64(0x00000000000000FFULL), 1);
|
||||
}
|
||||
MR_TEST_EXPORT(string, ffs64_basic, test_ffs64_basic);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: fls32 basic cases */
|
||||
static void test_fls32_basic(void) {
|
||||
MR_TEST_ASSERT_EQ_INT(mr_fls32(0), 0);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_fls32(1), 1);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_fls32(0x80000000U), 32);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_fls32(0x00010000U), 17);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_fls32(0x000000FFU), 8);
|
||||
}
|
||||
MR_TEST_EXPORT(string, fls32_basic, test_fls32_basic);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* Test: fls64 basic cases */
|
||||
static void test_fls64_basic(void) {
|
||||
MR_TEST_ASSERT_EQ_INT(mr_fls64(0), 0);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_fls64(1ULL), 1);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_fls64(0x8000000000000000ULL), 64);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_fls64(0x0000000100000000ULL), 33);
|
||||
MR_TEST_ASSERT_EQ_INT(mr_fls64(0x00000000000000FFULL), 8);
|
||||
}
|
||||
MR_TEST_EXPORT(string, fls64_basic, test_fls64_basic);
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
|
||||
121
test/test.c
121
test/test.c
@@ -10,6 +10,7 @@
|
||||
#if defined(MR_USE_TEST)
|
||||
#include <mr-X/mr_clock.h>
|
||||
#include <libc/mr_assert.h>
|
||||
#include <libc/mr_string.h>
|
||||
|
||||
/* Test status */
|
||||
mr_uint32_t __mr_test_status = __MR_TEST_MAGIC_PASS;
|
||||
@@ -24,45 +25,107 @@ static void end(void) {
|
||||
}
|
||||
__MR_TEST_EXPORT(sys, end, end, "1.end");
|
||||
|
||||
int mr_test_all_run(void) {
|
||||
static mr_bool_t testcase_run(const mr_testcase_t *cs) {
|
||||
mr_tick_t tick;
|
||||
|
||||
/* Check parameter */
|
||||
MR_ASSERT(cs->entry != MR_NULL);
|
||||
|
||||
/* Test case begin */
|
||||
mr_printf("[ RUN ] %s.%s\n", cs->suite, cs->name);
|
||||
|
||||
/* Reset test status */
|
||||
__mr_test_status = __MR_TEST_MAGIC_PASS;
|
||||
|
||||
/* Get begin tick */
|
||||
tick = mr_clock_tick();
|
||||
|
||||
/* Call test entry */
|
||||
cs->entry();
|
||||
|
||||
/* Get difference tick */
|
||||
tick = mr_clock_tick() - tick;
|
||||
|
||||
/* Test case end */
|
||||
if (__mr_test_status == __MR_TEST_MAGIC_PASS) {
|
||||
mr_printf(
|
||||
"[ " MR_COLOR(MR_COLOR_GREEN, "OK") " ] %s.%s (%d tick)\n",
|
||||
cs->suite, cs->name, tick);
|
||||
return MR_TRUE;
|
||||
} else {
|
||||
mr_printf(
|
||||
"[ " MR_COLOR(MR_COLOR_RED, "FAILED") " ] %s.%s (%d tick)\n",
|
||||
cs->suite, cs->name, tick);
|
||||
return MR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void mr_testcase_run(const char *suite, const char *name) {
|
||||
const mr_testcase_t *start = &__mr_testcase_sys_start;
|
||||
const mr_testcase_t *end = &__mr_testcase_sys_end;
|
||||
const mr_testcase_t *cs;
|
||||
|
||||
/* Each test cases */
|
||||
for (cs = start + 1; cs < end; cs++) {
|
||||
/* Match testcase */
|
||||
if ((!mr_strcmp(cs->suite, suite)) || (!mr_strcmp(cs->name, name))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Run testcase */
|
||||
testcase_run(cs);
|
||||
}
|
||||
}
|
||||
|
||||
void mr_testsuite_run(const char *suite) {
|
||||
const mr_testcase_t *start = &__mr_testcase_sys_start;
|
||||
const mr_testcase_t *end = &__mr_testcase_sys_end;
|
||||
const mr_testcase_t *cs;
|
||||
int pass, fail;
|
||||
mr_tick_t tick;
|
||||
mr_bool_t ret;
|
||||
|
||||
/* Test begin */
|
||||
mr_printf("[==========] Running tests\n");
|
||||
mr_printf("[==========] Running '%s' suite\n", suite);
|
||||
|
||||
/* Each test cases */
|
||||
for (pass = fail = 0, cs = start + 1; cs < end; cs++) {
|
||||
MR_ASSERT(cs->entry != MR_NULL);
|
||||
/* Match testcase */
|
||||
if (mr_strcmp(cs->suite, suite) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Test case begin */
|
||||
mr_printf("[ RUN ] %s.%s\n", cs->suite, cs->name);
|
||||
|
||||
/* Reset test status */
|
||||
__mr_test_status = __MR_TEST_MAGIC_PASS;
|
||||
|
||||
/* Get begin tick */
|
||||
tick = mr_clock_tick();
|
||||
|
||||
/* Call test entry */
|
||||
cs->entry();
|
||||
|
||||
/* Get difference tick */
|
||||
tick = mr_clock_tick() - tick;
|
||||
|
||||
/* Test case end */
|
||||
if (__mr_test_status == __MR_TEST_MAGIC_PASS) {
|
||||
mr_printf("[ " MR_COLOR(MR_COLOR_GREEN,
|
||||
"OK") " ] %s.%s (%d tick)\n",
|
||||
cs->suite, cs->name, tick);
|
||||
/* Run testcase */
|
||||
ret = testcase_run(cs);
|
||||
if (ret) {
|
||||
pass++;
|
||||
} else {
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test summary */
|
||||
mr_printf("[==========]\n");
|
||||
mr_printf("[ PASSED ] %d tests\n", pass);
|
||||
mr_printf("[ FAILED ] %d tests\n", fail);
|
||||
}
|
||||
|
||||
mr_bool_t mr_test_run(void) {
|
||||
const mr_testcase_t *start = &__mr_testcase_sys_start;
|
||||
const mr_testcase_t *end = &__mr_testcase_sys_end;
|
||||
const mr_testcase_t *cs;
|
||||
int pass, fail;
|
||||
mr_bool_t ret;
|
||||
|
||||
/* Test begin */
|
||||
mr_printf("[==========] Running 'all' tests\n");
|
||||
|
||||
/* Each test cases */
|
||||
for (pass = fail = 0, cs = start + 1; cs < end; cs++) {
|
||||
/* Run testcase */
|
||||
ret = testcase_run(cs);
|
||||
if (ret) {
|
||||
pass++;
|
||||
} else {
|
||||
mr_printf(
|
||||
"[ " MR_COLOR(MR_COLOR_RED, "FAILED") " ] %s.%s (%d tick)\n",
|
||||
cs->suite, cs->name, tick);
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
@@ -72,7 +135,7 @@ int mr_test_all_run(void) {
|
||||
mr_printf("[ PASSED ] %d tests\n", pass);
|
||||
mr_printf("[ FAILED ] %d tests\n", fail);
|
||||
|
||||
/* Test end */
|
||||
return 0;
|
||||
/* Return result */
|
||||
return (fail == 0) ? MR_TRUE : MR_FALSE;
|
||||
}
|
||||
#endif /* defined(MR_USE_TEST) */
|
||||
|
||||
Reference in New Issue
Block a user