1 /* radare - LGPL - Copyright 2020 - thestr4ng3r */
2 
3 #ifndef RADARE2_R2R_H
4 #define RADARE2_R2R_H
5 
6 #include <r_util.h>
7 
8 #if defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
9 #define R2R_OS "freebsd"
10 #elif defined(__linux__)
11 #define R2R_OS "linux"
12 #elif defined(__APPLE__)
13 #define R2R_OS "darwin"
14 #elif __WINDOWS__
15 #define R2R_OS "windows"
16 #else
17 #define R2R_OS "unknown"
18 #endif
19 
20 #if __i386__
21 #define R2R_ARCH "x86"
22 #elif __x86_64__
23 #define R2R_ARCH "x64"
24 #else
25 #define R2R_ARCH "unknown"
26 #endif
27 
28 #define R2R_ARCH_OS R2R_OS"-"R2R_ARCH
29 
30 typedef struct r2r_cmd_test_string_record {
31 	char *value;
32 	ut64 line_begin; // inclusive
33 	ut64 line_end; // exclusive
34 } R2RCmdTestStringRecord;
35 
36 typedef struct r2r_cmd_test_bool_record {
37 	bool value;
38 	ut64 line; // bools are always oneliners (e.g. BROKEN=1)
39 	bool set;
40 } R2RCmdTestBoolRecord;
41 
42 typedef struct r2r_cmd_test_num_record {
43 	ut64 value;
44 	ut64 line; // nums are always oneliners (e.g. TIMEOUT=10)
45 	bool set;
46 } R2RCmdTestNumRecord;
47 
48 typedef struct r2r_cmd_test_t {
49 	R2RCmdTestStringRecord name;
50 	R2RCmdTestStringRecord file;
51 	R2RCmdTestStringRecord args;
52 	R2RCmdTestStringRecord source;
53 	R2RCmdTestStringRecord cmds;
54 	R2RCmdTestStringRecord expect;
55 	R2RCmdTestStringRecord expect_err;
56 	R2RCmdTestStringRecord regexp_out;
57 	R2RCmdTestStringRecord regexp_err;
58 	R2RCmdTestBoolRecord broken;
59 	R2RCmdTestNumRecord timeout;
60 	ut64 run_line;
61 	bool load_plugins;
62 } R2RCmdTest;
63 
64 #define R2R_CMD_TEST_FOREACH_RECORD_NOP(name, field)
65 #define R2R_CMD_TEST_FOREACH_RECORD(macro_str, macro_bool, macro_int) \
66 	macro_str ("NAME", name) \
67 	macro_str ("FILE", file) \
68 	macro_str ("ARGS", args) \
69 	macro_int ("TIMEOUT", timeout) \
70 	macro_str ("SOURCE", source) \
71 	macro_str ("CMDS", cmds) \
72 	macro_str ("EXPECT", expect) \
73 	macro_str ("EXPECT_ERR", expect_err) \
74 	macro_str ("REGEXP_OUT", regexp_out) \
75 	macro_str ("REGEXP_ERR", regexp_err) \
76 	macro_bool ("BROKEN", broken)
77 
78 typedef enum r2r_asm_test_mode_t {
79 	R2R_ASM_TEST_MODE_ASSEMBLE = 1,
80 	R2R_ASM_TEST_MODE_DISASSEMBLE = (1 << 1),
81 	R2R_ASM_TEST_MODE_BIG_ENDIAN = (1 << 2),
82 	R2R_ASM_TEST_MODE_BROKEN = (1 << 3)
83 } R2RAsmTestMode;
84 
85 typedef struct r2r_asm_test_t {
86 	ut64 line;
87 	const char *arch;
88 	const char *cpu;
89 	int bits;
90 	int mode;
91 	ut64 offset;
92 	char *disasm;
93 	ut8 *bytes;
94 	size_t bytes_size;
95 } R2RAsmTest;
96 
97 typedef struct r2r_json_test_t {
98 	ut64 line;
99 	char *cmd;
100 	bool broken;
101 	bool load_plugins;
102 } R2RJsonTest;
103 
104 typedef struct r2r_fuzz_test_t {
105 	char *file;
106 } R2RFuzzTest;
107 
108 typedef enum r2r_test_type_t {
109 	R2R_TEST_TYPE_CMD,
110 	R2R_TEST_TYPE_ASM,
111 	R2R_TEST_TYPE_JSON,
112 	R2R_TEST_TYPE_FUZZ
113 } R2RTestType;
114 
115 typedef struct r2r_test_t {
116 	const char *path;
117 	R2RTestType type;
118 	union {
119 		R2RCmdTest *cmd_test;
120 		R2RAsmTest *asm_test;
121 		R2RJsonTest *json_test;
122 		R2RFuzzTest *fuzz_test;
123 	};
124 } R2RTest;
125 
126 typedef struct r2r_test_database_t {
127 	RPVector tests;
128 	RStrConstPool strpool;
129 } R2RTestDatabase;
130 
131 typedef struct r2r_run_config_t {
132 	const char *r2_cmd;
133 	const char *rasm2_cmd;
134 	const char *json_test_file;
135 	ut64 timeout_ms;
136 } R2RRunConfig;
137 
138 typedef struct r2r_process_output_t {
139 	char *out; // stdout
140 	char *err; // stderr
141 	int ret; // exit code of the process
142 	bool timeout;
143 } R2RProcessOutput;
144 
145 typedef struct r2r_asm_test_output_t {
146 	char *disasm;
147 	ut8 *bytes;
148 	size_t bytes_size;
149 	bool as_timeout;
150 	bool disas_timeout;
151 } R2RAsmTestOutput;
152 
153 typedef enum r2r_test_result_t {
154 	R2R_TEST_RESULT_OK,
155 	R2R_TEST_RESULT_FAILED,
156 	R2R_TEST_RESULT_BROKEN,
157 	R2R_TEST_RESULT_FIXED
158 } R2RTestResult;
159 
160 typedef struct r2r_test_result_info_t {
161 	R2RTest *test;
162 	R2RTestResult result;
163 	bool timeout;
164 	bool run_failed; // something went seriously wrong (e.g. r2 not found)
165 	ut64 time_elapsed;
166 	union {
167 		R2RProcessOutput *proc_out; // for test->type == R2R_TEST_TYPE_CMD, R2R_TEST_TYPE_JSON or R2R_TEST_TYPE_FUZZ
168 		R2RAsmTestOutput *asm_out;  // for test->type == R2R_TEST_TYPE_ASM
169 	};
170 } R2RTestResultInfo;
171 
172 R_API R2RCmdTest *r2r_cmd_test_new(void);
173 R_API void r2r_cmd_test_free(R2RCmdTest *test);
174 R_API RPVector *r2r_load_cmd_test_file(const char *file);
175 
176 R_API R2RAsmTest *r2r_asm_test_new(void);
177 R_API void r2r_asm_test_free(R2RAsmTest *test);
178 R_API RPVector *r2r_load_asm_test_file(RStrConstPool *strpool, const char *file);
179 
180 R_API R2RJsonTest *r2r_json_test_new(void);
181 R_API void r2r_json_test_free(R2RJsonTest *test);
182 R_API RPVector *r2r_load_json_test_file(const char *file);
183 
184 R_API R2RTestDatabase *r2r_test_database_new(void);
185 R_API void r2r_test_database_free(R2RTestDatabase *db);
186 R_API bool r2r_test_database_load(R2RTestDatabase *db, const char *path);
187 R_API bool r2r_test_database_load_fuzz(R2RTestDatabase *db, const char *path);
188 
189 typedef struct r2r_subprocess_t R2RSubprocess;
190 
191 R_API bool r2r_subprocess_init(void);
192 R_API void r2r_subprocess_fini(void);
193 R_API R2RSubprocess *r2r_subprocess_start(
194 		const char *file, const char *args[], size_t args_size,
195 		const char *envvars[], const char *envvals[], size_t env_size);
196 R_API bool r2r_subprocess_wait(R2RSubprocess *proc, ut64 timeout_ms);
197 R_API void r2r_subprocess_free(R2RSubprocess *proc);
198 
199 typedef R2RProcessOutput *(*R2RCmdRunner)(const char *file, const char *args[], size_t args_size,
200 	const char *envvars[], const char *envvals[], size_t env_size, ut64 timeout_ms, void *user);
201 
202 R_API void r2r_process_output_free(R2RProcessOutput *out);
203 R_API R2RProcessOutput *r2r_run_cmd_test(R2RRunConfig *config, R2RCmdTest *test, R2RCmdRunner runner, void *user);
204 R_API bool r2r_check_cmd_test(R2RProcessOutput *out, R2RCmdTest *test);
205 R_API bool r2r_check_jq_available(void);
206 R_API R2RProcessOutput *r2r_run_json_test(R2RRunConfig *config, R2RJsonTest *test, R2RCmdRunner runner, void *user);
207 R_API bool r2r_check_json_test(R2RProcessOutput *out, R2RJsonTest *test);
208 R_API R2RAsmTestOutput *r2r_run_asm_test(R2RRunConfig *config, R2RAsmTest *test);
209 R_API bool r2r_check_asm_test(R2RAsmTestOutput *out, R2RAsmTest *test);
210 R_API void r2r_asm_test_output_free(R2RAsmTestOutput *out);
211 R_API R2RProcessOutput *r2r_run_fuzz_test(R2RRunConfig *config, R2RFuzzTest *test, R2RCmdRunner runner, void *user);
212 R_API bool r2r_check_fuzz_test(R2RProcessOutput *out);
213 
214 R_API void r2r_test_free(R2RTest *test);
215 R_API char *r2r_test_name(R2RTest *test);
216 R_API bool r2r_test_broken(R2RTest *test);
217 R_API R2RTestResultInfo *r2r_run_test(R2RRunConfig *config, R2RTest *test);
218 R_API void r2r_test_result_info_free(R2RTestResultInfo *result);
219 
220 #endif //RADARE2_R2R_H
221