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:
Nikita Smith
2026-06-02 12:10:58 -07:00
committed by Ryan Fleury
parent a21a256333
commit fe2778133f
16 changed files with 494 additions and 340 deletions
+1 -2
View File
@@ -8,9 +8,8 @@ on:
paths-ignore: paths-ignore:
- '**.md' - '**.md'
# TODO: fix skips
env: env:
TORTURE_FLAGS: "--gen_crash_dump -s:d2r::d2r_line_table,d2r::d2r_checksums" TORTURE_FLAGS: "* --gen_crash_dump"
jobs: jobs:
build-ubuntu-24-04: build-ubuntu-24-04:
+1
View File
@@ -27,6 +27,7 @@ if "%TORTURE_ARGS:~0,3%" == "-- " set "TORTURE_ARGS=%TORTURE_ARGS:~3%" && goto p
set "TORTURE_ARGS=%TORTURE_ARGS:* -- =%" set "TORTURE_ARGS=%TORTURE_ARGS:* -- =%"
:parse_done :parse_done
if not defined TORTURE_ARGS set "TORTURE_ARGS=*
for %%m in (%MODE_VALUES%) do for %%c in (%CC_VALUES%) do ( for %%m in (%MODE_VALUES%) do for %%c in (%CC_VALUES%) do (
setlocal setlocal
+4
View File
@@ -38,6 +38,10 @@ while [[ $# -gt 0 ]]; do
esac esac
done done
if [[ "${#torture_args[@]}" == "0" ]]; then
torture_args=("*")
fi
for m in "${mode_values[@]}"; do for m in "${mode_values[@]}"; do
for c in "${cc_values[@]}"; do for c in "${cc_values[@]}"; do
# nuke artifacts from last run # nuke artifacts from last run
+2
View File
@@ -926,7 +926,9 @@ internal void * keys_from_hash_map_raw ( Arena *arena, HashMap *hm) { retur
// values // values
force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_u64) { MemoryCopy(buffer, &kv->value.value_u64, sizeof(kv->value.value_u64)); } force_inline HASH_MAP_EXTRACT_FUNC(hash_map_extract_value_u64) { MemoryCopy(buffer, &kv->value.value_u64, sizeof(kv->value.value_u64)); }
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 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, // 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 // where thunk calls into resolved function
//
// test: { /// test: {
// windows: { /// windows: {
// compile: "/Od /Z7 /c main.c module.c" /// skip: ""
// link: "/fixed /debug:full /dll module.obj" /// compile: "/Od /Z7 /c main.c module.c"
// link: "/fixed /debug:full /entry:main kernel32.lib module.lib delayimp.lib main.obj /out:main.exe /delayload:module.dll /incremental:no" /// link: "/fixed /debug:full /dll module.obj"
// launch: "main.exe" /// 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" /// linux: {
// compile: "-O0 -g main.c -L. -lmodule -o main -Wl,-rpath,%CWD%" /// skip: ""
// launch: "./main" /// 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" /// file: "module.c"
+180 -133
View File
@@ -23,19 +23,54 @@ global String8 g_output;
global String8 g_errors; global String8 g_errors;
// tools // tools
global B32 g_dbg_graphical; global B32 g_gui;
global String8 g_radbin_path; global String8 g_radbin_path;
global String8 g_cl_path; global String8 g_cl_path;
global String8 g_clang_path; global String8 g_clang_path;
global String8 g_gcc_path; global String8 g_gcc_path;
global String8 g_linker_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 internal String8
t_test_name_from_idx(Arena *arena, U64 test_idx) 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 * internal char *
t_string_from_result(T_RunStatus v) 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_Fail: return "FAIL";
case T_RunStatus_Crash: return "CRASH"; case T_RunStatus_Crash: return "CRASH";
case T_RunStatus_Pass: return "PASS"; case T_RunStatus_Pass: return "PASS";
case T_RunStatus_Skip: return "SKIP";
default: break;
} }
return 0; 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 internal void
t_break_if_debugger_present(void) t_break_if_debugger_present(void)
{ {
@@ -167,17 +216,22 @@ t_run_caller(void *raw_ctx)
ctx->result.status = T_RunStatus_Pass; ctx->result.status = T_RunStatus_Pass;
String8List test_out = {0}; 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) { if (ctx->result.status == T_RunStatus_Fail || ctx->result.status == T_RunStatus_Crash) {
for EachNode(n, String8Node, test_out.first) { for EachNode(n, String8Node, test_out.first) {
t_errorf("%S", n->string); t_errorf("%S", n->string);
} }
if (g_errors.size) { if (g_errors.size) {
t_errorf("stderr: \"%S\"\n", g_errors); t_errorf("%S\n", g_errors);
} }
if (g_output.size) { 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 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); t_run_caller(&ctx);
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
@@ -332,7 +386,7 @@ t_raddbg_path(void)
local_persist U8 buffer[4096]; local_persist U8 buffer[4096];
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer }; ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
Arena *arena = arena_alloc_(&params); Arena *arena = arena_alloc_(&params);
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 #if OS_WINDOWS
Temp scratch = scratch_begin(0, 0); Temp scratch = scratch_begin(0, 0);
path = full_path_from_path(arena, str8f(scratch.arena, "%S.exe", raddbg_base_name)); 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:; exit:;
for EachElement(i, read_capture_handles) { file_close(read_capture_handles[i]); } for EachElement(i, read_capture_handles) { file_close(read_capture_handles[i]); }
for EachElement(i, write_capture_handles) { file_close(write_capture_handles[i]); } for EachElement(i, write_capture_handles) { file_close(write_capture_handles[i]); }
AssertAlways(is_ok);
scratch_end(scratch); scratch_end(scratch);
return is_ok; return is_ok;
} }
@@ -883,7 +937,9 @@ internal int
t_test_compar(const void *raw_a, const void *raw_b) t_test_compar(const void *raw_a, const void *raw_b)
{ {
const T_Test *a = raw_a, *b = 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) { if (cmp == 0) {
cmp = u64_compar(&a->decl_line, &b->decl_line); cmp = u64_compar(&a->decl_line, &b->decl_line);
} }
@@ -1014,10 +1070,37 @@ t_errorf(char *fmt, ...)
scratch_end(scratch); 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 internal void
t_entry_point(CmdLine *cmdline) t_entry_point(CmdLine *cmdline)
{ {
Temp scratch = scratch_begin(0,0); Temp scratch = scratch_begin(0,0);
U64 exit_code = max_U64;
U64 dashes_size = 9999; U64 dashes_size = 9999;
U8 *dashes = push_array(scratch.arena, U8, dashes_size); U8 *dashes = push_array(scratch.arena, U8, dashes_size);
@@ -1038,23 +1121,8 @@ t_entry_point(CmdLine *cmdline)
B32 print_help = cmd_line_has_flag(cmdline, str8_lit("help")) || 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) { if (print_help) {
PrintHeader("Help"); t_help();
fprintf(stderr, " %s\n\n", BUILD_TITLE_STRING_LITERAL); goto exit;
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);
} }
} }
@@ -1086,7 +1154,7 @@ t_entry_point(CmdLine *cmdline)
// //
// Compiler overrides // 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_cl_path = cmd_line_string(cmdline, str8_lit("cl"));
g_clang_path = cmd_line_string(cmdline, str8_lit("clang")); g_clang_path = cmd_line_string(cmdline, str8_lit("clang"));
g_gcc_path = cmd_line_string(cmdline, str8_lit("gcc")); g_gcc_path = cmd_line_string(cmdline, str8_lit("gcc"));
@@ -1106,44 +1174,68 @@ t_entry_point(CmdLine *cmdline)
// //
// Handle optional -target // Handle optional -target
// //
String8List target = cmdline->inputs; U64List targets = {0};
{ {
CmdLineOpt *target_opt = cmd_line_opt_from_string(cmdline, str8_lit("target")); String8List inputs = {0};
if (target_opt == 0) {
target_opt = cmd_line_opt_from_string(cmdline, str8_lit("t")); 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) { 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; // accept inputs from the command line as target tests to run
str8_list_concat_in_place(&targets, &cmdline->inputs); str8_list_concat_in_place(&inputs, &cmdline->inputs);
// 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;
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) { for EachIndex(test_idx, g_torture_test_count) {
String8 name = str8_cstring(g_torture_tests[test_idx]->label); // match test names
if (do_namespace) { String8 test_name = t_test_name_from_idx(scratch.arena, test_idx);
name = t_test_name_from_idx(scratch.arena, test_idx);
} if (str8_match_wildcard(test_name, t, StringMatchFlag_CaseInsensitive)) {
if (str8_match_wildcard(name, pattern_n->string, 0)) { // set skip flag
if ( ! hash_table_search_string(ht, name)) { switch (mode) {
hash_table_push_string_raw(scratch.arena, ht, name, 0); case Mode_Default: break;
str8_list_push(scratch.arena, &target, str8_cstring(g_torture_tests[test_idx]->label)); case Mode_Skip: g_torture_tests[test_idx]->skip = 1; break;
case Mode_Force: g_torture_tests[test_idx]->skip = 0; break;
} }
// 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);
} }
match_count += 1;
} }
} }
if (ht->count == 0) { if (match_count == 0) {
fprintf(stderr, "ERROR: -target matches not found for the following patterns: "); fprintf(stderr, "WARNING: no matches found for input: %.*s\n", str8_varg(input_n->string));
for EachNode(n, String8Node, target_opt->value_strings.first) {
fprintf(stderr, "\"%.*s\"\n", str8_varg(n->string));
}
abort_self(1);
}
} else {
fprintf(stderr, "ERROR: -target has invalid number of arguments\n");
} }
} }
} }
@@ -1199,62 +1291,17 @@ t_entry_point(CmdLine *cmdline)
// Run tests // Run tests
// //
{ {
U64List target_indices_list = {0}; U64Array target_indices = u64_array_from_list(scratch.arena, &targets);
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);
U64 max_label_size = 0; U64 max_label_size = 0;
U64 max_group_size = 0; U64 max_group_size = 0;
for EachIndex(i, target_indices.count) { for EachIndex(i, target_indices.count) {
U64 test_idx = target_indices.v[i]; U64 test_idx = target_indices.v[i];
max_label_size = Max(max_label_size, cstring8_length((U8*)g_torture_tests[test_idx]->label)); 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 run_counters[T_RunStatus_Count] = {0};
U64 fail_count = 0;
U64 crash_count = 0;
U64 max_digit_count = count_digits_u64(target_indices.count, 10); U64 max_digit_count = count_digits_u64(target_indices.count, 10);
U64 total_time_start = now_time_us(); U64 total_time_start = now_time_us();
@@ -1262,6 +1309,8 @@ t_entry_point(CmdLine *cmdline)
Slowest slowest[5] = {0}; Slowest slowest[5] = {0};
for EachElement(i, slowest) { slowest[i].target_idx = max_U64; } for EachElement(i, slowest) { slowest[i].target_idx = max_U64; }
U64List skipped_tests = {0};
for EachIndex(i, target_indices.count) { for EachIndex(i, target_indices.count) {
if (i == 0) { PrintHeader("Tests"); } if (i == 0) { PrintHeader("Tests"); }
@@ -1274,7 +1323,7 @@ t_entry_point(CmdLine *cmdline)
U64 curr_digit_count = count_digits_u64(i+1, 10); U64 curr_digit_count = count_digits_u64(i+1, 10);
int idx_align_space_count = (int)(max_digit_count - curr_digit_count); 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%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); fprintf(stdout, " %.*s ", (int)dots_count, dots);
fflush(stdout); fflush(stdout);
@@ -1295,19 +1344,14 @@ t_entry_point(CmdLine *cmdline)
// run test // run test
U64 run_start_time = now_time_us(); 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(); U64 run_end_time = now_time_us();
// print result
if (result.status == T_RunStatus_Pass) { // update
fprintf(stdout, "\x1b[32m" "%s" "\x1b[0m", t_string_from_result(result.status)); run_counters[result.status] += 1;
pass_count += 1;
} else if (result.status == T_RunStatus_Fail) { // print run status
fprintf(stdout, "\x1b[31m" "%s" "\x1b[0m", t_string_from_result(result.status)); fprintf(stdout, "%s%s" T_RESET, t_color_from_result(result.status), 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;
}
if (result.status == T_RunStatus_Pass) { if (result.status == T_RunStatus_Pass) {
U64 d = run_end_time - run_start_time; 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 (result.status == T_RunStatus_Fail || result.status == T_RunStatus_Crash) {
if (g_stop_on_first_fail_or_crash) { goto exit; } 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(); 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) {
fprintf(stderr, "\n");
PrintHeader("Summary");
U64 total_time_dt = total_time_end - total_time_start; 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)); 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, "\n");
fprintf(stderr, " Crashed %llu\n", (unsigned long long)crash_count); PrintHeader("Summary");
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)); fprintf(stderr, " Time %.*s\n", str8_varg(total_time_str));
U64 slow_count = 0; U64 slow_count = 0;
@@ -1368,17 +1417,17 @@ t_entry_point(CmdLine *cmdline)
for EachElement(i, slowest) { for EachElement(i, slowest) {
Slowest s = slowest[i]; Slowest s = slowest[i];
label_max = Max(strlen(g_torture_tests[s.target_idx]->label), label_max); 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) { for EachElement(i, slowest) {
Slowest s = slowest[i]; Slowest s = slowest[i];
if (s.target_idx >= g_torture_test_count) { break; } 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)); String8 elapsed_time = string_from_elapsed_time(scratch.arena, date_time_from_micro_seconds(s.d));
fprintf(stderr, " %s %.*s:: %s %.*s %.*s\n", fprintf(stderr, " %.*s %.*s/ %s %.*s %.*s\n",
g_torture_tests[s.target_idx]->group, str8_varg(t_group_from_test_idx(s.target_idx)),
(int)(group_max - strlen(g_torture_tests[s.target_idx]->group)), spaces, (int)(group_max - t_group_from_test_idx(s.target_idx).size), spaces,
g_torture_tests[s.target_idx]->label, g_torture_tests[s.target_idx]->label,
(int)(label_max - strlen(g_torture_tests[s.target_idx]->label)) + 4, dots, (int)(label_max - strlen(g_torture_tests[s.target_idx]->label)) + 4, dots,
str8_varg(elapsed_time)); 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:; exit:;
if (fail_count + crash_count != 0) {
fflush(stdout);
abort_self(fail_count + crash_count);
}
} }
scratch_end(scratch); scratch_end(scratch);
// TODO: return exit_code;
} }
+36 -18
View File
@@ -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 typedef enum
{ {
T_RunStatus_Fail, #define X(n,...) T_RunStatus_##n,
T_RunStatus_Crash, T_Run_XList
T_RunStatus_Pass, #undef X
T_RunStatus_Count
} T_RunStatus; } T_RunStatus;
typedef struct typedef struct
@@ -25,20 +39,21 @@ typedef void (*T_Run)(Arena *arena, String8 user_data, T_RunResul
typedef struct typedef struct
{ {
T_Run run; char *file;
String8 user_data;
T_RunResult result;
} T_RunCtx;
typedef struct
{
char *group;
char *label; char *label;
int decl_line; int decl_line;
T_Run r; T_Run r;
B32 skip;
String8 user_data; String8 user_data;
} T_Test; } T_Test;
typedef struct
{
T_Test *test;
String8 user_data;
T_RunResult result;
} T_RunCtx;
typedef enum typedef enum
{ {
T_Compiler_Null, T_Compiler_Null,
@@ -61,25 +76,28 @@ extern T_Test g_torture_tests_[0xffffff];
internal void t_break_if_debugger_present(void); internal void t_break_if_debugger_present(void);
#define T_AddTest(name, l, ...) \ #define T_AddTest(name, f, l, skip, ...) \
T_RunSig(name); \ T_RunSig(name); \
__VA_ARGS__ void t_add_test_##name(void) \ __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 #if COMPILER_MSVC
# pragma section(".CRT$XCU", read) # pragma section(".CRT$XCU", read)
# define TEST_(name) \ # define TEST_(name, skip) \
T_AddTest(name, __LINE__) \ T_AddTest(name, __FILE__, __LINE__, skip) \
__declspec(allocate(".CRT$XCU")) void(*r_##name)(void) = t_add_test_##name; \ __declspec(allocate(".CRT$XCU")) void(*r_##name)(void) = t_add_test_##name; \
__pragma(comment(linker, "/include:" Stringify(r_##name))) __pragma(comment(linker, "/include:" Stringify(r_##name)))
#else #else
# define TEST_(name) T_AddTest(name, __LINE__, __attribute__((constructor))) # define TEST_(name, skip) T_AddTest(name, __FILE__, __LINE__, skip, __attribute__((constructor)))
#endif #endif
#define TEST(name) \ #define TEST(name) \
TEST_(name) \ TEST_(name, 0) \
T_RunSig(name)
#define SKIP(name) \
TEST_(name, 1) \
T_RunSig(name) T_RunSig(name)
#define T_Ok(c) do { if (!(c)) { \ #define T_Ok(c) do { if (!(c)) { \
@@ -113,7 +131,7 @@ internal String8 t_make_file_path(Arena *arena, String8 name);
// test runner // test runner
internal void t_run_caller(void *raw_ctx); internal void t_run_caller(void *raw_ctx);
internal void t_run_fail_handler(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 // tools
internal String8 t_radbin_path(void); internal String8 t_radbin_path(void);
-3
View File
@@ -1,8 +1,6 @@
// Copyright (c) Epic Games Tools // Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#define T_Group "Base"
TEST(str8_list_substr) TEST(str8_list_substr)
{ {
String8List zero_list = {0}; String8List zero_list = {0};
@@ -341,4 +339,3 @@ TEST(hash_map)
} }
} }
#undef T_Group
+2 -5
View File
@@ -5,8 +5,6 @@
// //
// [ ] d2r_types alias size and byte size on __float80 typedef mismatch // [ ] d2r_types alias size and byte size on __float80 typedef mismatch
#define T_Group "d2r"
internal RDI_Parsed * internal RDI_Parsed *
d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer) 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); 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); DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
String8 comp_dir = str8_lit("c:/DEVEL/"); String8 comp_dir = str8_lit("c:/DEVEL/");
@@ -303,7 +301,7 @@ TEST(d2r_line_table)
dw_writer_end(&writer); 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); 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); dw_writer_end(&writer);
} }
#undef T_Group
+180 -115
View File
@@ -1,32 +1,54 @@
// Copyright (c) Epic Games Tools // Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#define T_Group "Dbg"
#define T_Dbg_DefaultTimeout TIMEOUT_SEC(5) #define T_Dbg_DefaultTimeout TIMEOUT_SEC(5)
extern B32 g_stop_on_first_fail_or_crash; 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 // Debugger IPC Replies
typedef struct RD_IpcReply RD_IpcReply; typedef struct
struct RD_IpcReply
{ {
MD_ParseResult parse; MD_ParseResult parse;
MD_Node *root; MD_Node *root;
MD_Node *msg; MD_Node *msg;
}; } T_IpcReply;
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 };
}
internal B32 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); MD_Node *child = md_child_from_string(node, child_name, 0);
if (!md_node_is_nil(child) && !md_node_is_nil(child->first)) 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 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}; String8 value = {0};
if (rd_ipc_parse_string(node, child_name, &value)) if (t_ipc_parse_string(node, child_name, &value))
{ {
U64 v64 = 0; U64 v64 = 0;
if (try_u64_from_str8_c_rules(value, &v64)) 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; 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 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}; String8 value = {0};
if (rd_ipc_parse_string(node, child_name, &value)) if (t_ipc_parse_string(node, child_name, &value))
{ {
U64 v64 = 0; U64 v64 = 0;
if (try_u64_from_str8_c_rules(value, &v64)) 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 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; B32 is_ok = 0;
String8 s = {0}; String8 s = {0};
U64 value = 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; } 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; } 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 *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); MD_Node *modules_md = md_child_from_string(state_md, str8_lit("modules"), 0);
T_DbgState v = {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 (!t_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 (!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 (!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("ip"), &v.ip)) { t_infof("INFO: 'state' is missing 'ip'\n"); goto exit; }
result = push_array(arena, T_DbgState, 1); result = push_array(arena, T_DbgState, 1);
*result = v; *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; U64 line_count = 0;
for MD_EachNode(n, lines_md->first) { for MD_EachNode(n, lines_md->first) {
T_DbgLine line = {0}; 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 ( ! t_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 ( ! t_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 ( ! t_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 ( ! 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 ( ! 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_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); Node *n = push_array(scratch.arena, Node, 1);
n->v = line; 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); B32 is_ok = t_dbg_send_cmd(cmd, T_Dbg_DefaultTimeout, arena, &reply);
T_Eval e = {0}; 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 ( ! 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 ( ! 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 ( ! 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 ( ! 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 ( ! 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 ( ! 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("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; } if (eval_out) { *eval_out = e; }
exit:; exit:;
@@ -424,22 +446,11 @@ internal String8
t_string_from_dbg_script_cmd_kind(T_DbgScriptCmdKind v) t_string_from_dbg_script_cmd_kind(T_DbgScriptCmdKind v)
{ {
switch (v) { switch (v) {
#define X(n,v) case T_DbgScriptCmdKind_##n: return str8_lit(v);
T_DbgScriptCmdKind_XList
#undef X
case T_DbgScriptCmdKind_Null: return str8_zero(); case T_DbgScriptCmdKind_Null: return str8_zero();
case T_DbgScriptCmdKind_Breakpoint: return str8_lit("bp"); default: InvalidPath; break;
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;
} }
return str8_zero(); return str8_zero();
} }
@@ -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; } 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("link"))) { kind = T_DbgScriptDirectiveKind_Link; }
else if (str8_matchi(field->string, str8_lit("launch"))) { kind = T_DbgScriptDirectiveKind_Launch; } else if (str8_matchi(field->string, str8_lit("launch"))) { kind = T_DbgScriptDirectiveKind_Launch; }
AssertAlways(kind != T_DbgScriptDirectiveKind_Null); else if (str8_matchi(field->string, str8_lit("skip"))) { kind = T_DbgScriptDirectiveKind_Skip; }
// syntax check if (kind == T_DbgScriptDirectiveKind_Null) {
AssertAlways( !md_node_is_nil(field->first)); t_errorf_md(file_path, source, n, "unknown field in test header \"%S\"\n", field->string);
AssertAlways(md_node_is_nil(field->first->next)); goto exit;
Assert(field->first->flags & MD_NodeFlag_StringLiteral); }
// src_offset -> line T_DbgScriptDirective *dir = push_array(arena, T_DbgScriptDirective, 1);
// dir->kind = kind;
// TODO: super silly!! mdesk should export line numbers t_find_line_and_col(source, field, &dir->line, 0);
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); if (field->flags & MD_NodeFlag_HasBraceLeft) {
n->kind = kind; if (kind == T_DbgScriptDirectiveKind_Compile) {
n->line = line; for MD_EachNode(sub_field, field->first) {
n->args = str8_copy(arena, field->first->string); if (str8_matchi(sub_field->string, str8_lit("cc"))) {
// TODO: expand % in compile: and link: to current source file name and esacpe with %% 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]; T_DbgScriptDirectiveList *list = &script.directives[os][kind];
SLLQueuePush(list->first, list->last, n); SLLQueuePush(list->first, list->last, dir);
list->count += 1; list->count += 1;
} }
} }
@@ -541,52 +589,59 @@ t_dbg_script_from_source(Arena *arena, String8 file_path, String8 source, T_DbgS
// file // file
{ {
MD_Node *last_file = 0; MD_NodePtrList files = {0};
for MD_EachNode(n, script_parse.root->first->next) { 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"))) {
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));
AssertAlways(md_node_is_nil(n->first->next));
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) { md_node_ptr_list_push(scratch.arena, &files, n);
// 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)); if (files.count == 0) {
U64 file_dir_end = str8_find_needle(sub_source, 0, str8_lit("\n"), 0); MD_Node *whole_file = push_array(scratch.arena, MD_Node, 1);
U64 next_file_dir_begin = str8_find_needle_reverse(sub_source, 0, str8_lit("\n"), n->src_offset); whole_file->first = push_array(scratch.arena, MD_Node, 1);
sub_source = str8_substr(sub_source, r1u64(file_dir_end + 1, next_file_dir_begin)); 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); T_DbgScriptFile *file = push_array(arena, T_DbgScriptFile, 1);
file->path = t_make_file_path(arena, last_file->first->string); file->path = t_make_file_path(arena, n->first->string);
file->source = sub_source; file->source = sub_source;
file->line = line; t_find_line_and_col(source, n, &file->line, 0);
SLLQueuePush(script.files.first, script.files.last, file); SLLQueuePush(script.files.first, script.files.last, file);
script.files.count += 1; script.files.count += 1;
}
last_file = n; hash_map_push_raw_raw(scratch.arena, &files_hm, n, file);
}
}
// no file directives? assume script file as main source file
if (last_file == 0) {
T_DbgScriptFile *file = push_array(arena, T_DbgScriptFile, 1);
file->path = file_path;
file->source = source;
SLLQueuePush(script.files.first, script.files.last, file);
script.files.count += 1;
} }
} }
// programs // 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) { for MD_EachNode(n, script_parse.root->first->next) {
U64 order = 0; U64 order = 0;
if (try_u64_from_str8_c_rules(n->string, &order)) { 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); AssertAlways(file != 0);
// src_offset -> line T_DbgScriptProgram *p = hash_map_search_u64_raw(&hm, order);
//
// 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);
if (p == 0) { if (p == 0) {
p = push_array(arena, T_DbgScriptProgram, 1); p = push_array(arena, T_DbgScriptProgram, 1);
p->line = line; t_find_line_and_col(source, n, &p->line, 0);
p->order = order; p->order = order;
p->os = OperatingSystem_CURRENT; p->os = OperatingSystem_CURRENT;
p->file = file; p->file = file;
hash_table_push_u64_raw(scratch.arena, ht, order, p); hash_map_push_u64_raw(scratch.arena, &hm, order, p);
} else { } else {
t_errorf("ERROR: duplicate order number %llu found on line %llu\n", (unsigned long long)order, (unsigned long long)p->line); 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 // push new cmd
T_DbgScriptCmd *cmd = push_array(arena, T_DbgScriptCmd, 1); T_DbgScriptCmd *cmd = push_array(arena, T_DbgScriptCmd, 1);
cmd->kind = t_dbg_script_cmd_kind_from_string(cmd_n->string); 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); Assert(cmd->kind != T_DbgScriptCmdKind_Null);
SLLQueuePush(p->first, p->last, cmd); SLLQueuePush(p->first, p->last, cmd);
p->count += 1; 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.program_count = hm.count;
script.programs = values_from_hash_table_raw(arena, ht); script.programs = values_from_hash_map_raw(arena, &hm);
radsort(script.programs, script.program_count, t_dbg_script_program_is_before); 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) { if (program->os == OperatingSystem_CURRENT) {
for EachNode(cmd, T_DbgScriptCmd, program->first) { 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) { switch (cmd->kind) {
case T_DbgScriptCmdKind_Null: break; case T_DbgScriptCmdKind_Null: break;
@@ -694,7 +743,7 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
#else #else
T_DbgState *temp_status = t_dbg_state(scratch.arena, T_Dbg_DefaultTimeout); T_DbgState *temp_status = t_dbg_state(scratch.arena, T_Dbg_DefaultTimeout);
if (temp_status == 0) { 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; goto exit;
} }
U64 ip = temp_status->ip; U64 ip = temp_status->ip;
@@ -703,7 +752,7 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
// map IP -> source location // map IP -> source location
T_DbgLineArray lines = {0}; T_DbgLineArray lines = {0};
if (t_dbg_src_line(scratch.arena, ip, &lines, T_Dbg_DefaultTimeout) == 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; goto exit;
} }
@@ -712,13 +761,17 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
U64 at_line_u64 = at_line_s64 >= 0 ? (U64)at_line_s64 : 0; U64 at_line_u64 = at_line_s64 >= 0 ? (U64)at_line_s64 : 0;
AssertAlways(at_line_u64 > 0); AssertAlways(at_line_u64 > 0);
// match expected vs current debugger locations 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) { for EachIndex(i, lines.count) {
B32 mismatch = lines.v[i].line_num != at_line_u64 || B32 mismatch = lines.v[i].line_num != at_line_u64 ||
!str8_match(lines.v[i].file_path, program->file->path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive); !str8_match(lines.v[i].file_path, program->file->path, StringMatchFlag_CaseInsensitive|StringMatchFlag_SlashInsensitive);
if (mismatch) { 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(" 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(" 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); t_errorf(" IP : 0x%llx\n", (unsigned long long)ip);
@@ -758,6 +811,7 @@ T_RunSig(dbg_script_runner)
// source -> script // source -> script
T_DbgScript script = {0}; T_DbgScript script = {0};
if ( ! t_dbg_script_from_source(arena, user_data, source, &script)) { if ( ! t_dbg_script_from_source(arena, user_data, source, &script)) {
result_out->status = T_RunStatus_Fail;
goto exit; goto exit;
} }
@@ -769,16 +823,22 @@ T_RunSig(dbg_script_runner)
} }
} }
if (script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Skip].count) {
result_out->status = T_RunStatus_Skip;
goto exit;
}
// compiler vars // compiler vars
HashTable *script_vars = hash_table_init(arena, 1000); 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); hash_table_push_path_string(arena, script_vars, str8_lit("CWD"), g_wdir);
// run compilers // run compilers
for EachNode(directive, T_DbgScriptDirective, script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Compile].first) { 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 // pick default compiler if none selected
if (compiler == T_Compiler_Null) { if (directive->compile.cc == T_Compiler_Null) {
switch (OperatingSystem_CURRENT) { switch (OperatingSystem_CURRENT) {
case OperatingSystem_Windows: { compiler = T_Compiler_Cl; } break; case OperatingSystem_Windows: { compiler = T_Compiler_Cl; } break;
case OperatingSystem_Linux: { compiler = T_Compiler_Clang; } break; case OperatingSystem_Linux: { compiler = T_Compiler_Clang; } break;
@@ -796,10 +856,16 @@ T_RunSig(dbg_script_runner)
// invoke compiler with arguments from directive // invoke compiler with arguments from directive
String8 expanded_args = lnk_expand_env_vars_windows(arena, script_vars, directive->args); 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) { 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_errorf("ERROR: failed to launch compiler: \"%S %S\"\n", compiler_path, expanded_args);
T_Ok(0); 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) { if (g_last_exit_code) {
t_errorf("ERROR: %S:%llu: %S\n", script.file_path, (unsigned long long)directive->line, g_errors); 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) { 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") }); 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){ g_torture_tests_[g_torture_test_count++] = (T_Test){
.group = T_Group, .file = "raddbg",
.label = (char*)file_name_escaped.str, .label = (char*)file_name_escaped.str,
.r = t_dbg_script_runner, .r = t_dbg_script_runner,
.user_data = str8_copy(arena, file_path), .user_data = str8_copy(arena, file_path),
@@ -885,4 +951,3 @@ t_dbg_register_script_tests(Arena *arena, String8 folder_path)
scratch_end(scratch); scratch_end(scratch);
} }
#undef T_Group
+23 -16
View File
@@ -21,23 +21,28 @@ typedef struct
T_DbgScriptFile *last; T_DbgScriptFile *last;
} T_DbgScriptFileList; } 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 typedef enum
{ {
T_DbgScriptCmdKind_Null, T_DbgScriptCmdKind_Null,
T_DbgScriptCmdKind_Breakpoint, #define X(n,...) T_DbgScriptCmdKind_##n,
T_DbgScriptCmdKind_ClearBreakpoints, T_DbgScriptCmdKind_XList
T_DbgScriptCmdKind_Run, #undef X
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,
T_DbgScriptCmdKind_Count T_DbgScriptCmdKind_Count
} T_DbgScriptCmdKind; } T_DbgScriptCmdKind;
@@ -45,7 +50,8 @@ typedef struct T_DbgScriptCmd
{ {
struct T_DbgScriptCmd *next; struct T_DbgScriptCmd *next;
T_DbgScriptCmdKind kind; T_DbgScriptCmdKind kind;
U64 line; U64 line_num;
U64 col_num;
union { union {
struct { struct {
S64 delta; S64 delta;
@@ -78,6 +84,7 @@ typedef enum
T_DbgScriptDirectiveKind_Compile, T_DbgScriptDirectiveKind_Compile,
T_DbgScriptDirectiveKind_Link, T_DbgScriptDirectiveKind_Link,
T_DbgScriptDirectiveKind_Launch, T_DbgScriptDirectiveKind_Launch,
T_DbgScriptDirectiveKind_Skip,
T_DbgScriptDirectiveKind_Count, T_DbgScriptDirectiveKind_Count,
} T_DbgScriptDirectiveKind; } T_DbgScriptDirectiveKind;
@@ -89,7 +96,7 @@ typedef struct T_DbgScriptDirective
String8 args; String8 args;
union { union {
struct { struct {
T_Compiler compiler; T_Compiler cc;
} compile; } compile;
}; };
} T_DbgScriptDirective; } T_DbgScriptDirective;
-3
View File
@@ -1,8 +1,6 @@
// Copyright (c) Epic Games Tools // Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
#define T_Group "Dwarf"
internal U64 internal U64
t_dw_test_uleb128(U64 v, U64 expected_length) t_dw_test_uleb128(U64 v, U64 expected_length)
{ {
@@ -1040,4 +1038,3 @@ TEST(reg_split_spill)
} }
#endif #endif
#undef T_Group
+1 -1
View File
@@ -1,6 +1,6 @@
#define T_Group "MD" #define T_Group "MD"
TEST(md_tokenizer) SKIP(md_tokenizer)
{ {
MD_TokenizeResult result; MD_TokenizeResult result;
-4
View File
@@ -1,5 +1,3 @@
#define T_Group "p2r"
#if OS_WINDOWS #if OS_WINDOWS
// TODO: location is not baked consistently // TODO: location is not baked consistently
@@ -127,5 +125,3 @@ TEST(p2r_determ)
#endif #endif
#endif #endif
#undef T_Group
+1 -4
View File
@@ -433,8 +433,6 @@ t_write_entry_obj(void)
//////////////////////////////// ////////////////////////////////
#define T_Group "Linker"
TEST(machine_compat_check) TEST(machine_compat_check)
{ {
// unknown.obj // unknown.obj
@@ -4712,7 +4710,7 @@ TEST(relocate_undefined_section_symbol)
T_Ok(t_write_def_obj(obj_name, (T_COFF_DefObj){ T_Ok(t_write_def_obj(obj_name, (T_COFF_DefObj){
.machine = T_COFF_DefSetMachine(X64), .machine = T_COFF_DefSetMachine(X64),
.sections = (T_COFF_DefSection[]){ .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} {0}
}, },
.symbols = (T_COFF_DefSymbol[]){ .symbols = (T_COFF_DefSymbol[]){
@@ -7203,4 +7201,3 @@ TEST(lib_member_reloc_apply_off_out_of_bounds)
} }
#endif #endif
#undef T_Group