setting up some tests...

This commit is contained in:
ed committed 2026-10-04 18:10:34 -04:00
1 parent 1a60fd54fc
commit 4140e7e237
4 files changed
+202

No files matched your search

+1
View File
@@ -29,6 +29,7 @@ args:
parser_bounds
lexer_failures
parse_body_messages
dogfood_parse
clang
msvc : By default this project builds with clang, specifying msvc will build with MSVC.
debug
+27
View File
@@ -79,6 +79,7 @@ Push-Location $path_root
[bool] $parser_bounds = $false
[bool] $lexer_failures = $false
[bool] $parse_body_messages = $false
[bool] $dogfood_parse = $false
[array] $vendors = @( "clang", "msvc" )
@@ -101,6 +102,7 @@ if ( $args ) { $args | ForEach-Object {
"parser_bounds" { $parser_bounds = $true }
"lexer_failures" { $lexer_failures = $true }
"parse_body_messages" { $parse_body_messages = $true }
"dogfood_parse" { $dogfood_parse = $true }
}
}}
#endregion Arguments
@@ -140,6 +142,7 @@ $cannot_build = $cannot_build -and $test -eq $false
$cannot_build = $cannot_build -and $parser_bounds -eq $false
$cannot_build = $cannot_build -and $lexer_failures -eq $false
$cannot_build = $cannot_build -and $parse_body_messages -eq $false
$cannot_build = $cannot_build -and $dogfood_parse -eq $false
if ( $cannot_build ) {
Stop-stage "No build target specified"
}
@@ -522,6 +525,30 @@ if ($parse_body_messages)
$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable
invoke-stageTool -stage "parse_body_messages" -compiled $result -executable $executable -path_work $path_probe
}
if ($dogfood_parse)
{
$path_probe = join-path $path_test dogfood_parse
$path_build = join-path $path_probe build
if ( -not(Test-Path($path_build) )) {
new-item -ItemType Directory -Path $path_build | Out-Null
}
$includes = @( $path_base )
$unit = join-path $path_probe "test.cpp"
$executable = join-path $path_build "dogfood_parse.exe"
$compiler_args = @()
$compiler_args += ( $flag_define + 'GEN_TIME' )
$compiler_args += $flag_cpp17
$linker_args = @(
$flag_link_win_subsystem_console
)
$result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable
invoke-stageTool -stage "dogfood_parse" -compiled $result -executable $executable -path_work $path_probe
}
#endregion Building
pop-location # $path_root
+4
View File
@@ -22,6 +22,7 @@ $path_test_gen = Join-Path $path_test gen
$path_parser_bounds_build = Join-Path $path_test "parser_bounds\build"
$path_lexer_failures_build = Join-Path $path_test "lexer_failures\build"
$path_parse_body_messages_build = Join-Path $path_test "parse_body_messages\build"
$path_dogfood_parse_build = Join-Path $path_test "dogfood_parse\build"
$path_x64 = Join-Path $path_root x64
$path_release = Join-Path $path_root release
@@ -70,6 +71,9 @@ if ( Test-Path $path_lexer_failures_build ) {
if ( Test-Path $path_parse_body_messages_build ) {
Remove-Item $path_parse_body_messages_build -Recurse -Verbose
}
if ( Test-Path $path_dogfood_parse_build ) {
Remove-Item $path_dogfood_parse_build -Recurse -Verbose
}
if ( Test-Path $path_x64) {
Remove-Item $path_x64 -Recurse -Verbose
}
+170
View File
@@ -0,0 +1,170 @@
#define GEN_TIME
#define GEN_DEFINE_LIBRARY_CODE_CONSTANTS
#define GEN_ENFORCE_STRONG_CODE_TYPES
#include "gen.cpp"
using namespace gen;
global int g_failures = 0;
internal void expect(int condition, Str label) {
if (condition == false) { log_fmt("FAIL %S\n", label); ++g_failures; }
}
internal Str body_text(CodeBody body) {
return strbuilder_to_str(code_to_strbuilder(cast(Code, body)));
}
internal b32 body_has_variable(CodeBody body, Str name) { for (Code member : body) {
if (member->Type == CT_Variable && member->Name.is_equal(name)) return true;
if ((member->Type == CT_Struct || member->Type == CT_Union) && member->Body.ast != nullptr) {
if (body_has_variable(cast(CodeBody, member->Body), name))
return true;
}
} return false; }
internal Str bad_at(Str good) {
StrBuilder built = strbuilder_make_reserve(_ctx->Allocator_Temp, good.Len + 2);
strbuilder_append_str(& built, good);
strbuilder_append_str(& built, txt("\n@"));
return strbuilder_to_str(built);
}
internal void expect_context_good(Context* ctx, Str label) {
Str def = txt("struct Context\n{\n\tContext* parent;\n};\n\nContext* make_context();\n");
CodeBody body = parse_global_body(def);
Code found = InvalidCode;
for (Code code : body) if (code->Type == CT_Struct && code->Name.is_equal(txt("Context")))
found = code;
expect(found.ast != nullptr, label); if (found.ast != nullptr) {
Code member = InvalidCode;
for (Code code : cast(CodeBody, found->Body)) {
if (code->Type == CT_Variable && code->Name.is_equal(txt("parent")))
member = code;
}
expect(member.ast != nullptr, label);
}
expect(ctx->parse_info.messages == nullptr, label);
expect(ctx->parse_info.lexed.messages == nullptr, label);
}
internal void expect_context_bad(Str label) {
Context ctx = {}; init(& ctx);
Str good = txt("struct Context\n{\n\tContext* parent;\n};\n\nContext* make_context();\n");
CodeBody body = parse_global_body(bad_at(good));
Str text = body_text(body);
expect(str_contains(text, txt("Context")), label);
expect(str_contains(text, txt("parent")), label);
expect(ctx.parse_info.lexed.messages != nullptr, label);
if (ctx.parse_info.lexed.messages != nullptr) expect(str_contains(ctx.parse_info.lexed.messages->content, txt("Failed to lex token")), label);
expect_context_good(&ctx, txt("context-reuse"));
deinit(& ctx);
}
internal Str vec_def() {
Str type = txt("Vec2f");
Str unit_type = txt("f32");
return token_fmt("type", type, "unit_type", unit_type, stringize(
struct <type>
{
union {
struct {
<unit_type> x;
<unit_type> y;
};
<unit_type> Basis[2];
};
};
));
}
internal void expect_vec_good(Context* ctx, Str label) {
Str def = vec_def();
expect(str_contains(def, txt("struct Vec2f")), txt("vec-def-struct"));
expect(str_contains(def, txt("union")), txt("vec-def-union"));
expect(str_contains(def, txt("f32 x;")), txt("vec-def-x"));
expect(str_contains(def, txt("f32 y;")), txt("vec-def-y"));
expect(str_contains(def, txt("f32 Basis[2]")), txt("vec-def-Basis"));
CodeBody body = parse_global_body(def);
expect(body_has_variable(body, txt("x")), txt("vec-ast-x"));
expect(body_has_variable(body, txt("y")), txt("vec-ast-y"));
Str text = body_text(body);
expect(str_contains(text, txt("Vec2f")), txt("vec-name"));
expect(str_contains(text, txt("x")), txt("vec-x"));
expect(str_contains(text, txt("y")), txt("vec-y"));
expect(ctx->parse_info.messages == nullptr, txt("vec-parser-messages"));
expect(ctx->parse_info.lexed.messages == nullptr, txt("vec-lexer-messages"));
}
internal void expect_vec_bad(Str label) {
Context ctx = {}; init(& ctx);
CodeBody body = parse_global_body(bad_at(vec_def()));
Str text = body_text(body);
expect(str_contains(text, txt("Vec2f")), label);
expect(ctx.parse_info.lexed.messages != nullptr, label);
if (ctx.parse_info.lexed.messages != nullptr) expect(str_contains(ctx.parse_info.lexed.messages->content, txt("Failed to lex token")), label);
expect_vec_good(& ctx, txt("vec-reuse"));
deinit(& ctx);
}
internal Str unreal_def() { return txt("UCLASS()\nclass UGasaFixture\n{\n\tUPROPERTY()\n\tint Health;\n};\n"); }
internal void expect_unreal_good(Context* ctx, Str label) {
CodeBody body = parse_global_body(unreal_def());
Code found = InvalidCode;
for (Code code : body) if (code->Type == CT_Class && code->Name.is_equal(txt("UGasaFixture")))
found = code;
expect(found.ast != nullptr, label); if (found.ast != nullptr) {
b32 saw_prop = false;
b32 saw_health = false;
for (Code member : cast(CodeBody, found->Body)) {
if ( member->Type == CT_Untyped && member->Name.starts_with(txt("UPROPERTY"))) saw_prop = true;
if (saw_prop && member->Type == CT_Variable && member->Name.is_equal(txt("Health"))) saw_health = true;
}
expect(saw_prop, label);
expect(saw_health, label);
}
expect(ctx->parse_info.messages == nullptr, label);
expect(ctx->parse_info.lexed.messages == nullptr, label);
}
internal void expect_unreal_bad(Str label) {
Context ctx = {}; init(& ctx);
register_macros(args(
(Macro { txt("UCLASS"), MT_Statement, MF_Functional }),
(Macro { txt("UPROPERTY"), MT_Statement, MF_Functional })
));
CodeBody body = parse_global_body(bad_at(unreal_def()));
Str text = body_text(body);
expect(str_contains(text, txt("UGasaFixture")), label);
expect(ctx.parse_info.lexed.messages != nullptr, label);
if (ctx.parse_info.lexed.messages != nullptr) expect(str_contains(ctx.parse_info.lexed.messages->content, txt("Failed to lex token")), label);
expect_unreal_good(&ctx, txt("unreal-reuse"));
deinit(& ctx);
}
int main()
{
Context ctx = {}; init(& ctx);
expect_context_good(&ctx, txt("context"));
deinit(& ctx);
expect_context_bad(txt("context-at"));
init(& ctx);
expect_vec_good(& ctx, txt("vec"));
deinit(& ctx);
expect_vec_bad(txt("vec-at"));
init(& ctx);
register_macros(args(
(Macro { txt("UCLASS"), MT_Statement, MF_Functional }),
(Macro { txt("UPROPERTY"), MT_Statement, MF_Functional })
));
expect_unreal_good(& ctx, txt("unreal"));
deinit(& ctx);
expect_unreal_bad(txt("unreal-at"));
if (g_failures != 0) { log_fmt("dogfood parse fixtures failed: %d\n", g_failures); return 1; }
log_fmt("dogfood parse fixtures passed\n");
return 0;
}