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>
d5f7afdd
 #include <sys/types.h>
 #include <dirent.h>
62ee12b2
 #include <sys/mman.h>
b2e7c931
 
849cdc78
 #if HAVE_LIBXML2
 #include <libxml/parser.h>
 #endif
 
fe473bcb
 #include "../libclamav/clamav.h"
 #include "../libclamav/others.h"
 #include "../libclamav/matcher.h"
04f9bedf
 #include "../libclamav/version.h"
c5944b54
 #include "../libclamav/dsig.h"
a393d999
 #include "../libclamav/fpu.h"
a39b29cb
 #include "checks.h"
fe473bcb
 
a393d999
 static int fpu_words  = FPU_ENDIAN_INITME;
 #define NO_FPU_ENDIAN (fpu_words == FPU_ENDIAN_UNKNOWN)
 #define EA06_SCAN strstr(file, "clam.ea06.exe")
 #define FALSE_NEGATIVE (EA06_SCAN && NO_FPU_ENDIAN)
 
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
 
d5f7afdd
 static int get_test_file(int i, char *file, unsigned fsize, unsigned long *size);
 static struct cl_engine *g_engine;
 
d1b44b4d
 #ifdef CHECK_HAVE_LOOPS
fe473bcb
 /* 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)
d5f7afdd
 {
     const char *virname = NULL;
     char file[256];
     unsigned long size;
     unsigned long int scanned = 0;
     int ret;
 
     int fd = get_test_file(_i, file, sizeof(file), &size);
     cli_dbgmsg("scanning (scandesc) %s\n", file);
     ret = cl_scandesc(fd, &virname, &scanned, g_engine, CL_SCAN_STDOPT);
     cli_dbgmsg("scan end (scandesc) %s\n", file);
 
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scandesc failed for %s: %s", file, cl_strerror(ret));
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
     }
d5f7afdd
     close(fd);
 }
fe473bcb
 END_TEST
 
6ad45a29
 START_TEST (test_cl_scandesc_allscan)
 {
     const char *virname = NULL;
     char file[256];
     unsigned long size;
     unsigned long int scanned = 0;
     int ret;
 
     int fd = get_test_file(_i, file, sizeof(file), &size);
     cli_dbgmsg("scanning (scandesc) %s\n", file);
1f1bf36b
     ret = cl_scandesc(fd, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT);
a393d999
 
6ad45a29
     cli_dbgmsg("scan end (scandesc) %s\n", file);
 
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scandesc_allscan failed for %s: %s", file, cl_strerror(ret));
1f1bf36b
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
a393d999
     }
6ad45a29
     close(fd);
 }
 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) */
fe473bcb
 START_TEST (test_cl_scanfile)
d5f7afdd
 {
     const char *virname = NULL;
     char file[256];
     unsigned long size;
     unsigned long int scanned = 0;
     int ret;
 
     int fd = get_test_file(_i, file, sizeof(file), &size);
     close(fd);
 
     cli_dbgmsg("scanning (scanfile) %s\n", file);
     ret = cl_scanfile(file, &virname, &scanned, g_engine, CL_SCAN_STDOPT);
     cli_dbgmsg("scan end (scanfile) %s\n", file);
 
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS , "cl_scanfile failed for %s: %s", file, cl_strerror(ret));
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
     }
d5f7afdd
 }
 END_TEST
 
6ad45a29
 START_TEST (test_cl_scanfile_allscan)
 {
     const char *virname = NULL;
     char file[256];
     unsigned long size;
     unsigned long int scanned = 0;
     int ret;
 
     int fd = get_test_file(_i, file, sizeof(file), &size);
     close(fd);
 
     cli_dbgmsg("scanning (scanfile_allscan) %s\n", file);
1f1bf36b
     ret = cl_scanfile(file, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT);
6ad45a29
     cli_dbgmsg("scan end (scanfile_allscan) %s\n", file);
 
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile_allscan failed for %s: %s", file, cl_strerror(ret));
1f1bf36b
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
a393d999
     }
6ad45a29
 }
 END_TEST
 
d5f7afdd
 START_TEST (test_cl_scanfile_callback)
 {
     const char *virname = NULL;
     char file[256];
     unsigned long size;
     unsigned long int scanned = 0;
     int ret;
 
     int fd = get_test_file(_i, file, sizeof(file), &size);
     close(fd);
 
     cli_dbgmsg("scanning (scanfile_cb) %s\n", file);
     /* TODO: test callbacks */
     ret = cl_scanfile_callback(file, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
     cli_dbgmsg("scan end (scanfile_cb) %s\n", file);
 
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile_cb failed for %s: %s", file, cl_strerror(ret));
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
     }
d5f7afdd
 }
 END_TEST
 
6ad45a29
 START_TEST (test_cl_scanfile_callback_allscan)
 {
     const char *virname = NULL;
     char file[256];
     unsigned long size;
     unsigned long int scanned = 0;
     int ret;
 
     int fd = get_test_file(_i, file, sizeof(file), &size);
     close(fd);
 
     cli_dbgmsg("scanning (scanfile_cb_allscan) %s\n", file);
     /* TODO: test callbacks */
1f1bf36b
     ret = cl_scanfile_callback(file, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL);
6ad45a29
     cli_dbgmsg("scan end (scanfile_cb_allscan) %s\n", file);
 
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile_cb_allscan failed for %s: %s", file, cl_strerror(ret));
1f1bf36b
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
a393d999
     }
6ad45a29
 }
 END_TEST
 
d5f7afdd
 START_TEST (test_cl_scandesc_callback)
 {
     const char *virname = NULL;
     char file[256];
     unsigned long size;
     unsigned long int scanned = 0;
     int ret;
 
     int fd = get_test_file(_i, file, sizeof(file), &size);
 
     cli_dbgmsg("scanning (scandesc_cb) %s\n", file);
     /* TODO: test callbacks */
     ret = cl_scandesc_callback(fd, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
     cli_dbgmsg("scan end (scandesc_cb) %s\n", file);
 
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile failed for %s: %s", file, cl_strerror(ret));
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
     }
d5f7afdd
     close(fd);
 }
fe473bcb
 END_TEST
6ad45a29
 
 START_TEST (test_cl_scandesc_callback_allscan)
 {
     const char *virname = NULL;
     char file[256];
     unsigned long size;
     unsigned long int scanned = 0;
     int ret;
 
     int fd = get_test_file(_i, file, sizeof(file), &size);
 
     cli_dbgmsg("scanning (scandesc_cb_allscan) %s\n", file);
     /* TODO: test callbacks */
1f1bf36b
     ret = cl_scandesc_callback(fd, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL);
6ad45a29
     cli_dbgmsg("scan end (scandesc_cb_allscan) %s\n", file);
 
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scanfile_allscan failed for %s: %s", file, cl_strerror(ret));
1f1bf36b
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
a393d999
     }
6ad45a29
     close(fd);
 }
 END_TEST
 
d1b44b4d
 #endif
fe473bcb
 
 /* 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
 
d5f7afdd
 static char **testfiles = NULL;
 static unsigned testfiles_n = 0;
f0f3fe69
 
ca804a8d
 static const int expected_testfiles = 48;
d5f7afdd
 
f4f331ae
 static unsigned skip_files(void)
97fd85d1
 {
f4f331ae
     unsigned skipped = 0;
 
     /* skip .rar files if unrar is disabled */
97fd85d1
     const char *s = getenv("unrar_disabled");
f4f331ae
     if (s && !strcmp(s, "1")) {
         skipped += 2;
     }
97fd85d1
 
f4f331ae
     /* skip .bz2 files if bzip is disabled */
 #if HAVE_BZLIB_H
 #else
     skipped += 2;
 #endif
97fd85d1
 
f4f331ae
     /* skip [placeholder] files if xml is disabled */
 #if HAVE_LIBXML2
 #else
     skipped += 0;
 #endif
97fd85d1
 
f4f331ae
     return skipped;
97fd85d1
 }
 
d5f7afdd
 static void init_testfiles(void)
 {
     struct dirent *dirent;
     unsigned i = 0;
04ad6854
     int expect = expected_testfiles;
d5f7afdd
 
     DIR *d = opendir(OBJDIR"/../test");
     fail_unless(!!d, "opendir");
     if (!d)
 	return;
     testfiles = NULL;
     testfiles_n = 0;
     while ((dirent = readdir(d))) {
 	if (strncmp(dirent->d_name, "clam", 4))
 	    continue;
97fd85d1
         i++;
d5f7afdd
 	testfiles = cli_realloc(testfiles, i*sizeof(*testfiles));
 	fail_unless(!!testfiles, "cli_realloc");
 	testfiles[i-1] = strdup(dirent->d_name);
     }
     testfiles_n = i;
b02190b4
     if (get_fpu_endian() == FPU_ENDIAN_UNKNOWN)
         expect--;
f4f331ae
     expect -= skip_files();
04ad6854
     fail_unless_fmt(testfiles_n == expect, "testfiles: %d != %d", testfiles_n, expect);
d5f7afdd
 
     closedir(d);
 }
 
 static void free_testfiles(void)
 {
     unsigned i;
     for (i=0;i<testfiles_n;i++) {
 	free(testfiles[i]);
     }
     free(testfiles);
     testfiles = NULL;
     testfiles_n = 0;
 }
 
 static int inited = 0;
 
 static void engine_setup(void)
 {
     unsigned int sigs = 0;
     const char *hdb = OBJDIR"/clamav.hdb";
 
     init_testfiles();
     if (!inited)
 	fail_unless(cl_init(CL_INIT_DEFAULT) == 0, "cl_init");
     inited = 1;
     g_engine = cl_engine_new();
     fail_unless(!!g_engine, "engine");
     fail_unless_fmt(cl_load(hdb, g_engine, &sigs, CL_DB_STDOPT) == 0, "cl_load %s", hdb);
     fail_unless(sigs == 1, "sigs");
     fail_unless(cl_engine_compile(g_engine) == 0, "cl_engine_compile");
 }
 
 static void engine_teardown(void)
 {
     free_testfiles();
     cl_engine_free(g_engine);
 }
 
 static int get_test_file(int i, char *file, unsigned fsize, unsigned long *size)
 {
     int fd;
a2a004df
     STATBUF st;
d5f7afdd
 
04ad6854
     fail_unless(i < testfiles_n, "%i < %i %s", i, testfiles_n, file);
d5f7afdd
     snprintf(file, fsize, OBJDIR"/../test/%s", testfiles[i]);
 
     fd = open(file, O_RDONLY);
     fail_unless(fd > 0, "open");
a2a004df
     fail_unless(FSTAT(fd, &st) == 0, "fstat");
d5f7afdd
     *size = st.st_size;
     return fd;
 }
b32ad857
 #ifdef CHECK_HAVE_LOOPS
d5f7afdd
 
e8b63834
 static off_t pread_cb(void *handle, void *buf, size_t count, off_t offset)
62ee12b2
 {
     return pread(*((int*)handle), buf, count, offset);
 }
 
 START_TEST (test_cl_scanmap_callback_handle)
 {
     const char *virname = NULL;
81e57728
     unsigned long int scanned = 0;
62ee12b2
     cl_fmap_t *map;
     int ret;
592e246c
     char file[256];
     unsigned long size;
62ee12b2
 
592e246c
     int fd = get_test_file(_i, file, sizeof(file), &size);
62ee12b2
     /* intentionally use different way than scanners.c for testing */
592e246c
     map = cl_fmap_open_handle(&fd, 0, size, pread_cb, 1);
62ee12b2
     fail_unless(!!map, "cl_fmap_open_handle");
 
81e57728
     cli_dbgmsg("scanning (handle) %s\n", file);
62ee12b2
     ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
81e57728
     cli_dbgmsg("scan end (handle) %s\n", file);
 
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scanmap_callback failed for %s: %s", file, cl_strerror(ret));
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
     }
62ee12b2
     close(fd);
 }
 END_TEST
 
6ad45a29
 START_TEST (test_cl_scanmap_callback_handle_allscan)
 {
     const char *virname = NULL;
     unsigned long int scanned = 0;
     cl_fmap_t *map;
     int ret;
     char file[256];
     unsigned long size;
 
     int fd = get_test_file(_i, file, sizeof(file), &size);
     /* intentionally use different way than scanners.c for testing */
     map = cl_fmap_open_handle(&fd, 0, size, pread_cb, 1);
a393d999
     fail_unless(!!map, "cl_fmap_open_handle %s");
6ad45a29
 
     cli_dbgmsg("scanning (handle) allscan %s\n", file);
1f1bf36b
     ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL);
6ad45a29
     cli_dbgmsg("scan end (handle) allscan %s\n", file);
 
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scanmap_callback_allscan failed for %s: %s", file, cl_strerror(ret));
1f1bf36b
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s", virname);
a393d999
     }
6ad45a29
     close(fd);
 }
 END_TEST
 
62ee12b2
 START_TEST (test_cl_scanmap_callback_mem)
 {
     const char *virname = NULL;
81e57728
     unsigned long int scanned = 0;
62ee12b2
     cl_fmap_t *map;
     int ret;
     void *mem;
592e246c
     unsigned long size;
     char file[256];
62ee12b2
 
592e246c
     int fd = get_test_file(_i, file, sizeof(file), &size);
62ee12b2
 
592e246c
     mem = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
62ee12b2
     fail_unless(mem != MAP_FAILED, "mmap");
 
     /* intentionally use different way than scanners.c for testing */
592e246c
     map = cl_fmap_open_memory(mem, size);
62ee12b2
     fail_unless(!!map, "cl_fmap_open_mem");
 
81e57728
     cli_dbgmsg("scanning (mem) %s\n", file);
62ee12b2
     ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, CL_SCAN_STDOPT, NULL);
81e57728
     cli_dbgmsg("scan end (mem) %s\n", file);
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scanmap_callback failed for %s: %s", file, cl_strerror(ret));
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s for %s", virname, file);
     }
62ee12b2
     close(fd);
0d54f271
     cl_fmap_close(map);
62ee12b2
 
592e246c
     munmap(mem, size);
62ee12b2
 }
 END_TEST
6ad45a29
 
 START_TEST (test_cl_scanmap_callback_mem_allscan)
 {
     const char *virname = NULL;
     unsigned long int scanned = 0;
     cl_fmap_t *map;
     int ret;
     void *mem;
     unsigned long size;
     char file[256];
 
     int fd = get_test_file(_i, file, sizeof(file), &size);
 
     mem = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
     fail_unless(mem != MAP_FAILED, "mmap");
 
     /* intentionally use different way than scanners.c for testing */
     map = cl_fmap_open_memory(mem, size);
a393d999
     fail_unless(!!map, "cl_fmap_open_mem %s");
6ad45a29
 
     cli_dbgmsg("scanning (mem) allscan %s\n", file);
1f1bf36b
     ret = cl_scanmap_callback(map, &virname, &scanned, g_engine, CL_SCAN_ALLMATCHES+CL_SCAN_STDOPT, NULL);
6ad45a29
     cli_dbgmsg("scan end (mem) allscan %s\n", file);
a393d999
     if (!FALSE_NEGATIVE) {
       fail_unless_fmt(ret == CL_VIRUS, "cl_scanmap_callback failed for %s: %s", file, cl_strerror(ret));
1f1bf36b
       fail_unless_fmt(virname && !strcmp(virname, "ClamAV-Test-File.UNOFFICIAL"), "virusname: %s for %s", virname, file);
a393d999
     }
6ad45a29
     close(fd);
     cl_fmap_close(map);
     munmap(mem, size);
 }
 END_TEST
b32ad857
 #endif
62ee12b2
 
c47e43ce
 static Suite *test_cl_suite(void)
fe473bcb
 {
c47e43ce
     Suite *s = suite_create("cl_api");
     TCase *tc_cl = tcase_create("cl_dup");
d5f7afdd
     TCase *tc_cl_scan = tcase_create("cl_scan");
11bdd8a7
     char *user_timeout = NULL;
04ad6854
     int expect = expected_testfiles;
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_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);
 
d5f7afdd
     suite_add_tcase(s, tc_cl_scan);
     tcase_add_checked_fixture (tc_cl_scan, engine_setup, engine_teardown);
d1b44b4d
 #ifdef CHECK_HAVE_LOOPS
b02190b4
     if (get_fpu_endian() == FPU_ENDIAN_UNKNOWN)
         expect--;
f4f331ae
     expect -= skip_files();
04ad6854
     tcase_add_loop_test(tc_cl_scan, test_cl_scandesc, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scandesc_allscan, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scanfile, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scanfile_allscan, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scandesc_callback, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scandesc_callback_allscan, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scanfile_callback, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scanfile_callback_allscan, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_handle, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_handle_allscan, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem, 0, expect);
     tcase_add_loop_test(tc_cl_scan, test_cl_scanmap_callback_mem_allscan, 0, expect);
11bdd8a7
 
     user_timeout = getenv("T");
     if (user_timeout) {
         int timeout = atoi(user_timeout);
         tcase_set_timeout(tc_cl_scan, timeout);
c2b36ddd
 	printf("Using test case timeout of %d seconds set by user\n", timeout);
     } else {
 	printf("Using default test timeout; alter by setting 'T' env var (in seconds)\n");
11bdd8a7
     }
d1b44b4d
 #endif
fe473bcb
     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)
 {
da6e06dd
     void *sha256;
4e46d65d
     uint8_t hsha256[SHA256_HASH_SIZE];
     uint8_t buf[1000];
     int i;
 
     memset (buf, 0x61, sizeof (buf));
 
b2e7c931
     cl_sha256(tv1, sizeof(tv1), hsha256, NULL);
4e46d65d
     fail_unless(!memcmp (hsha256, res256[0], sizeof (hsha256)), "sha256 test vector #1 failed");
 
b2e7c931
     cl_sha256(tv2, sizeof(tv2), hsha256, NULL);
4e46d65d
     fail_unless(!memcmp (hsha256, res256[1], sizeof (hsha256)), "sha256 test vector #2 failed");
 
da6e06dd
     sha256 = cl_hash_init("sha256");
f077c617
     fail_unless(sha256 != NULL, "Could not create EVP_MD_CTX for sha256");
 
4e46d65d
     for (i = 0; i < 1000; i++)
da6e06dd
         cl_update_hash (sha256, buf, sizeof (buf));
     cl_finish_hash(sha256, hsha256);
4e46d65d
     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;
 
f9afc309
     cl_initialize_crypto();
 
a393d999
     fpu_words  = get_fpu_endian();
   
acba3cf5
     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
 
d5f7afdd
 
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);
c2b36ddd
     if (nf)
 	printf("NOTICE: Use the 'T' environment variable to adjust testcase timeout\n");
fe473bcb
     srunner_free(sr);
62ee12b2
 
849cdc78
 #if HAVE_LIBXML2
     xmlCleanupParser();
 #endif
f9afc309
     cl_cleanup_crypto();
 
fe473bcb
     return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
 }