mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-25 07:04:58 -07:00
odin test to work with the new core:testing package
This commit is contained in:
@@ -365,8 +365,8 @@ bool is_excluded_target_filename(String name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String test_suffix = str_lit("_test");
|
||||
if (build_context.command_kind != Command_test) {
|
||||
String test_suffix = str_lit("_test");
|
||||
if (string_ends_with(name, test_suffix) && name != test_suffix) {
|
||||
// Ignore *_test.odin files
|
||||
return true;
|
||||
|
||||
+39
-2
@@ -1865,6 +1865,20 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
||||
}
|
||||
|
||||
if (build_context.command_kind == Command_test) {
|
||||
AstPackage *testing_package = get_core_package(&c->info, str_lit("testing"));
|
||||
Scope *testing_scope = testing_package->scope;
|
||||
|
||||
// Add all of testing library as a dependency
|
||||
for_array(i, testing_scope->elements.entries) {
|
||||
Entity *e = testing_scope->elements.entries[i].value;
|
||||
if (e != nullptr) {
|
||||
e->flags |= EntityFlag_Used;
|
||||
add_dependency_to_set(c, e);
|
||||
}
|
||||
}
|
||||
|
||||
Entity *test_signature = scope_lookup_current(testing_scope, str_lit("Test_Signature"));
|
||||
|
||||
AstPackage *pkg = c->info.init_package;
|
||||
Scope *s = pkg->scope;
|
||||
for_array(i, s->elements.entries) {
|
||||
@@ -1884,6 +1898,7 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
bool is_tester = false;
|
||||
if (name != prefix) {
|
||||
is_tester = true;
|
||||
@@ -1893,11 +1908,11 @@ void generate_minimum_dependency_set(Checker *c, Entity *start) {
|
||||
|
||||
Type *t = base_type(e->type);
|
||||
GB_ASSERT(t->kind == Type_Proc);
|
||||
if (t->Proc.param_count == 0 && t->Proc.result_count == 0) {
|
||||
if (are_types_identical(t, base_type(test_signature->type))) {
|
||||
// Good
|
||||
} else {
|
||||
gbString str = type_to_string(t);
|
||||
error(e->token, "Testing procedures must have a signature type of proc(), got %s", str);
|
||||
error(e->token, "Testing procedures must have a signature type of proc(^testing.T), got %s", str);
|
||||
gb_string_free(str);
|
||||
is_tester = false;
|
||||
}
|
||||
@@ -2103,6 +2118,28 @@ Type *find_core_type(Checker *c, String name) {
|
||||
return e->type;
|
||||
}
|
||||
|
||||
|
||||
Entity *find_entity_in_pkg(CheckerInfo *info, String const &pkg, String const &name) {
|
||||
AstPackage *package = get_core_package(info, pkg);
|
||||
Entity *e = scope_lookup_current(package->scope, name);
|
||||
if (e == nullptr) {
|
||||
compiler_error("Could not find type declaration for '%.*s.%.*s'\n", LIT(pkg), LIT(name));
|
||||
// NOTE(bill): This will exit the program as it's cannot continue without it!
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
Type *find_type_in_pkg(CheckerInfo *info, String const &pkg, String const &name) {
|
||||
AstPackage *package = get_core_package(info, pkg);
|
||||
Entity *e = scope_lookup_current(package->scope, name);
|
||||
if (e == nullptr) {
|
||||
compiler_error("Could not find type declaration for '%.*s.%.*s'\n", LIT(pkg), LIT(name));
|
||||
// NOTE(bill): This will exit the program as it's cannot continue without it!
|
||||
}
|
||||
GB_ASSERT(e->type != nullptr);
|
||||
return e->type;
|
||||
}
|
||||
|
||||
CheckerTypePath *new_checker_type_path() {
|
||||
gbAllocator a = heap_allocator();
|
||||
auto *tp = gb_alloc_item(a, CheckerTypePath);
|
||||
|
||||
+30
-3
@@ -12930,12 +12930,39 @@ void ir_gen_tree(irGen *s) {
|
||||
ir_emit(proc, ir_alloc_instr(proc, irInstr_StartupRuntime));
|
||||
Array<irValue *> empty_args = {};
|
||||
if (build_context.command_kind == Command_test) {
|
||||
Type *t_Internal_Test = find_type_in_pkg(m->info, str_lit("testing"), str_lit("Internal_Test"));
|
||||
Type *array_type = alloc_type_array(t_Internal_Test, m->info->testing_procedures.count);
|
||||
Type *slice_type = alloc_type_slice(t_Internal_Test);
|
||||
irValue *all_tests_array = ir_add_global_generated(proc->module, array_type, nullptr);
|
||||
|
||||
for_array(i, m->info->testing_procedures) {
|
||||
Entity *e = m->info->testing_procedures[i];
|
||||
irValue **found = map_get(&proc->module->values, hash_entity(e));
|
||||
Entity *testing_proc = m->info->testing_procedures[i];
|
||||
String name = testing_proc->token.string;
|
||||
irValue **found = map_get(&m->values, hash_entity(testing_proc));
|
||||
GB_ASSERT(found != nullptr);
|
||||
ir_emit_call(proc, *found, empty_args);
|
||||
|
||||
irValue *v_name = ir_find_or_add_entity_string(m, name);
|
||||
irValue *v_p = *found;
|
||||
|
||||
|
||||
irValue *elem_ptr = ir_emit_array_epi(proc, all_tests_array, cast(i32)i);
|
||||
irValue *name_ptr = ir_emit_struct_ep(proc, elem_ptr, 0);
|
||||
irValue *p_ptr = ir_emit_struct_ep(proc, elem_ptr, 1);
|
||||
ir_emit_store(proc, name_ptr, v_name);
|
||||
ir_emit_store(proc, p_ptr, v_p);
|
||||
}
|
||||
|
||||
irValue *all_tests_slice = ir_add_local_generated(proc, slice_type, true);
|
||||
ir_fill_slice(proc, all_tests_slice,
|
||||
ir_array_elem(proc, all_tests_array),
|
||||
ir_const_int(m->info->testing_procedures.count));
|
||||
|
||||
|
||||
irValue *runner = ir_get_package_value(m, str_lit("testing"), str_lit("runner"));
|
||||
|
||||
auto args = array_make<irValue *>(temporary_allocator(), 1);
|
||||
args[0] = ir_emit_load(proc, all_tests_slice);
|
||||
ir_emit_call(proc, runner, args);
|
||||
} else {
|
||||
irValue **found = map_get(&proc->module->values, hash_entity(entry_point));
|
||||
if (found != nullptr) {
|
||||
|
||||
+49
-3
@@ -11496,6 +11496,13 @@ lbValue lb_find_runtime_value(lbModule *m, String const &name) {
|
||||
lbValue value = *found;
|
||||
return value;
|
||||
}
|
||||
lbValue lb_find_package_value(lbModule *m, String const &pkg, String const &name) {
|
||||
Entity *e = find_entity_in_pkg(m->info, pkg, name);
|
||||
lbValue *found = map_get(&m->values, hash_entity(e));
|
||||
GB_ASSERT_MSG(found != nullptr, "Unable to find value '%.*s.%.*s'", LIT(pkg), LIT(name));
|
||||
lbValue value = *found;
|
||||
return value;
|
||||
}
|
||||
|
||||
lbValue lb_get_type_info_ptr(lbModule *m, Type *type) {
|
||||
i32 index = cast(i32)lb_type_info_index(m->info, type);
|
||||
@@ -12885,12 +12892,51 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
LLVMBuildCall2(p->builder, LLVMGetElementType(lb_type(m, startup_runtime->type)), startup_runtime->value, nullptr, 0, "");
|
||||
|
||||
if (build_context.command_kind == Command_test) {
|
||||
Type *t_Internal_Test = find_type_in_pkg(m->info, str_lit("testing"), str_lit("Internal_Test"));
|
||||
Type *array_type = alloc_type_array(t_Internal_Test, m->info->testing_procedures.count);
|
||||
Type *slice_type = alloc_type_slice(t_Internal_Test);
|
||||
lbAddr all_tests_array_addr = lb_add_global_generated(p->module, array_type, {});
|
||||
lbValue all_tests_array = lb_addr_get_ptr(p, all_tests_array_addr);
|
||||
|
||||
LLVMTypeRef lbt_Internal_Test = lb_type(m, t_Internal_Test);
|
||||
|
||||
LLVMValueRef indices[2] = {};
|
||||
indices[0] = LLVMConstInt(lb_type(m, t_i32), 0, false);
|
||||
|
||||
for_array(i, m->info->testing_procedures) {
|
||||
Entity *e = m->info->testing_procedures[i];
|
||||
lbValue *found = map_get(&m->values, hash_entity(e));
|
||||
Entity *testing_proc = m->info->testing_procedures[i];
|
||||
String name = testing_proc->token.string;
|
||||
lbValue *found = map_get(&m->values, hash_entity(testing_proc));
|
||||
GB_ASSERT(found != nullptr);
|
||||
lb_emit_call(p, *found, {});
|
||||
|
||||
lbValue v_name = lb_find_or_add_entity_string(m, name);
|
||||
lbValue v_proc = *found;
|
||||
|
||||
indices[1] = LLVMConstInt(lb_type(m, t_int), i, false);
|
||||
|
||||
LLVMValueRef vals[2] = {};
|
||||
vals[0] = v_name.value;
|
||||
vals[1] = v_proc.value;
|
||||
GB_ASSERT(LLVMIsConstant(vals[0]));
|
||||
GB_ASSERT(LLVMIsConstant(vals[1]));
|
||||
|
||||
LLVMValueRef dst = LLVMConstInBoundsGEP(all_tests_array.value, indices, gb_count_of(indices));
|
||||
LLVMValueRef src = LLVMConstNamedStruct(lbt_Internal_Test, vals, gb_count_of(vals));
|
||||
|
||||
LLVMBuildStore(p->builder, src, dst);
|
||||
}
|
||||
|
||||
lbAddr all_tests_slice = lb_add_local_generated(p, slice_type, true);
|
||||
lb_fill_slice(p, all_tests_slice,
|
||||
lb_array_elem(p, all_tests_array),
|
||||
lb_const_int(m, t_int, m->info->testing_procedures.count));
|
||||
|
||||
|
||||
lbValue runner = lb_find_package_value(m, str_lit("testing"), str_lit("runner"));
|
||||
|
||||
auto args = array_make<lbValue>(heap_allocator(), 1);
|
||||
args[0] = lb_addr_load(p, all_tests_slice);
|
||||
lb_emit_call(p, runner, args);
|
||||
} else {
|
||||
lbValue *found = map_get(&m->values, hash_entity(entry_point));
|
||||
GB_ASSERT(found != nullptr);
|
||||
|
||||
+15
-1
@@ -5287,7 +5287,6 @@ ParseFileError process_imported_file(Parser *p, ImportedFile const &imported_fil
|
||||
AstFile *file = gb_alloc_item(heap_allocator(), AstFile);
|
||||
file->pkg = pkg;
|
||||
file->id = cast(i32)(imported_file.index+1);
|
||||
|
||||
TokenPos err_pos = {0};
|
||||
ParseFileError err = init_ast_file(file, fi->fullpath, &err_pos);
|
||||
err_pos.file_id = file->id;
|
||||
@@ -5328,6 +5327,16 @@ ParseFileError process_imported_file(Parser *p, ImportedFile const &imported_fil
|
||||
}
|
||||
}
|
||||
|
||||
if (build_context.command_kind == Command_test) {
|
||||
String name = file->fullpath;
|
||||
name = remove_extension_from_path(name);
|
||||
|
||||
String test_suffix = str_lit("_test");
|
||||
if (string_ends_with(name, test_suffix) && name != test_suffix) {
|
||||
file->is_test = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (parse_file(p, file)) {
|
||||
gb_mutex_lock(&p->file_add_mutex);
|
||||
defer (gb_mutex_unlock(&p->file_add_mutex));
|
||||
@@ -5373,6 +5382,11 @@ ParseFileError parse_packages(Parser *p, String init_filename) {
|
||||
try_add_import_path(p, init_fullpath, init_fullpath, init_pos, Package_Init);
|
||||
p->init_fullpath = init_fullpath;
|
||||
|
||||
if (build_context.command_kind == Command_test) {
|
||||
String s = get_fullpath_core(heap_allocator(), str_lit("testing"));
|
||||
try_add_import_path(p, s, s, init_pos, Package_Normal);
|
||||
}
|
||||
|
||||
for_array(i, build_context.extra_packages) {
|
||||
String path = build_context.extra_packages[i];
|
||||
String fullpath = path_to_full_path(heap_allocator(), path); // LEAK?
|
||||
|
||||
Reference in New Issue
Block a user