promote test-definition concepts from torture to base layer; reorganize tests to be nested in their respective layer; eliminate 't_group', just use containing layer

This commit is contained in:
Ryan Fleury
2026-06-02 12:11:01 -07:00
parent a151df283f
commit 4e72553006
29 changed files with 1090 additions and 1045 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ commands =
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.f1 = { .win = "raddbg_stable --ipc kill_all && build torture", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: [raddbg wsl]
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
+6 -1
View File
@@ -6,7 +6,6 @@ target:
executable: "build/raddbg.exe"
working_directory: build
arguments: "--user:raddbg_test.user --project:raddbg_test.project"
enabled: 1
debug_subprocesses: 0
}
target:
@@ -38,3 +37,9 @@ target:
working_directory: build
arguments: "--rdi raddbg.pdb"
}
target:
{
executable: "build/torture.exe"
working_directory: "build/"
enabled: 1
}
+4
View File
@@ -138,6 +138,10 @@
# define BUILD_DEBUG 1
#endif
#if !defined(BUILD_TESTS)
# define BUILD_TESTS 0
#endif
#if !defined(BUILD_SUPPLEMENTARY_UNIT)
# define BUILD_SUPPLEMENTARY_UNIT 0
#endif
+15
View File
@@ -670,6 +670,16 @@ Compiler;
# define Compiler_CURRENT Compiler_Null
#endif
typedef enum Linker
{
Linker_Null,
Linker_radlink,
Linker_msvc,
Linker_lld,
Linker_COUNT
}
Linker;
////////////////////////////////
//~ rjf: Access Flags
@@ -1076,6 +1086,11 @@ internal DateTime date_time_from_dense_time(DenseTime time);
internal DateTime date_time_from_micro_seconds(U64 time);
internal DateTime date_time_from_unix_time(U64 unix_time);
////////////////////////////////
//~ rjf: @per_os_impl Debugger Attachment Checking
internal B32 debugger_is_attached(void);
////////////////////////////////
//~ rjf: @per_os_impl Platform Time Functions
+1
View File
@@ -25,6 +25,7 @@
#include "base_markup.c"
#include "base_meta.c"
#include "base_log.c"
#include "base_test.c"
#include "base_entry_point.c"
#if OS_WINDOWS
+1
View File
@@ -27,6 +27,7 @@
#include "base_markup.h"
#include "base_meta.h"
#include "base_log.h"
#include "base_test.h"
#include "base_entry_point.h"
#if OS_WINDOWS
+8
View File
@@ -423,6 +423,10 @@ str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags
{
needle_first_char_adjusted = upper_from_char(needle_first_char_adjusted);
}
if(adjusted_flags & StringMatchFlag_SlashInsensitive)
{
needle_first_char_adjusted = correct_slash_from_char(needle_first_char_adjusted);
}
for(;p < stop_p; p += 1)
{
U8 haystack_char_adjusted = *p;
@@ -430,6 +434,10 @@ str8_find_needle(String8 string, U64 start_pos, String8 needle, StringMatchFlags
{
haystack_char_adjusted = upper_from_char(haystack_char_adjusted);
}
if(adjusted_flags & StringMatchFlag_SlashInsensitive)
{
haystack_char_adjusted = correct_slash_from_char(haystack_char_adjusted);
}
if(haystack_char_adjusted == needle_first_char_adjusted)
{
if(str8_match(str8_range(p + 1, string_opl), needle_tail, adjusted_flags))
+2
View File
@@ -0,0 +1,2 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
+85
View File
@@ -0,0 +1,85 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef BASE_TEST_H
#define BASE_TEST_H
typedef enum TestStatus
{
TestStatus_Fail,
TestStatus_Crash,
TestStatus_Pass,
TestStatus_Skip,
TestStatus_COUNT
}
TestStatus;
typedef struct TestResult TestResult;
struct TestResult
{
TestStatus status;
char *fail_file;
int fail_line;
char *fail_cond;
};
#define TEST_FUNCTION_SIG(name) void name(Arena *arena, String8 user_data, TestResult *result_out, String8List *test_out)
#define TEST_FUNCTION_DEF(name) TEST_FUNCTION_SIG(test__##name)
typedef TEST_FUNCTION_SIG(TestFunctionType);
typedef struct TestInfo TestInfo;
struct TestInfo
{
String8 layer;
String8 label;
int decl_line;
B32 skip;
TestFunctionType *test_fn;
};
#if BUILD_TESTS
global U64 test_infos_count = 0;
global TestInfo test_infos[0xffff] = {0};
#define AddTest(name, file_name, line, skip_, ...) \
TEST_FUNCTION_DEF(name);\
__VA_ARGS__ void add_test__##name(void)\
{\
String8 file = str8_lit(file_name);\
U64 src_pos = str8_find_needle(file, 0, s("src/"), StringMatchFlag_SlashInsensitive);\
String8 layer_folder = str8_skip(file, src_pos+4);\
U64 layer_slash_pos = str8_find_needle(layer_folder, 0, s("/"), StringMatchFlag_SlashInsensitive);\
String8 layer_name = str8_prefix(layer_folder, layer_slash_pos);\
test_infos[test_infos_count].layer = layer_name;\
test_infos[test_infos_count].label = str8_lit(#name);\
test_infos[test_infos_count].decl_line = (line);\
test_infos[test_infos_count].skip = (skip_);\
test_infos[test_infos_count].test_fn = test__##name;\
test_infos_count += 1;\
}
# if COMPILER_MSVC
# pragma section(".CRT$XCU", read)
# define DeclareTest(name, skip) \
AddTest(name, __FILE__, __LINE__, (skip))\
__declspec(allocate(".CRT$XCU")) void (*add_test_ptr__##name)(void) = add_test__##name;\
__pragma(comment(linker, "/include:" Stringify(add_test_ptr__##name)))
# elif COMPILER_GCC || COMPILER_CLANG
# define DeclareTest(name, skip) AddTest(name, __FILE__, __LINE__, (skip), __attribute__((constructor)))
# else
# error DeclareTest not defined for this compiler.
# endif
#else
# define DeclareTest(name, skip)
#endif
#define Test(name) DeclareTest(name, 0)\
TEST_FUNCTION_DEF(name)
#define SkippedTest(name) DeclareTest(name, 1)\
TEST_FUNCTION_DEF(name)
#define TestCheck(c) do { if (!(c)) {\
*result_out = (TestResult){ .fail_file = __FILE__, .fail_line = __LINE__, .fail_cond = Stringify(c) };\
if(debugger_is_attached()) { Trap(); }\
return;\
} } while(0)
#endif // BASE_TEST_H
@@ -338,4 +338,3 @@ TEST(hash_map)
T_Ok(hash_map_search_string_raw(&hm, str8_lit("/MNT/devel")) == &bar);
}
}
File diff suppressed because it is too large Load Diff
@@ -644,14 +644,14 @@ TEST(merge)
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.test=.test entry.obj test.obj");
T_Ok(g_last_exit_code != 0);
if (t_id_linker() == T_Linker_RAD) {
if (t_id_linker() == Linker_radlink) {
T_Ok(g_last_exit_code == LNK_Error_CircularMerge);
}
// circular merge with extra link
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.test=.data /merge:.data=.test entry.obj test.obj");
T_Ok(g_last_exit_code != 0);
if (t_id_linker() == T_Linker_RAD) {
if (t_id_linker() == Linker_radlink) {
T_Ok(g_last_exit_code == LNK_Error_CircularMerge);
}
@@ -677,14 +677,14 @@ TEST(merge)
// illegal merge with .reloc
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.test=.reloc entry.obj test.obj");
T_Ok(g_last_exit_code != 0);
if (t_id_linker() == T_Linker_RAD) {
if (t_id_linker() == Linker_radlink) {
T_Ok(g_last_exit_code == LNK_Error_IllegalSectionMerge);
}
// illegal merge with .rsrc
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /merge:.test=.rsrc entry.obj test.obj");
T_Ok(g_last_exit_code != 0);
if (t_id_linker() == T_Linker_RAD) {
if (t_id_linker() == Linker_radlink) {
T_Ok(g_last_exit_code == LNK_Error_IllegalSectionMerge);
}
@@ -1784,7 +1784,7 @@ TEST(abs_vs_common)
if (g_last_exit_code == 0) {
// TODO: validate that linker issues multiply defined symbol error
t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe common.obj abs.obj entry.obj");
if (t_id_linker() == T_Linker_RAD) {
if (t_id_linker() == Linker_radlink) {
T_Ok(g_last_exit_code == LNK_Error_MultiplyDefinedSymbol);
} else {
T_Ok(g_last_exit_code != 0);
@@ -2092,7 +2092,7 @@ TEST(undef_reloc_section)
T_Ok(t_write_file(str8_lit("sec_defn.obj"), sec_defn_obj));
t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe main.obj sec_defn.obj");
if (t_id_linker() == T_Linker_RAD) {
if (t_id_linker() == Linker_radlink) {
T_Ok(g_last_exit_code == LNK_Error_SectRefsDiscardedMemory);
} else {
T_Ok(g_last_exit_code != 0);
@@ -2420,7 +2420,7 @@ TEST(base_relocs)
// it is illegal to merge .reloc with other sections
t_invoke_linkerf("/subsystem:console /entry:my_entry /dynamicbase /largeaddressaware:no /out:a.exe /merge:.reloc=.rdata main.obj func.obj");
if (t_id_linker() == T_Linker_RAD) {
if (t_id_linker() == Linker_radlink) {
T_Ok(g_last_exit_code == LNK_Error_IllegalSectionMerge);
} else {
T_Ok(g_last_exit_code != 0);
@@ -2428,7 +2428,7 @@ TEST(base_relocs)
// the other way around is illegal too
t_invoke_linkerf("/subsystem:console /entry:my_entry /dynamicbase /largeaddressaware:no /out:a.exe /merge:.rdata=.reloc main.obj func.obj");
if (t_id_linker() == T_Linker_RAD) {
if (t_id_linker() == Linker_radlink) {
T_Ok(g_last_exit_code == LNK_Error_IllegalSectionMerge);
} else {
T_Ok(g_last_exit_code != 0);
@@ -2610,7 +2610,7 @@ TEST(import_export)
T_Ok(g_last_exit_code == 0);
// validate export table in export.dll
if (t_id_linker() == T_Linker_RAD) {
if (t_id_linker() == Linker_radlink) {
// validate export table in export.dll
{
String8 dll = t_read_file(arena, str8_lit("export.dll"));
@@ -2905,7 +2905,7 @@ TEST(comdat_no_duplicates)
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe a.obj b.obj entry.obj");
T_Ok(g_last_exit_code != 0);
if (t_id_linker() == T_Linker_RAD) { T_Ok(g_last_exit_code == LNK_Error_MultiplyDefinedSymbol); }
if (t_id_linker() == Linker_radlink) { T_Ok(g_last_exit_code == LNK_Error_MultiplyDefinedSymbol); }
t_invoke_linkerf("/subsystem:console /entry:entry /out:b.exe a.obj entry.obj");
T_Ok(g_last_exit_code == 0);
@@ -3001,7 +3001,7 @@ TEST(comdat_same_size)
t_invoke_linkerf("/subsystem:console /entry:entry /out:b.exe a.obj b.obj c.obj entry.obj");
T_Ok(g_last_exit_code != 0);
if (t_id_linker() == T_Linker_RAD) { T_Ok(g_last_exit_code == LNK_Error_MultiplyDefinedSymbol); }
if (t_id_linker() == Linker_radlink) { T_Ok(g_last_exit_code == LNK_Error_MultiplyDefinedSymbol); }
}
TEST(comdat_exact_match)
@@ -3313,7 +3313,7 @@ TEST(comdat_associative_loop)
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe loop.obj entry.obj");
T_Ok(g_last_exit_code != 0);
if (t_id_linker() == T_Linker_RAD) { T_Ok(g_last_exit_code == LNK_Error_AssociativeLoop); }
if (t_id_linker() == Linker_radlink) { T_Ok(g_last_exit_code == LNK_Error_AssociativeLoop); }
}
TEST(comdat_associative_non_comdat)
@@ -3430,7 +3430,7 @@ TEST(comdat_associative_out_of_bounds)
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj bad.obj");
T_Ok(g_last_exit_code != 0);
if (t_id_linker() == T_Linker_RAD) { T_Ok(g_last_exit_code == LNK_Error_IllData); }
if (t_id_linker() == Linker_radlink) { T_Ok(g_last_exit_code == LNK_Error_IllData); }
}
TEST(comdat_with_offset)
@@ -3790,7 +3790,7 @@ TEST(include)
// test unresolved include
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /include:ewq entry.obj");
T_Ok(g_last_exit_code != 0);
if (t_id_linker() == T_Linker_RAD) { T_Ok(g_last_exit_code == LNK_Error_UnresolvedSymbol); }
if (t_id_linker() == Linker_radlink) { T_Ok(g_last_exit_code == LNK_Error_UnresolvedSymbol); }
}
TEST(communal_var_vs_regular)
@@ -4811,7 +4811,7 @@ TEST(fail_if_mismatch)
T_Ok(t_write_file(str8_lit("a2.obj"), a2));
t_invoke_linkerf("entry.obj a1.obj a2.obj /entry:entry /subsystem:console /out:a2.exe");
if (t_id_linker() == T_Linker_RAD) T_Ok(g_last_exit_code == LNK_Error_FailIfMismatch);
if (t_id_linker() == Linker_radlink) T_Ok(g_last_exit_code == LNK_Error_FailIfMismatch);
else T_Ok(g_last_exit_code != 0);
// ------------------------------------------------------------
@@ -4829,14 +4829,14 @@ TEST(fail_if_mismatch)
T_Ok(t_write_file(str8_lit("conf_dirs.obj"), conf_dirs));
t_invoke_linkerf("entry.obj conf_dirs.obj /entry:entry /subsystem:console /out:conf_dirs.exe");
if (t_id_linker() == T_Linker_RAD) T_Ok(g_last_exit_code == LNK_Error_FailIfMismatch);
if (t_id_linker() == Linker_radlink) T_Ok(g_last_exit_code == LNK_Error_FailIfMismatch);
else T_Ok(g_last_exit_code != 0);
// ------------------------------------------------------------
// passing switch on command line
t_invoke_linkerf("entry.obj a1.obj /FAILIFMISMATCH:a=2 /out:cmddir.exe");
if (t_id_linker() == T_Linker_RAD) T_Ok(g_last_exit_code == LNK_Error_FailIfMismatch);
if (t_id_linker() == Linker_radlink) T_Ok(g_last_exit_code == LNK_Error_FailIfMismatch);
else T_Ok(g_last_exit_code != 0);
}
+11
View File
@@ -127,6 +127,17 @@ lnx_thread_entry_point(void *ptr)
return 0;
}
////////////////////////////////
//~ rjf: @per_os_impl Debugger Attachment Checking
internal B32
debugger_is_attached(void)
{
B32 result = 0;
// TODO(rjf)
return result;
}
////////////////////////////////
//~ rjf: @per_os_impl Platform Time Functions
@@ -1,6 +1,7 @@
#define T_Group "MD"
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
SKIP(md_tokenizer)
SkippedTest(md_tokenizer)
{
MD_TokenizeResult result;
@@ -126,5 +127,3 @@ SKIP(md_tokenizer)
T_Ok(result.tokens.v[1].flags & MD_TokenFlag_Identifier);
}
}
#undef T_Group
@@ -1,6 +1,207 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
// IPC Controller
typedef struct
{
B32 running;
U64 run_gen;
U64 ip;
Arch arch;
U64 vaddr_min;
U64 vaddr_max;
U64 ip_vaddr;
U64 sp_base;
U64 tls_root;
U64 tls_index;
U64 tls_offset;
U64 timestamp;
U64 exception_code;
U64 bp_flags;
String8 string;
OperatingSystem target_os;
U64 tls_model;
String8 stop_cause;
} T_DbgState;
typedef struct
{
String8 file_path;
TxtPt pt;
Rng1U64 voff_range;
} T_DbgLine;
typedef struct
{
U64 count;
T_DbgLine *v;
} T_DbgLineArray;
typedef struct
{
String8 expr;
String8 value;
String8 type;
String8 error;
} T_Eval;
////////////////////////////////
// Dbg Script
#define T_DbgScriptCmdKind_XList \
X(Breakpoint, "bp") \
X(ClearBreakpoints, "bp_clear") \
X(Halt, "halt") \
X(Run, "run") \
X(RunToLine, "run_to_line") \
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,
#define X(n,...) T_DbgScriptCmdKind_##n,
T_DbgScriptCmdKind_XList
#undef X
T_DbgScriptCmdKind_Count
} T_DbgScriptCmdKind;
#define T_DbgScriptDirectiveKind_XList \
X(Compile, "compile") \
X(Link, "link") \
X(Launch, "launch") \
X(Skip, "skip")
typedef enum
{
T_DbgScriptDirectiveKind_Null,
#define X(q,w) T_DbgScriptDirectiveKind_##q,
T_DbgScriptDirectiveKind_XList
#undef X
T_DbgScriptDirectiveKind_Count,
} T_DbgScriptDirectiveKind;
typedef struct T_DbgScriptFile
{
struct T_DbgScriptFile *next;
String8 path;
String8 source;
TxtPt pt;
} T_DbgScriptFile;
typedef struct
{
U64 count;
T_DbgScriptFile *first;
T_DbgScriptFile *last;
} T_DbgScriptFileList;
typedef struct T_DbgScriptCmd
{
struct T_DbgScriptCmd *next;
T_DbgScriptCmdKind kind;
TxtPt pt;
S64 at_delta;
} T_DbgScriptCmd;
typedef struct T_DbgScriptProgram
{
TxtPt pt;
U64 order;
OperatingSystem os;
T_DbgScriptFile *file;
U64 count;
T_DbgScriptCmd *first;
T_DbgScriptCmd *last;
struct T_DbgScriptProgram *next;
} T_DbgScriptProgram;
typedef struct
{
U64 count;
T_DbgScriptProgram *first;
T_DbgScriptProgram *last;
} T_DbgScriptProgramList;
typedef struct T_DbgScriptDirective
{
struct T_DbgScriptDirective *next;
T_DbgScriptDirectiveKind kind;
TxtPt pt;
String8 args;
union {
struct {
Compiler cc;
} compile;
};
} T_DbgScriptDirective;
typedef struct
{
U64 count;
T_DbgScriptDirective *first;
T_DbgScriptDirective *last;
} T_DbgScriptDirectiveList;
typedef struct
{
String8 file_path;
T_DbgScriptDirectiveList directives[OperatingSystem_COUNT][T_DbgScriptDirectiveKind_Count];
T_DbgScriptFileList files;
U64 program_count;
T_DbgScriptProgram **programs;
B32 skip;
} T_DbgScript;
////////////////////////////////
// IPC Controller
// error helper
internal void t_errorf_md(String8 file_name, String8 source, MD_Node *n, char *fmt, ...);
// reply parse helpers
internal B32 t_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out);
internal B32 t_ipc_parse_u32(MD_Node *node, String8 child_name, U32 *out);
internal B32 t_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out);
internal B32 t_ipc_parse_b32(MD_Node *node, String8 child_name, B32 *out);
#define t_ipc_parse_int(n, c, ptr) t_ipc_parse_int_(n, c, sizeof(*ptr), ptr)
// debugger commands
internal B32 t_dbg_send_cmd(String8 cmd, U64 timeout_us, Arena *reply_arena, MD_ParseResult *reply_out);
internal B32 t_dbg_send_cmdf(U64 timeout_us, Arena *reply_arena, MD_ParseResult *reply_out, char *fmt, ...);
internal T_DbgState * t_dbg_state(Arena *arena, U64 timeout_us);
internal B32 t_dbg_src_line(Arena *arena, U64 vaddr, T_DbgLineArray *lines_out, U64 timeout_us);
internal String8 t_dbg_value_from_expr(Arena *arena, String8 expr);
internal String8 t_dbg_value_from_exprf(Arena *arena, char *fmt, ...);
internal B32 t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us);
internal B32 t_dbg_ping(U64 timeout_us);
internal B32 t_dbg_bp_add_line(String8 file, U64 line);
internal B32 t_dbg_bp_add_func(String8 func_name);
internal B32 t_dbg_bp_add_addr(U64 addr);
internal B32 t_dbg_launch(String8 cmdline, U64 timeout_us);
internal B32 t_dbg_eval(Arena *arena, String8 expr, T_Eval *eval_out);
////////////////////////////////
// Dbg Script
internal String8 t_string_from_dbg_script_cmd_kind(T_DbgScriptCmdKind v);
internal T_DbgScriptCmdKind t_dbg_script_cmd_kind_from_string(String8 cmd);
internal B32 t_dbg_parse_script(Arena *arena, String8 file_path, String8 source, T_DbgScript *script_out);
internal B32 t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us);
internal void t_dbg_register_script_tests(Arena *arena, String8 folder_path);
#define T_Dbg_DefaultTimeout TIMEOUT_SEC(5)
extern B32 g_stop_on_first_fail_or_crash;
@@ -531,11 +732,11 @@ t_dbg_parse_script(Arena *arena, String8 file_path, String8 source, T_DbgScript
String8 msg_kind_string = {0};
switch(msg->kind)
{
default:{}break;
case MD_MsgKind_Note: {msg_kind_string = str8_lit("note");}break;
case MD_MsgKind_Warning: {msg_kind_string = str8_lit("warning");}break;
case MD_MsgKind_Error: {msg_kind_string = str8_lit("error");}break;
case MD_MsgKind_FatalError: {msg_kind_string = str8_lit("fatal error");}break;
default:{}break;
case MD_MsgKind_Note: {msg_kind_string = str8_lit("note");}break;
case MD_MsgKind_Warning: {msg_kind_string = str8_lit("warning");}break;
case MD_MsgKind_Error: {msg_kind_string = str8_lit("error");}break;
case MD_MsgKind_FatalError: {msg_kind_string = str8_lit("fatal error");}break;
}
TxtPt pt = mg_txt_pt_from_string_off(source, msg->node->src_offset);
String8 loc = push_str8f(scratch.arena, "%S:%I64d:%I64d", file_path, pt.line, pt.column);
@@ -570,9 +771,9 @@ t_dbg_parse_script(Arena *arena, String8 file_path, String8 source, T_DbgScript
T_DbgScriptDirectiveKind kind;
String8 string;
} dir_string_map[] = {
#define X(q,w) { T_DbgScriptDirectiveKind_##q, str8_lit(w) },
#define X(q,w) { T_DbgScriptDirectiveKind_##q, str8_lit(w) },
T_DbgScriptDirectiveKind_XList
#undef X
#undef X
};
// string -> directive
@@ -608,8 +809,8 @@ t_dbg_parse_script(Arena *arena, String8 file_path, String8 source, T_DbgScript
goto exit;
}
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; }
if (str8_matchi(cc->string, str8_lit("clang"))) { dir->compile.cc = Compiler_clang; }
else if (str8_matchi(cc->string, str8_lit("cl"))) { dir->compile.cc = Compiler_msvc; }
else {
t_errorf_md(file_path, source, cc, "unknown compiler name: \"%S\"\n", sub_field->string);
goto exit;
@@ -737,7 +938,7 @@ t_dbg_parse_script(Arena *arena, String8 file_path, String8 source, T_DbgScript
// find order number nodes
U64 order = 0;
if ( ! try_u64_from_str8_c_rules(n->string, &order)) {
continue;
continue;
}
// correlate MD node to the script file
@@ -877,7 +1078,7 @@ t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us)
// match expected vs current debugger locations
for EachIndex(i, lines.count) {
B32 mismatch = lines.v[i].pt.line != 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) {
t_errorf("ERROR: %S:%llu: location check did not pass:\n", script->file_path, cmd->pt.line);
t_errorf(" Expected: %S:%llu\n", program->file->path, at_line_u64);
@@ -914,7 +1115,7 @@ T_RunSig(dbg_script_runner)
// source -> script
T_DbgScript script = {0};
if ( ! t_dbg_parse_script(arena, user_data, source, &script)) {
result_out->status = T_RunStatus_Fail;
result_out->status = TestStatus_Fail;
goto exit;
}
@@ -934,36 +1135,36 @@ T_RunSig(dbg_script_runner)
// run compilers
for EachNode(directive, T_DbgScriptDirective, script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Compile].first) {
T_Compiler compiler = directive->compile.cc;
Compiler compiler = directive->compile.cc;
// pick default compiler if none selected
if (directive->compile.cc == T_Compiler_Null) {
if (directive->compile.cc == Compiler_Null) {
switch (OperatingSystem_CURRENT) {
case OperatingSystem_Windows: { compiler = T_Compiler_Cl; } break;
case OperatingSystem_Linux: { compiler = T_Compiler_Clang; } break;
case OperatingSystem_Windows: { compiler = Compiler_msvc; } break;
case OperatingSystem_Linux: { compiler = Compiler_clang; } break;
}
}
// get compiler path
String8 compiler_path = {0};
switch (compiler) {
case T_Compiler_Null: break;
case T_Compiler_Cl: compiler_path = t_cl_path(); break;
case T_Compiler_Clang: compiler_path = t_clang_path(); break;
case T_Compiler_Gcc: compiler_path = t_gcc_path(); break;
case Compiler_Null: break;
case Compiler_msvc: compiler_path = t_cl_path(); break;
case Compiler_clang: compiler_path = t_clang_path(); break;
case Compiler_gcc: compiler_path = t_gcc_path(); break;
}
// 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 (compiler == Compiler_msvc) { 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 (compiler == Compiler_msvc) { 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->pt.line, g_errors);
@@ -987,15 +1188,9 @@ T_RunSig(dbg_script_runner)
}
}
// if test does not have any directive -> skip
U64 total_directive_count = 0;
for EachIndex(i, ArrayCount(script.directives[OperatingSystem_CURRENT])) {
total_directive_count += script.directives[OperatingSystem_CURRENT][i].count;
}
// is skip flag set? -> exit
if (g_build_only || total_directive_count == 0 || script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Skip].count) {
result_out->status = T_RunStatus_Skip;
if (g_build_only || script.directives[OperatingSystem_CURRENT][T_DbgScriptDirectiveKind_Skip].count) {
result_out->status = TestStatus_Skip;
goto exit;
}
+41 -53
View File
@@ -72,31 +72,6 @@ t_test_group_from_name(Arena *arena, String8 pattern)
////////////////////////////////
internal char *
t_string_from_result(T_RunStatus v)
{
switch (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)
{
@@ -108,14 +83,14 @@ t_break_if_debugger_present(void)
#endif
}
internal T_Linker
internal Linker
t_id_linker(void)
{
String8 name = str8_chop_last_dot(str8_skip_last_slash(g_linker_path));
if (str8_match(name, str8_lit("radlink"), StringMatchFlag_CaseInsensitive)) { return T_Linker_RAD; }
if (str8_match(name, str8_lit("link"), StringMatchFlag_CaseInsensitive)) { return T_Linker_MSVC; }
if (str8_match(name, str8_lit("lld-link"), StringMatchFlag_CaseInsensitive)) { return T_Linker_LLVM; }
return T_Linker_Null;
if (str8_match(name, str8_lit("radlink"), StringMatchFlag_CaseInsensitive)) { return Linker_radlink; }
if (str8_match(name, str8_lit("link"), StringMatchFlag_CaseInsensitive)) { return Linker_msvc; }
if (str8_match(name, str8_lit("lld-link"), StringMatchFlag_CaseInsensitive)) { return Linker_lld; }
return Linker_Null;
}
internal B32
@@ -214,17 +189,17 @@ t_run_caller(void *raw_ctx)
g_is_first_print = 1;
T_RunCtx *ctx = raw_ctx;
ctx->result.status = T_RunStatus_Pass;
ctx->result.status = TestStatus_Pass;
String8List test_out = {0};
if (ctx->test->skip) {
ctx->result.status = T_RunStatus_Skip;
ctx->result.status = TestStatus_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 == TestStatus_Fail || ctx->result.status == TestStatus_Crash) {
for EachNode(n, String8Node, test_out.first) {
t_errorf("%S", n->string);
}
@@ -239,13 +214,13 @@ t_run_caller(void *raw_ctx)
scratch_end(scratch);
}
internal T_RunResult
internal TestResult
t_run(T_Test *test, String8 user_data)
{
T_RunCtx ctx = { .test = test, .user_data = user_data, .result.status = T_RunStatus_Fail };
T_RunCtx ctx = { .test = test, .user_data = user_data, .result.status = TestStatus_Fail };
t_run_caller(&ctx);
if (ctx.result.status == T_RunStatus_Fail || ctx.result.status == T_RunStatus_Crash) {
if (ctx.result.status == TestStatus_Fail || ctx.result.status == TestStatus_Crash) {
if (g_output.size > 0 || g_errors.size > 0) {
t_errorf("Last captured output:\n");
if (g_output.size) { t_errorf("%S\n", g_output); }
@@ -1104,6 +1079,8 @@ t_help(void)
fprintf(stderr, " torture +* Force-run all tests\n");
}
internal void t_dbg_register_script_tests(Arena *arena, String8 folder_path);
internal void
t_entry_point(CmdLine *cmdline)
{
@@ -1127,7 +1104,7 @@ 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) {
t_help();
goto exit;
@@ -1227,9 +1204,9 @@ t_entry_point(CmdLine *cmdline)
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;
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;
}
// append test when not in skipping mode
@@ -1310,7 +1287,7 @@ t_entry_point(CmdLine *cmdline)
max_group_size = Max(max_group_size, t_group_from_test_idx(test_idx).size);
}
U64 run_counters[T_RunStatus_Count] = {0};
U64 run_counters[TestStatus_COUNT] = {0};
U64 max_digit_count = count_digits_u64(target_indices.count, 10);
U64 total_time_start = now_time_us();
@@ -1353,16 +1330,27 @@ t_entry_point(CmdLine *cmdline)
// run test
U64 run_start_time = now_time_us();
T_RunResult result = t_run(test, test->user_data);
TestResult result = t_run(test, test->user_data);
U64 run_end_time = now_time_us();
// 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));
// rjf: map status -> color / string
char *status_name_cstr = 0;
char *color_cstr = 0;
switch(result.status)
{
default:
case TestStatus_Pass: {status_name_cstr = "PASS"; color_cstr = T_GREEN;}break;
case TestStatus_Fail: {status_name_cstr = "FAIL"; color_cstr = T_RED;}break;
case TestStatus_Crash:{status_name_cstr = "CRASH"; color_cstr = T_RED;}break;
}
if (result.status == T_RunStatus_Pass) {
// print run status
fprintf(stdout, "%s%s" T_RESET, color_cstr, status_name_cstr);
if (result.status == TestStatus_Pass) {
U64 d = run_end_time - run_start_time;
DateTime t = date_time_from_micro_seconds(d);
String8 s = string_from_elapsed_time(scratch.arena, t);
@@ -1387,15 +1375,15 @@ t_entry_point(CmdLine *cmdline)
}
fprintf(stdout, "\n");
if (result.status == T_RunStatus_Fail) {
if (result.status == TestStatus_Fail) {
fprintf(stdout, " ERROR: %s:%d: condition: \"%s\"\n", result.fail_file, result.fail_line, result.fail_cond);
}
if (result.status == T_RunStatus_Fail || result.status == T_RunStatus_Crash) {
if (result.status == TestStatus_Fail || result.status == TestStatus_Crash) {
if (g_stop_on_first_fail_or_crash) { goto exit; }
}
if (result.status == T_RunStatus_Skip) {
if (result.status == TestStatus_Skip) {
u64_list_push(scratch.arena, &skipped_tests, target_idx);
}
}
@@ -1407,10 +1395,10 @@ t_entry_point(CmdLine *cmdline)
fprintf(stderr, "\n");
PrintHeader("Summary");
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, " Passed %llu\n", (unsigned long long)run_counters[TestStatus_Pass]);
fprintf(stderr, " Failed %llu\n", (unsigned long long)run_counters[TestStatus_Fail]);
fprintf(stderr, " Crashed %llu\n", (unsigned long long)run_counters[TestStatus_Crash]);
fprintf(stderr, " Skipped %llu\n", (unsigned long long)run_counters[TestStatus_Skip]);
fprintf(stderr, " Time %.*s\n", str8_varg(total_time_str));
U64 slow_count = 0;
@@ -1444,7 +1432,7 @@ t_entry_point(CmdLine *cmdline)
}
}
exit_code = run_counters[T_RunStatus_Fail] + run_counters[T_RunStatus_Crash];
exit_code = run_counters[TestStatus_Fail] + run_counters[TestStatus_Crash];
exit:;
}
+20 -63
View File
@@ -11,31 +11,8 @@
#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
{
#define X(n,...) T_RunStatus_##n,
T_Run_XList
#undef X
T_RunStatus_Count
} T_RunStatus;
typedef struct
{
T_RunStatus status;
char *fail_file;
int fail_line;
char *fail_cond;
} T_RunResult;
#define T_RunSig(name) void t_##name(Arena *arena, String8 user_data, T_RunResult *result_out, String8List *test_out)
typedef void (*T_Run)(Arena *arena, String8 user_data, T_RunResult *result_out, String8List *test_out);
#define T_RunSig(name) void t_##name(Arena *arena, String8 user_data, TestResult *result_out, String8List *test_out)
typedef void (*T_Run)(Arena *arena, String8 user_data, TestResult *result_out, String8List *test_out);
typedef struct
{
@@ -50,26 +27,10 @@ typedef struct
typedef struct
{
T_Test *test;
String8 user_data;
T_RunResult result;
String8 user_data;
TestResult result;
} T_RunCtx;
typedef enum
{
T_Compiler_Null,
T_Compiler_Cl,
T_Compiler_Clang,
T_Compiler_Gcc,
} T_Compiler;
typedef enum
{
T_Linker_Null,
T_Linker_RAD,
T_Linker_MSVC,
T_Linker_LLVM
} T_Linker;
extern U64 g_torture_test_count;
extern T_Test **g_torture_tests;
extern T_Test g_torture_tests_[0xffffff];
@@ -77,34 +38,30 @@ extern T_Test g_torture_tests_[0xffffff];
internal void t_break_if_debugger_present(void);
#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){ f, Stringify(name), l, &t_##name, skip }; \
}
T_RunSig(name); \
__VA_ARGS__ void t_add_test_##name(void) \
{ \
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, 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)))
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, skip) T_AddTest(name, __FILE__, __LINE__, skip, __attribute__((constructor)))
#endif
#define TEST(name) \
TEST_(name, 0) \
T_RunSig(name)
TEST_(name, 0) \
T_RunSig(name)
#define SKIP(name) \
TEST_(name, 1) \
T_RunSig(name)
TEST_(name, 1) \
T_RunSig(name)
#define T_Ok(c) do { if (!(c)) { \
*result_out = (T_RunResult){ .fail_file = __FILE__, .fail_line = __LINE__, .fail_cond = Stringify(c) }; \
t_break_if_debugger_present(); \
return; \
} } while(0)
#define T_Ok(c) TestCheck(c)
#define T_MatchLinef(out, ...) T_Ok(t_match_linef(out, __VA_ARGS__))
#define t_outf(...) str8_list_pushf(arena, test_out, ## __VA_ARGS__)
@@ -129,9 +86,9 @@ internal B32 t_delete_file(String8 name);
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_Test *test, String8 user_data);
internal void t_run_caller(void *raw_ctx);
internal void t_run_fail_handler(void *raw_ctx);
internal TestResult t_run(T_Test *test, String8 user_data);
// tools
internal String8 t_radbin_path(void);
-205
View File
@@ -1,205 +0,0 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#pragma once
////////////////////////////////
// IPC Controller
typedef struct
{
B32 running;
U64 run_gen;
U64 ip;
Arch arch;
U64 vaddr_min;
U64 vaddr_max;
U64 ip_vaddr;
U64 sp_base;
U64 tls_root;
U64 tls_index;
U64 tls_offset;
U64 timestamp;
U64 exception_code;
U64 bp_flags;
String8 string;
OperatingSystem target_os;
U64 tls_model;
String8 stop_cause;
} T_DbgState;
typedef struct
{
String8 file_path;
TxtPt pt;
Rng1U64 voff_range;
} T_DbgLine;
typedef struct
{
U64 count;
T_DbgLine *v;
} T_DbgLineArray;
typedef struct
{
String8 expr;
String8 value;
String8 type;
String8 error;
} T_Eval;
////////////////////////////////
// Dbg Script
#define T_DbgScriptCmdKind_XList \
X(Breakpoint, "bp") \
X(ClearBreakpoints, "bp_clear") \
X(Halt, "halt") \
X(Run, "run") \
X(RunToLine, "run_to_line") \
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,
#define X(n,...) T_DbgScriptCmdKind_##n,
T_DbgScriptCmdKind_XList
#undef X
T_DbgScriptCmdKind_Count
} T_DbgScriptCmdKind;
#define T_DbgScriptDirectiveKind_XList \
X(Compile, "compile") \
X(Link, "link") \
X(Launch, "launch") \
X(Skip, "skip")
typedef enum
{
T_DbgScriptDirectiveKind_Null,
#define X(q,w) T_DbgScriptDirectiveKind_##q,
T_DbgScriptDirectiveKind_XList
#undef X
T_DbgScriptDirectiveKind_Count,
} T_DbgScriptDirectiveKind;
typedef struct T_DbgScriptFile
{
struct T_DbgScriptFile *next;
String8 path;
String8 source;
TxtPt pt;
} T_DbgScriptFile;
typedef struct
{
U64 count;
T_DbgScriptFile *first;
T_DbgScriptFile *last;
} T_DbgScriptFileList;
typedef struct T_DbgScriptCmd
{
struct T_DbgScriptCmd *next;
T_DbgScriptCmdKind kind;
TxtPt pt;
S64 at_delta;
} T_DbgScriptCmd;
typedef struct T_DbgScriptProgram
{
TxtPt pt;
U64 order;
OperatingSystem os;
T_DbgScriptFile *file;
U64 count;
T_DbgScriptCmd *first;
T_DbgScriptCmd *last;
struct T_DbgScriptProgram *next;
} T_DbgScriptProgram;
typedef struct
{
U64 count;
T_DbgScriptProgram *first;
T_DbgScriptProgram *last;
} T_DbgScriptProgramList;
typedef struct T_DbgScriptDirective
{
struct T_DbgScriptDirective *next;
T_DbgScriptDirectiveKind kind;
TxtPt pt;
String8 args;
union {
struct {
T_Compiler cc;
} compile;
};
} T_DbgScriptDirective;
typedef struct
{
U64 count;
T_DbgScriptDirective *first;
T_DbgScriptDirective *last;
} T_DbgScriptDirectiveList;
typedef struct
{
String8 file_path;
T_DbgScriptDirectiveList directives[OperatingSystem_COUNT][T_DbgScriptDirectiveKind_Count];
T_DbgScriptFileList files;
U64 program_count;
T_DbgScriptProgram **programs;
B32 skip;
} T_DbgScript;
////////////////////////////////
// IPC Controller
// error helper
internal void t_errorf_md(String8 file_name, String8 source, MD_Node *n, char *fmt, ...);
// reply parse helpers
internal B32 t_ipc_parse_string(MD_Node *node, String8 child_name, String8 *out);
internal B32 t_ipc_parse_u32(MD_Node *node, String8 child_name, U32 *out);
internal B32 t_ipc_parse_int_(MD_Node *node, String8 child_name, U64 out_size, void *out);
internal B32 t_ipc_parse_b32(MD_Node *node, String8 child_name, B32 *out);
#define t_ipc_parse_int(n, c, ptr) t_ipc_parse_int_(n, c, sizeof(*ptr), ptr)
// debugger commands
internal B32 t_dbg_send_cmd(String8 cmd, U64 timeout_us, Arena *reply_arena, MD_ParseResult *reply_out);
internal B32 t_dbg_send_cmdf(U64 timeout_us, Arena *reply_arena, MD_ParseResult *reply_out, char *fmt, ...);
internal T_DbgState * t_dbg_state(Arena *arena, U64 timeout_us);
internal B32 t_dbg_src_line(Arena *arena, U64 vaddr, T_DbgLineArray *lines_out, U64 timeout_us);
internal String8 t_dbg_value_from_expr(Arena *arena, String8 expr);
internal String8 t_dbg_value_from_exprf(Arena *arena, char *fmt, ...);
internal B32 t_dbg_send_cmd_and_wait_stop(String8 cmd, U64 timeout_us);
internal B32 t_dbg_ping(U64 timeout_us);
internal B32 t_dbg_bp_add_line(String8 file, U64 line);
internal B32 t_dbg_bp_add_func(String8 func_name);
internal B32 t_dbg_bp_add_addr(U64 addr);
internal B32 t_dbg_launch(String8 cmdline, U64 timeout_us);
internal B32 t_dbg_eval(Arena *arena, String8 expr, T_Eval *eval_out);
////////////////////////////////
// Dbg Script
internal String8 t_string_from_dbg_script_cmd_kind(T_DbgScriptCmdKind v);
internal T_DbgScriptCmdKind t_dbg_script_cmd_kind_from_string(String8 cmd);
internal B32 t_dbg_parse_script(Arena *arena, String8 file_path, String8 source, T_DbgScript *script_out);
internal B32 t_dbg_script_invoke(T_DbgScript *script, U64 timeout_us);
internal void t_dbg_register_script_tests(Arena *arena, String8 folder_path);
+9 -10
View File
@@ -6,6 +6,7 @@
#define BUILD_TITLE "TORTURE"
#define BUILD_TESTS 1
#define BUILD_CONSOLE_INTERFACE 1
#define OS_FEATURE_GRAPHICAL 1
#define DMN_INIT_MANUAL 1
@@ -94,8 +95,6 @@
#include "linker/lnk_log.h"
#include "linker/lnk_debug_helper.h"
#include "torture.h"
#include "torture_radlink.h"
#include "torture_dbg.h"
#include "base/base_inc.c"
#include "x64/x64.c"
@@ -167,15 +166,15 @@
#include "linker/pdb_ext/pdb_helpers.c"
#include "linker/pdb_ext/pdb_builder.c"
#include "linker/lnk_debug_helper.c"
#include "torture.c"
#include "torture_base.c"
#include "torture_md.c"
#include "torture_radlink.c"
#include "torture_dwarf.c"
#include "torture_d2r.c"
#include "torture_p2r.c"
#include "torture_dbg.c"
#include "base/tests/base_tests.c"
#include "mdesk/tests/mdesk_tests.c"
#include "linker/tests/linker_tests.c"
#include "dwarf/tests/dwarf_tests.c"
#include "rdi_from_dwarf/tests/rdi_from_dwarf_tests.c"
#include "rdi_from_pdb/tests/rdi_from_pdb_tests.c"
#include "raddbg/tests/raddbg_tests.c"
internal B32 frame(void) { return 0; }
-28
View File
@@ -1,28 +0,0 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#pragma once
////////////////////////////////
typedef enum
{
T_MsvcLinkExitCode_UnresolvedExternals = 1120,
T_MsvcLinkExitCode_CorruptOrInvalidSymbolTable = 1235,
T_MsvcLinkExitCode_SectionsFoundWithDifferentAttributes = 4078,
} T_MsvcLinkExitCode;
////////////////////////////////
internal T_Linker t_id_linker(void);
internal COFF_ObjSection * t_push_text_section(COFF_ObjWriter *obj_writer, String8 data);
internal COFF_ObjSection * t_push_data_section(COFF_ObjWriter *obj_writer, String8 data);
internal COFF_ObjSection * t_push_rdata_section(COFF_ObjWriter *obj_writer, String8 data);
internal String8 t_make_entry_obj(Arena *arena);
internal String8 t_make_sec_defn_obj(Arena *arena, String8 payload);
internal String8 t_make_obj_with_directive(Arena *arena, String8 directive);
internal B32 t_write_entry_obj(void);
+10
View File
@@ -156,6 +156,16 @@ w32_thread_entry_point(void *ptr)
return 0;
}
////////////////////////////////
//~ rjf: @per_os_impl Debugger Attachment Checking
internal B32
debugger_is_attached(void)
{
B32 result = IsDebuggerPresent();
return result;
}
////////////////////////////////
//~ rjf: @per_os_impl Platform Time Functions