static void init_testfiles(void)
{
    struct dirent *dirent;
    unsigned i = 0;
    int expect = expected_testfiles;

    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;
        i++;
	testfiles = cli_realloc(testfiles, i*sizeof(*testfiles));
	fail_unless(!!testfiles, "cli_realloc");
	testfiles[i-1] = strdup(dirent->d_name);
    }
    testfiles_n = i;
    if (get_fpu_endian() == FPU_ENDIAN_UNKNOWN)
        expect--;
    expect -= skip_files();
    fail_unless_fmt(testfiles_n == expect, "testfiles: %d != %d", testfiles_n, expect);

    closedir(d);
}
END_TEST
#endif

static Suite *test_cl_suite(void)
{
    Suite *s = suite_create("cl_api");
    TCase *tc_cl = tcase_create("cl_dup");
    TCase *tc_cl_scan = tcase_create("cl_scan");
    char *user_timeout = NULL;
    int expect = expected_testfiles;
    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);

    suite_add_tcase(s, tc_cl_scan);
    tcase_add_checked_fixture (tc_cl_scan, engine_setup, engine_teardown);
#ifdef CHECK_HAVE_LOOPS
    if (get_fpu_endian() == FPU_ENDIAN_UNKNOWN)
        expect--;
    expect -= skip_files();
    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);

    user_timeout = getenv("T");
    if (user_timeout) {
        int timeout = atoi(user_timeout);
        tcase_set_timeout(tc_cl_scan, timeout);
	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");
    }
#endif
    return s;
}
END_TEST
#endif

static Suite *test_cl_suite(void)
{
    Suite *s = suite_create("cl_api");
    TCase *tc_cl = tcase_create("cl_dup");
    TCase *tc_cl_scan = tcase_create("cl_scan");
    int expect = expected_testfiles;
    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);

    suite_add_tcase(s, tc_cl_scan);
    tcase_add_checked_fixture (tc_cl_scan, engine_setup, engine_teardown);
#ifdef CHECK_HAVE_LOOPS
    if (get_fpu_endian() == FPU_ENDIAN_UNKNOWN)
        expect--;
    expect -= skip_files();
    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);
#endif
    return s;
}