add parseh tests

This commit is contained in:
Andrew Kelley 2016-01-28 11:54:34 -07:00
parent 474340a003
commit f1c5d3d3a1
4 changed files with 149 additions and 29 deletions

View File

@ -14,3 +14,6 @@ Update the C integer types to be the correct size for the target.
Add the conditional compilation code for the page size global. It is hardcoded
for each target.
Make sure that parseh sends the correct command line parameters to libclang for
the given target.

View File

@ -672,7 +672,7 @@ static void render_node(AstRender *ar, AstNode *node) {
}
ar->indent -= ar->indent_size;
fprintf(ar->f, "}\n");
fprintf(ar->f, "}");
break;
}
case NodeTypeStructField:

View File

@ -397,6 +397,9 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
if (!enum_def) {
// this is a type that we can point to but that's it, same as `struct Foo;`.
add_typedef_node(c, type_name, create_symbol_node(c, "u8"));
AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name),
create_symbol_node(c, buf_ptr(type_name)));
c->aliases.append(alias_node);
return;
}
@ -404,7 +407,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
buf_init_from_buf(&node->data.struct_decl.name, type_name);
node->data.struct_decl.kind = ContainerKindEnum;
node->data.struct_decl.visib_mod = c->visib_mod;
node->data.struct_decl.visib_mod = VisibModExport;
node->data.struct_decl.directives = create_empty_directives(c);
ZigList<AstNode *> var_decls = {0};
@ -465,6 +468,43 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
}
static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
Buf bare_name = BUF_INIT;
buf_init_from_str(&bare_name, decl_name(record_decl));
Buf *type_name = buf_alloc();
buf_appendf(type_name, "struct_%s", buf_ptr(&bare_name));
if (c->type_table.maybe_get(type_name)) {
// we've already seen it
return;
}
RecordDecl *record_def = record_decl->getDefinition();
if (!record_def) {
// this is a type that we can point to but that's it, such as `struct Foo;`.
add_typedef_node(c, type_name, create_symbol_node(c, "u8"));
AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name),
create_symbol_node(c, buf_ptr(type_name)));
c->aliases.append(alias_node);
return;
}
emit_warning(c, record_decl, "skipping record %s, TODO", buf_ptr(&bare_name));
/*
AstNode *node = create_node(c, NodeTypeStructDecl);
buf_init_from_buf(&node->data.struct_decl.name, type_name);
node->data.struct_decl.kind = ContainerKindStruct;
node->data.struct_decl.visib_mod = VisibModExport;
node->data.struct_decl.directives = create_empty_directives(c);
normalize_parent_ptrs(node);
c->root->data.root.top_level_decls.append(node);
*/
}
static bool decl_visitor(void *context, const Decl *decl) {
Context *c = (Context*)context;
@ -478,6 +518,9 @@ static bool decl_visitor(void *context, const Decl *decl) {
case Decl::Enum:
visit_enum_decl(c, static_cast<const EnumDecl *>(decl));
break;
case Decl::Record:
visit_record_decl(c, static_cast<const RecordDecl *>(decl));
break;
default:
emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName());
}

View File

@ -24,10 +24,12 @@ struct TestCase {
ZigList<const char *> compile_errors;
ZigList<const char *> compiler_args;
ZigList<const char *> program_args;
bool is_parseh;
};
static ZigList<TestCase*> test_cases = {0};
static const char *tmp_source_path = ".tmp_source.zig";
static const char *tmp_h_path = ".tmp_header.h";
static const char *tmp_exe_path = "./.tmp_exe";
static const char *zig_exe = "./zig";
@ -94,6 +96,24 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
return test_case;
}
static TestCase *add_parseh_case(const char *case_name, const char *source, const char *output) {
TestCase *test_case = allocate<TestCase>(1);
test_case->case_name = case_name;
test_case->output = output;
test_case->is_parseh = true;
test_case->source_files.resize(1);
test_case->source_files.at(0).relative_path = tmp_h_path;
test_case->source_files.at(0).source_code = source;
test_case->compiler_args.append("parseh");
test_case->compiler_args.append(tmp_h_path);
test_case->compiler_args.append("--c-import-warnings");
test_cases.append(test_case);
return test_case;
}
static void add_compiling_test_cases(void) {
add_simple_case("hello world with libc", R"SOURCE(
#link("c")
@ -1771,6 +1791,39 @@ const x = 2 == 2.0;
}
//////////////////////////////////////////////////////////////////////////////
static void add_parseh_test_cases(void) {
add_parseh_case("simple data types", R"SOURCE(
#include <stdint.h>
int foo(char a, unsigned char b, signed char c);
void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d);
void baz(int8_t a, int16_t b, int32_t c, int64_t d);
)SOURCE", R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int;
pub extern fn bar(a: u8, b: u16, c: u32, d: u64);
pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT");
add_parseh_case("noreturn attribute", R"SOURCE(
void foo(void) __attribute__((noreturn));
)SOURCE", R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT");
add_parseh_case("enums", R"SOURCE(
enum Foo {
FooA,
FooB,
Foo1,
};
)SOURCE", R"OUTPUT(export enum enum_Foo {
A,
B,
_1,
}
pub const FooA = enum_Foo.A;
pub const FooB = enum_Foo.B;
pub const Foo1 = enum_Foo._1;
pub const Foo = enum_Foo;)OUTPUT");
}
static void print_compiler_invocation(TestCase *test_case) {
printf("%s", zig_exe);
for (int i = 0; i < test_case->compiler_args.length; i += 1) {
@ -1822,36 +1875,55 @@ static void run_test(TestCase *test_case) {
exit(1);
}
Buf program_stderr = BUF_INIT;
Buf program_stdout = BUF_INIT;
os_exec_process(tmp_exe_path, test_case->program_args, &return_code, &program_stderr, &program_stdout);
if (return_code != 0) {
printf("\nProgram exited with return code %d:\n", return_code);
print_compiler_invocation(test_case);
printf("%s", tmp_exe_path);
for (int i = 0; i < test_case->program_args.length; i += 1) {
printf(" %s", test_case->program_args.at(i));
if (test_case->is_parseh) {
if (buf_len(&zig_stderr) > 0) {
printf("\nparseh emitted warnings:\n");
print_compiler_invocation(test_case);
printf("%s\n", buf_ptr(&zig_stderr));
exit(1);
}
printf("\n");
printf("%s\n", buf_ptr(&program_stderr));
exit(1);
}
if (!buf_eql_str(&program_stdout, test_case->output)) {
printf("\n");
print_compiler_invocation(test_case);
printf("%s", tmp_exe_path);
for (int i = 0; i < test_case->program_args.length; i += 1) {
printf(" %s", test_case->program_args.at(i));
if (!strstr(buf_ptr(&zig_stdout), test_case->output)) {
printf("\n");
printf("========= Expected this output: =========\n");
printf("%s\n", test_case->output);
printf("================================================\n");
print_compiler_invocation(test_case);
printf("%s\n", buf_ptr(&zig_stdout));
exit(1);
}
} else {
Buf program_stderr = BUF_INIT;
Buf program_stdout = BUF_INIT;
os_exec_process(tmp_exe_path, test_case->program_args, &return_code, &program_stderr, &program_stdout);
if (return_code != 0) {
printf("\nProgram exited with return code %d:\n", return_code);
print_compiler_invocation(test_case);
printf("%s", tmp_exe_path);
for (int i = 0; i < test_case->program_args.length; i += 1) {
printf(" %s", test_case->program_args.at(i));
}
printf("\n");
printf("%s\n", buf_ptr(&program_stderr));
exit(1);
}
if (!buf_eql_str(&program_stdout, test_case->output)) {
printf("\n");
print_compiler_invocation(test_case);
printf("%s", tmp_exe_path);
for (int i = 0; i < test_case->program_args.length; i += 1) {
printf(" %s", test_case->program_args.at(i));
}
printf("\n");
printf("==== Test failed. Expected output: ====\n");
printf("%s\n", test_case->output);
printf("========= Actual output: ==============\n");
printf("%s\n", buf_ptr(&program_stdout));
printf("=======================================\n");
exit(1);
}
printf("\n");
printf("==== Test failed. Expected output: ====\n");
printf("%s\n", test_case->output);
printf("========= Actual output: ==============\n");
printf("%s\n", buf_ptr(&program_stdout));
printf("=======================================\n");
exit(1);
}
for (int i = 0; i < test_case->source_files.length; i += 1) {
@ -1881,6 +1953,7 @@ static void run_all_tests(bool reverse) {
static void cleanup(void) {
remove(tmp_source_path);
remove(tmp_h_path);
remove(tmp_exe_path);
}
@ -1900,6 +1973,7 @@ int main(int argc, char **argv) {
}
add_compiling_test_cases();
add_compile_failure_test_cases();
add_parseh_test_cases();
run_all_tests(reverse);
cleanup();
}