269 lines
8.5 KiB
C
269 lines
8.5 KiB
C
/* Copyright (c) (2012,2014-2020) Apple Inc. All rights reserved.
|
||
*
|
||
* corecrypto is licensed under Apple Inc.’s Internal Use License Agreement (which
|
||
* is contained in the License.txt file distributed with corecrypto) and only to
|
||
* people who accept that license. IMPORTANT: Any license rights granted to you by
|
||
* Apple Inc. (if any) are limited to internal use within your organization only on
|
||
* devices and computers you own or control, for the sole purpose of verifying the
|
||
* security characteristics and correct functioning of the Apple Software. You may
|
||
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
|
||
*/
|
||
|
||
#ifndef _TESTMORE_H_
|
||
#define _TESTMORE_H_ 1
|
||
|
||
#include <errno.h>
|
||
#include <string.h>
|
||
#include <stdio.h>
|
||
#include <corecrypto/ccn.h>
|
||
#include "cc_debug.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#define TM_UNUSED CC_UNUSED
|
||
|
||
/* This is included here, because its already included by all the test case */
|
||
#include "testlist.h"
|
||
|
||
/* rng to use for testing */
|
||
extern struct ccrng_state *global_test_rng;
|
||
unsigned int cc_rand(unsigned max);
|
||
cc_unit cc_rand_unit(void);
|
||
|
||
typedef int (*one_test_entry)(int argc, char *const *argv);
|
||
|
||
#define ONE_TEST_ENTRY(x) int x(int argc, char *const *argv)
|
||
|
||
struct one_test_s {
|
||
char *name; /* test name. */
|
||
one_test_entry entry; /* entry point. */
|
||
int sub_tests; /* number of subtests. */
|
||
int failed_tests; /* number of failed tests. */
|
||
int warning_tests; /* number of tests raised a warning. */
|
||
int todo_tests; /* number of todo tests */
|
||
int actual_tests; /* number of tests attempted. */
|
||
int planned_tests; /* number of planned tests. */
|
||
const char *plan_file; /* full path to file that called plan_tests() */
|
||
unsigned int plan_line;/* line number in plan_file at which plan_tests was called. */
|
||
unsigned long long duration; /* test duration in msecs. */
|
||
int executed; /* whether the test was run */
|
||
/* add more later: timing, etc... */
|
||
};
|
||
|
||
extern struct one_test_s testlist[];
|
||
|
||
int run_one_test(struct one_test_s *test, int argc, char * const *argv, size_t seed_nbytes, const unsigned char *seed);
|
||
|
||
/* this test harnes rely on shadowing for TODO, SKIP and SETUP blocks */
|
||
#pragma GCC diagnostic ignored "-Wshadow"
|
||
|
||
#define diag_linereturn() fputs("\n", stderr);
|
||
|
||
#define ok(THIS, args...) \
|
||
test_ok(!!(THIS), NULL, test_directive, test_reason, \
|
||
__FILE__, __LINE__, args)
|
||
|
||
#define is(THIS, THAT, args...) \
|
||
({ \
|
||
char test_string[200]={0}; \
|
||
snprintf(test_string,sizeof(test_string),args); \
|
||
__typeof__(THIS) _this = (THIS); \
|
||
__typeof__(THAT) _that = (THAT); \
|
||
test_ok((_this == _that), test_string, test_directive, test_reason, \
|
||
__FILE__, __LINE__, \
|
||
"# got: '%d'\n" \
|
||
"# expected: '%d'\n" , \
|
||
_this, _that); \
|
||
})
|
||
|
||
#define is_or_goto(THIS, THAT, TESTNAME, LABEL) \
|
||
({ \
|
||
__typeof__(THIS) _this = (THIS); \
|
||
__typeof__(THAT) _that = (THAT); \
|
||
test_ok((_this == _that), TESTNAME, test_directive, test_reason, \
|
||
__FILE__, __LINE__, \
|
||
"# got: '%d'\n" \
|
||
"# expected: '%d'\n" , \
|
||
_this, _that); \
|
||
if(_this != _that) goto LABEL; \
|
||
})
|
||
|
||
#define isnt(THIS, THAT, TESTNAME) \
|
||
cmp_ok((THIS), !=, (THAT), (TESTNAME))
|
||
#define diag(MSG, ARGS...) \
|
||
test_diag(test_directive, test_reason, __FILE__, __LINE__, MSG, ## ARGS)
|
||
#define cmp_ok(THIS, OP, THAT, TESTNAME) \
|
||
({ \
|
||
__typeof__(THIS) _this = (THIS); \
|
||
__typeof__(THAT) _that = (THAT); \
|
||
test_ok((_this OP _that), TESTNAME, test_directive, test_reason, \
|
||
__FILE__, __LINE__, \
|
||
"# '%d'\n" \
|
||
"# " #OP "\n" \
|
||
"# '%d'\n", \
|
||
_this, _that); \
|
||
})
|
||
#define eq_string(THIS, THAT, TESTNAME) \
|
||
({ \
|
||
const char *_this = (THIS); \
|
||
const char *_that = (THAT); \
|
||
test_ok(!strcmp(_this, _that), TESTNAME, test_directive, test_reason, \
|
||
__FILE__, __LINE__, \
|
||
"# '%s'\n" \
|
||
"# eq\n" \
|
||
"# '%s'\n", \
|
||
_this, _that); \
|
||
})
|
||
#define eq_stringn(THIS, THISLEN, THAT, THATLEN, TESTNAME) \
|
||
({ \
|
||
__typeof__(THISLEN) _thislen = (THISLEN); \
|
||
__typeof__(THATLEN) _thatlen = (THATLEN); \
|
||
const char *_this = (THIS); \
|
||
const char *_that = (THAT); \
|
||
test_ok(_thislen == _thatlen && !strncmp(_this, _that, _thislen), \
|
||
TESTNAME, test_directive, test_reason, \
|
||
__FILE__, __LINE__, \
|
||
"# '%.*s'\n" \
|
||
"# eq\n" \
|
||
"# '%.*s'\n", \
|
||
(int)_thislen, _this, (int)_thatlen, _that); \
|
||
})
|
||
#define like(THIS, REGEXP, TESTNAME) like_not_yet_implemented()
|
||
#define unlike(THIS, REGEXP, TESTNAME) unlike_not_yet_implemented()
|
||
#define is_deeply(STRUCT1, STRUCT2, TESTNAME) is_deeply_not_yet_implemented()
|
||
#define TODO switch(0) default
|
||
#define SKIP switch(0) default
|
||
#define SETUP switch(0) default
|
||
#define todo(REASON) const char *test_directive CC_UNUSED = "TODO", \
|
||
*test_reason CC_UNUSED = (REASON)
|
||
#define skip(WHY, HOW_MANY, UNLESS) if (!(UNLESS)) \
|
||
{ test_skip((WHY), (HOW_MANY), 0); break; }
|
||
#define setup(REASON) const char *test_directive = "SETUP", \
|
||
*test_reason = (REASON)
|
||
#define pass(TESTNAME) ok(1, (TESTNAME))
|
||
#define fail(TESTNAME) ok(0, (TESTNAME))
|
||
#define BAIL_OUT(WHY) test_bail_out(WHY, __FILE__, __LINE__)
|
||
#define plan_skip_all(REASON) test_plan_skip_all(REASON)
|
||
#define plan_tests(COUNT) test_plan_tests(COUNT, __FILE__, __LINE__)
|
||
|
||
#define ok_status(THIS, TESTNAME) \
|
||
({ \
|
||
int _this = (THIS); \
|
||
test_ok(!_this, TESTNAME, test_directive, test_reason, \
|
||
__FILE__, __LINE__, \
|
||
"# status: %d\n",_this); \
|
||
})
|
||
|
||
#define ok_status_or_goto(THIS, TESTNAME,LABEL) \
|
||
({ \
|
||
int _this = (THIS); \
|
||
test_ok(!_this, TESTNAME, test_directive, test_reason, \
|
||
__FILE__, __LINE__, \
|
||
"# status: %d\n",_this); \
|
||
if(_this) goto LABEL; \
|
||
})
|
||
|
||
#define ok_or_fail(THIS, args...) \
|
||
({ \
|
||
if (!ok(THIS,args)) return 0; \
|
||
})
|
||
|
||
#define ok_or_warning(THIS, TESTNAME) \
|
||
({ \
|
||
int _this = (THIS); \
|
||
test_ok(_this, TESTNAME, "WARNING", test_reason, \
|
||
__FILE__, __LINE__, \
|
||
"# status: %ld\n", _this); \
|
||
})
|
||
|
||
#define ok_or_goto(THIS, TESTNAME, LABEL) \
|
||
({ \
|
||
int _this = (THIS); \
|
||
test_ok(_this, TESTNAME, test_directive, test_reason, \
|
||
__FILE__, __LINE__, \
|
||
"# status: %d\n", _this);\
|
||
if(_this == 0) goto LABEL; \
|
||
})
|
||
|
||
#define ccn_cmp_print(_NLEN_, _P1_, _P2_) \
|
||
({ \
|
||
int _this = ccn_cmp(_NLEN_, (_P1_), (_P2_)); \
|
||
if(_this!=0) {ccn_lprint(_NLEN_,"Compare: ",(_P1_)); \
|
||
ccn_lprint(_NLEN_," and: ",(_P2_));} \
|
||
_this; \
|
||
})
|
||
|
||
#define ok_ccn_cmp(_NLEN_, _P1_, _P2_, args...) ok(ccn_cmp_print(_NLEN_, _P1_, _P2_)==0, args)
|
||
|
||
#define memcmp_print(_P1_, _P2_, _LEN_) \
|
||
({ \
|
||
int _this = memcmp((_P1_), (_P2_), _LEN_); \
|
||
if(_this!=0) {cc_print("Compare: ",_LEN_,(const uint8_t*)(_P1_)); \
|
||
cc_print(" and: ",_LEN_,(const uint8_t*)(_P2_));} \
|
||
_this; \
|
||
})
|
||
|
||
#define notmemcmp_print(_P1_, _P2_, _LEN_) \
|
||
({ \
|
||
int _this = memcmp((_P1_), (_P2_), _LEN_); \
|
||
if(_this==0) {cc_print("Compare: ",_LEN_,(const uint8_t*)(_P1_)); \
|
||
cc_print(" and: ",_LEN_,(const uint8_t*)(_P2_));} \
|
||
!_this; \
|
||
})
|
||
|
||
#define ok_memcmp(_P1_, _P2_, _LEN_, args...) ok(memcmp_print(_P1_, _P2_, _LEN_)==0, args)
|
||
#define ok_notmemcmp(_P1_, _P2_, _LEN_, args...) ok(notmemcmp_print(_P1_, _P2_, _LEN_)==0, args)
|
||
|
||
|
||
#define ok_memcmp_or_fail(_P1_, _P2_, _LEN_, args...) \
|
||
({ \
|
||
if(!ok(memcmp_print(_P1_, _P2_, _LEN_)==0, args)) return 0; \
|
||
})
|
||
|
||
#define ok_memcmp_or_goto(_P1_, _P2_, _LEN_, _LABEL_, args...) \
|
||
({ \
|
||
if(!ok(memcmp_print(_P1_, _P2_, _LEN_)==0, args)) goto _LABEL_; \
|
||
})
|
||
|
||
#define is_status(THIS, THAT, TESTNAME) \
|
||
({ \
|
||
OSStatus _this = (THIS); \
|
||
OSStatus _that = (THAT); \
|
||
test_ok(_this == _that, TESTNAME, test_directive, test_reason, \
|
||
__FILE__, __LINE__, \
|
||
"# got: %ld\n" \
|
||
"# expected: %ld\n", \
|
||
_this, _that); \
|
||
})
|
||
|
||
#define entryPoint(testname,supportname) \
|
||
int testname(TM_UNUSED int argc, TM_UNUSED char *const *argv) { \
|
||
char prString[80];\
|
||
sprintf(prString, "No %s Support in this release\n", supportname);\
|
||
plan_tests(1); \
|
||
diag(prString); \
|
||
ok(1, prString); \
|
||
return 0; \
|
||
}
|
||
|
||
|
||
extern const char *test_directive;
|
||
extern const char *test_reason;
|
||
|
||
void test_bail_out(const char *reason, const char *file, unsigned line);
|
||
int test_diag(const char *directive, const char *reason,
|
||
const char *file, unsigned line, const char *fmt, ...);
|
||
int test_ok(int passed, const char *description, const char *directive,
|
||
const char *reason, const char *file, unsigned line, const char *fmt, ...);
|
||
void test_plan_skip_all(const char *reason);
|
||
void test_plan_tests(int count, const char *file, unsigned line);
|
||
void test_skip(const char *reason, int how_many, int unless);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif /* __cplusplus */
|
||
|
||
#endif /* !_TESTMORE_H_ */
|