unit_tests/check_clamav.c
fe473bcb
 #if HAVE_CONFIG_H
 #include "clamav-config.h"
 #endif
 
 #include <stdio.h>
 
 #include <stdlib.h>
 #include <limits.h>
3dcc2d78
 #include <fcntl.h>
fe473bcb
 #include <string.h>
 #include <check.h>
 #include "../libclamav/clamav.h"
 #include "../libclamav/others.h"
 #include "../libclamav/matcher.h"
04f9bedf
 #include "../libclamav/version.h"
c5944b54
 #include "../libclamav/dsig.h"
4e46d65d
 #include "../libclamav/sha256.h"
a39b29cb
 #include "checks.h"
fe473bcb
 
 /* extern void cl_free(struct cl_engine *engine); */
 START_TEST (test_cl_free)
 /*
     struct cl_engine *engine = NULL;
     cl_free(NULL);
 */
 END_TEST
 
 /* extern struct cl_engine *cl_dup(struct cl_engine *engine); */
 START_TEST (test_cl_dup)
     /*
     struct cl_engine *engine;
     fail_unless(NULL == cl_dup(NULL), "cl_dup null pointer");
     */
 END_TEST
 
 /* extern int cl_build(struct cl_engine *engine); */
 START_TEST (test_cl_build)
     /*
     struct cl_engine *engine;
     fail_unless(CL_ENULLARG == cl_build(NULL), "cl_build null pointer");
     engine = calloc(sizeof(struct cl_engine),1);
     fail_unless(engine, "cl_build calloc");
     fail_unless(CL_ENULLARG == cl_build(engine), "cl_build(engine) with null ->root");
     */
 /*    engine->root = cli_calloc(CL_TARGET_TABLE_SIZE, sizeof(struct cli_matcher *)); */
 END_TEST
 
 /* extern void cl_debug(void); */
 START_TEST (test_cl_debug)
5cd3f734
 {
2b9e5d29
     int old_status = cli_debug_flag;
fe473bcb
     cli_debug_flag = 0;
     cl_debug();
     fail_unless(1 == cli_debug_flag, "cl_debug failed to set cli_debug_flag");
 
     cli_debug_flag = 1;
     cl_debug();
     fail_unless(1 == cli_debug_flag, "cl_debug failed when flag was already set");
2b9e5d29
     cli_debug_flag = old_status;
5cd3f734
 }
fe473bcb
 END_TEST
 
 /* extern const char *cl_retdbdir(void); */
 START_TEST (test_cl_retdbdir)
     fail_unless(!strcmp(DATADIR, cl_retdbdir()), "cl_retdbdir");
 END_TEST
 
add738d2
 #ifndef REPO_VERSION
 #define REPO_VERSION VERSION
 #endif
 
fe473bcb
 /* extern const char *cl_retver(void); */
 START_TEST (test_cl_retver)
5cd3f734
 {
04f9bedf
     const char *ver = cl_retver();
b105842c
     fail_unless(!strcmp(REPO_VERSION""VERSION_SUFFIX, ver),"cl_retver");
add738d2
     fail_unless(strcspn(ver,"012345789") < strlen(ver),
 		    "cl_retver must have a number");
5cd3f734
 }
fe473bcb
 END_TEST
 
 /* extern void cl_cvdfree(struct cl_cvd *cvd); */
 START_TEST (test_cl_cvdfree)
 /*
     struct cl_cvd *cvd1, *cvd2;
 
     cvd1 = malloc(sizeof(struct cl_cvd));
     fail_unless(cvd1, "cvd malloc");
     cl_cvdfree(cvd1);
 
     cvd2 = malloc(sizeof(struct cl_cvd));
     cvd2->time = malloc(1);
     cvd2->md5 = malloc(1);
     cvd2->dsig= malloc(1);
     cvd2->builder = malloc(1);
     fail_unless(cvd2, "cvd malloc");
     fail_unless(cvd2->time, "cvd malloc");
     fail_unless(cvd2->md5, "cvd malloc");
     fail_unless(cvd2->dsig, "cvd malloc");
     fail_unless(cvd2->builder, "cvd malloc");
     cl_cvdfree(cvd2);
     cl_cvdfree(NULL);
 */
 END_TEST
 
 /* extern int cl_statfree(struct cl_stat *dbstat); */
 START_TEST (test_cl_statfree)
 /*
     struct cl_stat *stat;
     fail_unless(CL_ENULLARG == cl_statfree(NULL), "cl_statfree(NULL)");
     
     stat = malloc(sizeof(struct cl_stat));
     fail_unless(NULL != stat, "malloc");
     fail_unless(CL_SUCCESS == cl_statfree(stat), "cl_statfree(empty_struct)");
     
     stat = malloc(sizeof(struct cl_stat));
     fail_unless(NULL != stat, "malloc");
     stat->stattab = strdup("test");
     fail_unless(NULL != stat->stattab, "strdup");
     fail_unless(CL_SUCCESS == cl_statfree(stat), "cl_statfree(stat with stattab)");
 
     stat = malloc(sizeof(struct cl_stat));
     fail_unless(NULL != stat, "malloc");
     stat->stattab = NULL;
     fail_unless(CL_SUCCESS == cl_statfree(stat), "cl_statfree(stat with stattab) set to NULL");
 */
 END_TEST
 
 /* extern unsigned int cl_retflevel(void); */
 START_TEST (test_cl_retflevel)
 END_TEST    
 
 /* extern struct cl_cvd *cl_cvdhead(const char *file); */
 START_TEST (test_cl_cvdhead)
 /*
     fail_unless(NULL == cl_cvdhead(NULL), "cl_cvdhead(null)");
     fail_unless(NULL == cl_cvdhead("input/cl_cvdhead/1.txt"), "cl_cvdhead(515 byte file, all nulls)");
 */
     /* the data read from the file is passed to cl_cvdparse, test cases for that are separate */
 END_TEST
 
 /* extern struct cl_cvd *cl_cvdparse(const char *head); */
 START_TEST (test_cl_cvdparse)
 END_TEST
 
 /* int cl_scandesc(int desc, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options) */
 START_TEST (test_cl_scandesc)
 END_TEST
 
 /* int cl_scanfile(const char *filename, const char **virname, unsigned long int *scanned, const struct cl_engine *engine, const struct cl_limits *limits, unsigned int options) */
 START_TEST (test_cl_scanfile)
 END_TEST
 
 /* int cl_load(const char *path, struct cl_engine **engine, unsigned int *signo, unsigned int options) */
 START_TEST (test_cl_load)
 END_TEST
 
 /* int cl_cvdverify(const char *file) */
 START_TEST (test_cl_cvdverify)
 END_TEST
 
 /* int cl_statinidir(const char *dirname, struct cl_stat *dbstat) */
 START_TEST (test_cl_statinidir)
 END_TEST
 
 /* int cl_statchkdir(const struct cl_stat *dbstat) */
 START_TEST (test_cl_statchkdir)
 END_TEST
 
 /* void cl_settempdir(const char *dir, short leavetemps) */
 START_TEST (test_cl_settempdir)
 END_TEST
 
 /* const char *cl_strerror(int clerror) */
 START_TEST (test_cl_strerror)
 END_TEST
 
c47e43ce
 static Suite *test_cl_suite(void)
fe473bcb
 {
c47e43ce
     Suite *s = suite_create("cl_api");
     TCase *tc_cl = tcase_create("cl_dup");
fe473bcb
 
     suite_add_tcase (s, tc_cl);
     tcase_add_test(tc_cl, test_cl_free);
     tcase_add_test(tc_cl, test_cl_dup);
     tcase_add_test(tc_cl, test_cl_build);
     tcase_add_test(tc_cl, test_cl_debug);
     tcase_add_test(tc_cl, test_cl_retdbdir);
     tcase_add_test(tc_cl, test_cl_retver);
     tcase_add_test(tc_cl, test_cl_cvdfree);
     tcase_add_test(tc_cl, test_cl_statfree);
     tcase_add_test(tc_cl, test_cl_retflevel);
     tcase_add_test(tc_cl, test_cl_cvdhead);
     tcase_add_test(tc_cl, test_cl_cvdparse);
     tcase_add_test(tc_cl, test_cl_scandesc);
     tcase_add_test(tc_cl, test_cl_scanfile);
     tcase_add_test(tc_cl, test_cl_load);
     tcase_add_test(tc_cl, test_cl_cvdverify);
     tcase_add_test(tc_cl, test_cl_statinidir);
     tcase_add_test(tc_cl, test_cl_statchkdir);
     tcase_add_test(tc_cl, test_cl_settempdir);
     tcase_add_test(tc_cl, test_cl_strerror);
 
     return s;
 }
 
c47e43ce
 static uint8_t le_data[4] = {0x67,0x45,0x23,0x01};
 static int32_t le_expected[4] = { 0x01234567, 0x67012345, 0x45670123, 0x23456701};
2565ef49
 uint8_t *data = NULL;
 uint8_t *data2 = NULL;
c47e43ce
 #define DATA_REP 100
 
 static void data_setup(void)
 {
         uint8_t *p;
         size_t i;
 
2565ef49
 	data = malloc(sizeof(le_data)*DATA_REP);
 	data2 = malloc(sizeof(le_data)*DATA_REP);
 	fail_unless(!!data, "unable to allocate memory for fixture");
         fail_unless(!!data2, "unable to allocate memory for fixture");
c47e43ce
         p = data;
         /* make multiple copies of le_data, we need to run readint tests in a loop, so we need
          * to give it some data to run it on */
         for(i=0; i<DATA_REP;i++) {
                 memcpy(p, le_data, sizeof(le_data));
                 p += sizeof(le_data);
         }
         memset(data2, 0, DATA_REP*sizeof(le_data));
 }
 
 static void data_teardown(void)
 {
         free(data);
377a2330
 	free(data2);
c47e43ce
 }
 
99f74adc
 #ifdef CHECK_HAVE_LOOPS
c47e43ce
 /* test reading with different alignments, _i is parameter from tcase_add_loop_test */
2565ef49
 START_TEST (test_cli_readint16)
 {
     size_t j;
     int16_t value;
     /* read 2 bytes apart, start is not always aligned*/
     for(j=_i;j <= DATA_REP*sizeof(le_data)-2;j += 2) {
         value = le_expected[j&3];
         fail_unless(cli_readint16(&data[j]) == value, "(1) data read must be little endian");
     }
     /* read 2 bytes apart, always aligned*/
     for(j=0;j <= DATA_REP*sizeof(le_data)-2;j += 2) {
         value = le_expected[j&3];
         fail_unless(cli_readint16(&data[j]) == value, "(2) data read must be little endian");
     }
 }
 END_TEST
 
 /* test reading with different alignments, _i is parameter from tcase_add_loop_test */
 START_TEST (test_cli_readint32)
c47e43ce
 {
     size_t j;
     int32_t value = le_expected[_i&3];
     /* read 4 bytes apart, start is not always aligned*/
2565ef49
     for(j=_i;j < DATA_REP*sizeof(le_data)-4;j += 4) {
c47e43ce
         fail_unless(cli_readint32(&data[j]) == value, "(1) data read must be little endian");
     }
     value = le_expected[0];
     /* read 4 bytes apart, always aligned*/
2565ef49
     for(j=0;j < DATA_REP*sizeof(le_data)-4;j += 4) {
c47e43ce
         fail_unless(cli_readint32(&data[j]) == value, "(2) data read must be little endian");
     }
 }
 END_TEST
 
 /* test writing with different alignments, _i is parameter from tcase_add_loop_test */
2565ef49
 START_TEST (test_cli_writeint32)
c47e43ce
 {
     size_t j;
     /* write 4 bytes apart, start is not always aligned*/
     for(j=_i;j < DATA_REP*sizeof(le_data) - 4;j += 4) {
         cli_writeint32(&data2[j], 0x12345678);
     }
     for(j=_i;j < DATA_REP*sizeof(le_data) - 4;j += 4) {
         fail_unless(cli_readint32(&data2[j]) == 0x12345678, "write/read mismatch");
     }
     /* write 4 bytes apart, always aligned*/
     for(j=0;j < DATA_REP*sizeof(le_data) - 4;j += 4) {
         cli_writeint32(&data2[j], 0x12345678);
     }
     for(j=0;j < DATA_REP*sizeof(le_data) - 4;j += 4) {
         fail_unless(cli_readint32(&data2[j]) == 0x12345678, "write/read mismatch");
     }
 }
 END_TEST
 
7b57a833
 static struct dsig_test {
     const char *md5;
     const char *dsig;
     int result;
 } dsig_tests [] = {
     {"ae307614434715274c60854c931a26de", "60uhCFmiN48J8r6c7coBv9Q1mehAWEGh6GPYA+60VhQcuXfb0iV1O+sCEyMiRXt/iYF6vXtPXHVd6DiuZ4Gfrry7sVQqNTt3o1/KwU1rc0l5FHgX/nC99fdr/fjaFtinMtRnUXHLeu0j8e6HK+7JLBpD37fZ60GC9YY86EclYGe", 
 	CL_SUCCESS},
     {"96b7feb3b2a863846438809fe481906f", "Zh5gmf09Zfj6V4gmRKu/NURzhFiE9VloI7w1G33BgDdGSs0Xhscx6sjPUpFSCPsjOalyS4L8q7RS+NdGvNCsLymiIH6RYItlOZsygFhcGuH4jt15KAaAkvEg2TwmqR8z41nUaMlZ0c8q1MXYCLvQJyFARsfzIxS3PAoN2Y3HPoe",
 	CL_SUCCESS},
     {"ae307614434715274c60854c931a26de", "Zh5gmf09Zfj6V4gmRKu/NURzhFiE9VloI7w1G33BgDdGSs0Xhscx6sjPUpFSCPsjOalyS4L8q7RS+NdGvNCsLymiIH6RYItlOZsygFhcGuH4jt15KAaAkvEg2TwmqR8z41nUaMlZ0c8q1MXYCLvQJyFARsfzIxS3PAoN2Y3HPoe",
871177cd
 	CL_EVERIFY},
7b57a833
     {"96b7feb3b2a863846438809fe481906f", "60uhCFmiN48J8r6c7coBv9Q1mehAWEGh6GPYA+60VhQcuXfb0iV1O+sCEyMiRXt/iYF6vXtPXHVd6DiuZ4Gfrry7sVQqNTt3o1/KwU1rc0l5FHgX/nC99fdr/fjaFtinMtRnUXHLeu0j8e6HK+7JLBpD37fZ60GC9YY86EclYGe",
871177cd
 	CL_EVERIFY},
7b57a833
     {"ae307614434715274060854c931a26de", "60uhCFmiN48J8r6c7coBv9Q1mehAWEGh6GPYA+60VhQcuXfb0iV1O+sCEyMiRXt/iYF6vXtPXHVd6DiuZ4Gfrry7sVQqNTt3o1/KwU1rc0l5FHgX/nC99fdr/fjaFtinMtRnUXHLeu0j8e6HK+7JLBpD37fZ60GC9YY86EclYGe",
871177cd
 	CL_EVERIFY},
7b57a833
     {"ae307614434715274c60854c931a26de", "60uhCFmiN48J8r6c7coBv9Q1mehAWEGh6GPYA+60VhQcuXfb0iV1O+sCEyMiRXt/iYF6vXtPXHVd6DiuZ4Gfrry7sVQqNTt3o1/KwU1rc0l5FHgX/nC99fdr/fjaatinMtRnUXHLeu0j8e6HK+7JLBpD37fZ60GC9YY86EclYGe",
871177cd
 	CL_EVERIFY},
7b57a833
     {"96b7feb3b2a863846438809fe481906f", "Zh5gmf09Zfj6V4gmRKu/NURzhFiE9VloI7w1G33BgDdGSs0Xhscx6sjPUpFSCPsjOalyS4L8q7RS+NdGvNCsLymiIH6RYItlOZsygFhcGuH4jt15KAaAkvEg2TwmqR8z41nUaMlZ0c8q1MYYCLvQJyFARsfzIxS3PAoN2Y3HPoe",
871177cd
 	CL_EVERIFY},
7b57a833
     {"ge307614434715274c60854c931a26dee","60uhCFmiN48J8r6c7coBv9Q1mehAWEGh6GPYA+60VhQcuXfb0iV1O+sCEyMiRXt/iYF6vXtPXHVd6DiuZ4Gfrry7sVQqNTt3o1/KwU1rc0l5FHgX/nC99fdr/fjaFtinMtRnUXHLeu0j8e6HK+7JLBpD37fZ60GC9YY86EclYGe",
871177cd
 	CL_EVERIFY},
7b57a833
     {"ae307614434715274c60854c931a26de", "60uhCFmiN48J8r6c7coBv9Q1mehAWEGh6GPYA+60VhQcuXfb0iV1O+sCEyMiRXt/iYF6vXtPXHVd6DiuZ4Gfrry7sVQqNTt3o1/KwU1rc0l5FHgX/nC99fdr/fjaFtinMtRnUXHLeu0j8e6HK+7JLBpD37fZ60GC9YY86EclYGee", 
871177cd
 	CL_EVERIFY},
7b57a833
     {"ae307614434715274c60854c931a26de", "60uhCFmiN48J8r6c7coBv9Q1mehAWEGh6GPYA+", 
871177cd
 	CL_EVERIFY}
7b57a833
 };
 
 static const size_t dsig_tests_cnt = sizeof(dsig_tests)/sizeof(dsig_tests[0]);
 
 START_TEST (test_cli_dsig)
 {
     fail_unless(cli_versig(dsig_tests[_i].md5, dsig_tests[_i].dsig) == dsig_tests[_i].result,
 		"digital signature verification test failed");
 }
 END_TEST
 
4e46d65d
 static uint8_t tv1[3] = {
   0x61, 0x62, 0x63
 };
 
 static uint8_t tv2[56] = {
   0x61, 0x62, 0x63, 0x64, 0x62, 0x63, 0x64, 0x65,
   0x63, 0x64, 0x65, 0x66, 0x64, 0x65, 0x66, 0x67,
   0x65, 0x66, 0x67, 0x68, 0x66, 0x67, 0x68, 0x69,
   0x67, 0x68, 0x69, 0x6a, 0x68, 0x69, 0x6a, 0x6b,
   0x69, 0x6a, 0x6b, 0x6c, 0x6a, 0x6b, 0x6c, 0x6d,
   0x6b, 0x6c, 0x6d, 0x6e, 0x6c, 0x6d, 0x6e, 0x6f,
   0x6d, 0x6e, 0x6f, 0x70, 0x6e, 0x6f, 0x70, 0x71
 };
 
 static uint8_t res256[3][SHA256_HASH_SIZE] = {
   { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
     0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
     0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad },
   { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93,
     0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
     0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 },
   { 0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7, 0xe2,
     0x84, 0xd7, 0x3e, 0x67, 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97, 0x20, 0x0e,
     0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0 }
 };
 
 START_TEST (test_sha256)
 {
     SHA256_CTX sha256;
     uint8_t hsha256[SHA256_HASH_SIZE];
     uint8_t buf[1000];
     int i;
 
     memset (buf, 0x61, sizeof (buf));
 
     sha256_init (&sha256);
     sha256_update (&sha256, tv1, sizeof (tv1));
     sha256_final (&sha256, hsha256);
     fail_unless(!memcmp (hsha256, res256[0], sizeof (hsha256)), "sha256 test vector #1 failed");
 
     sha256_init (&sha256);
     sha256_update (&sha256, tv2, sizeof (tv2));
     sha256_final (&sha256, hsha256);
     fail_unless(!memcmp (hsha256, res256[1], sizeof (hsha256)), "sha256 test vector #2 failed");
 
     sha256_init (&sha256);
     for (i = 0; i < 1000; i++)
 	sha256_update (&sha256, buf, sizeof (buf));
     sha256_final (&sha256, hsha256);
     fail_unless(!memcmp (hsha256, res256[2], sizeof (hsha256)), "sha256 test vector #3 failed");
 }
 END_TEST
 
c47e43ce
 static Suite *test_cli_suite(void)
 {
     Suite *s = suite_create("cli");
     TCase *tc_cli_others = tcase_create("byteorder_macros");
7b57a833
     TCase *tc_cli_dsig = tcase_create("digital signatures");
c47e43ce
 
     suite_add_tcase (s, tc_cli_others);
     tcase_add_checked_fixture (tc_cli_others, data_setup, data_teardown);
7b57a833
     tcase_add_loop_test(tc_cli_others, test_cli_readint32, 0, 16);
     tcase_add_loop_test(tc_cli_others, test_cli_readint16, 0, 16);
     tcase_add_loop_test(tc_cli_others, test_cli_writeint32, 0, 16);
 
     suite_add_tcase (s, tc_cli_dsig);
     tcase_add_loop_test(tc_cli_dsig, test_cli_dsig, 0, dsig_tests_cnt);
4e46d65d
     tcase_add_test(tc_cli_dsig, test_sha256);
c47e43ce
 
     return s;
 }
61b295f4
 #endif /* CHECK_HAVE_LOOPS */
c47e43ce
 
5ee56e41
 void errmsg_expected(void)
 {
 	fputs("cli_errmsg() expected here\n", stderr);
 }
 
3dcc2d78
 int open_testfile(const char *name)
 {
 	int fd;
 	const char * srcdir = getenv("srcdir");
 	char *str;
 
 	if(!srcdir) {
 		/* when run from automake srcdir is set, but if run manually then not */
 		srcdir = SRCDIR;
 	}
 
 	str = cli_malloc(strlen(name)+strlen(srcdir)+2);
 	fail_unless(!!str, "cli_malloc");
 	sprintf(str, "%s/%s", srcdir, name);
 
 	fd = open(str, O_RDONLY);
d5d06ecc
 	fail_unless_fmt(fd >= 0, "open() failed: %s", str);
3dcc2d78
 	free(str);
 	return fd;
 }
 
1279faf6
 void diff_file_mem(int fd, const char *ref, size_t len)
 {
e0ac8b20
 	char c1,c2;
1279faf6
 	size_t p, reflen = len;
 	char *buf = cli_malloc(len);
 
d5d06ecc
 	fail_unless_fmt(!!buf, "unable to malloc buffer: %d", len);
6a53bbdf
 	p = read(fd, buf, len);
d5d06ecc
 	fail_unless_fmt(p == len,  "file is smaller: %lu, expected: %lu", p, len);
1279faf6
 	p = 0;
 	while(len > 0) {
e0ac8b20
 		c1 = ref[p];
 		c2 = buf[p];
 		if(c1 != c2)
 			break;
1279faf6
 		p++;
 		len--;
 	}
e0ac8b20
 	if (len > 0)
d5d06ecc
 		fail_unless_fmt(c1 == c2, "file contents mismatch at byte: %lu, was: %c, expected: %c", p, c2, c1);
1279faf6
 	free(buf);
 	p = lseek(fd, 0, SEEK_END);
d5d06ecc
         fail_unless_fmt(p == reflen, "trailing garbage, file size: %ld, expected: %ld", p, reflen);
1279faf6
 	close(fd);
 }
 
 void diff_files(int fd, int ref_fd)
 {
 	char *ref;
 	ssize_t nread;
 	off_t siz = lseek(ref_fd, 0, SEEK_END);
d5d06ecc
 	fail_unless_fmt(siz != -1, "lseek failed");
1279faf6
 
 	ref = cli_malloc(siz);
d5d06ecc
 	fail_unless_fmt(!!ref, "unable to malloc buffer: %d", siz);
1279faf6
 
d5d06ecc
 	fail_unless_fmt(lseek(ref_fd, 0, SEEK_SET) == 0,"lseek failed");
1279faf6
 	nread = read(ref_fd, ref, siz);
d5d06ecc
         fail_unless_fmt(nread == siz, "short read, expected: %ld, was: %ld", siz, nread);
1279faf6
 	close(ref_fd);
 	diff_file_mem(fd, ref, siz);
 	free(ref);
 }
 
7866b37c
 #ifdef USE_MPOOL
47d40feb
 static mpool_t *pool;
563582a1
 #else
 static void *pool;
 #endif
 struct cli_dconf *dconf;
 
 void dconf_setup(void)
 {
 	pool = NULL;
 	dconf = NULL;
7866b37c
 #ifdef USE_MPOOL
47d40feb
 	pool = mpool_create();
563582a1
 	fail_unless(!!pool, "unable to create pool");
 #endif
47d40feb
 	dconf = cli_mpool_dconf_init(pool);
563582a1
 	fail_unless(!!dconf, "failed to init dconf");
 }
 
 void dconf_teardown(void)
 {
47d40feb
 	mpool_free(pool, dconf);
7866b37c
 #ifdef USE_MPOOL
563582a1
 	if (pool)
47d40feb
 		mpool_destroy(pool);
563582a1
 #endif
 }
 
acba3cf5
 static void check_version_compatible()
 {
     /* check 0.9.8 is not ABI compatible with 0.9.6,
      * if by accident you compile with check 0.9.6 header
      * and link with 0.9.8 then check will hang/crash. */
     if ((check_major_version != CHECK_MAJOR_VERSION) ||
 	(check_minor_version != CHECK_MINOR_VERSION) ||
 	(check_micro_version != CHECK_MICRO_VERSION)) {
 	fprintf(stderr, "ERROR: check version mismatch!\n"
 		"\tVersion from header: %u.%u.%u\n"
 		"\tVersion from library: %u.%u.%u\n"
 		"\tMake sure check.h and -lcheck are same version!\n",
 		CHECK_MAJOR_VERSION,
 		CHECK_MINOR_VERSION,
 		CHECK_MICRO_VERSION,
 		check_major_version,
 		check_minor_version,
 		check_micro_version);
 	exit(EXIT_FAILURE);
     }
 }
563582a1
 
15adbc84
 int main(void)
fe473bcb
 {
c47e43ce
     int nf;
acba3cf5
     Suite *s;
     SRunner *sr;
 
     check_version_compatible();
     s = test_cl_suite();
     sr = srunner_create(s);
99f74adc
 #ifdef CHECK_HAVE_LOOPS
c47e43ce
     srunner_add_suite(sr, test_cli_suite());
61b295f4
 #else
abbd1d36
     printf("*** Warning ***: your check version is too old,\nseveral important tests will not execute\n");
99f74adc
 #endif
4a6ade44
     srunner_add_suite(sr, test_jsnorm_suite());
eb290151
     srunner_add_suite(sr, test_str_suite());
9ee053fe
     srunner_add_suite(sr, test_regex_suite());
c92b0057
     srunner_add_suite(sr, test_disasm_suite());
5e07cfed
     srunner_add_suite(sr, test_uniq_suite());
ec285505
     srunner_add_suite(sr, test_matchers_suite());
1279faf6
     srunner_add_suite(sr, test_htmlnorm_suite());
d99c0c42
     srunner_add_suite(sr, test_bytecode_suite());
fe473bcb
 
     srunner_set_log(sr, "test.log");
a497dce5
     if(freopen("test-stderr.log","w+",stderr) == NULL) {
 	    fputs("Unable to redirect stderr!\n",stderr);
     }
5cd3f734
     cl_debug();
5ee56e41
 
fe473bcb
     srunner_run_all(sr, CK_NORMAL);
     nf = srunner_ntests_failed(sr);
     srunner_free(sr);
     return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }