mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-07 22:38:41 +00:00
rework file directive handling; remove T_Group; add SKIP to disable
tests that are not passing; change command line syntax for easier test run/skip/force; updated help; shortened --dbg_graphical -> --gui; add 'skip' directive to the dbg scripts
This commit is contained in:
committed by
Ryan Fleury
parent
a21a256333
commit
fe2778133f
@@ -8,9 +8,8 @@ on:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
|
||||
# TODO: fix skips
|
||||
env:
|
||||
TORTURE_FLAGS: "--gen_crash_dump -s:d2r::d2r_line_table,d2r::d2r_checksums"
|
||||
TORTURE_FLAGS: "* --gen_crash_dump"
|
||||
|
||||
jobs:
|
||||
build-ubuntu-24-04:
|
||||
|
||||
@@ -27,6 +27,7 @@ if "%TORTURE_ARGS:~0,3%" == "-- " set "TORTURE_ARGS=%TORTURE_ARGS:~3%" && goto p
|
||||
set "TORTURE_ARGS=%TORTURE_ARGS:* -- =%"
|
||||
|
||||
:parse_done
|
||||
if not defined TORTURE_ARGS set "TORTURE_ARGS=*
|
||||
|
||||
for %%m in (%MODE_VALUES%) do for %%c in (%CC_VALUES%) do (
|
||||
setlocal
|
||||
|
||||
@@ -38,6 +38,10 @@ while [[ $# -gt 0 ]]; do
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "${#torture_args[@]}" == "0" ]]; then
|
||||
torture_args=("*")
|
||||
fi
|
||||
|
||||
for m in "${mode_values[@]}"; do
|
||||
for c in "${cc_values[@]}"; do
|
||||
# nuke artifacts from last run
|
||||
|
||||
@@ -926,7 +926,9 @@ internal void * keys_from_hash_map_raw ( Arena *arena, HashMap *hm) { retur
|
||||
|
||||
// values
|
||||
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_u64) { MemoryCopy(buffer, &kv->value.value_u64, sizeof(kv->value.value_u64)); }
|
||||
internal U64 * values_from_hash_map_u64(Arena *arena, HashMap *hm) { return hash_map_extract(arena, hm, 0, 0, hash_map_extract_value_u64, sizeof(U64)).values; }
|
||||
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_raw) { MemoryCopy(buffer, &kv->value.value_raw, sizeof(kv->value.value_raw)); }
|
||||
internal U64 * values_from_hash_map_u64(Arena *arena, HashMap *hm) { return hash_map_extract(arena, hm, 0, 0, hash_map_extract_value_u64, sizeof(U64)).values; }
|
||||
internal void * values_from_hash_map_raw(Arena *arena, HashMap *hm) {return hash_map_extract(arena, hm, 0, 0, hash_map_extract_value_raw, sizeof(void *)).values; }
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/// test: {
|
||||
/// windows: {
|
||||
/// skip: ""
|
||||
/// compile: {
|
||||
/// cc: "clang"
|
||||
/// args: "-O0 -g -o main.exe %FILE%"
|
||||
/// }
|
||||
/// launch: "main.exe"
|
||||
/// }
|
||||
/// linux: {
|
||||
/// skip: ""
|
||||
/// compile: "-O0 -g -o main %FILE%"
|
||||
/// launch: "./main"
|
||||
/// }
|
||||
/// }
|
||||
|
||||
int main()
|
||||
{ /// 1: { step_into step_into }
|
||||
for (int i = 0; i < 1; /// 2: step_into
|
||||
++i, ({ goto exit; })) { /// 4: step_into
|
||||
int x = 0; /// 3: step_into
|
||||
}
|
||||
exit:;
|
||||
} /// 5: at
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
// TODO: step into alg needs to detect that it is about to step into a thunk and place breakpoint, respective to OS,
|
||||
// where thunk calls into resolved function
|
||||
//
|
||||
// test: {
|
||||
// windows: {
|
||||
// compile: "/Od /Z7 /c main.c module.c"
|
||||
// link: "/fixed /debug:full /dll module.obj"
|
||||
// link: "/fixed /debug:full /entry:main kernel32.lib module.lib delayimp.lib main.obj /out:main.exe /delayload:module.dll /incremental:no"
|
||||
// launch: "main.exe"
|
||||
// }
|
||||
// linux: {
|
||||
// compile: "-O0 -g module.c -fPIC -shared -o libmodule.so"
|
||||
// compile: "-O0 -g main.c -L. -lmodule -o main -Wl,-rpath,%CWD%"
|
||||
// launch: "./main"
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
/// test: {
|
||||
/// windows: {
|
||||
/// skip: ""
|
||||
/// compile: "/Od /Z7 /c main.c module.c"
|
||||
/// link: "/fixed /debug:full /dll module.obj"
|
||||
/// link: "/fixed /debug:full /entry:main kernel32.lib module.lib delayimp.lib main.obj /out:main.exe /delayload:module.dll /incremental:no"
|
||||
/// launch: "main.exe"
|
||||
/// }
|
||||
/// linux: {
|
||||
/// skip: ""
|
||||
/// compile: "-O0 -g module.c -fPIC -shared -o libmodule.so"
|
||||
/// compile: "-O0 -g main.c -L. -lmodule -o main -Wl,-rpath,%CWD%"
|
||||
/// launch: "./main"
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
|
||||
/// file: "module.c"
|
||||
|
||||
|
||||
+185
-138
@@ -23,19 +23,54 @@ global String8 g_output;
|
||||
global String8 g_errors;
|
||||
|
||||
// tools
|
||||
global B32 g_dbg_graphical;
|
||||
global B32 g_gui;
|
||||
global String8 g_radbin_path;
|
||||
global String8 g_cl_path;
|
||||
global String8 g_clang_path;
|
||||
global String8 g_gcc_path;
|
||||
global String8 g_linker_path;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal String8
|
||||
t_group_from_test(T_Test *test)
|
||||
{
|
||||
String8 file = str8_cstring(test->file);
|
||||
String8 group = str8_chop_last_dot(str8_skip_last_slash(file));
|
||||
if (str8_match_wildcard(group, str8_lit("torture_*"), StringMatchFlag_CaseInsensitive)) {
|
||||
group = str8_skip(group, str8_lit("torture_").size);
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
internal String8
|
||||
t_group_from_test_idx(U64 test_idx)
|
||||
{
|
||||
return t_group_from_test(g_torture_tests[test_idx]);
|
||||
}
|
||||
|
||||
internal String8
|
||||
t_test_name_from_idx(Arena *arena, U64 test_idx)
|
||||
{
|
||||
return str8f(arena, "%s::%s", g_torture_tests[test_idx]->group, g_torture_tests[test_idx]->label);
|
||||
return str8f(arena, "%.*s/%s", str8_varg(t_group_from_test_idx(test_idx)), g_torture_tests[test_idx]->label);
|
||||
}
|
||||
|
||||
internal String8List
|
||||
t_test_group_from_name(Arena *arena, String8 pattern)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List matches = {0};
|
||||
for EachIndex(i, g_torture_test_count) {
|
||||
if (str8_match_wildcard(t_test_name_from_idx(scratch.arena, i), pattern, 0)) {
|
||||
str8_list_push(arena, &matches, t_group_from_test_idx(i));
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return matches;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal char *
|
||||
t_string_from_result(T_RunStatus v)
|
||||
{
|
||||
@@ -43,10 +78,24 @@ t_string_from_result(T_RunStatus v)
|
||||
case T_RunStatus_Fail: return "FAIL";
|
||||
case T_RunStatus_Crash: return "CRASH";
|
||||
case T_RunStatus_Pass: return "PASS";
|
||||
case T_RunStatus_Skip: return "SKIP";
|
||||
default: break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal char *
|
||||
t_color_from_result(T_RunStatus v)
|
||||
{
|
||||
switch (v) {
|
||||
#define X(n,c,...) case T_RunStatus_##n: return c;
|
||||
T_Run_XList
|
||||
#undef X
|
||||
default: break;
|
||||
}
|
||||
return "null";
|
||||
}
|
||||
|
||||
internal void
|
||||
t_break_if_debugger_present(void)
|
||||
{
|
||||
@@ -167,17 +216,22 @@ t_run_caller(void *raw_ctx)
|
||||
ctx->result.status = T_RunStatus_Pass;
|
||||
|
||||
String8List test_out = {0};
|
||||
ctx->run(scratch.arena, ctx->user_data, &ctx->result, &test_out);
|
||||
|
||||
if (ctx->test->skip) {
|
||||
ctx->result.status = T_RunStatus_Skip;
|
||||
} else {
|
||||
ctx->test->r(scratch.arena, ctx->user_data, &ctx->result, &test_out);
|
||||
}
|
||||
|
||||
if (ctx->result.status == T_RunStatus_Fail || ctx->result.status == T_RunStatus_Crash) {
|
||||
for EachNode(n, String8Node, test_out.first) {
|
||||
t_errorf("%S", n->string);
|
||||
}
|
||||
if (g_errors.size) {
|
||||
t_errorf("stderr: \"%S\"\n", g_errors);
|
||||
t_errorf("%S\n", g_errors);
|
||||
}
|
||||
if (g_output.size) {
|
||||
t_errorf("stdout: \"%S\"\n", g_output);
|
||||
t_errorf("%S\n", g_output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,9 +239,9 @@ t_run_caller(void *raw_ctx)
|
||||
}
|
||||
|
||||
internal T_RunResult
|
||||
t_run(T_Run run, String8 user_data)
|
||||
t_run(T_Test *test, String8 user_data)
|
||||
{
|
||||
T_RunCtx ctx = { .run = run, .user_data = user_data, .result.status = T_RunStatus_Fail };
|
||||
T_RunCtx ctx = { .test = test, .user_data = user_data, .result.status = T_RunStatus_Fail };
|
||||
t_run_caller(&ctx);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
@@ -332,7 +386,7 @@ t_raddbg_path(void)
|
||||
local_persist U8 buffer[4096];
|
||||
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
|
||||
Arena *arena = arena_alloc_(¶ms);
|
||||
String8 raddbg_base_name = g_dbg_graphical ? str8_lit("raddbg") : str8_lit("raddbg_non_graphical");
|
||||
String8 raddbg_base_name = g_gui ? str8_lit("raddbg") : str8_lit("raddbg_non_graphical");
|
||||
#if OS_WINDOWS
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
path = full_path_from_path(arena, str8f(scratch.arena, "%S.exe", raddbg_base_name));
|
||||
@@ -779,7 +833,7 @@ t_invoke_env(String8 exe_path, String8 cmdline, String8List env, U64 timeout_us)
|
||||
exit:;
|
||||
for EachElement(i, read_capture_handles) { file_close(read_capture_handles[i]); }
|
||||
for EachElement(i, write_capture_handles) { file_close(write_capture_handles[i]); }
|
||||
AssertAlways(is_ok);
|
||||
|
||||
scratch_end(scratch);
|
||||
return is_ok;
|
||||
}
|
||||
@@ -883,7 +937,9 @@ internal int
|
||||
t_test_compar(const void *raw_a, const void *raw_b)
|
||||
{
|
||||
const T_Test *a = raw_a, *b = raw_b;
|
||||
int cmp = str8_compar(str8_cstring(a->group), str8_cstring(b->group), 0);
|
||||
String8 group_a = t_group_from_test((T_Test *)a);
|
||||
String8 group_b = t_group_from_test((T_Test *)b);
|
||||
int cmp = str8_compar(group_a, group_b, 0);
|
||||
if (cmp == 0) {
|
||||
cmp = u64_compar(&a->decl_line, &b->decl_line);
|
||||
}
|
||||
@@ -1014,10 +1070,37 @@ t_errorf(char *fmt, ...)
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal void
|
||||
t_help(void)
|
||||
{
|
||||
fprintf(stderr, "--- Help -------------------------------------------------------\n");
|
||||
fprintf(stderr, " %s\n\n", BUILD_TITLE_STRING_LITERAL);
|
||||
fprintf(stderr, " Usage: torture [Options] <Input>\n\n");
|
||||
fprintf(stderr, " Options:\n");
|
||||
fprintf(stderr, " -list Print available test targets\n");
|
||||
fprintf(stderr, " --gui Launch debugger with window\n");
|
||||
fprintf(stderr, " -cl:<path> Override default cl path\n");
|
||||
fprintf(stderr, " -clang:<path> Override default clang path\n");
|
||||
fprintf(stderr, " -gcc:<path> Override default gcc path\n");
|
||||
fprintf(stderr, " -linker:<path> Path to PE/COFF linker\n");
|
||||
fprintf(stderr, " -print_stdout Print to console stdout and stderr of a run\n");
|
||||
fprintf(stderr, " -out:<path> Directory path for test outputs (default \"%.*s\")\n", str8_varg(g_out));
|
||||
fprintf(stderr, " -verbose Enable verbose mode\n");
|
||||
fprintf(stderr, " -help Print help menu and exit\n");
|
||||
fprintf(stderr, "\nInputs are wildcard expressions. Prefix with ! to skip matches, or + to force-run matches.\n");
|
||||
fprintf(stderr, "\nExamples:\n");
|
||||
fprintf(stderr, " torture * Run all tests\n");
|
||||
fprintf(stderr, " torture bit_array Run 'bit_array' test\n");
|
||||
fprintf(stderr, " torture !* Skip all tests\n");
|
||||
fprintf(stderr, " torture * !bit_array Run all tests but skip 'bit_array'\n");
|
||||
fprintf(stderr, " torture +* Force-run all tests\n");
|
||||
}
|
||||
|
||||
internal void
|
||||
t_entry_point(CmdLine *cmdline)
|
||||
{
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
U64 exit_code = max_U64;
|
||||
|
||||
U64 dashes_size = 9999;
|
||||
U8 *dashes = push_array(scratch.arena, U8, dashes_size);
|
||||
@@ -1036,25 +1119,10 @@ t_entry_point(CmdLine *cmdline)
|
||||
//
|
||||
{
|
||||
B32 print_help = cmd_line_has_flag(cmdline, str8_lit("help")) ||
|
||||
cmd_line_has_flag(cmdline, str8_lit("h"));
|
||||
cmd_line_has_flag(cmdline, str8_lit("h"));
|
||||
if (print_help) {
|
||||
PrintHeader("Help");
|
||||
fprintf(stderr, " %s\n\n", BUILD_TITLE_STRING_LITERAL);
|
||||
fprintf(stderr, " Usage: torture [Options] [Files]\n\n");
|
||||
fprintf(stderr, " Options:\n");
|
||||
fprintf(stderr, " -target:{name[,name]} Selects targets to test\n");
|
||||
fprintf(stderr, " -skip:{name[,name]} Selects targets to skip\n");
|
||||
fprintf(stderr, " -list Print available test targets and exit\n");
|
||||
fprintf(stderr, " -out:{path} Directory path for test outputs (default \"%.*s\")\n", str8_varg(g_out));
|
||||
fprintf(stderr, " -verbose Enable verbose mode\n");
|
||||
fprintf(stderr, " -cl:{path} Override default cl path\n");
|
||||
fprintf(stderr, " -clang:{path} Override default clang path\n");
|
||||
fprintf(stderr, " -gcc:{path} Override default gcc path\n");
|
||||
fprintf(stderr, " -linker:{path} Path to PE/COFF linker\n");
|
||||
fprintf(stderr, " --dbg_graphical Launch debugger with window\n");
|
||||
fprintf(stderr, " -print_stdout Print to console stdout and stderr of a run\n");
|
||||
fprintf(stderr, " -help Print help menu and exit\n");
|
||||
abort_self(0);
|
||||
t_help();
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1086,7 +1154,7 @@ t_entry_point(CmdLine *cmdline)
|
||||
//
|
||||
// Compiler overrides
|
||||
//
|
||||
g_dbg_graphical = cmd_line_has_flag(cmdline, str8_lit("dbg_graphical"));
|
||||
g_gui = cmd_line_has_flag(cmdline, str8_lit("gui"));
|
||||
g_cl_path = cmd_line_string(cmdline, str8_lit("cl"));
|
||||
g_clang_path = cmd_line_string(cmdline, str8_lit("clang"));
|
||||
g_gcc_path = cmd_line_string(cmdline, str8_lit("gcc"));
|
||||
@@ -1106,44 +1174,68 @@ t_entry_point(CmdLine *cmdline)
|
||||
//
|
||||
// Handle optional -target
|
||||
//
|
||||
String8List target = cmdline->inputs;
|
||||
U64List targets = {0};
|
||||
{
|
||||
CmdLineOpt *target_opt = cmd_line_opt_from_string(cmdline, str8_lit("target"));
|
||||
if (target_opt == 0) {
|
||||
target_opt = cmd_line_opt_from_string(cmdline, str8_lit("t"));
|
||||
}
|
||||
String8List inputs = {0};
|
||||
|
||||
CmdLineOpt *target_opt = 0;
|
||||
if (target_opt == 0) { target_opt = cmd_line_opt_from_string(cmdline, str8_lit("target")); }
|
||||
if (target_opt == 0) { target_opt = cmd_line_opt_from_string(cmdline, str8_lit("t")); }
|
||||
|
||||
// handle explicit target switch
|
||||
if (target_opt) {
|
||||
HashTable *ht = hash_table_init(scratch.arena, g_torture_test_count*2);
|
||||
str8_list_concat_in_place(&inputs, &target_opt->value_strings);
|
||||
}
|
||||
|
||||
String8List targets = target_opt->value_strings;
|
||||
str8_list_concat_in_place(&targets, &cmdline->inputs);
|
||||
// accept inputs from the command line as target tests to run
|
||||
str8_list_concat_in_place(&inputs, &cmdline->inputs);
|
||||
|
||||
if (targets.node_count > 0) {
|
||||
for EachNode(pattern_n, String8Node, targets.first) {
|
||||
B32 do_namespace = str8_find_needle(pattern_n->string, 0, str8_lit("::"), 0) < pattern_n->string.size;
|
||||
for EachIndex(test_idx, g_torture_test_count) {
|
||||
String8 name = str8_cstring(g_torture_tests[test_idx]->label);
|
||||
if (do_namespace) {
|
||||
name = t_test_name_from_idx(scratch.arena, test_idx);
|
||||
}
|
||||
if (str8_match_wildcard(name, pattern_n->string, 0)) {
|
||||
if ( ! hash_table_search_string(ht, name)) {
|
||||
hash_table_push_string_raw(scratch.arena, ht, name, 0);
|
||||
str8_list_push(scratch.arena, &target, str8_cstring(g_torture_tests[test_idx]->label));
|
||||
}
|
||||
}
|
||||
// no inputs -> print help and exit
|
||||
if (inputs.node_count == 0) {
|
||||
t_help();
|
||||
goto exit;
|
||||
}
|
||||
|
||||
HashMap hm = {0};
|
||||
for EachNode(input_n, String8Node, inputs.first) {
|
||||
String8 t = input_n->string;
|
||||
|
||||
// parse mode
|
||||
typedef enum { Mode_Default, Mode_Skip, Mode_Force, } Mode;
|
||||
Mode mode = Mode_Default;
|
||||
if (str8_match_wildcard(t, str8_lit("+*"), 0)) { mode = Mode_Force; t = str8_skip(t, 1); }
|
||||
else if (str8_match_wildcard(t, str8_lit("!*"), 0)) { mode = Mode_Skip; t = str8_skip(t, 1); }
|
||||
|
||||
if (str8_find_needle(t, 0, str8_lit("/"), 0) >= t.size) {
|
||||
t = str8f(scratch.arena, "*/%S", t);
|
||||
}
|
||||
|
||||
U64 match_count = 0;
|
||||
|
||||
for EachIndex(test_idx, g_torture_test_count) {
|
||||
// match test names
|
||||
String8 test_name = t_test_name_from_idx(scratch.arena, test_idx);
|
||||
|
||||
if (str8_match_wildcard(test_name, t, StringMatchFlag_CaseInsensitive)) {
|
||||
// set skip flag
|
||||
switch (mode) {
|
||||
case Mode_Default: break;
|
||||
case Mode_Skip: g_torture_tests[test_idx]->skip = 1; break;
|
||||
case Mode_Force: g_torture_tests[test_idx]->skip = 0; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ht->count == 0) {
|
||||
fprintf(stderr, "ERROR: -target matches not found for the following patterns: ");
|
||||
for EachNode(n, String8Node, target_opt->value_strings.first) {
|
||||
fprintf(stderr, "\"%.*s\"\n", str8_varg(n->string));
|
||||
|
||||
// append test when not in skipping mode
|
||||
if ( ! hash_map_search_string_u64(&hm, test_name)) {
|
||||
hash_map_push_string_u64(scratch.arena, &hm, test_name, 1);
|
||||
u64_list_push(scratch.arena, &targets, test_idx);
|
||||
}
|
||||
abort_self(1);
|
||||
|
||||
match_count += 1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: -target has invalid number of arguments\n");
|
||||
}
|
||||
|
||||
if (match_count == 0) {
|
||||
fprintf(stderr, "WARNING: no matches found for input: %.*s\n", str8_varg(input_n->string));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1199,62 +1291,17 @@ t_entry_point(CmdLine *cmdline)
|
||||
// Run tests
|
||||
//
|
||||
{
|
||||
U64List target_indices_list = {0};
|
||||
if (target.node_count == 0) {
|
||||
for EachIndex(i, g_torture_test_count) { u64_list_push(scratch.arena, &target_indices_list, i); }
|
||||
} else {
|
||||
for EachNode(target_n, String8Node, target.first) {
|
||||
B32 is_target_unknown = 1;
|
||||
for EachIndex(i, g_torture_test_count) {
|
||||
if (str8_match(str8_cstring(g_torture_tests[i]->label), target_n->string, 0)) {
|
||||
u64_list_push(scratch.arena, &target_indices_list, i);
|
||||
is_target_unknown = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_target_unknown) {
|
||||
fprintf(stderr, "ERROR: unknown target \"%.*s\"\n", str8_varg(target_n->string));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// -skip
|
||||
//
|
||||
U64List final_target_list = {0};
|
||||
CmdLineOpt *skip_opt = cmd_line_opt_from_string(cmdline, str8_lit("skip"));
|
||||
CmdLineOpt *s_opt = cmd_line_opt_from_string(cmdline, str8_lit("s"));
|
||||
String8List skip_list = skip_opt ? skip_opt->value_strings : s_opt ? s_opt->value_strings : (String8List){0};
|
||||
for EachNode(n, U64Node, target_indices_list.first) {
|
||||
// should test be skipped?
|
||||
B32 include_test = 1;
|
||||
String8 test_name = t_test_name_from_idx(scratch.arena, n->data);
|
||||
for EachNode(pattern_n, String8Node, skip_list.first) {
|
||||
if (str8_match_wildcard(test_name, pattern_n->string, 0)) {
|
||||
include_test = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (include_test) {
|
||||
u64_list_push(scratch.arena, &final_target_list, n->data);
|
||||
}
|
||||
}
|
||||
|
||||
U64 skip_count = target_indices_list.count - final_target_list.count;
|
||||
U64Array target_indices = u64_array_from_list(scratch.arena, &final_target_list);
|
||||
U64Array target_indices = u64_array_from_list(scratch.arena, &targets);
|
||||
|
||||
U64 max_label_size = 0;
|
||||
U64 max_group_size = 0;
|
||||
for EachIndex(i, target_indices.count) {
|
||||
U64 test_idx = target_indices.v[i];
|
||||
max_label_size = Max(max_label_size, cstring8_length((U8*)g_torture_tests[test_idx]->label));
|
||||
max_group_size = Max(max_group_size, cstring8_length((U8*)g_torture_tests[test_idx]->group));
|
||||
max_group_size = Max(max_group_size, t_group_from_test_idx(test_idx).size);
|
||||
}
|
||||
|
||||
U64 pass_count = 0;
|
||||
U64 fail_count = 0;
|
||||
U64 crash_count = 0;
|
||||
U64 run_counters[T_RunStatus_Count] = {0};
|
||||
U64 max_digit_count = count_digits_u64(target_indices.count, 10);
|
||||
U64 total_time_start = now_time_us();
|
||||
|
||||
@@ -1262,6 +1309,8 @@ t_entry_point(CmdLine *cmdline)
|
||||
Slowest slowest[5] = {0};
|
||||
for EachElement(i, slowest) { slowest[i].target_idx = max_U64; }
|
||||
|
||||
U64List skipped_tests = {0};
|
||||
|
||||
for EachIndex(i, target_indices.count) {
|
||||
if (i == 0) { PrintHeader("Tests"); }
|
||||
|
||||
@@ -1274,7 +1323,7 @@ t_entry_point(CmdLine *cmdline)
|
||||
U64 curr_digit_count = count_digits_u64(i+1, 10);
|
||||
int idx_align_space_count = (int)(max_digit_count - curr_digit_count);
|
||||
fprintf(stdout, "[%.*s%llu/%llu] ", idx_align_space_count, spaces, (unsigned long long)i+1, (unsigned long long)target_indices.count);
|
||||
fprintf(stdout, "%s %.*s:: %s", test->group, (int)(max_group_size - cstring8_length((U8*)test->group)), spaces, test->label);
|
||||
fprintf(stdout, "%.*s %.*s/ %s", str8_varg(t_group_from_test(test)), (int)(max_group_size - t_group_from_test(test).size), spaces, test->label);
|
||||
fprintf(stdout, " %.*s ", (int)dots_count, dots);
|
||||
fflush(stdout);
|
||||
|
||||
@@ -1295,19 +1344,14 @@ t_entry_point(CmdLine *cmdline)
|
||||
|
||||
// run test
|
||||
U64 run_start_time = now_time_us();
|
||||
T_RunResult result = t_run(test->r, test->user_data);
|
||||
T_RunResult result = t_run(test, test->user_data);
|
||||
U64 run_end_time = now_time_us();
|
||||
// print result
|
||||
if (result.status == T_RunStatus_Pass) {
|
||||
fprintf(stdout, "\x1b[32m" "%s" "\x1b[0m", t_string_from_result(result.status));
|
||||
pass_count += 1;
|
||||
} else if (result.status == T_RunStatus_Fail) {
|
||||
fprintf(stdout, "\x1b[31m" "%s" "\x1b[0m", t_string_from_result(result.status));
|
||||
fail_count += 1;
|
||||
} else if (result.status == T_RunStatus_Crash) {
|
||||
fprintf(stdout, "\x1b[33m" "%s" "\x1b[0m", t_string_from_result(result.status));
|
||||
crash_count += 1;
|
||||
}
|
||||
|
||||
// update
|
||||
run_counters[result.status] += 1;
|
||||
|
||||
// print run status
|
||||
fprintf(stdout, "%s%s" T_RESET, t_color_from_result(result.status), t_string_from_result(result.status));
|
||||
|
||||
if (result.status == T_RunStatus_Pass) {
|
||||
U64 d = run_end_time - run_start_time;
|
||||
@@ -1341,18 +1385,23 @@ t_entry_point(CmdLine *cmdline)
|
||||
if (result.status == T_RunStatus_Fail || result.status == T_RunStatus_Crash) {
|
||||
if (g_stop_on_first_fail_or_crash) { goto exit; }
|
||||
}
|
||||
|
||||
if (result.status == T_RunStatus_Skip) {
|
||||
u64_list_push(scratch.arena, &skipped_tests, target_idx);
|
||||
}
|
||||
}
|
||||
U64 total_time_end = now_time_us();
|
||||
|
||||
if (target_indices.count > 0 && (pass_count > 0 || fail_count > 0 || crash_count > 0 || skip_count > 0)) {
|
||||
if (target_indices.count > 0 && sum_array_u64(ArrayCount(run_counters), run_counters) > 0) {
|
||||
U64 total_time_dt = total_time_end - total_time_start;
|
||||
String8 total_time_str = string_from_elapsed_time(scratch.arena, date_time_from_micro_seconds(total_time_dt));
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
PrintHeader("Summary");
|
||||
U64 total_time_dt = total_time_end - total_time_start;
|
||||
String8 total_time_str = string_from_elapsed_time(scratch.arena, date_time_from_micro_seconds(total_time_dt));
|
||||
fprintf(stderr, " Passed %llu\n", (unsigned long long)pass_count);
|
||||
fprintf(stderr, " Failed %llu\n", (unsigned long long)fail_count);
|
||||
fprintf(stderr, " Crashed %llu\n", (unsigned long long)crash_count);
|
||||
fprintf(stderr, " Skipped %llu\n", (unsigned long long)skip_count);
|
||||
fprintf(stderr, " Passed %llu\n", (unsigned long long)run_counters[T_RunStatus_Pass]);
|
||||
fprintf(stderr, " Failed %llu\n", (unsigned long long)run_counters[T_RunStatus_Fail]);
|
||||
fprintf(stderr, " Crashed %llu\n", (unsigned long long)run_counters[T_RunStatus_Crash]);
|
||||
fprintf(stderr, " Skipped %llu\n", (unsigned long long)run_counters[T_RunStatus_Skip]);
|
||||
fprintf(stderr, " Time %.*s\n", str8_varg(total_time_str));
|
||||
|
||||
U64 slow_count = 0;
|
||||
@@ -1368,17 +1417,17 @@ t_entry_point(CmdLine *cmdline)
|
||||
for EachElement(i, slowest) {
|
||||
Slowest s = slowest[i];
|
||||
label_max = Max(strlen(g_torture_tests[s.target_idx]->label), label_max);
|
||||
group_max = Max(strlen(g_torture_tests[s.target_idx]->group), group_max);
|
||||
group_max = Max(t_group_from_test_idx(s.target_idx).size, group_max);
|
||||
}
|
||||
|
||||
fprintf(stderr, " Slow Tests\n");
|
||||
fprintf(stderr, " \nSlow Tests\n");
|
||||
for EachElement(i, slowest) {
|
||||
Slowest s = slowest[i];
|
||||
if (s.target_idx >= g_torture_test_count) { break; }
|
||||
String8 elapsed_time = string_from_elapsed_time(scratch.arena, date_time_from_micro_seconds(s.d));
|
||||
fprintf(stderr, " %s %.*s:: %s %.*s %.*s\n",
|
||||
g_torture_tests[s.target_idx]->group,
|
||||
(int)(group_max - strlen(g_torture_tests[s.target_idx]->group)), spaces,
|
||||
fprintf(stderr, " %.*s %.*s/ %s %.*s %.*s\n",
|
||||
str8_varg(t_group_from_test_idx(s.target_idx)),
|
||||
(int)(group_max - t_group_from_test_idx(s.target_idx).size), spaces,
|
||||
g_torture_tests[s.target_idx]->label,
|
||||
(int)(label_max - strlen(g_torture_tests[s.target_idx]->label)) + 4, dots,
|
||||
str8_varg(elapsed_time));
|
||||
@@ -1386,12 +1435,10 @@ t_entry_point(CmdLine *cmdline)
|
||||
}
|
||||
}
|
||||
|
||||
exit_code = run_counters[T_RunStatus_Fail] + run_counters[T_RunStatus_Crash];
|
||||
exit:;
|
||||
if (fail_count + crash_count != 0) {
|
||||
fflush(stdout);
|
||||
abort_self(fail_count + crash_count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
scratch_end(scratch);
|
||||
// TODO: return exit_code;
|
||||
}
|
||||
|
||||
+36
-18
@@ -5,11 +5,25 @@
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
#define T_RESET "\x1b[0m"
|
||||
#define T_RED "\x1b[31m"
|
||||
#define T_GREEN "\x1b[32m"
|
||||
#define T_YELLOW "\x1b[33m"
|
||||
#define T_BLUE "\x1b[34m"
|
||||
|
||||
//#define X(n, c)
|
||||
#define T_Run_XList \
|
||||
X(Fail, T_RED) \
|
||||
X(Crash, T_RED) \
|
||||
X(Pass, T_GREEN) \
|
||||
X(Skip, T_RESET)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
T_RunStatus_Fail,
|
||||
T_RunStatus_Crash,
|
||||
T_RunStatus_Pass,
|
||||
#define X(n,...) T_RunStatus_##n,
|
||||
T_Run_XList
|
||||
#undef X
|
||||
T_RunStatus_Count
|
||||
} T_RunStatus;
|
||||
|
||||
typedef struct
|
||||
@@ -25,20 +39,21 @@ typedef void (*T_Run)(Arena *arena, String8 user_data, T_RunResul
|
||||
|
||||
typedef struct
|
||||
{
|
||||
T_Run run;
|
||||
String8 user_data;
|
||||
T_RunResult result;
|
||||
} T_RunCtx;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *group;
|
||||
char *file;
|
||||
char *label;
|
||||
int decl_line;
|
||||
T_Run r;
|
||||
B32 skip;
|
||||
String8 user_data;
|
||||
} T_Test;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
T_Test *test;
|
||||
String8 user_data;
|
||||
T_RunResult result;
|
||||
} T_RunCtx;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
T_Compiler_Null,
|
||||
@@ -61,25 +76,28 @@ extern T_Test g_torture_tests_[0xffffff];
|
||||
|
||||
internal void t_break_if_debugger_present(void);
|
||||
|
||||
#define T_AddTest(name, l, ...) \
|
||||
#define T_AddTest(name, f, l, skip, ...) \
|
||||
T_RunSig(name); \
|
||||
__VA_ARGS__ void t_add_test_##name(void) \
|
||||
{ \
|
||||
g_torture_tests_[g_torture_test_count++] = (T_Test){ .group = T_Group, .label = Stringify(name), .r = &t_##name, .decl_line = l }; \
|
||||
g_torture_tests_[g_torture_test_count++] = (T_Test){ f, Stringify(name), l, &t_##name, skip }; \
|
||||
}
|
||||
|
||||
#if COMPILER_MSVC
|
||||
# pragma section(".CRT$XCU", read)
|
||||
# define TEST_(name) \
|
||||
T_AddTest(name, __LINE__) \
|
||||
# define TEST_(name, skip) \
|
||||
T_AddTest(name, __FILE__, __LINE__, skip) \
|
||||
__declspec(allocate(".CRT$XCU")) void(*r_##name)(void) = t_add_test_##name; \
|
||||
__pragma(comment(linker, "/include:" Stringify(r_##name)))
|
||||
#else
|
||||
# define TEST_(name) T_AddTest(name, __LINE__, __attribute__((constructor)))
|
||||
# define TEST_(name, skip) T_AddTest(name, __FILE__, __LINE__, skip, __attribute__((constructor)))
|
||||
#endif
|
||||
|
||||
#define TEST(name) \
|
||||
TEST_(name) \
|
||||
TEST_(name, 0) \
|
||||
T_RunSig(name)
|
||||
#define SKIP(name) \
|
||||
TEST_(name, 1) \
|
||||
T_RunSig(name)
|
||||
|
||||
#define T_Ok(c) do { if (!(c)) { \
|
||||
@@ -113,7 +131,7 @@ internal String8 t_make_file_path(Arena *arena, String8 name);
|
||||
// test runner
|
||||
internal void t_run_caller(void *raw_ctx);
|
||||
internal void t_run_fail_handler(void *raw_ctx);
|
||||
internal T_RunResult t_run(T_Run run, String8 user_data);
|
||||
internal T_RunResult t_run(T_Test *test, String8 user_data);
|
||||
|
||||
// tools
|
||||
internal String8 t_radbin_path(void);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#define T_Group "Base"
|
||||
|
||||
TEST(str8_list_substr)
|
||||
{
|
||||
String8List zero_list = {0};
|
||||
@@ -341,4 +339,3 @@ TEST(hash_map)
|
||||
}
|
||||
}
|
||||
|
||||
#undef T_Group
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
//
|
||||
// [ ] d2r_types alias size and byte size on __float80 typedef mismatch
|
||||
|
||||
#define T_Group "d2r"
|
||||
|
||||
internal RDI_Parsed *
|
||||
d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer)
|
||||
{
|
||||
@@ -232,7 +230,7 @@ T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), s
|
||||
dw_writer_end(&writer);
|
||||
}
|
||||
|
||||
TEST(d2r_line_table)
|
||||
SKIP(d2r_line_table)
|
||||
{
|
||||
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
|
||||
String8 comp_dir = str8_lit("c:/DEVEL/");
|
||||
@@ -303,7 +301,7 @@ TEST(d2r_line_table)
|
||||
dw_writer_end(&writer);
|
||||
}
|
||||
|
||||
TEST(d2r_checksums)
|
||||
SKIP(d2r_checksums)
|
||||
{
|
||||
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
|
||||
|
||||
@@ -553,4 +551,3 @@ TEST(d2r_general)
|
||||
dw_writer_end(&writer);
|
||||
}
|
||||
|
||||
#undef T_Group
|
||||
|
||||
+194
-129
@@ -1,32 +1,54 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#define T_Group "Dbg"
|
||||
|
||||
#define T_Dbg_DefaultTimeout TIMEOUT_SEC(5)
|
||||
|
||||
extern B32 g_stop_on_first_fail_or_crash;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
t_find_line_and_col(String8 source, MD_Node *n, U64 *line_out, U64 *col_out)
|
||||
{
|
||||
U64 line = 1;
|
||||
U64 col = 1;
|
||||
for (U64 cursor = 0; cursor < source.size && cursor < n->src_offset; cursor += 1) {
|
||||
if (source.str[cursor] == '\n') {
|
||||
line += 1;
|
||||
col = 0;
|
||||
}
|
||||
col += 1;
|
||||
}
|
||||
if (line_out) { *line_out = line; }
|
||||
if (col_out) { *col_out = col; }
|
||||
}
|
||||
|
||||
internal void
|
||||
t_errorf_md(String8 file_name, String8 source, MD_Node *n, char *fmt, ...)
|
||||
{
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
String8 result = push_str8fv(scratch.arena, fmt, args);
|
||||
U64 line = 0, col = 0;
|
||||
t_find_line_and_col(source, n, &line, &col);
|
||||
t_errorf("ERROR: %S:%llu%llu: %S\n", file_name, (unsigned long long)line, (unsigned long long)col, result);
|
||||
va_end(args);
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// Debugger IPC Replies
|
||||
|
||||
typedef struct RD_IpcReply RD_IpcReply;
|
||||
struct RD_IpcReply
|
||||
typedef struct
|
||||
{
|
||||
MD_ParseResult parse;
|
||||
MD_Node *root;
|
||||
MD_Node *msg;
|
||||
};
|
||||
|
||||
internal RD_IpcReply
|
||||
rd_ipc_mdesk_reply_from_string(Arena *arena, String8 string)
|
||||
{
|
||||
MD_ParseResult parse = md_parse_from_text(arena, str8_lit("ipc_reply"), string);
|
||||
return (RD_IpcReply){ .parse = parse, .root = parse.root, parse.root->first };
|
||||
}
|
||||
} T_IpcReply;
|
||||
|
||||
internal B32
|
||||
rd_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out)
|
||||
t_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out)
|
||||
{
|
||||
MD_Node *child = md_child_from_string(node, child_name, 0);
|
||||
if (!md_node_is_nil(child) && !md_node_is_nil(child->first))
|
||||
@@ -38,10 +60,10 @@ rd_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out)
|
||||
}
|
||||
|
||||
internal B32
|
||||
rd_ipc_parse_u32(MD_Node *node, String8 child_name, U32 *out)
|
||||
t_ipc_parse_u32(MD_Node *node, String8 child_name, U32 *out)
|
||||
{
|
||||
String8 value = {0};
|
||||
if (rd_ipc_parse_string(node, child_name, &value))
|
||||
if (t_ipc_parse_string(node, child_name, &value))
|
||||
{
|
||||
U64 v64 = 0;
|
||||
if (try_u64_from_str8_c_rules(value, &v64))
|
||||
@@ -53,12 +75,12 @@ rd_ipc_parse_u32(MD_Node *node, String8 child_name, U32 *out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define rd_ipc_parse_int(n, c, ptr) rd_ipc_parse_int_(n, c, sizeof(*ptr), ptr)
|
||||
#define t_ipc_parse_int(n, c, ptr) t_ipc_parse_int_(n, c, sizeof(*ptr), ptr)
|
||||
internal B32
|
||||
rd_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out)
|
||||
t_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out)
|
||||
{
|
||||
String8 value = {0};
|
||||
if (rd_ipc_parse_string(node, child_name, &value))
|
||||
if (t_ipc_parse_string(node, child_name, &value))
|
||||
{
|
||||
U64 v64 = 0;
|
||||
if (try_u64_from_str8_c_rules(value, &v64))
|
||||
@@ -71,12 +93,12 @@ rd_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out)
|
||||
}
|
||||
|
||||
internal B32
|
||||
rd_ipc_parse_b32(MD_Node *node, String8 child_name, B32 *out)
|
||||
t_ipc_parse_b32(MD_Node *node, String8 child_name, B32 *out)
|
||||
{
|
||||
B32 is_ok = 0;
|
||||
String8 s = {0};
|
||||
U64 value = 0;
|
||||
if (rd_ipc_parse_string(node, child_name, &s))
|
||||
if (t_ipc_parse_string(node, child_name, &s))
|
||||
{
|
||||
if (str8_matchi(s, str8_lit("true"))) { value = 1; is_ok = 1; }
|
||||
else if (str8_matchi(s, str8_lit("false"))) { value = 0; is_ok = 1; }
|
||||
@@ -172,9 +194,9 @@ t_dbg_state(Arena *arena, U64 timeout_us)
|
||||
MD_Node *threads_md = md_child_from_string(state_md, str8_lit("threads"), 0);
|
||||
MD_Node *modules_md = md_child_from_string(state_md, str8_lit("modules"), 0);
|
||||
T_DbgState v = {0};
|
||||
if (!rd_ipc_parse_int(state_md, str8_lit("running"), &v.running)) { t_infof("INFO: 'state' is missing 'running'\n"); goto exit; }
|
||||
if (!rd_ipc_parse_int(state_md, str8_lit("run_gen"), &v.run_gen)) { t_infof("INFO: 'state' is missing 'run_gen'\n"); goto exit; }
|
||||
if (!rd_ipc_parse_int(state_md, str8_lit("ip"), &v.ip)) { t_infof("INFO: 'state' is missing 'ip'\n"); goto exit; }
|
||||
if (!t_ipc_parse_int(state_md, str8_lit("running"), &v.running)) { t_infof("INFO: 'state' is missing 'running'\n"); goto exit; }
|
||||
if (!t_ipc_parse_int(state_md, str8_lit("run_gen"), &v.run_gen)) { t_infof("INFO: 'state' is missing 'run_gen'\n"); goto exit; }
|
||||
if (!t_ipc_parse_int(state_md, str8_lit("ip"), &v.ip)) { t_infof("INFO: 'state' is missing 'ip'\n"); goto exit; }
|
||||
|
||||
result = push_array(arena, T_DbgState, 1);
|
||||
*result = v;
|
||||
@@ -201,11 +223,11 @@ t_dbg_src_line(Arena *arena, U64 vaddr, T_DbgLineArray *lines_out, U64 timeout_u
|
||||
U64 line_count = 0;
|
||||
for MD_EachNode(n, lines_md->first) {
|
||||
T_DbgLine line = {0};
|
||||
if ( ! rd_ipc_parse_string(n, str8_lit("file_path"), &line.file_path)) { t_infof("INFO: 'lines' is missing 'file_path'\n"); goto exit; }
|
||||
if ( ! rd_ipc_parse_int(n, str8_lit("line_num"), &line.line_num)) { t_infof("INFO: 'lines' is missing 'line_num'\n"); goto exit; }
|
||||
if ( ! rd_ipc_parse_int(n, str8_lit("column_num"), &line.column_num)) { t_infof("INFO: 'lines' is missing 'column_num'\n"); goto exit; }
|
||||
if ( ! rd_ipc_parse_int(n, str8_lit("voff_range_min"), &line.voff_range.min)) { t_infof("INFO: 'lines' is missing 'voff_range_min'\n"); goto exit; }
|
||||
if ( ! rd_ipc_parse_int(n, str8_lit("voff_range_max"), &line.voff_range.max)) { t_infof("INFO: 'lines' is missing 'voff_range_max'\n"); goto exit; }
|
||||
if ( ! t_ipc_parse_string(n, str8_lit("file_path"), &line.file_path)) { t_infof("INFO: 'lines' is missing 'file_path'\n"); goto exit; }
|
||||
if ( ! t_ipc_parse_int(n, str8_lit("line_num"), &line.line_num)) { t_infof("INFO: 'lines' is missing 'line_num'\n"); goto exit; }
|
||||
if ( ! t_ipc_parse_int(n, str8_lit("column_num"), &line.column_num)) { t_infof("INFO: 'lines' is missing 'column_num'\n"); goto exit; }
|
||||
if ( ! t_ipc_parse_int(n, str8_lit("voff_range_min"), &line.voff_range.min)) { t_infof("INFO: 'lines' is missing 'voff_range_min'\n"); goto exit; }
|
||||
if ( ! t_ipc_parse_int(n, str8_lit("voff_range_max"), &line.voff_range.max)) { t_infof("INFO: 'lines' is missing 'voff_range_max'\n"); goto exit; }
|
||||
|
||||
Node *n = push_array(scratch.arena, Node, 1);
|
||||
n->v = line;
|
||||
@@ -393,10 +415,10 @@ t_dbg_eval(Arena *arena, String8 expr, T_Eval *eval_out)
|
||||
B32 is_ok = t_dbg_send_cmd(cmd, T_Dbg_DefaultTimeout, arena, &reply);
|
||||
|
||||
T_Eval e = {0};
|
||||
if ( ! rd_ipc_parse_string(reply.root, str8_lit("expr"), &e.expr)) { t_errorf("ERROR: failed to parse reply member: expr\n"); Assert(0); goto exit; }
|
||||
if ( ! rd_ipc_parse_string(reply.root, str8_lit("value"), &e.value)) { t_errorf("ERROR: failed to parse reply member: value\n"); Assert(0); goto exit; }
|
||||
if ( ! rd_ipc_parse_string(reply.root, str8_lit("type"), &e.type)) { t_errorf("ERROR: failed to parse reply member: type\n"); Assert(0); goto exit; }
|
||||
if ( ! rd_ipc_parse_string(reply.root, str8_lit("error"), &e.error)) { t_errorf("ERROR: failed to parse reply member: error\n"); Assert(0); goto exit; }
|
||||
if ( ! t_ipc_parse_string(reply.root, str8_lit("expr"), &e.expr)) { t_errorf_md(str8_lit("IPC"), str8_zero(), reply.root, "ERROR: failed to parse reply member: expr\n"); Assert(0); goto exit; }
|
||||
if ( ! t_ipc_parse_string(reply.root, str8_lit("value"), &e.value)) { t_errorf_md(str8_lit("IPC"), str8_zero(), reply.root, "ERROR: failed to parse reply member: value\n"); Assert(0); goto exit; }
|
||||
if ( ! t_ipc_parse_string(reply.root, str8_lit("type"), &e.type)) { t_errorf_md(str8_lit("IPC"), str8_zero(), reply.root, "ERROR: failed to parse reply member: type\n"); Assert(0); goto exit; }
|
||||
if ( ! t_ipc_parse_string(reply.root, str8_lit("error"), &e.error)) { t_errorf_md(str8_lit("IPC"), str8_zero(), reply.root, "ERROR: failed to parse reply member: error\n"); Assert(0); goto exit; }
|
||||
if (eval_out) { *eval_out = e; }
|
||||
|
||||
exit:;
|
||||
@@ -424,22 +446,11 @@ internal String8
|
||||
t_string_from_dbg_script_cmd_kind(T_DbgScriptCmdKind v)
|
||||
{
|
||||
switch (v) {
|
||||
case T_DbgScriptCmdKind_Null: return str8_zero();
|
||||
case T_DbgScriptCmdKind_Breakpoint: return str8_lit("bp");
|
||||
case T_DbgScriptCmdKind_ClearBreakpoints: return str8_lit("bp_clear");
|
||||
case T_DbgScriptCmdKind_Run: return str8_lit("run");
|
||||
case T_DbgScriptCmdKind_Halt: return str8_lit("halt");
|
||||
case T_DbgScriptCmdKind_StepOver: return str8_lit("step_over");
|
||||
case T_DbgScriptCmdKind_StepInto: return str8_lit("step_into");
|
||||
case T_DbgScriptCmdKind_StepOut: return str8_lit("step_out");
|
||||
case T_DbgScriptCmdKind_StepOverInst: return str8_lit("step_over_inst");
|
||||
case T_DbgScriptCmdKind_StepIntoInst: return str8_lit("step_into_inst");
|
||||
case T_DbgScriptCmdKind_StepOverLine: return str8_lit("step_over_line");
|
||||
case T_DbgScriptCmdKind_StepIntoLine: return str8_lit("step_into_line");
|
||||
case T_DbgScriptCmdKind_KillAll: return str8_lit("kill_all");
|
||||
case T_DbgScriptCmdKind_At: return str8_lit("at");
|
||||
case T_DbgScriptCmdKind_Eval: return str8_lit("eval");
|
||||
default: InvalidPath;
|
||||
#define X(n,v) case T_DbgScriptCmdKind_##n: return str8_lit(v);
|
||||
T_DbgScriptCmdKind_XList
|
||||
#undef X
|
||||
case T_DbgScriptCmdKind_Null: return str8_zero();
|
||||
default: InvalidPath; break;
|
||||
}
|
||||
return str8_zero();
|
||||
}
|
||||
@@ -473,9 +484,9 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
||||
String8 comment = str8_skip_chop_whitespace(token_string);
|
||||
String8 prefix = str8_lit("///");
|
||||
if (str8_matchi(str8_prefix(comment, prefix.size), prefix)) {
|
||||
String8 script_part = str8_skip(comment, prefix.size);
|
||||
U64 script_part_base_off = (U64)(script_part.str - source.str);
|
||||
MD_TokenizeResult script_part_tokenize = md_tokenize_from_text(scratch.arena, script_part);
|
||||
String8 script_part = str8_skip(comment, prefix.size);
|
||||
U64 script_part_base_off = (U64)(script_part.str - source.str);
|
||||
MD_TokenizeResult script_part_tokenize = md_tokenize_from_text(scratch.arena, script_part);
|
||||
for EachIndex(script_token_idx, script_part_tokenize.tokens.count) {
|
||||
MD_Token script_token = script_part_tokenize.tokens.v[script_token_idx];
|
||||
script_token.range.min += script_part_base_off;
|
||||
@@ -508,28 +519,65 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
||||
if (str8_matchi(field->string, str8_lit("compile"))) { kind = T_DbgScriptDirectiveKind_Compile; }
|
||||
else if (str8_matchi(field->string, str8_lit("link"))) { kind = T_DbgScriptDirectiveKind_Link; }
|
||||
else if (str8_matchi(field->string, str8_lit("launch"))) { kind = T_DbgScriptDirectiveKind_Launch; }
|
||||
AssertAlways(kind != T_DbgScriptDirectiveKind_Null);
|
||||
|
||||
// syntax check
|
||||
AssertAlways( !md_node_is_nil(field->first));
|
||||
AssertAlways(md_node_is_nil(field->first->next));
|
||||
Assert(field->first->flags & MD_NodeFlag_StringLiteral);
|
||||
|
||||
// src_offset -> line
|
||||
//
|
||||
// TODO: super silly!! mdesk should export line numbers
|
||||
U64 line = 1;
|
||||
String8 text_before_src = str8_prefix(source, field->src_offset);
|
||||
for EachIndex(idx, text_before_src.size) { line += (text_before_src.str[idx] == '\n'); }
|
||||
|
||||
T_DbgScriptDirective *n = push_array(arena, T_DbgScriptDirective, 1);
|
||||
n->kind = kind;
|
||||
n->line = line;
|
||||
n->args = str8_copy(arena, field->first->string);
|
||||
// TODO: expand % in compile: and link: to current source file name and esacpe with %%
|
||||
|
||||
else if (str8_matchi(field->string, str8_lit("skip"))) { kind = T_DbgScriptDirectiveKind_Skip; }
|
||||
|
||||
if (kind == T_DbgScriptDirectiveKind_Null) {
|
||||
t_errorf_md(file_path, source, n, "unknown field in test header \"%S\"\n", field->string);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
T_DbgScriptDirective *dir = push_array(arena, T_DbgScriptDirective, 1);
|
||||
dir->kind = kind;
|
||||
t_find_line_and_col(source, field, &dir->line, 0);
|
||||
|
||||
if (field->flags & MD_NodeFlag_HasBraceLeft) {
|
||||
if (kind == T_DbgScriptDirectiveKind_Compile) {
|
||||
for MD_EachNode(sub_field, field->first) {
|
||||
if (str8_matchi(sub_field->string, str8_lit("cc"))) {
|
||||
MD_Node *cc = sub_field->first;
|
||||
if (cc->flags & MD_NodeFlag_StringLiteral) {
|
||||
if (str8_matchi(cc->string, str8_lit("clang"))) { dir->compile.cc = T_Compiler_Clang; }
|
||||
else if (str8_matchi(cc->string, str8_lit("cl"))) { dir->compile.cc = T_Compiler_Cl; }
|
||||
else {
|
||||
t_errorf_md(file_path, source, cc, "unknown compiler name: \"%S\"\n", sub_field->string);
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
t_errorf_md(file_path, source, sub_field, "value of CC must be a string literal e.g. CC: \"clang\"\n");
|
||||
goto exit;
|
||||
}
|
||||
} else if (str8_matchi(sub_field->string, str8_lit("args"))) {
|
||||
MD_Node *args = sub_field->first;
|
||||
if (args->flags & MD_NodeFlag_StringLiteral) {
|
||||
dir->args = str8_copy(arena, args->string);
|
||||
} else {
|
||||
t_errorf_md(file_path, source, args, "value of ARGS must be a string literal\n");
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
t_errorf_md(file_path, source, sub_field, "unknown field \"%S\"\n", sub_field->string);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (md_node_is_nil(field->first)) {
|
||||
t_errorf_md(file_path, source, field, "missing value on field %S\n", field->string);
|
||||
goto exit;
|
||||
}
|
||||
if ( ! md_node_is_nil(field->first->next)) {
|
||||
t_errorf_md(file_path, source, field, "field %S accepts only one value\n", field->string);
|
||||
goto exit;
|
||||
}
|
||||
if (~field->first->flags & MD_NodeFlag_StringLiteral) {
|
||||
t_errorf_md(file_path, source, field, "field %S accepts only strings\n", field->string);
|
||||
goto exit;
|
||||
}
|
||||
dir->args = str8_copy(arena, field->first->string);
|
||||
}
|
||||
|
||||
T_DbgScriptDirectiveList *list = &script.directives[os][kind];
|
||||
SLLQueuePush(list->first, list->last, n);
|
||||
SLLQueuePush(list->first, list->last, dir);
|
||||
list->count += 1;
|
||||
}
|
||||
}
|
||||
@@ -541,52 +589,59 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
||||
|
||||
// file
|
||||
{
|
||||
MD_Node *last_file = 0;
|
||||
MD_NodePtrList files = {0};
|
||||
for MD_EachNode(n, script_parse.root->first->next) {
|
||||
B32 is_end = (md_node_is_nil(n->next) && last_file != 0);
|
||||
if (str8_matchi(n->string, str8_lit("file")) || is_end) {
|
||||
if (!is_end) {
|
||||
AssertAlways( ! md_node_is_nil(n->first));
|
||||
AssertAlways(md_node_is_nil(n->first->next));
|
||||
if (str8_matchi(n->string, str8_lit("file"))) {
|
||||
AssertAlways( ! md_node_is_nil(n->first));
|
||||
|
||||
if ( ! md_node_is_nil(n->first->next) || ! (n->first->flags & MD_NodeFlag_StringLiteral)) {
|
||||
U32 line = 0;
|
||||
for EachIndex(idx, n->first->src_offset) { line += (source.str[idx] == '\n'); }
|
||||
t_errorf_md(file_path, source, n, "value of the 'file' must be a string, (e.g. file: \"main.c\")\n", file_path, line);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (last_file) {
|
||||
// src_offset -> base_line
|
||||
//
|
||||
// TODO: super silly!! mdesk should export line numbers
|
||||
U64 line = 1;
|
||||
for EachIndex(idx, last_file->src_offset) { line += (source.str[idx] == '\n'); }
|
||||
|
||||
String8 sub_source = str8_substr(source, r1u64(last_file->src_offset, is_end ? source.size : n->src_offset));
|
||||
U64 file_dir_end = str8_find_needle(sub_source, 0, str8_lit("\n"), 0);
|
||||
U64 next_file_dir_begin = str8_find_needle_reverse(sub_source, 0, str8_lit("\n"), n->src_offset);
|
||||
sub_source = str8_substr(sub_source, r1u64(file_dir_end + 1, next_file_dir_begin));
|
||||
|
||||
T_DbgScriptFile *file = push_array(arena, T_DbgScriptFile, 1);
|
||||
file->path = t_make_file_path(arena, last_file->first->string);
|
||||
file->source = sub_source;
|
||||
file->line = line;
|
||||
SLLQueuePush(script.files.first, script.files.last, file);
|
||||
script.files.count += 1;
|
||||
}
|
||||
|
||||
last_file = n;
|
||||
|
||||
md_node_ptr_list_push(scratch.arena, &files, n);
|
||||
}
|
||||
}
|
||||
|
||||
// no file directives? assume script file as main source file
|
||||
if (last_file == 0) {
|
||||
|
||||
if (files.count == 0) {
|
||||
MD_Node *whole_file = push_array(scratch.arena, MD_Node, 1);
|
||||
whole_file->first = push_array(scratch.arena, MD_Node, 1);
|
||||
whole_file->first->next = push_array(scratch.arena, MD_Node, 1);
|
||||
whole_file->src_offset = 0;
|
||||
whole_file->first->string = str8_skip_last_slash(file_path);
|
||||
md_node_ptr_list_push(scratch.arena, &files, whole_file);
|
||||
}
|
||||
|
||||
HashMap files_hm = {0};
|
||||
for EachNode(n_ptr, MD_NodePtrNode, files.first) {
|
||||
MD_Node *n = n_ptr->v;
|
||||
|
||||
U64 src_opl = source.size;
|
||||
if (n_ptr->next) {
|
||||
src_opl = n_ptr->next->v->src_offset;
|
||||
}
|
||||
|
||||
String8 sub_source = str8_substr(source, r1u64(n->src_offset, src_opl));
|
||||
U64 file_min = str8_find_needle(sub_source, 0, str8_lit("\n"), 0) + 1;
|
||||
U64 file_max = str8_find_needle_reverse(sub_source, 0, str8_lit("\n"), 0);
|
||||
sub_source = str8_substr(sub_source, r1u64(file_min, file_max));
|
||||
|
||||
T_DbgScriptFile *file = push_array(arena, T_DbgScriptFile, 1);
|
||||
file->path = file_path;
|
||||
file->source = source;
|
||||
file->path = t_make_file_path(arena, n->first->string);
|
||||
file->source = sub_source;
|
||||
t_find_line_and_col(source, n, &file->line, 0);
|
||||
SLLQueuePush(script.files.first, script.files.last, file);
|
||||
script.files.count += 1;
|
||||
|
||||
hash_map_push_raw_raw(scratch.arena, &files_hm, n, file);
|
||||
}
|
||||
}
|
||||
|
||||
// programs
|
||||
{
|
||||
HashTable *ht = hash_table_init(scratch.arena, 256); // <U64, T_DbgScriptProgram>
|
||||
HashMap hm = {0}; // <U64, T_DbgScriptProgram>
|
||||
for MD_EachNode(n, script_parse.root->first->next) {
|
||||
U64 order = 0;
|
||||
if (try_u64_from_str8_c_rules(n->string, &order)) {
|
||||
@@ -598,20 +653,14 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
||||
}
|
||||
AssertAlways(file != 0);
|
||||
|
||||
// src_offset -> line
|
||||
//
|
||||
// TODO: super silly!! mdesk should export line numbers
|
||||
U64 line = 1;
|
||||
for EachIndex(i, n->src_offset) { line += (source.str[i] == '\n'); }
|
||||
|
||||
T_DbgScriptProgram *p = hash_table_search_u64_raw(ht, order);
|
||||
T_DbgScriptProgram *p = hash_map_search_u64_raw(&hm, order);
|
||||
if (p == 0) {
|
||||
p = push_array(arena, T_DbgScriptProgram, 1);
|
||||
p->line = line;
|
||||
t_find_line_and_col(source, n, &p->line, 0);
|
||||
p->order = order;
|
||||
p->os = OperatingSystem_CURRENT;
|
||||
p->file = file;
|
||||
hash_table_push_u64_raw(scratch.arena, ht, order, p);
|
||||
hash_map_push_u64_raw(scratch.arena, &hm, order, p);
|
||||
} else {
|
||||
t_errorf("ERROR: duplicate order number %llu found on line %llu\n", (unsigned long long)order, (unsigned long long)p->line);
|
||||
}
|
||||
@@ -620,7 +669,7 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
||||
// push new cmd
|
||||
T_DbgScriptCmd *cmd = push_array(arena, T_DbgScriptCmd, 1);
|
||||
cmd->kind = t_dbg_script_cmd_kind_from_string(cmd_n->string);
|
||||
cmd->line = line;
|
||||
t_find_line_and_col(source, n, &cmd->line_num, &cmd->col_num);
|
||||
Assert(cmd->kind != T_DbgScriptCmdKind_Null);
|
||||
SLLQueuePush(p->first, p->last, cmd);
|
||||
p->count += 1;
|
||||
@@ -640,8 +689,8 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
|
||||
}
|
||||
}
|
||||
|
||||
script.program_count = ht->count;
|
||||
script.programs = values_from_hash_table_raw(arena, ht);
|
||||
script.program_count = hm.count;
|
||||
script.programs = values_from_hash_map_raw(arena, &hm);
|
||||
radsort(script.programs, script.program_count, t_dbg_script_program_is_before);
|
||||
}
|
||||
|
||||
@@ -666,7 +715,7 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
|
||||
|
||||
if (program->os == OperatingSystem_CURRENT) {
|
||||
for EachNode(cmd, T_DbgScriptCmd, program->first) {
|
||||
t_infof("[%llu] Command: %S:%llu %S\n", program->order, script->file_path, (unsigned long long)cmd->line, t_string_from_dbg_script_cmd_kind(cmd->kind));
|
||||
t_infof("[%llu] Command: %S:%llu %S\n", program->order, script->file_path, (unsigned long long)cmd->line_num, t_string_from_dbg_script_cmd_kind(cmd->kind));
|
||||
|
||||
switch (cmd->kind) {
|
||||
case T_DbgScriptCmdKind_Null: break;
|
||||
@@ -694,7 +743,7 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
|
||||
#else
|
||||
T_DbgState *temp_status = t_dbg_state(scratch.arena, T_Dbg_DefaultTimeout);
|
||||
if (temp_status == 0) {
|
||||
t_errorf("ERROR: %S:%llu: failed to query IP\n", script->file_path, (unsigned long long)cmd->line);
|
||||
t_errorf("ERROR: %S:%llu: failed to query IP\n", script->file_path, (unsigned long long)cmd->line_num);
|
||||
goto exit;
|
||||
}
|
||||
U64 ip = temp_status->ip;
|
||||
@@ -703,7 +752,7 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
|
||||
// map IP -> source location
|
||||
T_DbgLineArray lines = {0};
|
||||
if (t_dbg_src_line(scratch.arena, ip, &lines, T_Dbg_DefaultTimeout) == 0) {
|
||||
t_errorf("ERROR: %S:%llu: IP (0x%llx) does not map to a source line\n", script->file_path, (unsigned long long)cmd->line, (unsigned long long)ip);
|
||||
t_errorf("ERROR: %S:%llu: IP (0x%llx) does not map to a source line\n", script->file_path, (unsigned long long)cmd->line_num, (unsigned long long)ip);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -711,14 +760,18 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
|
||||
S64 at_line_s64 = (S64)(program->line - program->file->line) + cmd->at.delta;
|
||||
U64 at_line_u64 = at_line_s64 >= 0 ? (U64)at_line_s64 : 0;
|
||||
AssertAlways(at_line_u64 > 0);
|
||||
|
||||
if (lines.count == 0) {
|
||||
t_errorf("ERROR: %S:%llu:%llu: no source location maps for vaddr: 0x%llx\n", script->file_path, (unsigned long long)cmd->line_num, (unsigned long long)cmd->col_num, (unsigned long long)ip);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// match expected vs current debugger locations
|
||||
|
||||
for EachIndex(i, lines.count) {
|
||||
B32 mismatch = lines.v[i].line_num != at_line_u64 ||
|
||||
!str8_match(lines.v[i].file_path, program->file->path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive);
|
||||
if (mismatch) {
|
||||
t_errorf("ERROR: %S:%llu: location check did not pass:\n", script->file_path, (unsigned long long)cmd->line);
|
||||
t_errorf("ERROR: %S:%llu: location check did not pass:\n", script->file_path, (unsigned long long)cmd->line_num);
|
||||
t_errorf(" Expected: %S:%llu\n", program->file->path, (unsigned long long)at_line_u64);
|
||||
t_errorf(" Got : %S:%llu\n", lines.v[i].file_path, (unsigned long long)lines.v[i].line_num);
|
||||
t_errorf(" IP : 0x%llx\n", (unsigned long long)ip);
|
||||
@@ -758,6 +811,7 @@ T_RunSig(dbg_script_runner)
|
||||
// source -> script
|
||||
T_DbgScript script = {0};
|
||||
if ( ! t_dbg_script_from_source(arena, user_data, source, &script)) {
|
||||
result_out->status = T_RunStatus_Fail;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -768,17 +822,23 @@ T_RunSig(dbg_script_runner)
|
||||
T_Ok(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Skip].count) {
|
||||
result_out->status = T_RunStatus_Skip;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// compiler vars
|
||||
HashTable *script_vars = hash_table_init(arena, 1000);
|
||||
hash_table_push_path_string(arena, script_vars, str8_lit("FILE"), user_data);
|
||||
hash_table_push_path_string(arena, script_vars, str8_lit("CWD"), g_wdir);
|
||||
|
||||
// run compilers
|
||||
for EachNode(directive, T_DbgScriptDirective, script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Compile].first) {
|
||||
T_Compiler compiler = directive->compile.compiler;
|
||||
|
||||
T_Compiler compiler = directive->compile.cc;
|
||||
|
||||
// pick default compiler if none selected
|
||||
if (compiler == T_Compiler_Null) {
|
||||
if (directive->compile.cc == T_Compiler_Null) {
|
||||
switch (OperatingSystem_CURRENT) {
|
||||
case OperatingSystem_Windows: { compiler = T_Compiler_Cl; } break;
|
||||
case OperatingSystem_Linux: { compiler = T_Compiler_Clang; } break;
|
||||
@@ -796,10 +856,16 @@ T_RunSig(dbg_script_runner)
|
||||
|
||||
// invoke compiler with arguments from directive
|
||||
String8 expanded_args = lnk_expand_env_vars_windows(arena, script_vars, directive->args);
|
||||
|
||||
if (compiler == T_Compiler_Cl) { expanded_args = str8f(arena, "/nologo %S", expanded_args); }
|
||||
|
||||
if (t_invoke(compiler_path, expanded_args, max_U64) == 0) {
|
||||
t_errorf("ERROR: failed to launch compiler: \"%S %S\"\n", compiler_path, expanded_args);
|
||||
T_Ok(0);
|
||||
}
|
||||
|
||||
if (compiler == T_Compiler_Cl) { g_output = str8_skip(g_output, str8_chop_line(&g_output).size); } // file name print
|
||||
|
||||
if (g_last_exit_code) {
|
||||
t_errorf("ERROR: %S:%llu: %S\n", script.file_path, (unsigned long long)directive->line, g_errors);
|
||||
if (g_stop_on_first_fail_or_crash) {
|
||||
@@ -875,7 +941,7 @@ t_dbg_register_script_tests(Arena *arena, String8 folder_path)
|
||||
String8 file_name_escaped = str8_list_join(arena, &file_name_parts, &(StringJoin){.sep=str8_lit("-"), .post = str8_lit("\0") });
|
||||
|
||||
g_torture_tests_[g_torture_test_count++] = (T_Test){
|
||||
.group = T_Group,
|
||||
.file = "raddbg",
|
||||
.label = (char*)file_name_escaped.str,
|
||||
.r = t_dbg_script_runner,
|
||||
.user_data = str8_copy(arena, file_path),
|
||||
@@ -885,4 +951,3 @@ t_dbg_register_script_tests(Arena *arena, String8 folder_path)
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
#undef T_Group
|
||||
|
||||
+24
-17
@@ -21,31 +21,37 @@ typedef struct
|
||||
T_DbgScriptFile *last;
|
||||
} T_DbgScriptFileList;
|
||||
|
||||
#define T_DbgScriptCmdKind_XList \
|
||||
X(Breakpoint, "bp") \
|
||||
X(ClearBreakpoints, "bp_clear") \
|
||||
X(Run, "run") \
|
||||
X(Halt, "halt") \
|
||||
X(StepOver, "step_over") \
|
||||
X(StepInto, "step_into") \
|
||||
X(StepOut, "step_out") \
|
||||
X(StepOverInst, "step_over_inst") \
|
||||
X(StepIntoInst, "step_over_inst") \
|
||||
X(StepOverLine, "step_over_line") \
|
||||
X(StepIntoLine, "step_into_line") \
|
||||
X(KillAll, "kll_all") \
|
||||
X(At, "at") \
|
||||
X(Eval, "eval")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
T_DbgScriptCmdKind_Null,
|
||||
T_DbgScriptCmdKind_Breakpoint,
|
||||
T_DbgScriptCmdKind_ClearBreakpoints,
|
||||
T_DbgScriptCmdKind_Run,
|
||||
T_DbgScriptCmdKind_Halt,
|
||||
T_DbgScriptCmdKind_StepOver,
|
||||
T_DbgScriptCmdKind_StepInto,
|
||||
T_DbgScriptCmdKind_StepOut,
|
||||
T_DbgScriptCmdKind_StepOverInst,
|
||||
T_DbgScriptCmdKind_StepIntoInst,
|
||||
T_DbgScriptCmdKind_StepOverLine,
|
||||
T_DbgScriptCmdKind_StepIntoLine,
|
||||
T_DbgScriptCmdKind_KillAll,
|
||||
T_DbgScriptCmdKind_At,
|
||||
T_DbgScriptCmdKind_Eval,
|
||||
#define X(n,...) T_DbgScriptCmdKind_##n,
|
||||
T_DbgScriptCmdKind_XList
|
||||
#undef X
|
||||
T_DbgScriptCmdKind_Count
|
||||
} T_DbgScriptCmdKind;
|
||||
|
||||
typedef struct T_DbgScriptCmd
|
||||
{
|
||||
struct T_DbgScriptCmd *next;
|
||||
T_DbgScriptCmdKind kind;
|
||||
U64 line;
|
||||
T_DbgScriptCmdKind kind;
|
||||
U64 line_num;
|
||||
U64 col_num;
|
||||
union {
|
||||
struct {
|
||||
S64 delta;
|
||||
@@ -78,6 +84,7 @@ typedef enum
|
||||
T_DbgScriptDirectiveKind_Compile,
|
||||
T_DbgScriptDirectiveKind_Link,
|
||||
T_DbgScriptDirectiveKind_Launch,
|
||||
T_DbgScriptDirectiveKind_Skip,
|
||||
T_DbgScriptDirectiveKind_Count,
|
||||
} T_DbgScriptDirectiveKind;
|
||||
|
||||
@@ -89,7 +96,7 @@ typedef struct T_DbgScriptDirective
|
||||
String8 args;
|
||||
union {
|
||||
struct {
|
||||
T_Compiler compiler;
|
||||
T_Compiler cc;
|
||||
} compile;
|
||||
};
|
||||
} T_DbgScriptDirective;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#define T_Group "Dwarf"
|
||||
|
||||
internal U64
|
||||
t_dw_test_uleb128(U64 v, U64 expected_length)
|
||||
{
|
||||
@@ -1040,4 +1038,3 @@ TEST(reg_split_spill)
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef T_Group
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#define T_Group "MD"
|
||||
|
||||
TEST(md_tokenizer)
|
||||
SKIP(md_tokenizer)
|
||||
{
|
||||
MD_TokenizeResult result;
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define T_Group "p2r"
|
||||
|
||||
#if OS_WINDOWS
|
||||
|
||||
// TODO: location is not baked consistently
|
||||
@@ -127,5 +125,3 @@ TEST(p2r_determ)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef T_Group
|
||||
|
||||
|
||||
@@ -433,8 +433,6 @@ t_write_entry_obj(void)
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
#define T_Group "Linker"
|
||||
|
||||
TEST(machine_compat_check)
|
||||
{
|
||||
// unknown.obj
|
||||
@@ -4712,7 +4710,7 @@ TEST(relocate_undefined_section_symbol)
|
||||
T_Ok(t_write_def_obj(obj_name, (T_COFF_DefObj){
|
||||
.machine = T_COFF_DefSetMachine(X64),
|
||||
.sections = (T_COFF_DefSection[]){
|
||||
{ target_name, sect_name, target_name, .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT },
|
||||
{ target_name, sect_name, str8_cstring(target_name), .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT },
|
||||
{0}
|
||||
},
|
||||
.symbols = (T_COFF_DefSymbol[]){
|
||||
@@ -7203,4 +7201,3 @@ TEST(lib_member_reloc_apply_off_out_of_bounds)
|
||||
}
|
||||
#endif
|
||||
|
||||
#undef T_Group
|
||||
|
||||
Reference in New Issue
Block a user