Rizin
unix-like reverse engineering framework and cli tools
rz-test.c File Reference
#include "rz_test.h"
#include <assert.h>
#include <rz_cons.h>
#include <rz_main.h>
#include <rz_windows.h>

Go to the source code of this file.

Classes

struct  rz_testfile_counts_t
 
struct  rz_test_state_t
 

Macros

#define Color_INSERT   Color_BGREEN
 
#define Color_DELETE   Color_BRED
 
#define Color_BGINSERT   "\x1b[48;5;22m"
 
#define Color_BGDELETE   "\x1b[48;5;52m"
 
#define Color_HLINSERT   Color_BGINSERT Color_INSERT
 
#define Color_HLDELETE   Color_BGDELETE Color_DELETE
 
#define WORKERS_DEFAULT   8
 
#define RIZIN_CMD_DEFAULT   "rizin"
 
#define RZ_ASM_CMD_DEFAULT   "rz-asm"
 
#define JSON_TEST_FILE_DEFAULT   "bins/elf/crackme0x00b"
 
#define TIMEOUT_DEFAULT   960
 
#define STRV(x)   #x
 
#define STR(x)   STRV(x)
 
#define WORKERS_DEFAULT_STR   STR(WORKERS_DEFAULT)
 
#define TIMEOUT_DEFAULT_STR   STR(TIMEOUT_DEFAULT)
 
#define DO_KEY_STR(key, field)
 
#define DO_KEY_BOOL(key, field)
 
#define DO_KEY_NUM(key, field)
 

Typedefs

typedef struct rz_testfile_counts_t RzTestFileCounts
 
typedef struct rz_test_state_t RzTestState
 

Functions

static void * worker_th (RzTestState *state)
 
static void print_state (RzTestState *state, ut64 prev_completed)
 
static void print_log (RzTestState *state, ut64 prev_completed, ut64 prev_paths_completed)
 
static void interact (RzTestState *state)
 
static bool interact_fix (RzTestResultInfo *result, RzPVector *fixup_results)
 
static void interact_break (RzTestResultInfo *result, RzPVector *fixup_results)
 
static void interact_commands (RzTestResultInfo *result, RzPVector *fixup_results)
 
static int help (bool verbose)
 
static void path_left_free_kv (HtPPKv *kv)
 
static bool rz_test_chdir (const char *argv0)
 
static bool rz_test_test_run_unit (void)
 
static bool rz_test_chdir_fromtest (const char *test_path)
 
int rz_test_main (int argc, const char **argv)
 
static void test_result_to_json (PJ *pj, RzTestResultInfo *result)
 
static void print_diff (const char *actual, const char *expected, const char *regexp)
 
static RzSubprocessOutputprint_runner (const char *file, const char *args[], size_t args_size, const char *envvars[], const char *envvals[], size_t env_size, ut64 timeout_ms, void *user)
 
static void print_result_diff (RzTestRunConfig *config, RzTestResultInfo *result)
 
static void print_new_results (RzTestState *state, ut64 prev_completed)
 
static void print_state_counts (RzTestState *state)
 
static char * format_cmd_kv (const char *key, const char *val)
 
static char * replace_lines (const char *src, size_t from, size_t to, const char *news)
 
static void fixup_tests (RzPVector *results, const char *edited_file, ut64 start_line, st64 delta)
 
static char * read_test_file_for_fix (const char *path)
 
static void save_test_file_for_fix (const char *path, const char *newc)
 
static char * replace_cmd_kv (const char *path, const char *content, size_t line_begin, size_t line_end, const char *key, const char *value, RzPVector *fixup_results)
 
static void replace_cmd_kv_file (const char *path, ut64 line_begin, ut64 line_end, const char *key, const char *value, RzPVector *fixup_results)
 
static bool interact_fix_cmd (RzTestResultInfo *result, RzPVector *fixup_results)
 
static void replace_file_line (const char *path, ut64 line_idx, const char *line_new)
 
static void replace_asm_test (RZ_NONNULL const char *path, ut64 line_idx, int mode, RZ_NONNULL const char *disasm, RZ_NONNULL const ut8 *bytes, size_t bytes_sz, ut64 offset, RZ_NULLABLE const char *il)
 
static bool asm_test_failed_both_ways (RzAsmTest *test, RzAsmTestOutput *out)
 
static bool interact_fix_asm (RzTestResultInfo *result)
 
static void interact_break_cmd (RzTestResultInfo *result, RzPVector *fixup_results)
 
static void interact_break_asm (RzTestResultInfo *result)
 
int MAIN_NAME (int argc, const ARGV_TYPE **argv)
 

Variables

static bool log_mode = false
 

Macro Definition Documentation

◆ Color_BGDELETE

#define Color_BGDELETE   "\x1b[48;5;52m"

Definition at line 13 of file rz-test.c.

◆ Color_BGINSERT

#define Color_BGINSERT   "\x1b[48;5;22m"

Definition at line 12 of file rz-test.c.

◆ Color_DELETE

#define Color_DELETE   Color_BRED

Definition at line 11 of file rz-test.c.

◆ Color_HLDELETE

#define Color_HLDELETE   Color_BGDELETE Color_DELETE

Definition at line 15 of file rz-test.c.

◆ Color_HLINSERT

#define Color_HLINSERT   Color_BGINSERT Color_INSERT

Definition at line 14 of file rz-test.c.

◆ Color_INSERT

#define Color_INSERT   Color_BGREEN

Definition at line 10 of file rz-test.c.

◆ DO_KEY_BOOL

#define DO_KEY_BOOL (   key,
  field 
)
Value:
if (test->field.set && test->field.line >= start_line) { \
test->field.line += delta; \
}
-lz4-versions
static st64 delta
Definition: vmenus.c:2425

◆ DO_KEY_NUM

#define DO_KEY_NUM (   key,
  field 
)
Value:
if (test->field.set && test->field.line >= start_line) { \
test->field.line += delta; \
}

◆ DO_KEY_STR

#define DO_KEY_STR (   key,
  field 
)
Value:
if (test->field.value) { \
if (test->field.line_begin >= start_line) { \
test->field.line_begin += delta; \
} \
if (test->field.line_end >= start_line) { \
test->field.line_end += delta; \
} \
}

◆ JSON_TEST_FILE_DEFAULT

#define JSON_TEST_FILE_DEFAULT   "bins/elf/crackme0x00b"

Definition at line 20 of file rz-test.c.

◆ RIZIN_CMD_DEFAULT

#define RIZIN_CMD_DEFAULT   "rizin"

Definition at line 18 of file rz-test.c.

◆ RZ_ASM_CMD_DEFAULT

#define RZ_ASM_CMD_DEFAULT   "rz-asm"

Definition at line 19 of file rz-test.c.

◆ STR

#define STR (   x)    STRV(x)

Definition at line 24 of file rz-test.c.

◆ STRV

#define STRV (   x)    #x

Definition at line 23 of file rz-test.c.

◆ TIMEOUT_DEFAULT

#define TIMEOUT_DEFAULT   960

Definition at line 21 of file rz-test.c.

◆ TIMEOUT_DEFAULT_STR

#define TIMEOUT_DEFAULT_STR   STR(TIMEOUT_DEFAULT)

Definition at line 26 of file rz-test.c.

◆ WORKERS_DEFAULT

#define WORKERS_DEFAULT   8

Definition at line 17 of file rz-test.c.

◆ WORKERS_DEFAULT_STR

#define WORKERS_DEFAULT_STR   STR(WORKERS_DEFAULT)

Definition at line 25 of file rz-test.c.

Typedef Documentation

◆ RzTestFileCounts

◆ RzTestState

typedef struct rz_test_state_t RzTestState

Function Documentation

◆ asm_test_failed_both_ways()

static bool asm_test_failed_both_ways ( RzAsmTest test,
RzAsmTestOutput out 
)
static

Check if both assembly and disassembly passes failed, making it non-trivial to repair automatically.

Definition at line 1228 of file rz-test.c.

1228  {
1229  // check that both ways are requested
1230  if (!(test->mode & RZ_ASM_TEST_MODE_ASSEMBLE) || !(test->mode & RZ_ASM_TEST_MODE_ASSEMBLE)) {
1231  return false;
1232  }
1233  // check that disasm is wrong
1234  if (out->disasm && !strcmp(test->disasm, out->disasm)) {
1235  return false;
1236  }
1237  // check that asm is wrong too
1238  if (out->bytes && out->bytes_size == test->bytes_size && !memcmp(out->bytes, test->bytes, test->bytes_size)) {
1239  return false;
1240  }
1241  // determined that both ways are broken
1242  return true;
1243 }
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
@ RZ_ASM_TEST_MODE_ASSEMBLE
Definition: rz_test.h:89

References out, and RZ_ASM_TEST_MODE_ASSEMBLE.

Referenced by interact_fix_asm().

◆ fixup_tests()

static void fixup_tests ( RzPVector results,
const char *  edited_file,
ut64  start_line,
st64  delta 
)
static

Definition at line 1078 of file rz-test.c.

1078  {
1079  void **it;
1080  rz_pvector_foreach (results, it) {
1081  RzTestResultInfo *result = *it;
1082  if (result->test->type != RZ_TEST_TYPE_CMD) {
1083  continue;
1084  }
1085  if (result->test->path != edited_file) { // this works because all the paths come from the string pool
1086  continue;
1087  }
1088  RzCmdTest *test = result->test->cmd_test;
1089  test->run_line += delta;
1090 
1091 #define DO_KEY_STR(key, field) \
1092  if (test->field.value) { \
1093  if (test->field.line_begin >= start_line) { \
1094  test->field.line_begin += delta; \
1095  } \
1096  if (test->field.line_end >= start_line) { \
1097  test->field.line_end += delta; \
1098  } \
1099  }
1100 
1101 #define DO_KEY_BOOL(key, field) \
1102  if (test->field.set && test->field.line >= start_line) { \
1103  test->field.line += delta; \
1104  }
1105 
1106 #define DO_KEY_NUM(key, field) \
1107  if (test->field.set && test->field.line >= start_line) { \
1108  test->field.line += delta; \
1109  }
1110 
1112 #undef DO_KEY_STR
1113 #undef DO_KEY_BOOL
1114 #undef DO_KEY_NUM
1115  }
1116 }
#define DO_KEY_NUM(key, field)
#define DO_KEY_STR(key, field)
#define DO_KEY_BOOL(key, field)
@ RZ_TEST_TYPE_CMD
Definition: rz_test.h:120
#define RZ_CMD_TEST_FOREACH_RECORD(macro_str, macro_bool, macro_int)
Definition: rz_test.h:74
#define rz_pvector_foreach(vec, it)
Definition: rz_vector.h:334
RzCmdTest * cmd_test
Definition: rz_test.h:130
const char * path
Definition: rz_test.h:127
RzTestType type
Definition: rz_test.h:128

References rz_test_test_t::cmd_test, delta, DO_KEY_BOOL, DO_KEY_NUM, DO_KEY_STR, rz_test_test_t::path, RZ_CMD_TEST_FOREACH_RECORD, rz_pvector_foreach, RZ_TEST_TYPE_CMD, rz_test_test_result_info_t::test, and rz_test_test_t::type.

Referenced by replace_cmd_kv().

◆ format_cmd_kv()

static char* format_cmd_kv ( const char *  key,
const char *  val 
)
static

Definition at line 1029 of file rz-test.c.

1029  {
1030  RzStrBuf buf;
1031  rz_strbuf_init(&buf);
1032  rz_strbuf_appendf(&buf, "%s=", key);
1033  if (strchr(val, '\n')) {
1034  rz_strbuf_appendf(&buf, "<<EOF\n%sEOF", val);
1035  } else {
1037  }
1038  return rz_strbuf_drain_nofree(&buf);
1039 }
ut16 val
Definition: armass64_const.h:6
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
voidpf void * buf
Definition: ioapi.h:138
RZ_API RZ_OWN char * rz_strbuf_drain_nofree(RzStrBuf *sb)
Definition: strbuf.c:349
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33

References key, rz_strbuf_append(), rz_strbuf_appendf(), rz_strbuf_drain_nofree(), rz_strbuf_init(), and val.

Referenced by replace_cmd_kv().

◆ help()

static int help ( bool  verbose)
static

Definition at line 62 of file rz-test.c.

62  {
63  printf("Usage: rz-test [-qvVnL] [-j threads] [test file/dir | @test-type]\n");
64  if (verbose) {
65  printf(
66  " -h print this help\n"
67  " -v show version\n"
68  " -q quiet\n"
69  " -V verbose\n"
70  " -i interactive mode\n"
71  " -n do nothing (don't run any test, just load/parse them)\n"
72  " -L log mode (better printing for CI, logfiles, etc.)\n"
73  " -F [dir] run fuzz tests (open and default analysis) on all files in the given dir\n"
74  " -j [threads] how many threads to use for running tests concurrently (default is " WORKERS_DEFAULT_STR ")\n"
75  " -r [rizin] path to rizin executable (default is " RIZIN_CMD_DEFAULT ")\n"
76  " -m [rz-asm] path to rz-asm executable (default is " RZ_ASM_CMD_DEFAULT ")\n"
77  " -f [file] file to use for json tests (default is " JSON_TEST_FILE_DEFAULT ")\n"
78  " -C [dir] chdir before running rz-test (default follows executable symlink + test/new\n"
79  " -t [seconds] timeout per test (default is " TIMEOUT_DEFAULT_STR ")\n"
80  " -o [file] output test run information in JSON format to file\n"
81  " -e [dir] exclude a particular directory while testing (this option can appear many times)\n"
82  " -s [num] number of expected successful tests\n"
83  " -x [num] number of expected failed tests"
84  "\n"
85  "Supported test types: @json @unit @fuzz @cmds\n"
86  "OS/Arch for archos tests: " RZ_TEST_ARCH_OS "\n");
87  }
88  return 1;
89 }
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
#define WORKERS_DEFAULT_STR
Definition: rz-test.c:25
#define RIZIN_CMD_DEFAULT
Definition: rz-test.c:18
#define RZ_ASM_CMD_DEFAULT
Definition: rz-test.c:19
#define TIMEOUT_DEFAULT_STR
Definition: rz-test.c:26
#define JSON_TEST_FILE_DEFAULT
Definition: rz-test.c:20
#define RZ_TEST_ARCH_OS
Definition: rz_test.h:33
static int verbose
Definition: z80asm.c:73

References JSON_TEST_FILE_DEFAULT, printf(), RIZIN_CMD_DEFAULT, RZ_ASM_CMD_DEFAULT, RZ_TEST_ARCH_OS, TIMEOUT_DEFAULT_STR, verbose, and WORKERS_DEFAULT_STR.

Referenced by rz_test_main().

◆ interact()

static void interact ( RzTestState state)
static

Definition at line 953 of file rz-test.c.

953  {
954  void **it;
955  RzPVector failed_results;
956  rz_pvector_init(&failed_results, NULL);
957  rz_pvector_foreach (&state->results, it) {
958  RzTestResultInfo *result = *it;
959  if (result->result == RZ_TEST_RESULT_FAILED) {
960  rz_pvector_push(&failed_results, result);
961  }
962  }
963  if (rz_pvector_empty(&failed_results)) {
964  goto beach;
965  }
966 
967 #if __WINDOWS__
968  (void)SetConsoleOutputCP(65001); // UTF-8
969 #endif
970  printf("\n");
971  printf("#####################\n");
972  printf(" %" PFMT64u " failed test(s) " UTF8_POLICE_CARS_REVOLVING_LIGHT "\n",
973  (ut64)rz_pvector_len(&failed_results));
974 
975  rz_pvector_foreach (&failed_results, it) {
976  RzTestResultInfo *result = *it;
977  if (result->test->type != RZ_TEST_TYPE_CMD && result->test->type != RZ_TEST_TYPE_ASM) {
978  continue;
979  }
980 
981  printf("#####################\n\n");
982  print_result_diff(&state->run_config, result);
983  bool have_commands = result->test->type == RZ_TEST_TYPE_CMD;
984  menu:
985  printf("Wat do? "
987  "(i)gnore " UTF8_SEE_NO_EVIL_MONKEY " "
989  "%s"
990  "(q)uit " UTF8_DOOR "\n",
991  have_commands ? "(c)ommands " UTF8_KEYBOARD UTF8_VS16 " " : "");
992  printf("> ");
993  char buf[0x30];
994  if (!fgets(buf, sizeof(buf), stdin)) {
995  break;
996  }
997  if (strlen(buf) != 2) {
998  goto menu;
999  }
1000  switch (buf[0]) {
1001  case 'f':
1002  if (!interact_fix(result, &failed_results)) {
1003  printf("This test has failed too hard to be fixed.\n");
1004  goto menu;
1005  }
1006  break;
1007  case 'i':
1008  break;
1009  case 'b':
1010  interact_break(result, &failed_results);
1011  break;
1012  case 'c':
1013  if (have_commands) {
1014  interact_commands(result, &failed_results);
1015  break;
1016  }
1017  goto menu;
1018  case 'q':
1019  goto beach;
1020  default:
1021  goto menu;
1022  }
1023  }
1024 
1025 beach:
1026  rz_pvector_clear(&failed_results);
1027 }
#define NULL
Definition: cris-opc.c:27
static void print_result_diff(RzTestRunConfig *config, RzTestResultInfo *result)
Definition: rz-test.c:771
static void interact_break(RzTestResultInfo *result, RzPVector *fixup_results)
Definition: rz-test.c:1314
static void interact_commands(RzTestResultInfo *result, RzPVector *fixup_results)
Definition: rz-test.c:1327
static bool interact_fix(RzTestResultInfo *result, RzPVector *fixup_results)
Definition: rz-test.c:1282
#define UTF8_POLICE_CARS_REVOLVING_LIGHT
Definition: rz_cons.h:422
#define UTF8_SEE_NO_EVIL_MONKEY
Definition: rz_cons.h:424
#define UTF8_DOOR
Definition: rz_cons.h:428
#define UTF8_WHITE_HEAVY_CHECK_MARK
Definition: rz_cons.h:423
#define UTF8_KEYBOARD
Definition: rz_cons.h:426
#define UTF8_VS16
Definition: rz_cons.h:431
#define UTF8_SKULL_AND_CROSSBONES
Definition: rz_cons.h:425
@ RZ_TEST_RESULT_FAILED
Definition: rz_test.h:163
@ RZ_TEST_TYPE_ASM
Definition: rz_test.h:121
#define PFMT64u
Definition: rz_types.h:395
RZ_API void rz_pvector_init(RzPVector *vec, RzPVectorFree free)
Definition: vector.c:298
static size_t rz_pvector_len(const RzPVector *vec)
Definition: rz_vector.h:231
static bool rz_pvector_empty(RzPVector *vec)
Definition: rz_vector.h:246
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_pvector_clear(RzPVector *vec)
Definition: vector.c:326
Definition: dis.h:43
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References interact_break(), interact_commands(), interact_fix(), NULL, PFMT64u, print_result_diff(), printf(), rz_test_test_result_info_t::result, rz_pvector_clear(), rz_pvector_empty(), rz_pvector_foreach, rz_pvector_init(), rz_pvector_len(), rz_pvector_push(), RZ_TEST_RESULT_FAILED, RZ_TEST_TYPE_ASM, RZ_TEST_TYPE_CMD, rz_test_test_result_info_t::test, rz_test_test_t::type, ut64(), UTF8_DOOR, UTF8_KEYBOARD, UTF8_POLICE_CARS_REVOLVING_LIGHT, UTF8_SEE_NO_EVIL_MONKEY, UTF8_SKULL_AND_CROSSBONES, UTF8_VS16, and UTF8_WHITE_HEAVY_CHECK_MARK.

Referenced by rz_test_main().

◆ interact_break()

static void interact_break ( RzTestResultInfo result,
RzPVector fixup_results 
)
static

Definition at line 1314 of file rz-test.c.

1314  {
1315  switch (result->test->type) {
1316  case RZ_TEST_TYPE_CMD:
1317  interact_break_cmd(result, fixup_results);
1318  break;
1319  case RZ_TEST_TYPE_ASM:
1320  interact_break_asm(result);
1321  break;
1322  default:
1323  break;
1324  }
1325 }
static void interact_break_cmd(RzTestResultInfo *result, RzPVector *fixup_results)
Definition: rz-test.c:1293
static void interact_break_asm(RzTestResultInfo *result)
Definition: rz-test.c:1307

References interact_break_asm(), interact_break_cmd(), RZ_TEST_TYPE_ASM, RZ_TEST_TYPE_CMD, rz_test_test_result_info_t::test, and rz_test_test_t::type.

Referenced by interact().

◆ interact_break_asm()

static void interact_break_asm ( RzTestResultInfo result)
static

Definition at line 1307 of file rz-test.c.

1307  {
1308  assert(result->test->type == RZ_TEST_TYPE_ASM);
1309  RzAsmTest *test = result->test->asm_test;
1310  replace_asm_test(result->test->path, test->line,
1311  test->mode | RZ_ASM_TEST_MODE_BROKEN, test->disasm, test->bytes, test->bytes_size, test->offset, test->il);
1312 }
assert(limit<=UINT32_MAX/2)
static void replace_asm_test(RZ_NONNULL const char *path, ut64 line_idx, int mode, RZ_NONNULL const char *disasm, RZ_NONNULL const ut8 *bytes, size_t bytes_sz, ut64 offset, RZ_NULLABLE const char *il)
Definition: rz-test.c:1200
@ RZ_ASM_TEST_MODE_BROKEN
Definition: rz_test.h:92
RzAsmTest * asm_test
Definition: rz_test.h:131

References rz_test_test_t::asm_test, assert(), rz_test_test_t::path, replace_asm_test(), RZ_ASM_TEST_MODE_BROKEN, RZ_TEST_TYPE_ASM, rz_test_test_result_info_t::test, and rz_test_test_t::type.

Referenced by interact_break().

◆ interact_break_cmd()

static void interact_break_cmd ( RzTestResultInfo result,
RzPVector fixup_results 
)
static

Definition at line 1293 of file rz-test.c.

1293  {
1294  assert(result->test->type == RZ_TEST_TYPE_CMD);
1295  RzCmdTest *test = result->test->cmd_test;
1296  ut64 line_begin;
1297  ut64 line_end;
1298  if (test->broken.set) {
1299  line_begin = test->broken.set;
1300  line_end = line_begin + 1;
1301  } else {
1302  line_begin = line_end = test->run_line;
1303  }
1304  replace_cmd_kv_file(result->test->path, line_begin, line_end, "BROKEN", "1", fixup_results);
1305 }
static void replace_cmd_kv_file(const char *path, ut64 line_begin, ut64 line_end, const char *key, const char *value, RzPVector *fixup_results)
Definition: rz-test.c:1156

References assert(), rz_test_test_t::cmd_test, rz_test_test_t::path, replace_cmd_kv_file(), RZ_TEST_TYPE_CMD, rz_test_test_result_info_t::test, rz_test_test_t::type, and ut64().

Referenced by interact_break().

◆ interact_commands()

static void interact_commands ( RzTestResultInfo result,
RzPVector fixup_results 
)
static

Definition at line 1327 of file rz-test.c.

1327  {
1328  assert(result->test->type == RZ_TEST_TYPE_CMD);
1329  RzCmdTest *test = result->test->cmd_test;
1330  if (!test->cmds.value) {
1331  return;
1332  }
1333  char *name = NULL;
1334  int fd = rz_file_mkstemp("rz-test-cmds", &name);
1335  if (fd == -1) {
1336  free(name);
1337  eprintf("Failed to open tmp file\n");
1338  return;
1339  }
1340  size_t cmds_sz = strlen(test->cmds.value);
1341  if (write(fd, test->cmds.value, cmds_sz) != cmds_sz) {
1342  eprintf("Failed to write to tmp file\n");
1343  free(name);
1344  close(fd);
1345  return;
1346  }
1347  close(fd);
1348 
1349  char *editor = rz_sys_getenv("EDITOR");
1350  if (!editor || !*editor) {
1351  free(editor);
1352  editor = strdup("vim");
1353  if (!editor) {
1354  free(name);
1355  return;
1356  }
1357  }
1358  rz_sys_cmdf("%s '%s'", editor, name);
1359  free(editor);
1360 
1361  char *newcmds = rz_file_slurp(name, NULL);
1362  if (!newcmds) {
1363  eprintf("Failed to read edited command file\n");
1364  free(name);
1365  return;
1366  }
1367  rz_str_trim(newcmds);
1368 
1369  // if it's multiline we want exactly one trailing newline
1370  if (strchr(newcmds, '\n')) {
1371  char *tmp = newcmds;
1372  newcmds = rz_str_newf("%s\n", newcmds);
1373  free(tmp);
1374  if (!newcmds) {
1375  free(name);
1376  return;
1377  }
1378  }
1379 
1380  replace_cmd_kv_file(result->test->path, test->cmds.line_begin, test->cmds.line_end, "CMDS", newcmds, fixup_results);
1381  free(name);
1382  free(newcmds);
1383 }
static static fork write
Definition: sflib.h:33
static static fork const void static count close
Definition: sflib.h:33
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API int rz_file_mkstemp(RZ_NULLABLE const char *prefix, char **oname)
Definition: file.c:1058
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API void rz_str_trim(RZ_NONNULL RZ_INOUT char *str)
Removes whitespace characters (space, tab, newline etc.) from the beginning and end of a string.
Definition: str_trim.c:190
RZ_API int rz_sys_cmdf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
Definition: sys.c:483
Definition: z80asm.h:102
static const z80_opcode fd[]
Definition: z80_tab.h:997

References assert(), close, rz_test_test_t::cmd_test, eprintf, fd, free(), NULL, rz_test_test_t::path, replace_cmd_kv_file(), rz_file_mkstemp(), rz_file_slurp(), rz_str_newf(), rz_str_trim(), rz_sys_cmdf(), rz_sys_getenv(), RZ_TEST_TYPE_CMD, strdup(), rz_test_test_result_info_t::test, autogen_x86imm::tmp, rz_test_test_t::type, and write.

Referenced by interact().

◆ interact_fix()

static bool interact_fix ( RzTestResultInfo result,
RzPVector fixup_results 
)
static

Definition at line 1282 of file rz-test.c.

1282  {
1283  switch (result->test->type) {
1284  case RZ_TEST_TYPE_CMD:
1285  return interact_fix_cmd(result, fixup_results);
1286  case RZ_TEST_TYPE_ASM:
1287  return interact_fix_asm(result);
1288  default:
1289  return false;
1290  }
1291 }
static bool interact_fix_cmd(RzTestResultInfo *result, RzPVector *fixup_results)
Definition: rz-test.c:1170
static bool interact_fix_asm(RzTestResultInfo *result)
Definition: rz-test.c:1245

References interact_fix_asm(), interact_fix_cmd(), RZ_TEST_TYPE_ASM, RZ_TEST_TYPE_CMD, rz_test_test_result_info_t::test, and rz_test_test_t::type.

Referenced by interact().

◆ interact_fix_asm()

static bool interact_fix_asm ( RzTestResultInfo result)
static

Definition at line 1245 of file rz-test.c.

1245  {
1246  assert(result->test->type == RZ_TEST_TYPE_ASM);
1247  RzAsmTest *test = result->test->asm_test;
1248  RzAsmTestOutput *out = result->asm_out;
1249 
1250  const char *disasm = test->mode & RZ_ASM_TEST_MODE_DISASSEMBLE ? out->disasm : test->disasm;
1251  if (!disasm) {
1252  return false;
1253  }
1254 
1255  const ut8 *bytes;
1256  size_t bytes_sz;
1257  if (test->mode & RZ_ASM_TEST_MODE_ASSEMBLE) {
1258  bytes = out->bytes;
1259  bytes_sz = out->bytes_size;
1260  } else {
1261  bytes = test->bytes;
1262  bytes_sz = test->bytes_size;
1263  }
1264  if (!bytes) {
1265  return false;
1266  }
1267 
1269  // both disasm and asm failed, so trying to fix here would likely only make things worse
1270  return false;
1271  }
1272 
1273  if (test->il && (out->il_failed || !out->il)) {
1274  // IL wasn't lifted or validation failed, this can only be fixed in code
1275  return false;
1276  }
1277 
1278  replace_asm_test(result->test->path, test->line, test->mode, disasm, bytes, bytes_sz, test->offset, out->il);
1279  return true;
1280 }
static ut8 bytes[32]
Definition: asm_arc.c:23
uint8_t ut8
Definition: lh5801.h:11
static bool asm_test_failed_both_ways(RzAsmTest *test, RzAsmTestOutput *out)
Definition: rz-test.c:1228
@ RZ_ASM_TEST_MODE_DISASSEMBLE
Definition: rz_test.h:90
RzAsmTestOutput * asm_out
Definition: rz_test.h:176

References rz_test_test_result_info_t::asm_out, rz_test_test_t::asm_test, asm_test_failed_both_ways(), assert(), bytes, out, rz_test_test_t::path, replace_asm_test(), RZ_ASM_TEST_MODE_ASSEMBLE, RZ_ASM_TEST_MODE_DISASSEMBLE, RZ_TEST_TYPE_ASM, rz_test_test_result_info_t::test, and rz_test_test_t::type.

Referenced by interact_fix().

◆ interact_fix_cmd()

static bool interact_fix_cmd ( RzTestResultInfo result,
RzPVector fixup_results 
)
static

Definition at line 1170 of file rz-test.c.

1170  {
1171  assert(result->test->type == RZ_TEST_TYPE_CMD);
1172  if (result->run_failed || result->proc_out->ret != 0) {
1173  return false;
1174  }
1175  RzCmdTest *test = result->test->cmd_test;
1176  RzSubprocessOutput *out = result->proc_out;
1177  if (test->expect.value && out->out) {
1178  replace_cmd_kv_file(result->test->path, test->expect.line_begin, test->expect.line_end, "EXPECT", (char *)out->out, fixup_results);
1179  }
1180  if (test->expect_err.value && out->err) {
1181  replace_cmd_kv_file(result->test->path, test->expect_err.line_begin, test->expect_err.line_end, "EXPECT_ERR", (char *)out->err, fixup_results);
1182  }
1183  return true;
1184 }
int ret
True if the process has exited because of a timeout.
Definition: rz_subprocess.h:49
RzSubprocessOutput * proc_out
Definition: rz_test.h:175

References assert(), rz_test_test_t::cmd_test, out, rz_test_test_t::path, rz_test_test_result_info_t::proc_out, replace_cmd_kv_file(), rz_process_output_t::ret, rz_test_test_result_info_t::run_failed, RZ_TEST_TYPE_CMD, rz_test_test_result_info_t::test, and rz_test_test_t::type.

Referenced by interact_fix().

◆ MAIN_NAME()

int MAIN_NAME ( int  argc,
const ARGV_TYPE **  argv 
)

Definition at line 1385 of file rz-test.c.

1385  {
1386  char **utf8_argv = ARGV_TYPE_TO_UTF8(argc, argv);
1387  int ret = rz_test_main(argc, (const char **)utf8_argv);
1388  FREE_UTF8_ARGV(argc, utf8_argv);
1389  return ret;
1390 }
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
int rz_test_main(int argc, const char **argv)
Definition: rz-test.c:187
#define ARGV_TYPE_TO_UTF8(argc, argv)
Definition: rz_main.h:30
#define FREE_UTF8_ARGV(argc, utf8_argv)
Definition: rz_main.h:31

References argv, ARGV_TYPE_TO_UTF8, FREE_UTF8_ARGV, and rz_test_main().

◆ path_left_free_kv()

static void path_left_free_kv ( HtPPKv *  kv)
static

Definition at line 91 of file rz-test.c.

91  {
92  free(kv->key);
93  free(kv->value);
94 }

References free().

Referenced by rz_test_main().

◆ print_diff()

static void print_diff ( const char *  actual,
const char *  expected,
const char *  regexp 
)
static

Definition at line 722 of file rz-test.c.

722  {
723  RzDiff *d = NULL;
724  char *uni = NULL;
725  const char *output = actual;
726 
727  if (regexp) {
728  RzList *matches = rz_regex_get_match_list(regexp, "e", actual);
729  output = rz_list_to_str(matches, '\0');
730  rz_list_free(matches);
731  }
732 
733  d = rz_diff_lines_new(expected, output, NULL);
734  if (!d) {
735  goto cleanup;
736  }
737 
738  uni = rz_diff_unified_text(d, "expected", "actual", false, true);
739  if (!uni) {
740  goto cleanup;
741  }
742  puts(uni);
743  free(uni);
744 
745 cleanup:
746  rz_diff_free(d);
747  if (regexp) {
748  free((char *)output);
749  }
750 }
RZ_API RZ_OWN RzDiff * rz_diff_lines_new(RZ_BORROW const char *a, RZ_BORROW const char *b, RZ_NULLABLE RzDiffIgnoreLine ignore)
Returns the structure needed to diff lines.
Definition: diff.c:219
RZ_API void rz_diff_free(RZ_NULLABLE RzDiff *diff)
frees the diff structure
Definition: diff.c:295
void cleanup(void)
Definition: enough.c:244
RZ_API RZ_OWN char * rz_list_to_str(RZ_NONNULL RzList *list, char ch)
Casts a RzList containg strings into a concatenated string.
Definition: list.c:785
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
RZ_API RzList * rz_regex_get_match_list(const char *pattern, const char *flags, const char *text)
Definition: regcomp.c:155
#define d(i)
Definition: sha256.c:44
Definition: diff.c:89
RZ_API RZ_OWN char * rz_diff_unified_text(RZ_NONNULL RzDiff *diff, RZ_NULLABLE const char *from, RZ_NULLABLE const char *to, bool show_time, bool color)
Produces a diff output with A and B inputs presented immediately adjacent to each other.
Definition: unified_diff.c:333
diff_output_t output
Definition: zipcmp.c:237

References cleanup(), d, free(), NULL, output, rz_diff_free(), rz_diff_lines_new(), rz_diff_unified_text(), rz_list_free(), rz_list_to_str(), and rz_regex_get_match_list().

Referenced by print_result_diff().

◆ print_log()

static void print_log ( RzTestState state,
ut64  prev_completed,
ut64  prev_paths_completed 
)
static

Definition at line 929 of file rz-test.c.

929  {
930  print_new_results(state, prev_completed);
931  ut64 paths_completed = rz_pvector_len(&state->completed_paths);
932  for (; prev_paths_completed < paths_completed; prev_paths_completed++) {
933  const char *name = (const char *)rz_pvector_at(&state->completed_paths, prev_paths_completed);
934  if (!name) {
935  name = "unknown path. something is very wrong.";
936  }
937  printf("[**] %50s ", name);
938  if (state->path_left) {
939  RzTestFileCounts *counts = ht_pp_find(state->path_left, name, NULL);
940  if (counts) {
941  state->ok_count += counts->ok;
942  state->xx_count += counts->xx;
943  state->br_count += counts->br;
944  state->fx_count += counts->fx;
945  }
946  }
948  printf("\n");
949  fflush(stdout);
950  }
951 }
static void print_new_results(RzTestState *state, ut64 prev_completed)
Definition: rz-test.c:861
static void print_state_counts(RzTestState *state)
Definition: rz-test.c:903
static void * rz_pvector_at(const RzPVector *vec, size_t index)
Definition: rz_vector.h:236

References rz_testfile_counts_t::br, rz_testfile_counts_t::fx, NULL, rz_testfile_counts_t::ok, print_new_results(), print_state_counts(), printf(), rz_pvector_at(), rz_pvector_len(), ut64(), and rz_testfile_counts_t::xx.

Referenced by rz_test_main().

◆ print_new_results()

static void print_new_results ( RzTestState state,
ut64  prev_completed 
)
static

Definition at line 861 of file rz-test.c.

861  {
862  // Detailed test result (with diff if necessary)
863  ut64 completed = (ut64)rz_pvector_len(&state->results);
864  ut64 i;
865  for (i = prev_completed; i < completed; i++) {
866  RzTestResultInfo *result = rz_pvector_at(&state->results, (size_t)i);
867  if (state->test_results) {
868  test_result_to_json(state->test_results, result);
869  }
870  if (!state->verbose && (result->result == RZ_TEST_RESULT_OK || result->result == RZ_TEST_RESULT_FIXED || result->result == RZ_TEST_RESULT_BROKEN)) {
871  continue;
872  }
873  char *name = rz_test_test_name(result->test);
874  if (!name) {
875  continue;
876  }
878  switch (result->result) {
879  case RZ_TEST_RESULT_OK:
881  break;
883  printf(Color_RED "[XX]" Color_RESET);
884  break;
886  printf(Color_BLUE "[BR]" Color_RESET);
887  break;
889  printf(Color_CYAN "[FX]" Color_RESET);
890  break;
891  }
892  if (result->timeout) {
893  printf(Color_CYAN " TIMEOUT" Color_RESET);
894  }
895  printf(" %s " Color_YELLOW "%s" Color_RESET "\n", result->test->path, name);
896  if (result->result == RZ_TEST_RESULT_FAILED || (state->verbose && result->result == RZ_TEST_RESULT_BROKEN)) {
897  print_result_diff(&state->run_config, result);
898  }
899  free(name);
900  }
901 }
lzma_index ** i
Definition: index.h:629
RZ_API char * rz_test_test_name(RzTest *test)
Definition: run.c:451
static void test_result_to_json(PJ *pj, RzTestResultInfo *result)
Definition: rz-test.c:618
#define RZ_CONS_CLEAR_LINE
Definition: rz_cons.h:593
#define Color_RESET
Definition: rz_cons.h:617
#define Color_CYAN
Definition: rz_cons.h:633
#define RZ_CONS_CURSOR_UP
Definition: rz_cons.h:600
#define Color_GREEN
Definition: rz_cons.h:627
#define Color_RED
Definition: rz_cons.h:623
#define Color_YELLOW
Definition: rz_cons.h:631
#define Color_BLUE
Definition: rz_cons.h:635
@ RZ_TEST_RESULT_OK
Definition: rz_test.h:162
@ RZ_TEST_RESULT_FIXED
Definition: rz_test.h:165
@ RZ_TEST_RESULT_BROKEN
Definition: rz_test.h:164

References Color_BLUE, Color_CYAN, Color_GREEN, Color_RED, Color_RESET, Color_YELLOW, free(), i, rz_test_test_t::path, print_result_diff(), printf(), rz_test_test_result_info_t::result, RZ_CONS_CLEAR_LINE, RZ_CONS_CURSOR_UP, rz_pvector_at(), rz_pvector_len(), RZ_TEST_RESULT_BROKEN, RZ_TEST_RESULT_FAILED, RZ_TEST_RESULT_FIXED, RZ_TEST_RESULT_OK, rz_test_test_name(), rz_test_test_result_info_t::test, test_result_to_json(), rz_test_test_result_info_t::timeout, and ut64().

Referenced by print_log(), and print_state().

◆ print_result_diff()

static void print_result_diff ( RzTestRunConfig config,
RzTestResultInfo result 
)
static

Definition at line 771 of file rz-test.c.

771  {
772  if (result->run_failed) {
773  printf(Color_RED "RUN FAILED (e.g. wrong rizin path)" Color_RESET "\n");
774  return;
775  }
776  switch (result->test->type) {
777  case RZ_TEST_TYPE_CMD: {
779  const char *expect = result->test->cmd_test->expect.value;
780  const char *out = (const char *)result->proc_out->out;
781  const char *regexp_out = result->test->cmd_test->regexp_out.value;
782  if (expect && !rz_test_cmp_cmd_output(out, expect, regexp_out)) {
783  printf("-- stdout\n");
784  print_diff(out, expect, regexp_out);
785  }
786  expect = result->test->cmd_test->expect_err.value;
787  const char *err = (const char *)result->proc_out->err;
788  const char *regexp_err = result->test->cmd_test->regexp_err.value;
789  if (expect && !rz_test_cmp_cmd_output(err, expect, regexp_err)) {
790  printf("-- stderr\n");
791  print_diff(err, expect, regexp_err);
792  } else if (*err) {
793  printf("-- stderr\n%s\n", err);
794  }
795  if (result->proc_out->ret != 0) {
796  printf("-- exit status: " Color_RED "%d" Color_RESET "\n", result->proc_out->ret);
797  }
798  break;
799  }
800  case RZ_TEST_TYPE_ASM: {
801  RzAsmTest *test = result->test->asm_test;
802  RzAsmTestOutput *out = result->asm_out;
803  char *expect_hex = rz_hex_bin2strdup(test->bytes, test->bytes_size);
804  printf("-- <asm> " Color_YELLOW "%s %c--%c %s%s" Color_RESET "\n",
805  test->disasm,
806  test->mode & RZ_ASM_TEST_MODE_DISASSEMBLE ? '<' : '-',
807  test->mode & RZ_ASM_TEST_MODE_ASSEMBLE ? '>' : '-',
808  expect_hex ? expect_hex : "",
809  test->il ? " ---> <IL>" : "");
810  if (test->mode & RZ_ASM_TEST_MODE_DISASSEMBLE) {
811  const char *expect = test->disasm;
812  const char *actual = out->disasm;
813  if (expect && actual && strcmp(actual, expect)) {
814  printf("-- disassembly\n");
815  print_diff(actual, expect, NULL);
816  }
817  }
818  if (test->mode & RZ_ASM_TEST_MODE_ASSEMBLE) {
819  printf("-- assembly\n");
820  if (out->bytes && (out->bytes_size != test->bytes_size || memcmp(out->bytes, test->bytes, out->bytes_size))) {
821  char *actual = rz_hex_bin2strdup(out->bytes, out->bytes_size);
822  print_diff(actual ? actual : "", expect_hex ? expect_hex : "", NULL);
823  free(actual);
824  }
825  }
826  if (test->il) {
827  const char *expect = test->il;
828  const char *actual = out->il;
829  const char *report = out->il_report;
830  bool il_printed = false;
831  const char *hdr = "-- IL\n";
832  if (expect && actual && strcmp(actual, expect)) {
833  printf("%s", hdr);
834  il_printed = true;
835  print_diff(actual, expect, NULL);
836  }
837  if (report) {
838  if (!il_printed) {
839  printf("%s", hdr);
840  if (actual) {
841  printf("%s\n", actual);
842  }
843  }
844  printf(Color_RED "%s" Color_RESET "\n", report);
845  }
846  }
847  free(expect_hex);
848  break;
849  }
850  case RZ_TEST_TYPE_JSON:
851  break;
852  case RZ_TEST_TYPE_FUZZ:
854  printf("-- stdout\n%s\n", (const char *)result->proc_out->out);
855  printf("-- stderr\n%s\n", (const char *)result->proc_out->err);
856  printf("-- exit status: " Color_RED "%d" Color_RESET "\n", result->proc_out->ret);
857  break;
858  }
859 }
static bool err
Definition: armass.c:435
RZ_API RzSubprocessOutput * rz_test_run_cmd_test(RzTestRunConfig *config, RzCmdTest *test, RzTestCmdRunner runner, void *user)
Definition: run.c:161
RZ_API bool rz_test_cmp_cmd_output(const char *output, const char *expect, const char *regexp)
Definition: run.c:192
RZ_API RzSubprocessOutput * rz_test_run_fuzz_test(RzTestRunConfig *config, RzFuzzTest *test, RzTestCmdRunner runner, void *user)
Definition: run.c:433
#define expect(expr, value)
Definition: lz4.c:170
static void print_diff(const char *actual, const char *expected, const char *regexp)
Definition: rz-test.c:722
static RzSubprocessOutput * print_runner(const char *file, const char *args[], size_t args_size, const char *envvars[], const char *envvals[], size_t env_size, ut64 timeout_ms, void *user)
Definition: rz-test.c:752
RZ_API char * rz_hex_bin2strdup(const ut8 *in, int len)
Definition: hex.c:415
@ RZ_TEST_TYPE_JSON
Definition: rz_test.h:122
@ RZ_TEST_TYPE_FUZZ
Definition: rz_test.h:123
ut8 * out
< Output generated by the process
Definition: rz_subprocess.h:41
ut8 * err
Number of bytes in the err field.
Definition: rz_subprocess.h:45
RzCmdTestStringRecord expect
Definition: rz_test.h:59
RzCmdTestStringRecord regexp_out
Definition: rz_test.h:61
RzCmdTestStringRecord regexp_err
Definition: rz_test.h:62
RzCmdTestStringRecord expect_err
Definition: rz_test.h:60
RzFuzzTest * fuzz_test
Definition: rz_test.h:133
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4

References rz_test_test_result_info_t::asm_out, rz_test_test_t::asm_test, rz_test_test_t::cmd_test, Color_RED, Color_RESET, Color_YELLOW, err, rz_process_output_t::err, rz_test_cmd_test_t::expect, expect, rz_test_cmd_test_t::expect_err, free(), rz_test_test_t::fuzz_test, if(), NULL, rz_process_output_t::out, out, print_diff(), print_runner(), printf(), rz_test_test_result_info_t::proc_out, rz_test_cmd_test_t::regexp_err, rz_test_cmd_test_t::regexp_out, rz_process_output_t::ret, rz_test_test_result_info_t::run_failed, RZ_ASM_TEST_MODE_ASSEMBLE, RZ_ASM_TEST_MODE_DISASSEMBLE, rz_hex_bin2strdup(), rz_test_cmp_cmd_output(), rz_test_run_cmd_test(), rz_test_run_fuzz_test(), RZ_TEST_TYPE_ASM, RZ_TEST_TYPE_CMD, RZ_TEST_TYPE_FUZZ, RZ_TEST_TYPE_JSON, rz_test_test_result_info_t::test, rz_test_test_t::type, and rz_test_cmd_test_string_record::value.

Referenced by interact(), and print_new_results().

◆ print_runner()

static RzSubprocessOutput* print_runner ( const char *  file,
const char *  args[],
size_t  args_size,
const char *  envvars[],
const char *  envvals[],
size_t  env_size,
ut64  timeout_ms,
void *  user 
)
static

Definition at line 752 of file rz-test.c.

753  {
754  size_t i;
755  for (i = 0; i < env_size; i++) {
756  printf("%s=%s ", envvars[i], envvals[i]);
757  }
758  printf("%s", file);
759  for (i = 0; i < args_size; i++) {
760  const char *str = args[i];
761  if (strpbrk(str, "\n \'\"")) {
762  printf(" '%s'", str); // TODO: escape
763  } else {
764  printf(" %s", str);
765  }
766  }
767  printf("\n");
768  return NULL;
769 }
int args
Definition: mipsasm.c:18
Definition: gzappend.c:170

References args, i, NULL, printf(), and cmd_descs_generate::str.

Referenced by print_result_diff().

◆ print_state()

static void print_state ( RzTestState state,
ut64  prev_completed 
)
static

Definition at line 908 of file rz-test.c.

908  {
909 #if __WINDOWS__
910  setvbuf(stdout, NULL, _IOFBF, 8192);
911 #endif
912  print_new_results(state, prev_completed);
913 
914  // [x/x] OK 42 BR 0 ...
916  int w = printf("[%" PFMT64u "/%" PFMT64u "]", (ut64)rz_pvector_len(&state->results), (ut64)rz_pvector_len(&state->db->tests));
917  while (w >= 0 && w < 20) {
918  printf(" ");
919  w++;
920  }
921  printf(" ");
923  fflush(stdout);
924 #if __WINDOWS__
925  setvbuf(stdout, NULL, _IONBF, 0);
926 #endif
927 }
#define w
Definition: crypto_rc6.c:13

References NULL, PFMT64u, print_new_results(), print_state_counts(), printf(), RZ_CONS_CLEAR_LINE, rz_pvector_len(), ut64(), and w.

Referenced by rz_test_main().

◆ print_state_counts()

static void print_state_counts ( RzTestState state)
static

Definition at line 903 of file rz-test.c.

903  {
904  printf("%8" PFMT64u " OK %8" PFMT64u " BR %8" PFMT64u " XX %8" PFMT64u " FX",
905  state->ok_count, state->br_count, state->xx_count, state->fx_count);
906 }

References PFMT64u, and printf().

Referenced by print_log(), and print_state().

◆ read_test_file_for_fix()

static char* read_test_file_for_fix ( const char *  path)
static

Definition at line 1118 of file rz-test.c.

1118  {
1119  char *content = rz_file_slurp(path, NULL);
1120  if (!content) {
1121  eprintf("Failed to read file \"%s\"\n", path);
1122  }
1123  return content;
1124 }
static static fork const void static count static fd const char const char static newpath const char static path const char path
Definition: sflib.h:35

References eprintf, NULL, path, and rz_file_slurp().

Referenced by replace_cmd_kv_file(), and replace_file_line().

◆ replace_asm_test()

static void replace_asm_test ( RZ_NONNULL const char *  path,
ut64  line_idx,
int  mode,
RZ_NONNULL const char *  disasm,
RZ_NONNULL const ut8 bytes,
size_t  bytes_sz,
ut64  offset,
RZ_NULLABLE const char *  il 
)
static

Definition at line 1200 of file rz-test.c.

1201  {
1202  char *hex = rz_hex_bin2strdup(bytes, bytes_sz);
1203  if (!hex) {
1204  return;
1205  }
1206  char offset_str[0x20];
1207  if ((!offset && !il) || snprintf(offset_str, sizeof(offset_str), " 0x%" PFMT64x, offset) < 0) {
1208  *offset_str = '\0';
1209  }
1210  char *line = rz_str_newf("%s%s%s%s \"%s\" %s%s%s%s",
1211  (mode & RZ_ASM_TEST_MODE_ASSEMBLE) ? "a" : "",
1212  (mode & RZ_ASM_TEST_MODE_DISASSEMBLE) ? "d" : "",
1213  (mode & RZ_ASM_TEST_MODE_BIG_ENDIAN) ? "E" : "",
1214  (mode & RZ_ASM_TEST_MODE_BROKEN) ? "B" : "",
1215  disasm, hex, offset_str, il ? " " : "", il ? il : "");
1216  free(hex);
1217  if (!line) {
1218  return;
1219  }
1220  replace_file_line(path, line_idx, line);
1221  free(line);
1222 }
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
snprintf
Definition: kernel.h:364
line
Definition: setup.py:34
static const char hex[16]
Definition: print.c:21
static void replace_file_line(const char *path, ut64 line_idx, const char *line_new)
Definition: rz-test.c:1186
@ RZ_ASM_TEST_MODE_BIG_ENDIAN
Definition: rz_test.h:91
#define PFMT64x
Definition: rz_types.h:393

References bytes, free(), hex, setup::line, path, PFMT64x, replace_file_line(), RZ_ASM_TEST_MODE_ASSEMBLE, RZ_ASM_TEST_MODE_BIG_ENDIAN, RZ_ASM_TEST_MODE_BROKEN, RZ_ASM_TEST_MODE_DISASSEMBLE, rz_hex_bin2strdup(), rz_str_newf(), and snprintf.

Referenced by interact_break_asm(), and interact_fix_asm().

◆ replace_cmd_kv()

static char* replace_cmd_kv ( const char *  path,
const char *  content,
size_t  line_begin,
size_t  line_end,
const char *  key,
const char *  value,
RzPVector fixup_results 
)
static

Definition at line 1136 of file rz-test.c.

1136  {
1137  char *kv = format_cmd_kv(key, value);
1138  if (!kv) {
1139  return NULL;
1140  }
1141  size_t kv_lines = rz_str_char_count(kv, '\n') + 1;
1142  char *newc = replace_lines(content, line_begin, line_end, kv);
1143  free(kv);
1144  if (!newc) {
1145  return NULL;
1146  }
1147  size_t lines_before = line_end - line_begin;
1148  st64 delta = (st64)kv_lines - (st64)lines_before;
1149  if (line_end == line_begin) {
1150  delta++;
1151  }
1152  fixup_tests(fixup_results, path, line_end, delta);
1153  return newc;
1154 }
static int value
Definition: cmd_api.c:93
static char * format_cmd_kv(const char *key, const char *val)
Definition: rz-test.c:1029
static char * replace_lines(const char *src, size_t from, size_t to, const char *news)
Definition: rz-test.c:1041
static void fixup_tests(RzPVector *results, const char *edited_file, ut64 start_line, st64 delta)
Definition: rz-test.c:1078
RZ_API int rz_str_char_count(const char *string, char ch)
Definition: str.c:611
#define st64
Definition: rz_types_base.h:10

References delta, fixup_tests(), format_cmd_kv(), free(), key, NULL, path, replace_lines(), rz_str_char_count(), st64, and value.

Referenced by replace_cmd_kv_file().

◆ replace_cmd_kv_file()

static void replace_cmd_kv_file ( const char *  path,
ut64  line_begin,
ut64  line_end,
const char *  key,
const char *  value,
RzPVector fixup_results 
)
static

Definition at line 1156 of file rz-test.c.

1156  {
1157  char *content = read_test_file_for_fix(path);
1158  if (!content) {
1159  return;
1160  }
1161  char *newc = replace_cmd_kv(path, content, line_begin, line_end, key, value, fixup_results);
1162  free(content);
1163  if (!newc) {
1164  return;
1165  }
1167  free(newc);
1168 }
static char * replace_cmd_kv(const char *path, const char *content, size_t line_begin, size_t line_end, const char *key, const char *value, RzPVector *fixup_results)
Definition: rz-test.c:1136
static void save_test_file_for_fix(const char *path, const char *newc)
Definition: rz-test.c:1126
static char * read_test_file_for_fix(const char *path)
Definition: rz-test.c:1118

References free(), key, path, read_test_file_for_fix(), replace_cmd_kv(), save_test_file_for_fix(), and value.

Referenced by interact_break_cmd(), interact_commands(), and interact_fix_cmd().

◆ replace_file_line()

static void replace_file_line ( const char *  path,
ut64  line_idx,
const char *  line_new 
)
static

Definition at line 1186 of file rz-test.c.

1186  {
1187  char *content = read_test_file_for_fix(path);
1188  if (!content) {
1189  return;
1190  }
1191  char *newc = replace_lines(content, line_idx, line_idx + 1, line_new);
1192  free(content);
1193  if (!newc) {
1194  return;
1195  }
1197  free(newc);
1198 }

References free(), path, read_test_file_for_fix(), replace_lines(), and save_test_file_for_fix().

Referenced by replace_asm_test().

◆ replace_lines()

static char* replace_lines ( const char *  src,
size_t  from,
size_t  to,
const char *  news 
)
static

Definition at line 1041 of file rz-test.c.

1041  {
1042  const char *begin = src;
1043  size_t line = 1;
1044  while (line < from) {
1045  begin = strchr(begin, '\n');
1046  if (!begin) {
1047  break;
1048  }
1049  begin++;
1050  line++;
1051  }
1052  if (!begin) {
1053  return NULL;
1054  }
1055 
1056  const char *end = begin;
1057  while (line < to) {
1058  end = strchr(end, '\n');
1059  if (!end) {
1060  break;
1061  }
1062  end++;
1063  line++;
1064  }
1065 
1066  RzStrBuf buf;
1067  rz_strbuf_init(&buf);
1068  rz_strbuf_append_n(&buf, src, begin - src);
1069  rz_strbuf_append(&buf, news);
1070  rz_strbuf_append(&buf, "\n");
1071  if (end) {
1073  }
1074  return rz_strbuf_drain_nofree(&buf);
1075 }
lzma_index * src
Definition: index.h:567
RZ_API bool rz_strbuf_append_n(RzStrBuf *sb, const char *s, size_t l)
Definition: strbuf.c:229
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125

References test_evm::end, from, setup::line, NULL, rz_strbuf_append(), rz_strbuf_append_n(), rz_strbuf_drain_nofree(), rz_strbuf_init(), src, and to.

Referenced by replace_cmd_kv(), and replace_file_line().

◆ rz_test_chdir()

static bool rz_test_chdir ( const char *  argv0)
static

Definition at line 96 of file rz-test.c.

96  {
97 #if __UNIX__
98  if (rz_file_is_directory("db")) {
99  return true;
100  }
101  char src_path[PATH_MAX];
102  char *rz_test_path = rz_file_path(argv0);
103  bool found = false;
104 
105  ssize_t linklen = readlink(rz_test_path, src_path, sizeof(src_path) - 1);
106  if (linklen != -1) {
107  src_path[linklen] = '\0';
108  char *p = strstr(src_path, RZ_SYS_DIR "binrz" RZ_SYS_DIR "rz-test" RZ_SYS_DIR "rz-test");
109  if (p) {
110  *p = 0;
111  strcat(src_path, RZ_SYS_DIR "test" RZ_SYS_DIR);
112  if (rz_file_is_directory(src_path)) {
113  if (chdir(src_path) != -1) {
114  eprintf("Running from %s\n", src_path);
115  found = true;
116  } else {
117  eprintf("Cannot find '%s' directory\n", src_path);
118  }
119  }
120  }
121  } else {
122  eprintf("Cannot follow the link %s\n", src_path);
123  }
124  free(rz_test_path);
125  return found;
126 #else
127  return false;
128 #endif
129 }
static static fork const void static count static fd const char const char static newpath chdir
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len readlink
Definition: sflib.h:65
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
void * p
Definition: libc.cpp:67
RZ_API bool rz_file_is_directory(const char *str)
Definition: file.c:167
RZ_API char * rz_file_path(const char *bin)
Definition: file.c:354
#define RZ_SYS_DIR
Definition: rz_types.h:218
int ssize_t
Definition: sftypes.h:39

References chdir, eprintf, found, free(), p, readlink, rz_file_is_directory(), rz_file_path(), and RZ_SYS_DIR.

Referenced by rz_test_main().

◆ rz_test_chdir_fromtest()

static bool rz_test_chdir_fromtest ( const char *  test_path)
static

Definition at line 135 of file rz-test.c.

135  {
136  if (!test_path || *test_path == '@') {
137  test_path = "";
138  }
139  char *abs_test_path = rz_file_abspath(test_path);
140  if (!rz_file_is_directory(abs_test_path)) {
141  char *last_slash = (char *)rz_str_lchr(abs_test_path, RZ_SYS_DIR[0]);
142  if (last_slash) {
143  *last_slash = 0;
144  }
145  }
146  if (chdir(abs_test_path) == -1) {
147  free(abs_test_path);
148  return false;
149  }
150  free(abs_test_path);
151  bool found = false;
152  char *cwd = NULL;
153  char *old_cwd = NULL;
154  while (true) {
155  cwd = rz_sys_getdir();
156  if (old_cwd && !strcmp(old_cwd, cwd)) {
157  break;
158  }
159  if (rz_file_is_directory("test")) {
160  rz_sys_chdir("test");
161  if (rz_file_is_directory("db")) {
162  found = true;
163  eprintf("Running from %s\n", cwd);
164  break;
165  }
166  rz_sys_chdir("..");
167  }
168  if (rz_file_is_directory("db")) {
169  found = true;
170  eprintf("Running from %s\n", cwd);
171  break;
172  }
173  free(old_cwd);
174  old_cwd = cwd;
175  cwd = NULL;
176  if (chdir("..") == -1) {
177  break;
178  }
179  }
180  free(old_cwd);
181  free(cwd);
182  return found;
183 }
RZ_API char * rz_file_abspath(const char *file)
Definition: file.c:267
RZ_API const char * rz_str_lchr(const char *str, char chr)
Definition: str.c:669
RZ_API bool rz_sys_chdir(RZ_NONNULL const char *s)
Change current directory to s, taking care of home expansion ~.
Definition: sys.c:532
RZ_API char * rz_sys_getdir(void)
Get current working directory.
Definition: sys.c:521

References chdir, test-lz4-speed::cwd, eprintf, found, free(), NULL, rz_file_abspath(), rz_file_is_directory(), rz_str_lchr(), rz_sys_chdir(), RZ_SYS_DIR, and rz_sys_getdir().

Referenced by rz_test_main().

◆ rz_test_main()

int rz_test_main ( int  argc,
const char **  argv 
)

Definition at line 187 of file rz-test.c.

187  {
188  int workers_count = WORKERS_DEFAULT;
189  bool verbose = false;
190  bool nothing = false;
191  bool quiet = false;
192  bool interactive = false;
193  char *rizin_cmd = NULL;
194  char *rz_asm_cmd = NULL;
195  char *json_test_file = NULL;
196  char *output_file = NULL;
197  char *fuzz_dir = NULL;
198  RzPVector *except_dir = rz_pvector_new(free);
199  const char *rz_test_dir = NULL;
200  ut64 timeout_sec = TIMEOUT_DEFAULT;
201  st64 expect_succ = -1;
202  st64 expect_fail = -1;
203  int ret = 0;
204 
205  if (!except_dir) {
206  RZ_LOG_ERROR("Fail to create RzPVector\n");
207  ret = -1;
208  goto beach;
209  }
210 
211 #if __WINDOWS__
212  UINT old_cp = GetConsoleOutputCP();
213  {
214  HANDLE streams[] = { GetStdHandle(STD_OUTPUT_HANDLE), GetStdHandle(STD_ERROR_HANDLE) };
215  DWORD mode;
216  int i;
217  for (i = 0; i < RZ_ARRAY_SIZE(streams); i++) {
218  GetConsoleMode(streams[i], &mode);
219  SetConsoleMode(streams[i],
220  mode | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
221  }
222  }
223 #endif
224 
225  RzGetopt opt;
226  rz_getopt_init(&opt, argc, (const char **)argv, "hqvj:r:m:f:C:LnVt:F:io:e:s:x:");
227 
228  int c;
229  while ((c = rz_getopt_next(&opt)) != -1) {
230  switch (c) {
231  case 'h':
232  ret = help(true);
233  goto beach;
234  case 'q':
235  quiet = true;
236  break;
237  case 'v':
238  if (quiet) {
239  printf(RZ_VERSION "\n");
240  } else {
241  char *s = rz_str_version("rz-test");
242  printf("%s\n", s);
243  free(s);
244  }
245  ret = 0;
246  goto beach;
247  case 'V':
248  verbose = true;
249  break;
250  case 'i':
251  interactive = true;
252  break;
253  case 'L':
254  log_mode = true;
255  break;
256  case 'F':
257  free(fuzz_dir);
258  fuzz_dir = strdup(opt.arg);
259  break;
260  case 'j':
261  workers_count = atoi(opt.arg);
262  if (workers_count <= 0) {
263  eprintf("Invalid thread count\n");
264  ret = help(false);
265  goto beach;
266  }
267  break;
268  case 'r':
269  free(rizin_cmd);
270  rizin_cmd = strdup(opt.arg);
271  break;
272  case 'C':
273  rz_test_dir = opt.arg;
274  break;
275  case 'n':
276  nothing = true;
277  break;
278  case 'm':
279  free(rz_asm_cmd);
280  rz_asm_cmd = strdup(opt.arg);
281  break;
282  case 'f':
283  free(json_test_file);
284  json_test_file = strdup(opt.arg);
285  break;
286  case 't':
287  timeout_sec = strtoull(opt.arg, NULL, 0);
288  if (!timeout_sec) {
289  timeout_sec = UT64_MAX;
290  }
291  break;
292  case 'o':
293  free(output_file);
294  output_file = strdup(opt.arg);
295  break;
296  case 'e':
297  rz_pvector_push(except_dir, strdup(opt.arg));
298  break;
299  case 's':
300  // rz_num_math returns 0 for both '0' and invalid str
301  expect_succ = rz_num_math(NULL, opt.arg);
302  if (!rz_num_is_valid_input(NULL, opt.arg) || expect_succ < 0) {
303  RZ_LOG_ERROR("Number of expected successful tests is invalid\n");
304  goto beach;
305  }
306  break;
307  case 'x':
308  expect_fail = rz_num_math(NULL, opt.arg);
309  if (!rz_num_is_valid_input(NULL, opt.arg) || expect_fail < 0) {
310  RZ_LOG_ERROR("Number of expected failed tests is invalid\n");
311  goto beach;
312  }
313  break;
314  default:
315  ret = help(false);
316  goto beach;
317  }
318  }
319 
320  char *cwd = rz_sys_getdir();
321  if (rz_test_dir) {
322  if (chdir(rz_test_dir) == -1) {
323  eprintf("Cannot find %s directory.\n", rz_test_dir);
324  ret = -1;
325  goto beach;
326  }
327  } else {
328  bool dir_found = (opt.ind < argc && argv[opt.ind][0] != '.')
330  : rz_test_chdir(argv[0]);
331  if (!dir_found) {
332  eprintf("Cannot find db/ directory related to the given test.\n");
333  ret = -1;
334  goto beach;
335  }
336  }
337 
338  if (fuzz_dir) {
339  char *tmp = fuzz_dir;
340  fuzz_dir = rz_file_abspath_rel(cwd, fuzz_dir);
341  free(tmp);
342  }
343 
344  if (!rz_subprocess_init()) {
345  eprintf("Subprocess init failed\n");
346  ret = -1;
347  goto beach;
348  }
349  atexit(rz_subprocess_fini);
350 
351  rz_sys_setenv("TZ", "UTC");
352  ut64 time_start = rz_time_now_mono();
353  RzTestState state = { 0 };
354  // Avoid PATH search for each process launched
355  if (!rizin_cmd) {
356  rizin_cmd = rz_file_path(RIZIN_CMD_DEFAULT);
357  }
358  if (!rz_asm_cmd) {
359  rz_asm_cmd = rz_file_path(RZ_ASM_CMD_DEFAULT);
360  }
361  state.run_config.rz_cmd = rizin_cmd;
362  state.run_config.rz_asm_cmd = rz_asm_cmd;
363  state.run_config.json_test_file = json_test_file ? json_test_file : JSON_TEST_FILE_DEFAULT;
364  state.run_config.timeout_ms = timeout_sec > UT64_MAX / 1000 ? UT64_MAX : timeout_sec * 1000;
365  state.verbose = verbose;
367  if (!state.db) {
368  ret = -1;
369  goto beach;
370  }
371  rz_pvector_init(&state.queue, NULL);
373  rz_pvector_init(&state.completed_paths, NULL);
374  if (output_file) {
375  state.test_results = pj_new();
376  pj_a(state.test_results);
377  }
378  state.lock = rz_th_lock_new(false);
379  if (!state.lock) {
380  ret = -1;
381  goto beach;
382  }
383  state.cond = rz_th_cond_new();
384  if (!state.cond) {
385  ret = -1;
386  goto beach;
387  }
388 
389  if (opt.ind < argc) {
390  // Manually specified path(s)
391  int i;
392  for (i = opt.ind; i < argc; i++) {
393  const char *arg = argv[i];
394  char *alloc_arg = NULL;
395  if (*arg == '@') {
396  arg++;
397  eprintf("Category: %s\n", arg);
398  if (!strcmp(arg, "unit")) {
399  if (!rz_test_test_run_unit()) {
400  ret = -1;
401  goto beach;
402  }
403  continue;
404  } else if (!strcmp(arg, "fuzz")) {
405  if (!fuzz_dir) {
406  eprintf("No fuzz dir given. Use -F [dir]\n");
407  ret = -1;
408  goto beach;
409  }
410  if (!rz_test_test_database_load_fuzz(state.db, fuzz_dir)) {
411  eprintf("Failed to load fuzz tests from \"%s\"\n", fuzz_dir);
412  }
413  continue;
414  } else if (!strcmp(arg, "json")) {
415  arg = "db/json";
416  } else if (!strcmp(arg, "dasm")) {
417  arg = "db/asm";
418  } else if (!strcmp(arg, "cmds")) {
419  arg = "db";
420  } else {
421  arg = alloc_arg = rz_str_newf("db/%s", arg + 1);
422  }
423  }
424  char *tf = rz_file_abspath_rel(cwd, arg);
425  if (!tf || !rz_test_test_database_load(state.db, tf)) {
426  eprintf("Failed to load tests from \"%s\"\n", tf);
428  free(tf);
429  free(alloc_arg);
430  ret = -1;
431  goto beach;
432  }
433  RZ_FREE(alloc_arg);
434  free(tf);
435  }
436  } else {
437  // Default db path
438  if (!rz_test_test_database_load(state.db, "db")) {
439  eprintf("Failed to load tests from ./db\n");
441  ret = -1;
442  goto beach;
443  }
444  if (fuzz_dir && !rz_test_test_database_load_fuzz(state.db, fuzz_dir)) {
445  eprintf("Failed to load fuzz tests from \"%s\"\n", fuzz_dir);
446  }
447  }
448 
449  // filter out except_dir
450  if (!rz_pvector_empty(except_dir)) {
451  void **it;
452  rz_pvector_foreach (except_dir, it) {
453  const char *p = rz_file_abspath_rel(cwd, (char *)*it), *tp;
454  for (ut32 i = 0; i < rz_pvector_len(&state.db->tests); i++) {
455  RzTest *test = rz_pvector_at(&state.db->tests, i);
456  if (rz_file_is_abspath(test->path)) {
457  tp = strdup(test->path);
458  } else {
459  tp = rz_file_abspath_rel(cwd, test->path);
460  }
461  if (rz_str_startswith(tp, p)) {
463  rz_pvector_remove_at(&state.db->tests, i--);
464  }
465  RZ_FREE(tp);
466  }
467  RZ_FREE(p);
468  }
469  }
470 
471  RZ_FREE(cwd);
472  uint32_t loaded_tests = rz_pvector_len(&state.db->tests);
473  printf("Loaded %u tests.\n", loaded_tests);
474  if (nothing) {
475  goto coast;
476  }
477 
478  bool jq_available = rz_test_check_jq_available();
479  if (!jq_available) {
480  eprintf("Skipping json tests because jq is not available.\n");
481  size_t i;
482  for (i = 0; i < rz_pvector_len(&state.db->tests);) {
483  RzTest *test = rz_pvector_at(&state.db->tests, i);
484  if (test->type == RZ_TEST_TYPE_JSON) {
486  rz_pvector_remove_at(&state.db->tests, i);
487  continue;
488  }
489  i++;
490  }
491  }
492 
493  if (rz_pvector_len(&state.db->tests) != 0) {
494  rz_pvector_insert_range(&state.queue, 0, state.db->tests.v.a, rz_pvector_len(&state.db->tests));
495  } else {
496  eprintf("No tests discovered\n");
497  }
498 
499  if (log_mode) {
500  // Log mode prints the state after every completed file.
501  // The count of tests left per file is stored in a ht.
502  state.path_left = ht_pp_new(NULL, path_left_free_kv, NULL);
503  if (state.path_left) {
504  void **it;
505  rz_pvector_foreach (&state.queue, it) {
506  RzTest *test = *it;
507  RzTestFileCounts *counts = ht_pp_find(state.path_left, test->path, NULL);
508  if (!counts) {
509  counts = calloc(1, sizeof(RzTestFileCounts));
510  ht_pp_insert(state.path_left, test->path, counts);
511  }
512  counts->tests_left++;
513  }
514  }
515  }
516 
517  rz_th_lock_enter(state.lock);
518 
521  int i;
522  for (i = 0; i < workers_count; i++) {
524  if (!th) {
525  eprintf("Failed to start thread.\n");
526  rz_th_lock_leave(state.lock);
527  exit(-1);
528  }
529  rz_pvector_push(&workers, th);
530  }
531 
532  ut64 prev_completed = UT64_MAX;
533  ut64 prev_paths_completed = 0;
534  while (true) {
535  ut64 completed = (ut64)rz_pvector_len(&state.results);
536  if (log_mode) {
537  print_log(&state, prev_completed, prev_paths_completed);
538  } else if (completed != prev_completed) {
539  print_state(&state, prev_completed);
540  }
541  prev_completed = completed;
542  prev_paths_completed = (ut64)rz_pvector_len(&state.completed_paths);
543  if (completed == rz_pvector_len(&state.db->tests)) {
544  break;
545  }
546  rz_th_cond_wait(state.cond, state.lock);
547  }
548 
549  rz_th_lock_leave(state.lock);
550 
551  printf("\n");
552 
553  void **it;
554  rz_pvector_foreach (&workers, it) {
555  RzThread *th = *it;
556  rz_th_wait(th);
557  rz_th_free(th);
558  }
560 
561  ut64 seconds = (rz_time_now_mono() - time_start) / 1000000;
562  printf("Finished in");
563  if (seconds > 60) {
564  ut64 minutes = seconds / 60;
565  printf(" %" PFMT64u " minutes and", minutes);
566  seconds -= (minutes * 60);
567  }
568  printf(" %" PFMT64u " seconds.\n", seconds % 60);
569 
570  if (output_file) {
571  pj_end(state.test_results);
572  char *results = pj_drain(state.test_results);
573  rz_file_dump(output_file, (ut8 *)results, strlen(results), false);
574  free(results);
575  }
576 
577  if (interactive) {
578  interact(&state);
579  }
580 
581  if (expect_succ > 0 && expect_succ != state.ok_count) {
582  ret = 1;
583  }
584 
585  if (expect_fail > 0 && expect_fail != state.xx_count) {
586  ret = 1;
587  }
588 
589  if (expect_fail < 0 && expect_succ < 0 && state.xx_count) {
590  ret = 1;
591  }
592 
593 coast:
594  rz_pvector_clear(&state.queue);
595  rz_pvector_clear(&state.results);
596  rz_pvector_clear(&state.completed_paths);
598  rz_th_lock_free(state.lock);
599  rz_th_cond_free(state.cond);
600  ht_pp_free(state.path_left);
601 beach:
602  free(output_file);
603  free(rizin_cmd);
604  free(rz_asm_cmd);
605  free(json_test_file);
606  free(fuzz_dir);
607  rz_pvector_free(except_dir);
608 #if __WINDOWS__
609  if (old_cp) {
610  (void)SetConsoleOutputCP(old_cp);
611  // chcp doesn't pick up the code page switch for some reason
612  (void)rz_sys_cmdf("chcp %u > NUL", old_cp);
613  }
614 #endif
615  return ret;
616 }
RZ_API bool rz_test_check_jq_available(void)
Definition: run.c:223
RZ_API void rz_test_test_result_info_free(RzTestResultInfo *result)
Definition: run.c:552
uint32_t ut32
RZ_API void rz_th_free(RZ_NULLABLE RzThread *th)
Frees a RzThread structure.
Definition: thread.c:246
RZ_API RZ_OWN RzThread * rz_th_new(RZ_NONNULL RzThreadFunction function, RZ_NULLABLE void *user)
Creates and starts a new thread.
Definition: thread.c:198
RZ_API bool rz_th_wait(RZ_NONNULL RzThread *th)
Awaits indefinetely for a thread to join.
Definition: thread.c:231
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
RZ_API bool rz_test_test_database_load(RzTestDatabase *db, const char *path)
Definition: load.c:756
RZ_API RzTestDatabase * rz_test_test_database_new(void)
Definition: load.c:567
RZ_API void rz_test_test_database_free(RzTestDatabase *db)
Definition: load.c:577
RZ_API void rz_test_test_free(RzTest *test)
Definition: load.c:546
RZ_API bool rz_test_test_database_load_fuzz(RzTestDatabase *db, const char *path)
Definition: load.c:782
static RzSocket * s
Definition: rtr.c:28
static int help(bool verbose)
Definition: rz-test.c:62
static void path_left_free_kv(HtPPKv *kv)
Definition: rz-test.c:91
static bool log_mode
Definition: rz-test.c:185
static void interact(RzTestState *state)
Definition: rz-test.c:953
static bool rz_test_chdir(const char *argv0)
Definition: rz-test.c:96
static void print_log(RzTestState *state, ut64 prev_completed, ut64 prev_paths_completed)
Definition: rz-test.c:929
static bool rz_test_test_run_unit(void)
Definition: rz-test.c:131
#define TIMEOUT_DEFAULT
Definition: rz-test.c:21
static void print_state(RzTestState *state, ut64 prev_completed)
Definition: rz-test.c:908
static bool rz_test_chdir_fromtest(const char *test_path)
Definition: rz-test.c:135
#define WORKERS_DEFAULT
Definition: rz-test.c:17
static void * worker_th(RzTestState *state)
Definition: rz-test.c:664
RZ_API bool rz_file_is_abspath(const char *file)
Definition: file.c:214
RZ_API bool rz_file_dump(const char *file, const ut8 *buf, int len, bool append)
Definition: file.c:838
RZ_API char * rz_file_abspath_rel(const char *cwd, const char *file)
Definition: file.c:219
RZ_API void rz_getopt_init(RzGetopt *go, int argc, const char **argv, const char *ostr)
Definition: getopt.c:17
RZ_API int rz_getopt_next(RzGetopt *opt)
Definition: getopt.c:29
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RZ_API int rz_num_is_valid_input(RzNum *num, const char *input_value)
Definition: unum.c:676
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API char * pj_drain(PJ *j)
Definition: pj.c:50
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API PJ * pj_a(PJ *j)
Definition: pj.c:81
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
RZ_API char * rz_str_version(const char *program)
Definition: str.c:4051
RZ_API void rz_subprocess_fini(void)
Definition: subprocess.c:814
RZ_API bool rz_subprocess_init(void)
Definition: subprocess.c:787
RZ_API int rz_sys_setenv(const char *key, const char *value)
Set an environment variable in the calling process.
Definition: sys.c:405
void *(* RzThreadFunction)(void *user)
Definition: rz_th.h:28
RZ_API ut64 rz_time_now_mono(void)
Returns the current time in microseconds, using the monotonic clock.
Definition: time.c:102
#define RZ_ARRAY_SIZE(x)
Definition: rz_types.h:300
#define RZ_FREE(x)
Definition: rz_types.h:369
#define UT64_MAX
Definition: rz_types_base.h:86
static void ** rz_pvector_insert_range(RzPVector *vec, size_t index, void **first, size_t count)
Definition: rz_vector.h:289
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
RZ_API void * rz_pvector_remove_at(RzPVector *vec, size_t index)
Definition: vector.c:355
RZ_API void rz_pvector_free(RzPVector *vec)
Definition: vector.c:336
#define RZ_VERSION
Definition: rz_version.h:8
unsigned int uint32_t
Definition: sftypes.h:29
#define c(i)
Definition: sha256.c:43
const char * arg
Definition: rz_getopt.h:15
Definition: thread.h:84
struct child_worker * workers
uint64_t streams
Definition: list.c:103
RZ_API void rz_th_cond_free(RZ_NULLABLE RzThreadCond *cond)
Frees a RzThreadCond struct.
Definition: thread_cond.c:77
RZ_API void rz_th_cond_wait(RZ_NONNULL RzThreadCond *cond, RZ_NONNULL RzThreadLock *lock)
The function shall block on a condition variable and shall be called with RzThreadLock locked by the ...
Definition: thread_cond.c:63
RZ_API RZ_OWN RzThreadCond * rz_th_cond_new(void)
Condition variables are intended to be used to communicate changes in the state of data shared betwee...
Definition: thread_cond.c:13
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl)
Releases a RzThreadLock structure.
Definition: thread_lock.c:75
RZ_API void rz_th_lock_free(RZ_NULLABLE RzThreadLock *thl)
Frees a RzThreadLock structure.
Definition: thread_lock.c:89
RZ_API RZ_OWN RzThreadLock * rz_th_lock_new(bool recursive)
Allocates and initialize a RzThreadLock structure.
Definition: thread_lock.c:14
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl)
Acquires a RzThreadLock structure.
Definition: thread_lock.c:45
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING
Definition: tty.c:64
DWORD * HANDLE
DWORD
static void nothing(void)
Definition: xtensa-dis.c:44

References rz_getopt_t::arg, argv, c, calloc(), chdir, test-lz4-speed::cwd, DWORD, ENABLE_VIRTUAL_TERMINAL_PROCESSING, eprintf, test-lz4-list::exit, free(), HANDLE, help(), i, rz_getopt_t::ind, interact(), JSON_TEST_FILE_DEFAULT, log_mode, nothing(), NULL, p, path_left_free_kv(), PFMT64u, pj_a(), pj_drain(), pj_end(), pj_new(), print_log(), print_state(), printf(), RIZIN_CMD_DEFAULT, RZ_ARRAY_SIZE, RZ_ASM_CMD_DEFAULT, rz_file_abspath_rel(), rz_file_dump(), rz_file_is_abspath(), rz_file_path(), RZ_FREE, rz_getopt_init(), rz_getopt_next(), RZ_LOG_ERROR, rz_num_is_valid_input(), rz_num_math(), rz_pvector_at(), rz_pvector_clear(), rz_pvector_empty(), rz_pvector_foreach, rz_pvector_free(), rz_pvector_init(), rz_pvector_insert_range(), rz_pvector_len(), rz_pvector_new(), rz_pvector_push(), rz_pvector_remove_at(), rz_str_newf(), rz_str_startswith(), rz_str_version(), rz_subprocess_fini(), rz_subprocess_init(), rz_sys_cmdf(), rz_sys_getdir(), rz_sys_setenv(), rz_test_chdir(), rz_test_chdir_fromtest(), rz_test_check_jq_available(), rz_test_test_database_free(), rz_test_test_database_load(), rz_test_test_database_load_fuzz(), rz_test_test_database_new(), rz_test_test_free(), rz_test_test_result_info_free(), rz_test_test_run_unit(), RZ_TEST_TYPE_JSON, rz_th_cond_free(), rz_th_cond_new(), rz_th_cond_wait(), rz_th_free(), rz_th_lock_enter(), rz_th_lock_free(), rz_th_lock_leave(), rz_th_lock_new(), rz_th_new(), rz_th_wait(), rz_time_now_mono(), RZ_VERSION, s, st64, strdup(), streams, rz_testfile_counts_t::tests_left, TIMEOUT_DEFAULT, autogen_x86imm::tmp, ut64(), UT64_MAX, verbose, worker_th(), workers, and WORKERS_DEFAULT.

Referenced by MAIN_NAME().

◆ rz_test_test_run_unit()

static bool rz_test_test_run_unit ( void  )
static

Definition at line 131 of file rz-test.c.

131  {
132  return rz_sys_system("make -C unit all run") == 0;
133 }
RZ_API int rz_sys_system(const char *command)
Definition: sys.c:1658

References rz_sys_system().

Referenced by rz_test_main().

◆ save_test_file_for_fix()

static void save_test_file_for_fix ( const char *  path,
const char *  newc 
)
static

Definition at line 1126 of file rz-test.c.

1126  {
1127  if (rz_file_dump(path, (const ut8 *)newc, -1, false)) {
1128 #if __UNIX__
1129  sync();
1130 #endif
1131  } else {
1132  eprintf("Failed to write file \"%s\"\n", path);
1133  }
1134 }

References eprintf, path, and rz_file_dump().

Referenced by replace_cmd_kv_file(), and replace_file_line().

◆ test_result_to_json()

static void test_result_to_json ( PJ pj,
RzTestResultInfo result 
)
static

Definition at line 618 of file rz-test.c.

618  {
619  rz_return_if_fail(pj && result);
620  pj_o(pj);
621  pj_k(pj, "type");
622  RzTest *test = result->test;
623  switch (test->type) {
624  case RZ_TEST_TYPE_CMD:
625  pj_s(pj, "cmd");
626  pj_ks(pj, "name", test->cmd_test->name.value);
627  break;
628  case RZ_TEST_TYPE_ASM:
629  pj_s(pj, "asm");
630  pj_ks(pj, "arch", test->asm_test->arch);
631  pj_ki(pj, "bits", test->asm_test->bits);
632  pj_kn(pj, "line", test->asm_test->line);
633  break;
634  case RZ_TEST_TYPE_JSON:
635  pj_s(pj, "json");
636  pj_ks(pj, "cmd", test->json_test->cmd);
637  break;
638  case RZ_TEST_TYPE_FUZZ:
639  pj_s(pj, "fuzz");
640  pj_ks(pj, "file", test->fuzz_test->file);
641  break;
642  }
643  pj_k(pj, "result");
644  switch (result->result) {
645  case RZ_TEST_RESULT_OK:
646  pj_s(pj, "ok");
647  break;
649  pj_s(pj, "failed");
650  break;
652  pj_s(pj, "broken");
653  break;
655  pj_s(pj, "fixed");
656  break;
657  }
658  pj_kb(pj, "run_failed", result->run_failed);
659  pj_kn(pj, "time_elapsed", result->time_elapsed);
660  pj_kb(pj, "timeout", result->timeout);
661  pj_end(pj);
662 }
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
RZ_API PJ * pj_kb(PJ *j, const char *k, bool v)
Definition: pj.c:177
RZ_API PJ * pj_ki(PJ *j, const char *k, int d)
Definition: pj.c:149
RZ_API PJ * pj_k(PJ *j, const char *k)
Definition: pj.c:104
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_s(PJ *j, const char *k)
Definition: pj.c:197
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
Definition: pj.c:121

References pj_end(), pj_k(), pj_kb(), pj_ki(), pj_kn(), pj_ks(), pj_o(), pj_s(), rz_test_test_result_info_t::result, rz_test_test_result_info_t::run_failed, rz_return_if_fail, RZ_TEST_RESULT_BROKEN, RZ_TEST_RESULT_FAILED, RZ_TEST_RESULT_FIXED, RZ_TEST_RESULT_OK, RZ_TEST_TYPE_ASM, RZ_TEST_TYPE_CMD, RZ_TEST_TYPE_FUZZ, RZ_TEST_TYPE_JSON, rz_test_test_result_info_t::test, rz_test_test_result_info_t::time_elapsed, and rz_test_test_result_info_t::timeout.

Referenced by print_new_results().

◆ worker_th()

static void * worker_th ( RzTestState state)
static

Definition at line 664 of file rz-test.c.

664  {
665  rz_th_lock_enter(state->lock);
666  while (true) {
667  if (rz_pvector_empty(&state->queue)) {
668  break;
669  }
670  RzTest *test = rz_pvector_pop(&state->queue);
671  rz_th_lock_leave(state->lock);
672 
673  RzTestResultInfo *result = rz_test_run_test(&state->run_config, test);
674 
675  rz_th_lock_enter(state->lock);
676  rz_pvector_push(&state->results, result);
677  if (!log_mode) {
678  switch (result->result) {
679  case RZ_TEST_RESULT_OK:
680  state->ok_count++;
681  break;
683  state->xx_count++;
684  break;
686  state->br_count++;
687  break;
689  state->fx_count++;
690  break;
691  }
692  }
693  if (state->path_left) {
694  RzTestFileCounts *counts = ht_pp_find(state->path_left, test->path, NULL);
695  if (counts) {
696  switch (result->result) {
697  case RZ_TEST_RESULT_OK:
698  counts->ok++;
699  break;
701  counts->xx++;
702  break;
704  counts->br++;
705  break;
707  counts->fx++;
708  break;
709  }
710  counts->tests_left--;
711  if (!counts->tests_left) {
712  rz_pvector_push(&state->completed_paths, (void *)test->path);
713  }
714  }
715  }
716  rz_th_cond_signal(state->cond);
717  }
718  rz_th_lock_leave(state->lock);
719  return NULL;
720 }
RZ_API RzTestResultInfo * rz_test_run_test(RzTestRunConfig *config, RzTest *test)
Definition: run.c:482
RZ_API void * rz_pvector_pop(RzPVector *vec)
Definition: vector.c:372
RZ_API void rz_th_cond_signal(RZ_NONNULL RzThreadCond *cond)
This function shall unblock at least one of the threads that are blocked on the specified condition.
Definition: thread_cond.c:34

References rz_testfile_counts_t::br, rz_testfile_counts_t::fx, log_mode, NULL, rz_testfile_counts_t::ok, rz_test_test_result_info_t::result, rz_pvector_empty(), rz_pvector_pop(), rz_pvector_push(), RZ_TEST_RESULT_BROKEN, RZ_TEST_RESULT_FAILED, RZ_TEST_RESULT_FIXED, RZ_TEST_RESULT_OK, rz_test_run_test(), rz_th_cond_signal(), rz_th_lock_enter(), rz_th_lock_leave(), rz_testfile_counts_t::tests_left, and rz_testfile_counts_t::xx.

Referenced by rz_test_main().

Variable Documentation

◆ log_mode

bool log_mode = false
static

Definition at line 185 of file rz-test.c.

Referenced by rz_test_main(), and worker_th().