/* * Copyright (C) 2019 The Android Open Source Project * * 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. */ #pragma once #include #include #include #include #include __BEGIN_CDECLS /* * This function returns a time in nanoseconds based on hardware counters * it is expected to: * - Be non-wrapping or have very long (years) roll-over period * - Have a resolution below 100nsc */ uint64_t get_current_time_ns(void); /* * Test functions can be defined with: * TEST(SuiteName, TestName) { * ... test body ... * } * or with: * TEST_F(SuiteName, TestName) { * ... test body ... * } * or with: * TEST_P(SuiteName, TestName) { * ... test body ... * } * * NOTE: SuiteName and TestName should not contain underscores. * * Use EXPECT_ or ASSERT_ directly in test functions or from nested * functions to check test conditions. Where can be: * EQ for == * NE for != * LT for < * LE for <= * GT for > * GE for >= * * The test functions follows this pattern: * _(val1, val2 [, format, ...]) * If val1 val2 is not true, then both values will be printed and a test * failure will be recorded. For ASSERT_ it will also jump to a test_abort * label in the calling function. * * Call RUN_ALL_TESTS() to run all tests defined by TEST (or * RUN_ALL_SUITE_TESTS("SuiteName") to only run tests with the specified * SuiteName). RUN_ALL_TESTS and RUN_ALL_SUITE_TESTS return true if all the * tests passed. * * Test functions defined with TEST_F or TEST_P expect the type _t * and _SetUp and _TearDown functions to be defined. * The _SetUp function will be called once before each test in * SuiteName in run and the _TearDown function will be called once * after each test in SuiteName is run. These functions can be defined with * TEST_F_SETUP() { * ... setup body ... * } * and with: * TEST_F_TEARDOWN() { * ... teardown body ... * } * A pointer to a _t variable will be passed as "_state" to the * setup, teardown and test functions. * * TEST_FIXTURE_ALIAS(NewSuiteName, OldSuiteName) can be used to use the test * fixture defined for OldSuiteName with NewSuiteName. * * Tests defined with TEST_P will only run when their suite is run if they have * been instantiated with parameters using INSTANTIATE_TEST_SUITE_P. These tests * can access their parameter using GetParam() */ #ifndef trusty_unittest_printf #error trusty_unittest_printf must be defined #endif /** * struct test_context - struct representing the state of a test run. * @tests_total: Number of conditions checked * @tests_skipped: Number of tests skipped * @tests_disabled: Number of disabled tests skipped * @tests_failed: Number of conditions failed * @inst_name: Name of the current parameter instantiation * @suite_name: Name of the current test suite * @param_name: Name of the current parameter * @test_name: Name of current test case * @test_param: The current test parameter * @all_ok: State of current test case * @skipped: Current test was skipped. * @hard_fail: Type of test failure (when @all_ok is false) * @test_start_time: Test Start Time in ns * @suite_duration_ms:Test Suite duration in ms */ struct test_context { unsigned int tests_total; unsigned int tests_skipped; unsigned int tests_disabled; unsigned int tests_failed; const char* inst_name; const char* suite_name; const char* param_name; const char* test_name; const void* test_param; bool all_ok; bool skipped; bool hard_fail; uint64_t test_start_time; uint64_t suite_duration_ms; }; /** * struct test_list_node - node to hold test function in list of tests * @node: List node * @suite: Name of test suite (optionally used for filtering) * @name: Name of test (optionally used for filtering) * @func: Test function * @needs_param: Indicates if the test function is parameterized */ struct test_list_node { struct list_node node; const char* suite; const char* name; void (*func)(void); bool needs_param; }; /** * struct test_param_gen - struct representing a parameter generator * @gen_param: Function to generate the parameter for a test * @priv: Private data passed to gen_param */ struct test_param_gen { const void* (*gen_param)(void*, int); void* priv; }; /** * typedef test_param_to_string_t - Converts a test parameter to its string form * @param: Parameter to convert * @buf: Buffer to fill with a NULL terminated string representation of * @param * @buf_size: Size in bytes of @buf * * When called, this function is passed a pointer to the parameter for the test * that is being executed in @param and must return a null-terminated string * representing the passed in parameter in @buf of at most size @buf_size. */ typedef void (*test_param_to_string_t)(const void* param, char* buf, size_t buf_size); /** * struct test_param_list_node - holds parameter generators * @node: List node * @param_gen: Parameter generator * @to_string: Function to convert a parameter to its string form * @inst_name: Name of the instantiation associated with the generator * @suite: Name of test suite associated with the generator */ struct test_param_list_node { struct list_node node; struct test_param_gen param_gen; test_param_to_string_t to_string; const char* inst_name; const char* suite; }; static struct test_context _test_context; /* * List of tests. Tests are added by a __attribute__((constructor)) function * per test defined by the TEST macro. */ static struct list_node _test_list = LIST_INITIAL_VALUE(_test_list); /* * List of parameter generators. Parameter generators are added by a * __attribute__((constructor)) function per instantiation defined with * INSTANTIATE_TEST_SUITE_P. */ static struct list_node _test_param_list = LIST_INITIAL_VALUE(_test_param_list); static inline void trusty_unittest_print_status_name_param_duration( const char* status, const char* param_gen_inst_name, /* parameter generator instance name */ const char* suite_name, const char* test_name, const char* param_name, const char* duration_ms) { if (param_gen_inst_name) { trusty_unittest_printf("[ %s ] %s/%s.%s/%s%s\n", status, param_gen_inst_name, suite_name, test_name, param_name, duration_ms); } else { trusty_unittest_printf("[ %s ] %s.%s%s\n", status, suite_name, test_name, duration_ms); } } static inline void trusty_unittest_print_status_name(const char* suite_name, const char* test_name, const char* status) { trusty_unittest_print_status_name_param_duration( status, _test_context.inst_name, suite_name, test_name, _test_context.param_name, ""); } static inline void trusty_unittest_print_status(const char* status) { trusty_unittest_print_status_name_param_duration( status, _test_context.inst_name, _test_context.suite_name, _test_context.test_name, _test_context.param_name, ""); } static inline void trusty_unittest_print_status_duration( const char* status, uint64_t test_duration_ms) { char duration_str[16] = ""; /* print duration at end of test case */ snprintf(duration_str, sizeof(duration_str), " (%" PRIu64 " ms)", test_duration_ms); trusty_unittest_print_status_name_param_duration( status, _test_context.inst_name, _test_context.suite_name, _test_context.test_name, _test_context.param_name, (const char*)duration_str); } static inline void TEST_BEGIN_FUNC(const char* suite_name, const char* test_name) { _test_context.suite_name = suite_name; _test_context.test_name = test_name; _test_context.all_ok = true; _test_context.hard_fail = false; _test_context.skipped = false; _test_context.tests_total++; trusty_unittest_print_status("RUN "); /* * initialize the test start time * (after the print status is slightly better) */ _test_context.test_start_time = get_current_time_ns(); } static inline void TEST_END_FUNC(void) { uint64_t test_duration_ms = (get_current_time_ns() - _test_context.test_start_time) / 1000000; _test_context.suite_duration_ms += test_duration_ms; if (_test_context.skipped) { trusty_unittest_print_status_duration(" SKIPPED", test_duration_ms); } else if (_test_context.all_ok) { trusty_unittest_print_status_duration(" OK", test_duration_ms); } else { trusty_unittest_print_status_duration(" FAILED ", test_duration_ms); } _test_context.test_name = NULL; } #define STRINGIFY(x) #x #define TEST_FIXTURE_ALIAS(new_suite_name, old_suite_name) \ typedef old_suite_name##_t new_suite_name##_t; \ \ static void new_suite_name##_SetUp(new_suite_name##_t* _state) { \ old_suite_name##_SetUp(_state); \ } \ static void new_suite_name##_TearDown(new_suite_name##_t* _state) { \ old_suite_name##_TearDown(_state); \ } #define TEST_INTERNAL(suite_name, test_name, w_param, pre, post, arg, argp) \ static void suite_name##_##test_name##_inner argp; \ \ static void suite_name##_##test_name(void) { \ TEST_BEGIN_FUNC(STRINGIFY(suite_name), STRINGIFY(test_name)); \ { \ pre; \ if (!_test_context.hard_fail && !_test_context.skipped) { \ suite_name##_##test_name##_inner arg; \ } \ post; \ } \ TEST_END_FUNC(); \ } \ \ static struct test_list_node suite_name##_##test_name##_node = { \ .node = LIST_INITIAL_CLEARED_VALUE, \ .suite = #suite_name, \ .name = #test_name, \ .func = suite_name##_##test_name, \ .needs_param = w_param, \ }; \ \ __attribute__((constructor)) void suite_name##_##test_name##_add(void) { \ list_add_tail(&_test_list, &suite_name##_##test_name##_node.node); \ } \ \ static void suite_name##_##test_name##_inner argp #define TEST_F_SETUP(suite_name) \ static void suite_name##_SetUp(suite_name##_t* _state) #define TEST_F_TEARDOWN(suite_name) \ static void suite_name##_TearDown(suite_name##_t* _state) #define TEST(suite_name, test_name) \ TEST_INTERNAL(suite_name, test_name, false, , , (), (void)) #define TEST_F_CUSTOM_ARGS(suite_name, test_name, arg, argp) \ TEST_INTERNAL(suite_name, test_name, false, suite_name##_t state; \ suite_name##_SetUp(&state);, suite_name##_TearDown(&state); \ , arg, argp) #define TEST_F(suite_name, test_name) \ TEST_F_CUSTOM_ARGS(suite_name, test_name, (&state), \ (suite_name##_t * _state)) #define TEST_P_CUSTOM_ARGS(suite_name, test_name, arg, argp) \ TEST_INTERNAL(suite_name, test_name, true, suite_name##_t state; \ suite_name##_SetUp(&state);, suite_name##_TearDown(&state); \ , arg, argp) #define TEST_P(suite_name, test_name) \ TEST_P_CUSTOM_ARGS(suite_name, test_name, (&state), \ (suite_name##_t * _state)) struct test_array_param { const void* arr; int elem_size; int count; }; static inline const void* test_gen_array_param(void* priv, int i) { struct test_array_param* param = (struct test_array_param*)priv; if (i >= param->count) { return NULL; } return (uint8_t*)param->arr + param->elem_size * i; } struct test_range_param { long begin; long end; long step; long current; }; static inline const void* test_gen_range_param(void* priv, int i) { struct test_range_param* range_param = (struct test_range_param*)priv; range_param->current = range_param->begin + range_param->step * i; if (range_param->current >= range_param->end) { return NULL; } return &range_param->current; } struct combined_params { struct test_param_gen* generators; int generator_count; int* idxs; const void** current; }; static inline void update_combined_params(struct combined_params* params, int j, bool reset) { if (reset) { params->idxs[j] = 0; } params->current[j] = params->generators[j].gen_param( params->generators[j].priv, params->idxs[j]); params->idxs[j]++; } static inline const void* test_gen_combined_param(void* priv, int i) { struct combined_params* params = (struct combined_params*)priv; if (i == 0) { for (int j = 0; j < params->generator_count; j++) { update_combined_params(params, j, true); } return params->current; } for (int j = 0; j < params->generator_count; j++) { update_combined_params(params, j, false); if (params->current[j] != NULL) { return params->current; } update_combined_params(params, j, true); } return NULL; } #define FIRST_ARG(arg0, args...) arg0 #define SECOND_ARG(arg0, arg1, args...) arg1 /* Parentheses are used to prevent commas from being interpreted when they are * passed in macro arguments. DELETE_PAREN is used to remove these parentheses * inside the macro that uses the commas e.g.: * * MY_MACRO((1, 2, 3)) * * #define MY_MACRO(arg) * DELETE_PAREN arg */ #define DELETE_PAREN(args...) args #define testing_Range(_begin, end_step...) \ (static struct test_range_param range_param = \ { \ .begin = _begin, \ .end = FIRST_ARG(end_step, ), \ .step = SECOND_ARG(end_step, 1, ), \ }; \ param_node.param_gen.gen_param = test_gen_range_param; \ param_node.param_gen.priv = &range_param;) #define testing_ValuesIn(array) \ (static struct test_array_param array_param = \ { \ .arr = array, \ .elem_size = sizeof(array[0]), \ .count = countof(array), \ }; \ \ param_node.param_gen.gen_param = test_gen_array_param; \ param_node.param_gen.priv = &array_param;) /* * (args, args) is passed to __typeof__ to guarantee that it resolves to const * char* instead of const char[] in cases where args contains a single string. * When args is a single string, it is inlined and typeof will resolve to const * char[]. */ #define testing_Values(args...) \ (static __typeof__(args, args) new_arr[] = {args}; \ DELETE_PAREN testing_ValuesIn(new_arr)) #define testing_Bool() testing_Values(false, true) #define test_set_combine_params(generator, i, count) \ { \ DELETE_PAREN generator; \ if (i < count) { \ param_gens[i].gen_param = param_node.param_gen.gen_param; \ param_gens[i].priv = param_node.param_gen.priv; \ } \ } #define testing_Combine_internal(arg0, arg1, arg2, arg3, arg4, arg5, arg6, \ arg7, arg8, arg9, da0, da1, da2, da3, da4, \ da5, da6, da7, da8, da9, count, args...) \ (static struct test_param_gen param_gens[count]; static int idxs[count]; \ static const void* current_params[count]; \ static struct combined_params combined_params = \ { \ param_gens, \ count, \ idxs, \ current_params, \ }; \ \ test_set_combine_params(arg0, 0, count); \ test_set_combine_params(arg1, 1, count); \ test_set_combine_params(arg2, 2, count); \ test_set_combine_params(arg3, 3, count); \ test_set_combine_params(arg4, 4, count); \ test_set_combine_params(arg5, 5, count); \ test_set_combine_params(arg6, 6, count); \ test_set_combine_params(arg7, 7, count); \ test_set_combine_params(arg8, 8, count); \ test_set_combine_params(arg9, 9, count); \ param_node.param_gen.gen_param = test_gen_combined_param; \ param_node.param_gen.priv = &combined_params;) #define testing_Combine(generators...) \ testing_Combine_internal(generators, (), (), (), (), (), (), (), (), (), \ (), 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) #define INSTANTIATE_TEST_SUITE_P_INTERNAL(_inst_name, suite_name, param_gen, \ param_to_string, args...) \ \ __attribute__((constructor)) void suite_name##_##_inst_name##param_add( \ void) { \ static struct test_param_list_node param_node = { \ .node = LIST_INITIAL_CLEARED_VALUE, \ .to_string = param_to_string, \ .inst_name = STRINGIFY(_inst_name), \ .suite = #suite_name, \ }; \ \ DELETE_PAREN param_gen; \ \ list_add_tail(&_test_param_list, ¶m_node.node); \ } static inline bool has_disabled_prefix(const char* str) { const char disabled_prefix[] = "DISABLED_"; return strncmp(str, disabled_prefix, strlen(disabled_prefix)) == 0; } static inline bool trusty_unittest_test_is_disabled( struct test_list_node* entry) { return has_disabled_prefix(entry->suite) || has_disabled_prefix(entry->name); } /** * trusty_unittest_count_param_entries - Count parameter entries for a given * test suite. * * @suite: Name of test suite associated with the parameters * suite is never going to be NULL (see invocation), * no need to guard against this case. * * For each parameter generator associated with the suite, accrue * the number of parameter entries. * * Not meant for external use. * * Return: count of parameter entries */ static int trusty_unittest_count_param_entries( struct test_list_node* test_case) { int param_count = 0; int i; struct test_param_list_node* param_entry; bool has_param_gen = 0; bool invalid_run = false; /* * for each parameter generator associated with the suite, * accrue the number of parameter entries */ list_for_every_entry(&_test_param_list, param_entry, struct test_param_list_node, node) { if (!strcmp(test_case->suite, param_entry->suite)) { i = 0; has_param_gen = true; /* For each parameter from the generator */ while (param_entry->param_gen.gen_param(param_entry->param_gen.priv, i)) { i++; } if (!i) { /* * No parameter entries: parameterized test case exist * but the test generator is empty */ trusty_unittest_print_status_name_param_duration( " FAILED ", param_entry->inst_name, test_case->suite, test_case->name, "NO PARAMS: Parameterized Test Case Generator without Params!", ""); invalid_run = true; } param_count += i; } } /* * No parameter generator: parameterized test case exist * but the test suite is not associated with any param generator */ if (!has_param_gen) { trusty_unittest_print_status_name_param_duration( " FAILED ", "NO PARAM GENERATOR", test_case->suite, test_case->name, "NO PARAMS: Parameterized Test Case without Param Generator!", ""); } return invalid_run ? 0 : param_count; } /** * trusty_unittest_has_parameterized_test_case - test suite with parameterized * test cases * * @suite: Name of test suite associated with the parameters. * suite is never going to be NULL (see invocation), * no need to guard against this case. * * Check whether a test suite has parameterized test cases. * Not meant for external use. * * Return: True if parameterized test */ static bool trusty_unittest_has_parameterized_test_case(const char* suite) { struct test_list_node* test_case; list_for_every_entry(&_test_list, test_case, struct test_list_node, node) { if (!strcmp(suite, test_case->suite)) { if (test_case->needs_param) { return true; } } } return false; } /** * trusty_unittest_count_test_cases - Count test cases associated with test * suite. * * @suite: Name of test suite. * When suite is NULL, all test cases from all test suites are counted. * * This test case count shall comply to the GTest parser requirements * and thus shall not include disabled test cases. * Not meant for external use. * * Return: count of test cases, -1 in case of detected test suite coding error */ static int trusty_unittest_count_test_cases(const char* suite) { struct test_list_node* test_case; struct test_param_list_node* param_entry; bool test_code_error = false; size_t test_case_count = 0; bool disabled; int param_entries = 0; const char* param_entries_suite = NULL; int current_test_case_count; /* count all non parameterized and parameterized test cases */ list_for_every_entry(&_test_list, test_case, struct test_list_node, node) { /* exclude tests not part of the requested suite */ if (suite && strcmp(suite, test_case->suite)) { continue; } /* only count non-disabled test case as required by the GTest parser */ disabled = trusty_unittest_test_is_disabled(test_case); if (test_case->needs_param) { if (!param_entries_suite || !param_entries || strcmp(param_entries_suite, test_case->suite)) { /* count param_entries for test_case->suite */ param_entries = trusty_unittest_count_param_entries(test_case); param_entries_suite = test_case->suite; } if (!param_entries) { /* * Test code error shall be fixed and will prevent test * execution however we don't bail right away with the goal of * logging all erroneous test cases. */ test_code_error = true; continue; } current_test_case_count = param_entries; } else { current_test_case_count = 1; } if (!disabled) { /* non parameterized (singular) test case */ test_case_count += current_test_case_count; } } /* * Search for a test coding issue where a test generator exists * but is not backed by existing test case */ list_for_every_entry(&_test_param_list, param_entry, struct test_param_list_node, node) { if (!trusty_unittest_has_parameterized_test_case(param_entry->suite)) { test_code_error = true; trusty_unittest_print_status_name_param_duration( " FAILED ", param_entry->inst_name, param_entry->suite, "NO_TESTS", "Parameter Generator without tests!", ""); } } return test_code_error ? -1 : test_case_count; } /** * trusty_unittest_run_test_suite - run each test case associated with test * suite. * * @suite: Name of test suite * when suite is NULL, all test cases * from all test suites are executed. * @needs_param: when true run the parameterised test cases, * otherwise run the non-parameterised test cases * * Not meant for external use. * * Return: count of executed test cases */ static int trusty_unittest_run_test_suite(const char* suite, bool needs_param) { struct test_list_node* entry; int test_case_count = 0; list_for_every_entry(&_test_list, entry, struct test_list_node, node) { if ((!suite || !strcmp(suite, entry->suite)) && (entry->needs_param == needs_param)) { if (trusty_unittest_test_is_disabled(entry)) { trusty_unittest_print_status_name(entry->suite, entry->name, "DISABLED"); _test_context.tests_disabled++; } else { test_case_count++; entry->func(); } } } return test_case_count; } /* * The testing framework uses 3 global variables to keep track of tests and * related data: * * _test_context: contains information about the overall execution of the * framework (e.g. total tests run) and information about the currently * executing test (e.g. test name, suite name). * * _test_list: contains a list of tests that can be run. Each test belongs to a * test suite and may require parameters to be run. * * _test_param_list: contains a list of parameter generators for tests that * require parameters. Each generator is associated with a specific test suite. * Parameter generators are functions that return parameters that apply to all * the tests that require parameters (i.e. parameterized tests) in a given test * suite. * * Tests are only run as part of test suites. When a test suite is run all of * the non-paremeterized tests belonging to that suite are run first followed by * the parameterized tests in the suite. All of the parameterized tests in a * suite are run once for each value returned by a parameter generator * associated with that suite. */ static inline bool RUN_ALL_SUITE_TESTS(const char* suite) { struct test_param_list_node* param_entry; const void* test_param; int i; char param_str[64]; int actual_test_count = 0; int expected_test_count = trusty_unittest_count_test_cases(suite); if (expected_test_count == -1) { trusty_unittest_printf("Test Coding Error - aborting execution.\n"); return false; } trusty_unittest_printf( "[==========] Running %d tests from %s test suite%s.\n", expected_test_count, suite ? suite : "all", suite ? "" : "s"); _test_context.tests_total = 0; _test_context.tests_disabled = 0; _test_context.tests_failed = 0; _test_context.test_param = NULL; _test_context.inst_name = NULL; _test_context.param_name = param_str; _test_context.suite_duration_ms = 0; /* Run all the non-parameterized tests in the suite */ actual_test_count = trusty_unittest_run_test_suite(suite, false); /* For each parameter generator associated with the suite */ list_for_every_entry(&_test_param_list, param_entry, struct test_param_list_node, node) { if (!suite || !strcmp(suite, param_entry->suite)) { i = 0; /* For each parameter from the generator */ while ((test_param = param_entry->param_gen.gen_param( param_entry->param_gen.priv, i))) { /* Set the parameter for the next run */ _test_context.inst_name = param_entry->inst_name; _test_context.test_param = test_param; if (param_entry->to_string) { param_entry->to_string(test_param, param_str, sizeof(param_str)); } else { snprintf(param_str, sizeof(param_str), "%d", i); } /* Run all the parameterized tests in the suite */ actual_test_count += trusty_unittest_run_test_suite( param_entry->suite, true); i++; } } } if (actual_test_count != expected_test_count) { trusty_unittest_printf("[ RUN ] %s.test_count_match_check\n", suite ? suite : "all_suites"); trusty_unittest_printf( "[----------] %d tests ran, but expected %d tests.\n", actual_test_count, expected_test_count); trusty_unittest_print_status_name(suite ? suite : "all_suites", "test_count_match_check", " FAILED "); ++_test_context.tests_failed; ++_test_context.tests_total; } else if (actual_test_count == 0 && _test_context.tests_disabled == 0) { trusty_unittest_printf("[ RUN ] %s.test_count_empty_check\n", suite ? suite : "all_suites"); trusty_unittest_printf("[----------] 0 tests but none disabled.\n"); trusty_unittest_print_status_name(suite ? suite : "all_suites", "test_count_empty_check", " FAILED "); ++_test_context.tests_failed; ++_test_context.tests_total; } trusty_unittest_printf( "[==========] %d tests ran (%" PRIu64 " ms total).\n", _test_context.tests_total, _test_context.suite_duration_ms); if (_test_context.tests_total != _test_context.tests_failed) { trusty_unittest_printf( "[ PASSED ] %d tests.\n", _test_context.tests_total - _test_context.tests_failed); } if (_test_context.tests_skipped) { trusty_unittest_printf("[ SKIPPED ] %d tests.\n", _test_context.tests_skipped); } if (_test_context.tests_disabled) { trusty_unittest_printf("[ DISABLED ] %d tests.\n", _test_context.tests_disabled); } if (_test_context.tests_failed) { trusty_unittest_printf("[ FAILED ] %d tests.\n", _test_context.tests_failed); } return _test_context.tests_failed == 0; } static inline bool RUN_ALL_TESTS(void) { return RUN_ALL_SUITE_TESTS(NULL); } /** * GTEST_SKIP() - Skip current test * * This will skip the current test without triggering a failure. It will use * same test_abort label as the ASSERT_... macros. Calling this after a test has * failed or calling ASSERT_.../EXPECT_... macros after GTEST_SKIP has jumped * to test_abort is not supported. */ #define GTEST_SKIP() \ { \ if (!_test_context.skipped) { \ _test_context.skipped = true; \ _test_context.tests_skipped++; \ } \ goto test_abort; \ } #define ASSERT_EXPECT_TEST(op, op_pre, op_sep, op_args, is_hard_fail, \ fail_action, vals_type, vals_format_placeholder, \ print_cast, print_op, val1, val2, extra_msg...) \ { \ vals_type _val1 = val1; \ vals_type _val2 = val2; \ if (!op_pre(_val1 DELETE_PAREN op_sep _val2 DELETE_PAREN op_args)) { \ trusty_unittest_printf("%s: @ %s:%d\n", _test_context.test_name, \ __FILE__, __LINE__); \ trusty_unittest_printf( \ " expected: %s (" vals_format_placeholder ") " print_op \ " %s (" vals_format_placeholder ")\n", \ #val1, print_cast _val1, #val2, print_cast _val2); \ trusty_unittest_printf(" " extra_msg); \ trusty_unittest_printf("\n"); \ if (_test_context.all_ok) { \ _test_context.all_ok = false; \ _test_context.tests_failed++; \ } \ _test_context.hard_fail |= is_hard_fail; \ fail_action \ } \ } static inline bool HasFailure(void) { return !_test_context.all_ok; } /** * INSTANTIATE_TEST_SUITE_P - Instantiate parameters for a test suite * @inst_name: Name for instantiation of parameters. Should not contain * underscores. * @suite_name: Name of test suite associated with the parameters * @param_gen: One of the parameter generators (see below) * @param_to_string: Function of type &typedef test_param_to_string_t * used to convert a parameter to its string form. This * argument is optional. * * Parameter Generators: * testing_Range(being, end, step): * Returns the values {begin, being+step, being+step+step, ...} up to but not * including end. step is optional and defaults to 1. * * testing_Values(v1, v2, ..., vN): * Returns the values {v1, v2, ..., vN) * * testing_ValuesIn(array) * Returns the values in array * * testing_Bool() * Returns {false, true} * * testing_Combine(g1, [g2, g3, g4, g5]): * Returns the values of the combinations of the provided generators * (min 1, max 5) an as an array. */ #define INSTANTIATE_TEST_SUITE_P(inst_name, suite_name, param_gen_args...) \ INSTANTIATE_TEST_SUITE_P_INTERNAL(inst_name, suite_name, param_gen_args, \ NULL, ) /** * GetParam() - Returns a pointer to the current test parameter * * Context: This function can be called within a parameterized test to * retrieve the current parameter to the test. * * Return: a pointer to the current test parameter. * * This pointer should be cast to the expected parameter type for the executing * test. */ static inline const void* GetParam(void) { return _test_context.test_param; } #define ASSERT_EXPECT_LONG_TEST(op, is_hard_fail, fail_action, val1, val2, \ args...) \ ASSERT_EXPECT_TEST(op, , (op), (), is_hard_fail, fail_action, \ __typeof__(val2), "%ld", (long), #op, val1, val2, args) #define ASSERT_EXPECT_STR_TEST(func, is_hard_fail, fail_action, args...) \ ASSERT_EXPECT_TEST(func, func, (, ), (), is_hard_fail, fail_action, \ const char*, "\"%s\"", , args) #define ASSERT_EXPECT_STRN_TEST(func, n, is_hard_fail, fail_action, args...) \ ASSERT_EXPECT_TEST(func, func, (, ), (, n), is_hard_fail, fail_action, \ const char*, "\"%s\"", , args) #define EXPECT_TEST(op, args...) ASSERT_EXPECT_LONG_TEST(op, false, , args) #define EXPECT_EQ(args...) EXPECT_TEST(==, args) #define EXPECT_NE(args...) EXPECT_TEST(!=, args) #define EXPECT_LT(args...) EXPECT_TEST(<, args) #define EXPECT_LE(args...) EXPECT_TEST(<=, args) #define EXPECT_GT(args...) EXPECT_TEST(>, args) #define EXPECT_GE(args...) EXPECT_TEST(>=, args) #define EXPECT_STR_TEST(func, args...) \ ASSERT_EXPECT_STR_TEST(func, false, , args) #define EXPECT_STREQ(args...) EXPECT_STR_TEST(!strcmp, "==", args) #define EXPECT_STRNE(args...) EXPECT_STR_TEST(strcmp, "!=", args) #define EXPECT_STRCASEEQ(args...) \ EXPECT_STR_TEST(!strcasecmp, "== (ignoring case)", args) #define EXPECT_STRCASENE(args...) \ EXPECT_STR_TEST(strcasecmp, "!= (ignoring case)", args) #define EXPECT_STRN_TEST(func, n, args...) \ ASSERT_EXPECT_STRN_TEST(func, n, false, , args) #define EXPECT_STREQN(val1, val2, n, args...) \ EXPECT_STR_TEST(!strncmp, n, "==", val1, val2, args) #define EXPECT_STRNEN(val1, val2, n, args...) \ EXPECT_STR_TEST(strncmp, n, "!=", val1, val2, args) #define EXPECT_STRCASEEQN(val1, val2, n, args...) \ EXPECT_STR_TEST(!strncasecmp, n, "== (ignoring case)", val1, val2, args) #define EXPECT_STRCASENEN(val1, val2, n, args...) \ EXPECT_STR_TEST(strncasecmp, n, "!= (ignoring case)", val1, val2, args) #define ASSERT_TEST(op, args...) \ ASSERT_EXPECT_LONG_TEST(op, true, goto test_abort;, args) #define ASSERT_EQ(args...) ASSERT_TEST(==, args) #define ASSERT_NE(args...) ASSERT_TEST(!=, args) #define ASSERT_LT(args...) ASSERT_TEST(<, args) #define ASSERT_LE(args...) ASSERT_TEST(<=, args) #define ASSERT_GT(args...) ASSERT_TEST(>, args) #define ASSERT_GE(args...) ASSERT_TEST(>=, args) #define ASSERT_STR_TEST(func, args...) \ ASSERT_EXPECT_STR_TEST(func, true, goto test_abort;, args) #define ASSERT_STREQ(args...) ASSERT_STR_TEST(!strcmp, "==", args) #define ASSERT_STRNE(args...) ASSERT_STR_TEST(strcmp, "!=", args) #define ASSERT_STRCASEEQ(args...) \ ASSERT_STR_TEST(!strcasecmp, "== (ignoring case)", args) #define ASSERT_STRCASENE(args...) \ ASSERT_STR_TEST(strcasecmp, "!= (ignoring case)", args) #define ASSERT_STRN_TEST(func, n, args...) \ ASSERT_EXPECT_STRN_TEST(func, n, true, goto test_abort;, args) #define ASSERT_STREQN(val1, val2, n, args...) \ ASSERT_STRN_TEST(!strncmp, n, "==", val1, val2, args) #define ASSERT_STRNEN(val1, val2, n, args...) \ ASSERT_STRN_TEST(strncmp, n, "!=", val1, val2, args) #define ASSERT_STRCASEEQN(val1, val2, n, args...) \ ASSERT_STRN_TEST(!strncasecmp, n, "== (ignoring case)", val1, val2, args) #define ASSERT_STRCASENEN(val1, val2, n, args...) \ ASSERT_STRN_TEST(strncasecmp, n, "!= (ignoring case)", val1, val2, args) __END_CDECLS