clamav/unit_tests/check_bytecode.c
Micah Snyder 2552cfd0d1 CMake: Add CTest support to match Autotools checks
An ENABLE_TESTS CMake option is provided so that users can disable
testing if they don't want it. Instructions for how to use this
included in the INSTALL.cmake.md file.

If you run `ctest`, each testcase will write out a log file to the
<build>/unit_tests directory.

As with Autotools' make check, the test files are from test/.split
and unit_tests/.split files, but for CMake these are generated at
build time instead of at test time.

On Posix systems, sets the LD_LIBRARY_PATH so that ClamAV-compiled
libraries can be loaded when running tests.

On Windows systems, CTest will identify and collect all library
dependencies and assemble a temporarily install under the
build/unit_tests directory so that the libraries can be loaded when
running tests.

The same feature is used on Windows when using CMake to install to
collect all DLL dependencies so that users don't have to install them
manually afterwards.

Each of the CTest tests are run using a custom wrapper around Python's
unittest framework, which is also responsible for finding and inserting
valgrind into the valgrind tests on Posix systems.

Unlike with Autotools, the CMake CTest Valgrind-tests are enabled by
default, if Valgrind can be found. There's no need to set VG=1.
CTest's memcheck module is NOT supported, because we use Python to
orchestrate our tests.

Added a bunch of Windows compatibility changes to the unit tests.
These were primarily changing / to PATHSEP and making adjustments
to use Win32 C headers and ifdef out the POSIX ones which aren't
available on Windows. Also disabled a bunch of tests on Win32
that don't work on Windows, notably the mmap ones and FD-passing
(i.e. FILEDES) ones.

Add JSON_C_HAVE_INTTYPES_H definition to clamav-config.h to eliminate
warnings on Windows where json.h is included after inttypes.h because
json-c's inttypes replacement relies on it.
This is a it of a hack and may be removed if json-c fixes their
inttypes header stuff in the future.

Add preprocessor definitions on Windows to disable MSVC warnings about
CRT secure and nonstandard functions. While there may be a better
solution, this is needed to be able to see other more serious warnings.

Add missing file comment block and copyright statement for clamsubmit.c.
Also change json-c/json.h include filename to json.h in clamsubmit.c.
The directory name is not required.

Changed the hash table data integer type from long, which is poorly
defined, to size_t -- which is capable of storing a pointer. Fixed a
bunch of casts regarding this variable to eliminate warnings.

Fixed two bugs causing utf8 encoding unit tests to fail on Windows:
- The in_size variable should be the number of bytes, not the character
  count. This was was causing the SHIFT_JIS (japanese codepage) to UTF8
  transcoding test to only transcode half the bytes.
- It turns out that the MultiByteToWideChar() API can't transcode
  UTF16-BE to UTF16-LE. The solution is to just iterate over the buffer
  and flip the bytes on each uint16_t. This but was causing the UTF16-BE
  to UTF8 tests to fail.

I also split up the utf8 transcoding tests into separate tests so I
could see all of the failures instead of just the first one.

Added a flags parameter to the unit test function to open testfiles
because it turns out that on Windows if a file contains the \r\n it will
replace it with just \n if you opened the file as a text file instead of
as binary. However, if we open the CBC files as binary, then a bunch of
bytecode tests fail. So I've changed the tests to open the CBC files in
the bytecode tests as text files and open all other files as binary.

Ported the feature tests from shell scripts to Python using a modified
version of our QA test-framework, which is largely compatible and will
allow us to migrate some QA tests into this repo. I'd like to add GitHub
Actions pipelines in the future so that all public PR's get some testing
before anyone has to manually review them.

The clamd --log option was missing from the help string, though it
definitely works. I've added it in this commit.
It appears that clamd.c was never clang-format'd, so this commit also
reformats clamd.c.

Some of the check_clamd tests expected the path returned by clamd to
match character for character with original path sent to clamd. However,
as we now evaluate real paths before a scan, the path returned by clamd
isn't going to match the relative (and possibly symlink-ridden) path
passed to clamdscan. I fixed this test by changing the test to search
for the basename: <signature> FOUND within the response instead of
matching the exact path.

Autotools: Link check_clamd with libclamav so we can use our utility
functions in check_clamd.c.
2021-02-25 11:41:26 -08:00

639 lines
18 KiB
C

/*
* Unit tests for bytecode functions.
*
* Copyright (C) 2013-2020 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
* Copyright (C) 2009-2013 Sourcefire, Inc.
*
* Authors: Török Edvin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but 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., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <check.h>
#include <fcntl.h>
#include <errno.h>
// libclamav
#include "clamav.h"
#include "others.h"
#include "bytecode.h"
#include "dconf.h"
#include "bytecode_priv.h"
#include "pe.h"
#include "checks.h"
#ifdef CL_THREAD_SAFE
#include <pthread.h>
#endif
static void runtest(const char *file, uint64_t expected, int fail, int nojit,
const char *infile, struct cli_pe_hook_data *pedata,
struct cli_exe_section *sections, const char *expectedvirname,
int testmode)
{
fmap_t *map = NULL;
int rc;
int fd = open_testfile(file, O_RDONLY);
FILE *f;
struct cli_bc bc;
cli_ctx cctx;
struct cli_bc_ctx *ctx;
struct cli_all_bc bcs;
uint64_t v;
struct cl_engine *engine;
int fdin = -1;
char filestr[512];
const char *virname = NULL;
struct cl_scan_options options;
memset(&cctx, 0, sizeof(cctx));
memset(&options, 0, sizeof(struct cl_scan_options));
cctx.options = &options;
cctx.options->general |= CL_SCAN_GENERAL_ALLMATCHES;
cctx.virname = &virname;
cctx.engine = engine = cl_engine_new();
ck_assert_msg(!!cctx.engine, "cannot create engine");
rc = cl_engine_compile(engine);
ck_assert_msg(!rc, "cannot compile engine");
cctx.fmap = cli_calloc(sizeof(fmap_t *), engine->maxreclevel + 2);
ck_assert_msg(!!cctx.fmap, "cannot allocate fmap");
ck_assert_msg(fd >= 0, "retmagic open failed");
f = fdopen(fd, "r");
ck_assert_msg(!!f, "retmagic fdopen failed");
cl_debug();
if (!nojit) {
rc = cli_bytecode_init(&bcs);
ck_assert_msg(rc == CL_SUCCESS, "cli_bytecode_init failed");
} else {
bcs.engine = NULL;
}
bcs.all_bcs = &bc;
bcs.count = 1;
rc = cli_bytecode_load(&bc, f, NULL, 1, 0);
ck_assert_msg(rc == CL_SUCCESS, "cli_bytecode_load failed");
fclose(f);
if (testmode && have_clamjit)
engine->bytecode_mode = CL_BYTECODE_MODE_TEST;
rc = cli_bytecode_prepare2(engine, &bcs, BYTECODE_ENGINE_MASK);
ck_assert_msg(rc == CL_SUCCESS, "cli_bytecode_prepare failed");
if (have_clamjit && !nojit && nojit != -1 && !testmode) {
ck_assert_msg(bc.state == bc_jit, "preparing for JIT failed");
}
ctx = cli_bytecode_context_alloc();
ctx->bytecode_timeout = fail == CL_ETIMEOUT ? 10 : 10000;
ck_assert_msg(!!ctx, "cli_bytecode_context_alloc failed");
ctx->ctx = &cctx;
if (infile) {
snprintf(filestr, sizeof(filestr), OBJDIR PATHSEP "%s", infile);
fdin = open(filestr, O_RDONLY);
if (fdin < 0 && errno == ENOENT)
fdin = open_testfile(infile, O_RDONLY);
ck_assert_msg(fdin >= 0, "failed to open infile");
map = fmap(fdin, 0, 0, filestr);
ck_assert_msg(!!map, "unable to fmap infile");
if (pedata)
ctx->hooks.pedata = pedata;
ctx->sections = sections;
cli_bytecode_context_setfile(ctx, map);
}
cli_bytecode_context_setfuncid(ctx, &bc, 0);
rc = cli_bytecode_run(&bcs, &bc, ctx);
ck_assert_msg(rc == fail, "cli_bytecode_run failed, expected: %u, have: %u\n",
fail, rc);
if (rc == CL_SUCCESS) {
v = cli_bytecode_context_getresult_int(ctx);
ck_assert_msg(v == expected, "Invalid return value from bytecode run, expected: %llx, have: %llx\n",
expected, v);
}
if (infile && expectedvirname) {
ck_assert_msg(ctx->virname &&
!strcmp(ctx->virname, expectedvirname),
"Invalid virname, expected: %s\n", expectedvirname);
}
cli_bytecode_context_destroy(ctx);
if (map)
funmap(map);
cli_bytecode_destroy(&bc);
cli_bytecode_done(&bcs);
free(cctx.fmap);
cl_engine_free(engine);
if (fdin >= 0)
close(fdin);
}
START_TEST(test_retmagic_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "retmagic.cbc", 0x1234f00d, CL_SUCCESS, 0, NULL, NULL, NULL, NULL, 0);
runtest("input" PATHSEP "retmagic.cbc", 0x1234f00d, CL_SUCCESS, 0, NULL, NULL, NULL, NULL, 1);
}
END_TEST
START_TEST(test_retmagic_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "retmagic.cbc", 0x1234f00d, CL_SUCCESS, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_arith_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "arith.cbc", 0xd5555555, CL_SUCCESS, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_arith_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "arith.cbc", 0xd5555555, CL_SUCCESS, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_apicalls_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "apicalls.cbc", 0xf00d, CL_SUCCESS, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_apicalls_int)
{
runtest("input" PATHSEP "apicalls.cbc", 0xf00d, CL_SUCCESS, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_apicalls2_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "apicalls2.cbc", 0xf00d, CL_SUCCESS, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_apicalls2_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "apicalls2.cbc", 0xf00d, CL_SUCCESS, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_div0_jit)
{
cl_init(CL_INIT_DEFAULT);
/* must not crash on div#0 but catch it */
runtest("input" PATHSEP "div0.cbc", 0, CL_EBYTECODE, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_div0_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "div0.cbc", 0, CL_EBYTECODE, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_lsig_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "lsig.cbc", 0, 0, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_lsig_int)
{
runtest("input" PATHSEP "lsig.cbc", 0, 0, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_inf_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "inf.cbc", 0, CL_ETIMEOUT, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_inf_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "inf.cbc", 0, CL_ETIMEOUT, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_matchwithread_jit)
{
struct cli_exe_section sect;
struct cli_pe_hook_data pedata;
cl_init(CL_INIT_DEFAULT);
memset(&pedata, 0, sizeof(pedata));
pedata.ep = 64;
cli_writeint32(&pedata.opt32.ImageBase, 0x400000);
pedata.hdr_size = 0x400;
pedata.nsections = 1;
sect.rva = 4096;
sect.vsz = 4096;
sect.raw = 0;
sect.rsz = 512;
sect.urva = 4096;
sect.uvsz = 4096;
sect.uraw = 1;
sect.ursz = 512;
runtest("input" PATHSEP "matchwithread.cbc", 0, 0, 0, ".." PATHSEP "test" PATHSEP "clam.exe", &pedata,
&sect, "ClamAV-Test-File-detected-via-bytecode", 0);
}
END_TEST
START_TEST(test_matchwithread_int)
{
struct cli_exe_section sect;
struct cli_pe_hook_data pedata;
cl_init(CL_INIT_DEFAULT);
memset(&pedata, 0, sizeof(pedata));
pedata.ep = 64;
cli_writeint32(&pedata.opt32.ImageBase, 0x400000);
pedata.hdr_size = 0x400;
pedata.nsections = 1;
sect.rva = 4096;
sect.vsz = 4096;
sect.raw = 0;
sect.rsz = 512;
sect.urva = 4096;
sect.uvsz = 4096;
sect.uraw = 1;
sect.ursz = 512;
runtest("input" PATHSEP "matchwithread.cbc", 0, 0, 1, ".." PATHSEP "test" PATHSEP "clam.exe", &pedata,
&sect, "ClamAV-Test-File-detected-via-bytecode", 0);
}
END_TEST
START_TEST(test_pdf_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "pdf.cbc", 0, 0, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_pdf_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "pdf.cbc", 0, 0, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_bswap_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "bswap.cbc", 0xbeef, 0, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_bswap_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "bswap.cbc", 0xbeef, 0, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_inflate_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "inflate.cbc", 0xbeef, 0, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_inflate_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "inflate.cbc", 0xbeef, 0, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_api_extract_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "api_extract_7.cbc", 0xf00d, 0, 0, "input" PATHSEP "apitestfile", NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_api_files_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "api_files_7.cbc", 0xf00d, 0, 0, "input" PATHSEP "apitestfile", NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_apicalls2_7_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "apicalls2_7.cbc", 0xf00d, 0, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_apicalls_7_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "apicalls_7.cbc", 0xf00d, 0, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_arith_7_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "arith_7.cbc", 0xd55555dd, CL_SUCCESS, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_debug_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "debug_7.cbc", 0xf00d, 0, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_inf_7_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "inf_7.cbc", 0, CL_ETIMEOUT, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_lsig_7_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "lsig_7.cbc", 0, 0, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_retmagic_7_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "retmagic_7.cbc", 0x1234f00d, CL_SUCCESS, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_testadt_jit)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "testadt_7.cbc", 0xf00d, 0, 0, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_api_extract_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "api_extract_7.cbc", 0xf00d, 0, 1, "input" PATHSEP "apitestfile", NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_api_files_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "api_files_7.cbc", 0xf00d, 0, 1, "input" PATHSEP "apitestfile", NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_apicalls2_7_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "apicalls2_7.cbc", 0xf00d, 0, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_apicalls_7_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "apicalls_7.cbc", 0xf00d, 0, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_arith_7_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "arith_7.cbc", 0xd55555dd, CL_SUCCESS, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_debug_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "debug_7.cbc", 0xf00d, 0, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_inf_7_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "inf_7.cbc", 0, CL_ETIMEOUT, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_lsig_7_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "lsig_7.cbc", 0, 0, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_retmagic_7_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "retmagic_7.cbc", 0x1234f00d, CL_SUCCESS, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
START_TEST(test_testadt_int)
{
cl_init(CL_INIT_DEFAULT);
runtest("input" PATHSEP "testadt_7.cbc", 0xf00d, 0, 1, NULL, NULL, NULL, NULL, 0);
}
END_TEST
static void runload(const char *dbname, struct cl_engine *engine, unsigned signoexp)
{
const char *srcdir = getenv("srcdir");
char *str;
unsigned signo = 0;
int rc;
if (!srcdir) {
/* when run from automake srcdir is set, but if run manually then not */
srcdir = SRCDIR;
}
str = cli_malloc(strlen(dbname) + strlen(srcdir) + 2);
ck_assert_msg(!!str, "cli_malloc");
sprintf(str, "%s" PATHSEP "%s", srcdir, dbname);
rc = cl_load(str, engine, &signo, CL_DB_STDOPT);
ck_assert_msg(rc == CL_SUCCESS, "failed to load %s: %s\n",
str, cl_strerror(rc));
ck_assert_msg(signo == signoexp, "different number of signatures loaded, expected %u, got %u\n",
signoexp, signo);
free(str);
rc = cl_engine_compile(engine);
ck_assert_msg(rc == CL_SUCCESS, "failed to load %s: %s\n",
str, cl_strerror(rc));
}
START_TEST(test_load_bytecode_jit)
{
struct cl_engine *engine;
cl_init(CL_INIT_DEFAULT);
engine = cl_engine_new();
ck_assert_msg(!!engine, "failed to create engine\n");
runload("input" PATHSEP "bytecode.cvd", engine, 5);
cl_engine_free(engine);
}
END_TEST
START_TEST(test_load_bytecode_int)
{
struct cl_engine *engine;
cl_init(CL_INIT_DEFAULT);
engine = cl_engine_new();
engine->dconf->bytecode = BYTECODE_INTERPRETER;
ck_assert_msg(!!engine, "failed to create engine\n");
runload("input" PATHSEP "bytecode.cvd", engine, 5);
cl_engine_free(engine);
}
END_TEST
#if defined(CL_THREAD_SAFE) && defined(C_LINUX) && ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= (2 << 16) + 4)
#define DO_BARRIER
#endif
#ifdef DO_BARRIER
static pthread_barrier_t barrier;
static void *thread(void *arg)
{
struct cl_engine *engine;
engine = cl_engine_new();
ck_assert_msg(!!engine, "failed to create engine\n");
/* run all cl_load at once, to maximize chance of a crash
* in case of a race condition */
pthread_barrier_wait(&barrier);
runload("input" PATHSEP "bytecode.cvd", engine, 5);
cl_engine_free(engine);
return NULL;
}
START_TEST(test_parallel_load)
{
#define N 5
pthread_t threads[N];
unsigned i;
cl_init(CL_INIT_DEFAULT);
pthread_barrier_init(&barrier, NULL, N);
for (i = 0; i < N; i++) {
pthread_create(&threads[i], NULL, thread, NULL);
}
for (i = 0; i < N; i++) {
pthread_join(threads[i], NULL);
}
/* DB load used to crash due to 'static' variable in cache.c,
* and also due to something wrong in LLVM 2.7.
* Enabled the mutex around codegen in bytecode2llvm.cpp, and this test is
* here to make sure it doesn't crash */
}
END_TEST
#endif
Suite *test_bytecode_suite(void)
{
Suite *s = suite_create("bytecode");
TCase *tc_cli_arith = tcase_create("arithmetic");
suite_add_tcase(s, tc_cli_arith);
tcase_set_timeout(tc_cli_arith, 20);
tcase_add_test(tc_cli_arith, test_retmagic_jit);
tcase_add_test(tc_cli_arith, test_arith_jit);
tcase_add_test(tc_cli_arith, test_apicalls_jit);
tcase_add_test(tc_cli_arith, test_apicalls2_jit);
tcase_add_test(tc_cli_arith, test_div0_jit);
tcase_add_test(tc_cli_arith, test_lsig_jit);
tcase_add_test(tc_cli_arith, test_inf_jit);
tcase_add_test(tc_cli_arith, test_matchwithread_jit);
tcase_add_test(tc_cli_arith, test_pdf_jit);
tcase_add_test(tc_cli_arith, test_bswap_jit);
tcase_add_test(tc_cli_arith, test_inflate_jit);
tcase_add_test(tc_cli_arith, test_arith_int);
tcase_add_test(tc_cli_arith, test_apicalls_int);
tcase_add_test(tc_cli_arith, test_apicalls2_int);
tcase_add_test(tc_cli_arith, test_div0_int);
tcase_add_test(tc_cli_arith, test_lsig_int);
tcase_add_test(tc_cli_arith, test_inf_int);
tcase_add_test(tc_cli_arith, test_matchwithread_int);
tcase_add_test(tc_cli_arith, test_pdf_int);
tcase_add_test(tc_cli_arith, test_bswap_int);
tcase_add_test(tc_cli_arith, test_inflate_int);
tcase_add_test(tc_cli_arith, test_retmagic_int);
tcase_add_test(tc_cli_arith, test_api_extract_jit);
tcase_add_test(tc_cli_arith, test_api_files_jit);
tcase_add_test(tc_cli_arith, test_apicalls2_7_jit);
tcase_add_test(tc_cli_arith, test_apicalls_7_jit);
tcase_add_test(tc_cli_arith, test_apicalls_7_jit);
tcase_add_test(tc_cli_arith, test_arith_7_jit);
tcase_add_test(tc_cli_arith, test_debug_jit);
tcase_add_test(tc_cli_arith, test_inf_7_jit);
tcase_add_test(tc_cli_arith, test_lsig_7_jit);
tcase_add_test(tc_cli_arith, test_retmagic_7_jit);
tcase_add_test(tc_cli_arith, test_testadt_jit);
tcase_add_test(tc_cli_arith, test_api_extract_int);
tcase_add_test(tc_cli_arith, test_api_files_int);
tcase_add_test(tc_cli_arith, test_apicalls2_7_int);
tcase_add_test(tc_cli_arith, test_apicalls_7_int);
tcase_add_test(tc_cli_arith, test_apicalls_7_int);
tcase_add_test(tc_cli_arith, test_arith_7_int);
tcase_add_test(tc_cli_arith, test_debug_int);
tcase_add_test(tc_cli_arith, test_inf_7_int);
tcase_add_test(tc_cli_arith, test_lsig_7_int);
tcase_add_test(tc_cli_arith, test_retmagic_int);
tcase_add_test(tc_cli_arith, test_testadt_int);
tcase_add_test(tc_cli_arith, test_load_bytecode_jit);
tcase_add_test(tc_cli_arith, test_load_bytecode_int);
#ifdef DO_BARRIER
tcase_add_test(tc_cli_arith, test_parallel_load);
#endif
return s;
}