Files
mars-matrixssl/core/include/testsupp/testsupp.h
Janne Johansson d0a51a7e43 MatrixSSL 4.0.0
2018-09-13 12:17:26 +03:00

271 lines
9.6 KiB
C

/**
* @file testsupp.h
* @version $Format:%h%d$
*
* Common testing framework for building test programs.
*/
/*
* Copyright (c) 2017-2018 INSIDE Secure Corporation
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#ifndef _h_TESTSUPP_H_
# define _h_TESTSUPP_H_ 1
# ifndef _h_PS_CORECONFIG
# ifdef MATRIX_CONFIGURATION_INCDIR_FIRST
# include <coreConfig.h> /* Must be first included */
# else
# include "coreConfig.h" /* Must be first included */
# endif
# endif /* _h_PS_CORECONFIG */
#include "cl_header_begin.h"
/* Classification of test results. */
typedef enum { OK, FAILED, WEAK, SKIPPED } TEST_RESULT;
# ifndef TEST_TAG
/* It is recommended to override the tag. */
# define TEST_TAG TEST
# endif /* TEST_TAG */
# define debugf(x, ...) PS_LOGF_TRACE(TEST_TAG, x ,##__VA_ARGS__ )
/* Internal variable for extended status information. */
extern char extra_info[128];
/* Breakpoint for tests. */
int test(int condition);
/* Breakpoint for failures. */
TEST_RESULT fail(void);
/* Reporting failures. */
TEST_RESULT fail_at(const char *file, int line, const char *cond);
/* Convenience macro for ensuring condition is true. */
#define FAIL_IF(condition) \
do { \
if (test(condition)) { \
return fail_at(__FILE__, __LINE__, #condition); } \
} while (0)
/* Find tests from command line input. */
int test_match(int argc, char **argv, const char *string);
/* List test. */
# define TEST(fun) \
do { \
int res; \
if (argc == 2 && argv[1] != NULL && \
!Strcmp(argv[1], "--list")) { \
Printf("%s\n", #fun); \
break; \
} else if (test_match(argc, argv, #fun)) { \
Printf("%s ... ", #fun); \
Fflush(stdout); \
res = fun(); \
counter[(int) res]++; \
Printf("%s%s\n", res == OK ? "OK" : \
res == WEAK ? "OK (but size considered weak)" : \
res == SKIPPED ? "OK (not supported)" : \
"FAILED", extra_info); \
extra_info[0] = 0; \
} \
} while (0)
TEST_RESULT ok_partial(const char *file, int line);
#define OK_PARTIAL ok_partial(__FILE__, __LINE__)
extern int counter[4];
/* Provide usual facilities. */
void testsupp_start_test_program(int argc, char **argv);
/* Give test statistics. */
int testsupp_summarize_results(void);
/* Finish test, with handling of a special case: listing of tests.
Also includes testsupp_summarize_results() when needed. */
int testsupp_finish(void);
/* Process all tests registered via TestAdd(). */
void testsupp_process(int argc, char **argv);
/* Provide main.
Without oldstyle tests TESTSUPP_MAIN() will suffice. */
#define TESTSUPP_MAIN(possible_oldstyle_test_and_semicolon) \
int main(int argc, char **argv) \
{ \
testsupp_start_test_program(argc, argv); \
testsupp_process(argc, argv); \
possible_oldstyle_test_and_semicolon \
return testsupp_finish(); \
} \
extern int require_semicolon
/* Alternatively the test needs to implement main function.
Something like this: */
# ifdef EXAMPLE_MAIN
int main(int argc, char **argv)
{
testsupp_start_test_program(argc, argv);
testsupp_process(argc, argv);
/* Tests can also be executed using the old style:
Define test function, list it with TEST(). */
TEST(TEST_OldStyle);
return testsupp_finish();
}
# endif /* EXAMPLE_MAIN */
/* Internal part: using test entries directly. */
#include "list.h"
/* Defines single test, including its name, function to execute and
desired outcome. */
struct TestEntry
{
const char *TestName;
void *TestParameter;
enum { TEST_DISABLED, TEST_ENABLED } TestStatus;
TEST_RESULT TestExpectedResult;
TEST_RESULT (*TestFunction)(void);
void (*TestFreeFunction)(void);
DLListEntry dle;
};
/* Get name of the current test. */
const char *CurrentTestGetName(void);
/* Get parameter (generic void * pointer) of the current test. */
void *CurrentTestGetParameter(void);
/* Add test to list of tests. */
void TestAdd(struct TestEntry *te);
/* Process tests: print or execute them. */
void TestProcess(int argc, char **argv);
/* Clean memory reserved for tests. */
void TestCleanup(void);
/* Default AUTO_TEST parameters. */
extern struct TestEntry AutoTestEntryDefault;
/* Add test to list of tests to perform. */
#define AUTO_TEST_ADD(name) AUTO_TEST_ADD_COMMON(name, )
/* Add test to list, but disable it for now.
Test will only run if explicitly requested. */
#define AUTO_TEST_ADD_DISABLED(name) \
AUTO_TEST_ADD_COMMON(name, te.TestStatus = TEST_DISABLED;)
/* Add test to list, but expect it to fail.
This will reverse interpretation of test results. */
#define AUTO_TEST_ADD_XFAIL(name) \
AUTO_TEST_ADD_COMMON(name, te.TestExpectedResult = FAILED;)
/* Define a test and add it to tests to perform. */
#define AUTO_TEST(name) AUTO_TEST_ADD(name); TEST_RESULT name(void)
/* Define a test and add it to list of tests, but do not run it by default. */
#define AUTO_TEST_DISABLED(name) \
AUTO_TEST_ADD_DISABLED(name); TEST_RESULT name(void)
/* Define a test and add it to list of tests.
The test is expected to fail for now.
(E.g. missing test or software feature.) */
#define AUTO_TEST_XFAIL(name) \
AUTO_TEST_ADD_XFAIL(name); TEST_RESULT name(void)
/* Worker macros. */
#define AUTO_TEST_ADD_CONCAT_(s_a, s_b) s_a ## s_b
#define AUTO_TEST_ADD_CONCAT(s_a, s_b) AUTO_TEST_ADD_CONCAT_(s_a, s_b)
/* Worker macro, use AUTO_TEST or AUTO_TEST_ADD etc. instead. */
#define AUTO_TEST_ADD_COMMON(name, extra_code) \
TEST_RESULT name(void); \
static void AUTO_TEST_ADD_CONCAT(name,_constructor_auto_add)(void) \
PS_GCC_SPECIFIC(__attribute__((__constructor__))); \
\
static void AUTO_TEST_ADD_CONCAT(name,_constructor_auto_add)(void) \
{ \
static struct TestEntry te; \
te.TestName = #name; \
te.TestParameter = AutoTestEntryDefault.TestParameter; \
te.TestStatus = AutoTestEntryDefault.TestStatus; \
te.TestExpectedResult = AutoTestEntryDefault.TestExpectedResult; \
te.TestFunction = &name; \
te.TestFreeFunction = AutoTestEntryDefault.TestFreeFunction; \
extra_code \
\
TestAdd(&te); \
}
/* Examples of tests */
# ifdef DO_NOT_COMPILE_TEST_EXAMPLES
/* These examples intent to illustrate how to use AUTO_TEST and
its variants. (Note: also remember to use TESTSUPP_MAIN or equivalent. */
AUTO_TEST(TEST_Arithmetic)
{
FAIL_IF(1 + 1 != 2);
return OK;
}
AUTO_TEST(TEST_Arithmetic2)
{
FAIL_IF(1 * 1 != 1);
return OK;
}
AUTO_TEST_DISABLED(TEST_Arithmetic3)
{
/* Disabled the test due to a small error in the test. */
/* Test can be executed if explicitly requested. */
FAIL_IF(1.5 * 1.5 != 2.0);
return OK;
}
#include "math.h"
AUTO_TEST_XFAIL(TEST_Arithmetic4)
{
/* This test fails on most devices, because of math library precision. */
FAIL_IF(M_PI != 3.14);
return OK;
}
# endif /* DO_NOT_COMPILE_TEST_EXAMPLES */
#include "cl_header_end.h"
#endif /* testsupp.h */
/* end of file testsupp.h */