blob: 0ca9b5569760d7ac345c70cd3ce20ae360e173d9 [file] [log] [blame]
/*
* Copyright (c) 2013, Google, Inc. All rights reserved
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIB_UNITTEST_INCLUDE_UNITTEST_H_
#define _LIB_UNITTEST_INCLUDE_UNITTEST_H_
/*
* Macros for writing unit tests.
*
* Sample usage:
*
* A test case runs a collection of tests like this, with
* BEGIN_TEST_CASE and END_TEST_CASE and the beginning and end of the
* function and RUN_TEST to call each individual test, as follows:
*
* BEGIN_TEST_CASE(foo_tests);
*
* RUN_TEST(test_foo);
* RUN_TEST(test_bar);
* RUN_TEST(test_baz);
*
* END_TEST_CASE;
*
* This creates a static function foo_tests() and registers it with the
* unit test framework. foo_tests() can be executed either by a shell
* command or by a call to run_all_tests(), which runs all registered
* unit tests.
*
* A test looks like this, using the BEGIN_TEST and END_TEST macros at
* the beginning and end of the test and the EXPECT_* macros to
* validate test results, as shown:
*
* static bool test_foo(void)
* {
* BEGIN_TEST;
*
* ...declare variables and do stuff...
* int foo_value = foo_func();
* ...See if the stuff produced the correct value...
* EXPECT_EQ(1, foo_value, "foo_func failed");
* ... there are EXPECT_* macros for many conditions...
* EXPECT_TRUE(foo_condition(), "condition should be true");
* EXPECT_NEQ(ERR_TIMED_OUT, foo_event(), "event timed out");
*
* END_TEST;
* }
*
* To your rules.mk file, add lib/unittest to MODULE_DEPS:
*
* MODULE_DEPS += \
* lib/unittest \
*/
#include <stdbool.h>
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <trace.h>
#include <stdarg.h>
#define PRINT_BUFFER_SIZE (512)
/*
* Type for unit test result Output
*/
typedef void (*test_output_func) (const char *line, int len, void *arg);
/*
* Printf dedicated to the unittest library
* the default output is the printf
*/
void unittest_printf (const char *format, ...);
/*
* Function to set the callback for printing
* the unit test output
*/
void unittest_set_output_function (test_output_func fun, void *arg);
/*
* Macros to format the error string
*/
#define EXPECTED_STRING "%s:\n expected "
#define UNITTEST_TRACEF(str, x...) do { \
unittest_printf(" [FAILED] \n %s:%d:\n " str, \
__PRETTY_FUNCTION__, __LINE__, ## x); \
} while (0)
/*
* BEGIN_TEST_CASE and END_TEST_CASE define a function that calls
* RUN_TEST.
*/
#define BEGIN_TEST_CASE(case_name) \
bool case_name(void) \
{ \
bool all_success = true; \
unittest_printf("\nCASE %-49s [STARTED] \n", #case_name);
#define DEFINE_REGISTER_TEST_CASE(case_name) \
static void _register_##case_name(void) \
{ \
unittest_register_test_case(&_##case_name##_element); \
} \
void (*_register_##case_name##_ptr)(void) __SECTION(".ctors") = \
_register_##case_name;
#define END_TEST_CASE(case_name) \
if (all_success) { \
unittest_printf("CASE %-59s [PASSED]\n", #case_name); \
} else { \
unittest_printf("CASE %-59s [FAILED]\n", #case_name); \
} \
return all_success; \
} \
static struct test_case_element _##case_name##_element = { \
.next = NULL, \
.failed_next = NULL, \
.name = #case_name, \
.test_case = case_name, \
}; \
DEFINE_REGISTER_TEST_CASE(case_name);
#define RUN_TEST(test) \
unittest_printf(" %-50s [RUNNING]", #test ); \
if (! test ()) { \
all_success = false; \
} else { \
unittest_printf(" [PASSED] \n"); \
}
/*
* BEGIN_TEST and END_TEST go in a function that is called by RUN_TEST
* and that call the EXPECT_ macros.
*/
#define BEGIN_TEST bool all_ok = true
#define END_TEST return all_ok
/*
* Use the EXPECT_* macros to check test results.
*/
#define EXPECT_EQ(expected, actual, msg) \
{ \
typeof(actual) _e = expected; \
typeof(actual) _a = actual; \
if (_e != _a) { \
UNITTEST_TRACEF (EXPECTED_STRING #expected " (%d), " \
"actual " #actual " (%d)\n", \
msg, (int)_e, (int)_a); \
all_ok = false; \
} \
}
#define EXPECT_NEQ(expected, actual, msg) \
{ \
const typeof(expected) _e = expected; \
if (_e == actual) { \
UNITTEST_TRACEF(EXPECTED_STRING #expected " (%d), " #actual \
" to differ, but they are the same %d\n", \
msg, (int)_e); \
all_ok = false; \
} \
}
#define EXPECT_LE(expected, actual, msg) \
{ \
const typeof(actual) _e = expected; \
const typeof(actual) _a = actual; \
if (_e > _a) { \
UNITTEST_TRACEF(EXPECTED_STRING #expected " (%d) to be" \
" less-than-or-equal-to actual " \
#actual " (%d)\n", \
msg, (int)_e, (int)_a); \
all_ok = false; \
} \
}
#define EXPECT_LT(expected, actual, msg) \
{ \
const typeof(actual) _e = expected; \
const typeof(actual) _a = actual; \
if (_e >= _a) { \
UNITTEST_TRACEF(EXPECTED_STRING #expected " (%d) to be" \
" less-than actual " \
#actual " (%d)\n", \
msg, (int)_e, (int)_a); \
all_ok = false; \
} \
}
#define EXPECT_GE(expected, actual, msg) \
{ \
const typeof(actual) _e = expected; \
const typeof(actual) _a = actual; \
if (_e < _a) { \
UNITTEST_TRACEF(EXPECTED_STRING #expected " (%d) to be" \
" greater-than-or-equal-to actual " \
#actual " (%d)\n", \
msg, (int)_e, (int)_a); \
all_ok = false; \
} \
}
#define EXPECT_GT(expected, actual, msg) \
{ \
const typeof(actual) _e = expected; \
const typeof(actual) _a = actual; \
if (_e <= _a) { \
UNITTEST_TRACEF(EXPECTED_STRING #expected " (%d) to be" \
" greater-than actual " \
#actual " (%d)\n", \
msg, (int)_e, (int)_a); \
all_ok = false; \
} \
}
#define EXPECT_TRUE(actual, msg) \
if (!(actual)) { \
UNITTEST_TRACEF("%s: " #actual " is false\n", msg); \
all_ok = false; \
}
#define EXPECT_FALSE(actual, msg) \
if (actual) { \
UNITTEST_TRACEF("%s: " #actual " is true\n", msg); \
all_ok = false; \
}
#define EXPECT_BYTES_EQ(expected, actual, length, msg) \
if (!expect_bytes_eq(expected, actual, length, msg)) { \
all_ok = false; \
}
#define EXPECT_BYTES_NE(bytes1, bytes2, length, msg) \
if (!memcmp(bytes1, bytes2, length)) { \
UNITTEST_TRACEF(#bytes1 " and " #bytes2 " are the same; " \
"expected different\n"); \
hexdump8(bytes1, length); \
all_ok = false; \
}
/* For comparing uint64_t, like hw_id_t. */
#define EXPECT_EQ_LL(expected, actual, msg) \
{ \
const typeof(actual) _e = expected; \
const typeof(actual) _a = actual; \
if (_e != _a) { \
UNITTEST_TRACEF("%s: expected %llu, actual %llu\n", \
msg, _e, _a); \
all_ok = false; \
} \
}
/*
* The ASSERT_* macros are similar to the EXPECT_* macros except that
* they return on failure.
*/
#define ASSERT_NOT_NULL(p) \
if (!p) { \
UNITTEST_TRACEF("ERROR: NULL pointer\n"); \
return false; \
}
/*
* The list of test cases is made up of these elements.
*/
struct test_case_element {
struct test_case_element *next;
struct test_case_element *failed_next;
const char *name;
bool (*test_case)(void);
};
/*
* Registers a test case with the unit test framework.
*/
void unittest_register_test_case(struct test_case_element *elem);
/*
* Runs all registered test cases.
*/
bool run_all_tests(void);
/*
* Returns false if expected does not equal actual and prints msg and a hexdump8
* of the input buffers.
*/
bool expect_bytes_eq(const uint8_t *expected, const uint8_t *actual, size_t len,
const char *msg);
#endif /* _LIB_UNITTEST_INCLUDE_UNITTEST_H_ */