From af536ac343564e5120f99cbf3b7fc9efa984eb93 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 16 Mar 2017 16:02:35 -0400 Subject: [PATCH] introduce new test syntax * remove setFnTest builtin * add test "name" { ... } syntax * remove --check-unused argument. functions are always lazy now. --- doc/langref.md | 4 +- doc/vim/syntax/zig.vim | 2 +- src/all_types.hpp | 22 +- src/analyze.cpp | 166 +++++--- src/ast_render.cpp | 3 + src/codegen.cpp | 8 +- src/codegen.hpp | 1 - src/ir.cpp | 65 +--- src/ir_print.cpp | 9 - src/main.cpp | 5 - src/parser.cpp | 32 +- src/tokenizer.cpp | 2 + src/tokenizer.hpp | 1 + std/compiler_rt.zig | 12 +- std/cstr.zig | 8 +- std/fmt.zig | 12 +- std/hash_map.zig | 4 +- std/list.zig | 4 +- std/math.zig | 4 +- std/mem.zig | 12 +- std/rand.zig | 12 +- std/sort.zig | 8 +- test/cases/array.zig | 24 +- test/cases/atomics.zig | 8 +- test/cases/bool.zig | 20 +- test/cases/cast.zig | 12 +- test/cases/const_slice_child.zig | 4 +- test/cases/defer.zig | 8 +- test/cases/enum.zig | 20 +- test/cases/enum_with_members.zig | 4 +- test/cases/error.zig | 27 +- test/cases/eval.zig | 74 +--- test/cases/fn.zig | 39 +- test/cases/for.zig | 12 +- test/cases/generics.zig | 35 +- test/cases/goto.zig | 8 +- test/cases/if.zig | 8 +- test/cases/import.zig | 4 +- test/cases/ir_block_deps.zig | 4 +- test/cases/math.zig | 68 +--- test/cases/misc.zig | 179 +++------ .../index.zig | 4 +- test/cases/null.zig | 32 +- test/cases/pub_enum/index.zig | 8 +- test/cases/sizeof_and_typeof.zig | 4 +- test/cases/struct.zig | 78 ++-- .../cases/struct_contains_slice_of_itself.zig | 4 +- test/cases/switch.zig | 32 +- test/cases/switch_prong_err_enum.zig | 4 +- test/cases/switch_prong_implicit_cast.zig | 4 +- test/cases/this.zig | 12 +- test/cases/try.zig | 8 +- test/cases/typedef.zig | 4 +- test/cases/undefined.zig | 12 +- test/cases/var_args.zig | 12 +- test/cases/void.zig | 4 +- test/cases/while.zig | 20 +- test/run_tests.cpp | 363 ++++++++++++------ 58 files changed, 648 insertions(+), 911 deletions(-) diff --git a/doc/langref.md b/doc/langref.md index 9b806fc3840f3dae949d382ab1882e16904d8bb9..cf759ae3f5343208730877aeb9b32eacba12e56a 100644 --- a/doc/langref.md +++ b/doc/langref.md @@ -5,7 +5,9 @@ ``` Root = many(TopLevelItem) "EOF" -TopLevelItem = ErrorValueDecl | Block | TopLevelDecl +TopLevelItem = ErrorValueDecl | Block | TopLevelDecl | TestDecl + +TestDecl = "test" String Block TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | TypeDecl | UseDecl) diff --git a/doc/vim/syntax/zig.vim b/doc/vim/syntax/zig.vim index 3880120f37d19950c143194aa5e6f44fce078254..a3e39415ec055d9a23f85bcfa337ed6667d0afb8 100644 --- a/doc/vim/syntax/zig.vim +++ b/doc/vim/syntax/zig.vim @@ -15,7 +15,7 @@ syn keyword zigConditional if else switch try syn keyword zigRepeat while for syn keyword zigConstant null undefined this -syn keyword zigKeyword fn use +syn keyword zigKeyword fn use test syn keyword zigType bool f32 f64 void Unreachable type error syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong c_long_double diff --git a/src/all_types.hpp b/src/all_types.hpp index 8fe633460cfd18a1283f086a2c628fc0db6710a1..48777b6df0d6dc8b05be0a02dd9566f45d186b39 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -311,6 +311,7 @@ enum NodeType { NodeTypeVariableDeclaration, NodeTypeTypeDecl, NodeTypeErrorValueDecl, + NodeTypeTestDecl, NodeTypeBinOpExpr, NodeTypeUnwrapErrorExpr, NodeTypeNumberLiteral, @@ -435,6 +436,14 @@ struct AstNodeErrorValueDecl { ErrorTableEntry *err; }; +struct AstNodeTestDecl { + // always invalid if it's not VisibModPrivate but can be parsed that way + VisibMod visib_mod; + Buf *name; + + AstNode *body; +}; + enum BinOpType { BinOpTypeInvalid, BinOpTypeAssign, @@ -781,6 +790,7 @@ struct AstNode { AstNodeVariableDeclaration variable_declaration; AstNodeTypeDecl type_decl; AstNodeErrorValueDecl error_value_decl; + AstNodeTestDecl test_decl; AstNodeBinOpExpr bin_op_expr; AstNodeUnwrapErrorExpr unwrap_err_expr; AstNodePrefixOpExpr prefix_op_expr; @@ -1091,7 +1101,7 @@ enum FnInline { struct FnTableEntry { LLVMValueRef llvm_value; AstNode *proto_node; - AstNode *fn_def_node; + AstNode *body_node; ScopeFnDef *fndef_scope; // parent should be the top level decls or container decls Scope *child_scope; // parent is scope for last parameter ScopeBlock *def_scope; // parent is child_scope @@ -1161,7 +1171,6 @@ enum BuiltinFnId { BuiltinFnIdTruncate, BuiltinFnIdIntType, BuiltinFnIdUnreachable, - BuiltinFnIdSetFnTest, BuiltinFnIdSetFnVisible, BuiltinFnIdSetDebugSafety, BuiltinFnIdAlloca, @@ -1411,8 +1420,8 @@ struct CodeGen { ZigList lib_dirs; uint32_t test_fn_count; + TypeTableEntry *test_fn_type; - bool check_unused; bool each_lib_rpath; ZigList error_decls; @@ -1630,7 +1639,6 @@ enum IrInstructionId { IrInstructionIdTypeOf, IrInstructionIdToPtrType, IrInstructionIdPtrTypeChild, - IrInstructionIdSetFnTest, IrInstructionIdSetFnVisible, IrInstructionIdSetDebugSafety, IrInstructionIdArrayType, @@ -1973,12 +1981,6 @@ struct IrInstructionPtrTypeChild { IrInstruction *value; }; -struct IrInstructionSetFnTest { - IrInstruction base; - - IrInstruction *fn_value; -}; - struct IrInstructionSetFnVisible { IrInstruction base; diff --git a/src/analyze.cpp b/src/analyze.cpp index 4f806b9e1be6337248d7748b0b5a399f7ab56d11..8e3c82822fe12f92190492561949b7ce6aa99cd1 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -130,7 +130,6 @@ Scope *create_loop_scope(AstNode *node, Scope *parent) { } ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry) { - assert(!node || node->type == NodeTypeFnDef); ScopeFnDef *scope = allocate(1); init_scope(&scope->base, ScopeIdFnDef, node, parent); scope->fn_entry = fn_entry; @@ -1756,7 +1755,8 @@ FnTableEntry *create_fn(AstNode *proto_node) { FnTableEntry *fn_entry = create_fn_raw(inline_value, internal_linkage); fn_entry->proto_node = proto_node; - fn_entry->fn_def_node = proto_node->data.fn_proto.fn_def_node; + fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr : + proto_node->data.fn_proto.fn_def_node->data.fn_def.body; return fn_entry; } @@ -1799,76 +1799,107 @@ static void typecheck_panic_fn(CodeGen *g) { } } +static TypeTableEntry *get_test_fn_type(CodeGen *g) { + if (g->test_fn_type) + return g->test_fn_type; + + FnTypeId fn_type_id = {0}; + fn_type_id.return_type = g->builtin_types.entry_void; + g->test_fn_type = get_fn_type(g, &fn_type_id); + return g->test_fn_type; +} + static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { ImportTableEntry *import = tld_fn->base.import; - AstNode *proto_node = tld_fn->base.source_node; - assert(proto_node->type == NodeTypeFnProto); - AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; + AstNode *source_node = tld_fn->base.source_node; + if (source_node->type == NodeTypeFnProto) { + AstNodeFnProto *fn_proto = &source_node->data.fn_proto; - AstNode *fn_def_node = fn_proto->fn_def_node; + AstNode *fn_def_node = fn_proto->fn_def_node; - FnTableEntry *fn_table_entry = create_fn(tld_fn->base.source_node); - get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_'); + FnTableEntry *fn_table_entry = create_fn(source_node); + get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_'); - tld_fn->fn_entry = fn_table_entry; + tld_fn->fn_entry = fn_table_entry; - if (fn_table_entry->fn_def_node) { - fn_table_entry->fndef_scope = create_fndef_scope( - fn_table_entry->fn_def_node, tld_fn->base.parent_scope, fn_table_entry); + if (fn_table_entry->body_node) { + fn_table_entry->fndef_scope = create_fndef_scope( + fn_table_entry->body_node, tld_fn->base.parent_scope, fn_table_entry); - for (size_t i = 0; i < fn_proto->params.length; i += 1) { - AstNode *param_node = fn_proto->params.at(i); - assert(param_node->type == NodeTypeParamDecl); - if (buf_len(param_node->data.param_decl.name) == 0) { - add_node_error(g, param_node, buf_sprintf("missing parameter name")); + for (size_t i = 0; i < fn_proto->params.length; i += 1) { + AstNode *param_node = fn_proto->params.at(i); + assert(param_node->type == NodeTypeParamDecl); + if (buf_len(param_node->data.param_decl.name) == 0) { + add_node_error(g, param_node, buf_sprintf("missing parameter name")); + } } } - } - Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope; - fn_table_entry->type_entry = analyze_fn_type(g, proto_node, child_scope); + Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope; + fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope); - if (fn_table_entry->type_entry->id == TypeTableEntryIdInvalid) { - tld_fn->base.resolution = TldResolutionInvalid; - return; - } + if (fn_table_entry->type_entry->id == TypeTableEntryIdInvalid) { + tld_fn->base.resolution = TldResolutionInvalid; + return; + } + + if (!fn_table_entry->type_entry->data.fn.is_generic) { + g->fn_protos.append(fn_table_entry); + + if (fn_def_node) + g->fn_defs.append(fn_table_entry); + + if (import == g->root_import && scope_is_root_decls(tld_fn->base.parent_scope)) { + if (buf_eql_str(&fn_table_entry->symbol_name, "main")) { + g->main_fn = fn_table_entry; + + if (!g->link_libc && tld_fn->base.visib_mod != VisibModExport) { + TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void); + TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type; + if (actual_return_type != err_void) { + add_node_error(g, fn_proto->return_type, + buf_sprintf("expected return type of main to be '%%void', instead is '%s'", + buf_ptr(&actual_return_type->name))); + } + } + } else if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) { + g->panic_fn = fn_table_entry; + typecheck_panic_fn(g); + } + } else if (import->package == g->panic_package && scope_is_root_decls(tld_fn->base.parent_scope)) { + if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) { + g->panic_fn = fn_table_entry; + typecheck_panic_fn(g); + } + } + } + } else if (source_node->type == NodeTypeTestDecl) { + FnTableEntry *fn_table_entry = create_fn_raw(FnInlineAuto, false); + + get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_'); + + tld_fn->fn_entry = fn_table_entry; + + fn_table_entry->proto_node = source_node; + fn_table_entry->fndef_scope = create_fndef_scope(source_node, tld_fn->base.parent_scope, fn_table_entry); + fn_table_entry->type_entry = get_test_fn_type(g); + fn_table_entry->body_node = source_node->data.test_decl.body; + fn_table_entry->is_test = true; + g->test_fn_count += 1; - if (!fn_table_entry->type_entry->data.fn.is_generic) { g->fn_protos.append(fn_table_entry); + g->fn_defs.append(fn_table_entry); - if (fn_def_node) - g->fn_defs.append(fn_table_entry); - - if (import == g->root_import && scope_is_root_decls(tld_fn->base.parent_scope)) { - if (buf_eql_str(&fn_table_entry->symbol_name, "main")) { - g->main_fn = fn_table_entry; - - if (!g->link_libc && tld_fn->base.visib_mod != VisibModExport) { - TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void); - TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type; - if (actual_return_type != err_void) { - add_node_error(g, fn_proto->return_type, - buf_sprintf("expected return type of main to be '%%void', instead is '%s'", - buf_ptr(&actual_return_type->name))); - } - } - } else if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) { - g->panic_fn = fn_table_entry; - typecheck_panic_fn(g); - } - } else if (import->package == g->panic_package && scope_is_root_decls(tld_fn->base.parent_scope)) { - if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) { - g->panic_fn = fn_table_entry; - typecheck_panic_fn(g); - } - } + } else { + zig_unreachable(); } } static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { - if (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport || + if (tld->visib_mod == VisibModExport || (buf_eql_str(tld->name, "panic") && - (decls_scope->import->package == g->panic_package || decls_scope->import == g->root_import))) + (decls_scope->import->package == g->panic_package || decls_scope->import == g->root_import)) || + (tld->id == TldIdVar && g->is_test_build)) { g->resolve_queue.append(tld); } @@ -1882,6 +1913,27 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { } } +static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope) { + assert(node->type == NodeTypeTestDecl); + + if (node->data.test_decl.visib_mod != VisibModPrivate) { + add_node_error(g, node, buf_sprintf("tests require no visibility modifier")); + } + + if (!g->is_test_build) + return; + + ImportTableEntry *import = get_scope_import(&decls_scope->base); + if (import->package != g->root_package) + return; + + Buf *test_name = node->data.test_decl.name; + + TldFn *tld_fn = allocate(1); + init_tld(&tld_fn->base, TldIdFn, test_name, VisibModPrivate, node, &decls_scope->base); + g->resolve_queue.append(&tld_fn->base); +} + static void preview_error_value_decl(CodeGen *g, AstNode *node) { assert(node->type == NodeTypeErrorValueDecl); @@ -1975,6 +2027,9 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { // error value declarations do not depend on other top level decls preview_error_value_decl(g, node); break; + case NodeTypeTestDecl: + preview_test_decl(g, node, decls_scope); + break; case NodeTypeContainerDecl: case NodeTypeParamDecl: case NodeTypeFnDecl: @@ -2650,7 +2705,8 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { fn_table_entry->anal_state = FnAnalStateProbing; - AstNode *return_type_node = fn_table_entry->proto_node->data.fn_proto.return_type; + AstNode *return_type_node = (fn_table_entry->proto_node != nullptr) ? + fn_table_entry->proto_node->data.fn_proto.return_type : fn_table_entry->fndef_scope->base.source_node; assert(fn_table_entry->fndef_scope); if (!fn_table_entry->child_scope) @@ -2674,7 +2730,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) { } if (g->verbose) { fprintf(stderr, "\n"); - ast_render(stderr, fn_table_entry->fn_def_node, 4); + ast_render(stderr, fn_table_entry->body_node, 4); fprintf(stderr, "\n{ // (IR)\n"); ir_print(stderr, &fn_table_entry->ir_executable, 4); fprintf(stderr, "}\n"); diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 8a17cc4cf522f2e491f05be14e2a9b54b0ea101b..c10844df46641bd1c3d6e93e3e83528e77611e19 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -170,6 +170,8 @@ static const char *node_type_str(NodeType node_type) { return "TypeDecl"; case NodeTypeErrorValueDecl: return "ErrorValueDecl"; + case NodeTypeTestDecl: + return "TestDecl"; case NodeTypeNumberLiteral: return "NumberLiteral"; case NodeTypeStringLiteral: @@ -915,6 +917,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { case NodeTypeFnDecl: case NodeTypeParamDecl: case NodeTypeErrorValueDecl: + case NodeTypeTestDecl: case NodeTypeStructField: case NodeTypeUse: zig_panic("TODO more ast rendering"); diff --git a/src/codegen.cpp b/src/codegen.cpp index fd2d8dd3a9442238140eb78b9f03d3524c2b9319..5456fbce3db18a84693e1f66caa53fa4d4cad8a5 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -138,10 +138,6 @@ void codegen_set_verbose(CodeGen *g, bool verbose) { g->verbose = verbose; } -void codegen_set_check_unused(CodeGen *g, bool check_unused) { - g->check_unused = check_unused; -} - void codegen_set_each_lib_rpath(CodeGen *g, bool each_lib_rpath) { g->each_lib_rpath = each_lib_rpath; } @@ -323,7 +319,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { return get_di_scope(g, scope->parent); unsigned line_number = fn_table_entry->proto_node->line + 1; unsigned scope_line = line_number; - bool is_definition = fn_table_entry->fn_def_node != nullptr; + bool is_definition = fn_table_entry->body_node != nullptr; unsigned flags = 0; bool is_optimized = g->is_release_build; ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder, @@ -2492,7 +2488,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdToPtrType: case IrInstructionIdPtrTypeChild: case IrInstructionIdFieldPtr: - case IrInstructionIdSetFnTest: case IrInstructionIdSetFnVisible: case IrInstructionIdSetDebugSafety: case IrInstructionIdArrayType: @@ -4054,7 +4049,6 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX); create_builtin_fn(g, BuiltinFnIdIntType, "intType", 2); create_builtin_fn(g, BuiltinFnIdUnreachable, "unreachable", 0); - create_builtin_fn(g, BuiltinFnIdSetFnTest, "setFnTest", 1); create_builtin_fn(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2); create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); create_builtin_fn(g, BuiltinFnIdAlloca, "alloca", 2); diff --git a/src/codegen.hpp b/src/codegen.hpp index dc2fb99ed896d95710f19a85bf3b1578ecbbb21d..72dacf71c4acf3b2f16c22da81742a6e4543f2ad 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -19,7 +19,6 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target); void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_is_release(CodeGen *codegen, bool is_release); void codegen_set_is_test(CodeGen *codegen, bool is_test); -void codegen_set_check_unused(CodeGen *codegen, bool check_unused); void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); void codegen_set_is_static(CodeGen *codegen, bool is_static); diff --git a/src/ir.cpp b/src/ir.cpp index 053985145403dda48537a3d6fefcff28d264be2a..79647cdb97be606b0b9d8af4d62317663f90344e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -282,10 +282,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *) return IrInstructionIdPtrTypeChild; } -static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnTest *) { - return IrInstructionIdSetFnTest; -} - static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnVisible *) { return IrInstructionIdSetFnVisible; } @@ -1147,17 +1143,6 @@ static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstN return &instruction->base; } -static IrInstruction *ir_build_set_fn_test(IrBuilder *irb, Scope *scope, AstNode *source_node, - IrInstruction *fn_value) -{ - IrInstructionSetFnTest *instruction = ir_build_instruction(irb, scope, source_node); - instruction->fn_value = fn_value; - - ir_ref_instruction(fn_value, irb->current_basic_block); - - return &instruction->base; -} - static IrInstruction *ir_build_set_fn_visible(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn_value, IrInstruction *is_visible) { @@ -2287,13 +2272,6 @@ static IrInstruction *ir_instruction_ptrtypechild_get_dep(IrInstructionPtrTypeCh } } -static IrInstruction *ir_instruction_setfntest_get_dep(IrInstructionSetFnTest *instruction, size_t index) { - switch (index) { - case 0: return instruction->fn_value; - default: return nullptr; - } -} - static IrInstruction *ir_instruction_setfnvisible_get_dep(IrInstructionSetFnVisible *instruction, size_t index) { switch (index) { case 0: return instruction->fn_value; @@ -2807,8 +2785,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t return ir_instruction_toptrtype_get_dep((IrInstructionToPtrType *) instruction, index); case IrInstructionIdPtrTypeChild: return ir_instruction_ptrtypechild_get_dep((IrInstructionPtrTypeChild *) instruction, index); - case IrInstructionIdSetFnTest: - return ir_instruction_setfntest_get_dep((IrInstructionSetFnTest *) instruction, index); case IrInstructionIdSetFnVisible: return ir_instruction_setfnvisible_get_dep((IrInstructionSetFnVisible *) instruction, index); case IrInstructionIdSetDebugSafety: @@ -3810,15 +3786,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo return arg; return ir_build_typeof(irb, scope, node, arg); } - case BuiltinFnIdSetFnTest: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_instruction) - return arg0_value; - - return ir_build_set_fn_test(irb, scope, node, arg0_value); - } case BuiltinFnIdSetFnVisible: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -5543,6 +5510,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop zig_panic("TODO IR gen NodeTypeErrorValueDecl"); case NodeTypeTypeDecl: zig_panic("TODO IR gen NodeTypeTypeDecl"); + case NodeTypeTestDecl: + zig_panic("TODO IR gen NodeTypeTestDecl"); } zig_unreachable(); } @@ -5633,10 +5602,7 @@ bool ir_gen_fn(CodeGen *codegen, FnTableEntry *fn_entry) { assert(fn_entry); IrExecutable *ir_executable = &fn_entry->ir_executable; - AstNode *fn_def_node = fn_entry->fn_def_node; - assert(fn_def_node->type == NodeTypeFnDef); - - AstNode *body_node = fn_def_node->data.fn_def.body; + AstNode *body_node = fn_entry->body_node; assert(fn_entry->child_scope); @@ -8180,7 +8146,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal result = entry->value; } else { // Analyze the fn body block like any other constant expression. - AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body; + AstNode *body_node = fn_entry->body_node; result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec); @@ -8219,7 +8185,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal FnTableEntry *impl_fn = create_fn(fn_proto_node); impl_fn->param_source_nodes = allocate(new_fn_arg_count); buf_init_from_buf(&impl_fn->symbol_name, &fn_entry->symbol_name); - impl_fn->fndef_scope = create_fndef_scope(impl_fn->fn_def_node, parent_scope, impl_fn); + impl_fn->fndef_scope = create_fndef_scope(impl_fn->body_node, parent_scope, impl_fn); impl_fn->child_scope = &impl_fn->fndef_scope->base; FnTypeId inst_fn_type_id = {0}; init_fn_type_id(&inst_fn_type_id, fn_proto_node, new_fn_arg_count); @@ -9582,24 +9548,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, return ira->codegen->builtin_types.entry_type; } -static TypeTableEntry *ir_analyze_instruction_set_fn_test(IrAnalyze *ira, - IrInstructionSetFnTest *set_fn_test_instruction) -{ - IrInstruction *fn_value = set_fn_test_instruction->fn_value->other; - - FnTableEntry *fn_entry = ir_resolve_fn(ira, fn_value); - if (!fn_entry) - return ira->codegen->builtin_types.entry_invalid; - - if (!fn_entry->is_test) { - fn_entry->is_test = true; - ira->codegen->test_fn_count += 1; - } - - ir_build_const_from(ira, &set_fn_test_instruction->base); - return ira->codegen->builtin_types.entry_void; -} - static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira, IrInstructionSetFnVisible *set_fn_visible_instruction) { @@ -12253,8 +12201,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); case IrInstructionIdPtrTypeChild: return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); - case IrInstructionIdSetFnTest: - return ir_analyze_instruction_set_fn_test(ira, (IrInstructionSetFnTest *)instruction); case IrInstructionIdSetFnVisible: return ir_analyze_instruction_set_fn_visible(ira, (IrInstructionSetFnVisible *)instruction); case IrInstructionIdSetGlobalAlign: @@ -12469,7 +12415,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { case IrInstructionIdCall: case IrInstructionIdReturn: case IrInstructionIdUnreachable: - case IrInstructionIdSetFnTest: case IrInstructionIdSetFnVisible: case IrInstructionIdSetDebugSafety: case IrInstructionIdImport: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 3c9e53662edc43a5e8cc58e4c0e19ca1487e2041..b5f5a169837449c3d31367830947b5dec41a5dc9 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -339,12 +339,6 @@ static void ir_print_enum_field_ptr(IrPrint *irp, IrInstructionEnumFieldPtr *ins fprintf(irp->f, ")"); } -static void ir_print_set_fn_test(IrPrint *irp, IrInstructionSetFnTest *instruction) { - fprintf(irp->f, "@setFnTest("); - ir_print_other_instruction(irp, instruction->fn_value); - fprintf(irp->f, ")"); -} - static void ir_print_set_fn_visible(IrPrint *irp, IrInstructionSetFnVisible *instruction) { fprintf(irp->f, "@setFnVisible("); ir_print_other_instruction(irp, instruction->fn_value); @@ -932,9 +926,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { case IrInstructionIdEnumFieldPtr: ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction); break; - case IrInstructionIdSetFnTest: - ir_print_set_fn_test(irp, (IrInstructionSetFnTest *)instruction); - break; case IrInstructionIdSetFnVisible: ir_print_set_fn_visible(irp, (IrInstructionSetFnVisible *)instruction); break; diff --git a/src/main.cpp b/src/main.cpp index 87d06ee7feef064e4e91d1fe5215426605658cb5..2705dcbf4a123e7e8ff300d484cd7db9489b0696 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,7 +56,6 @@ static int usage(const char *arg0) { " -mmacosx-version-min [ver] (darwin only) set Mac OS X deployment target\n" " -mios-version-min [ver] (darwin only) set iOS deployment target\n" " -framework [name] (darwin only) link against framework\n" - " --check-unused perform semantic analysis on unused declarations\n" " --linker-script [path] use a custom linker script\n" " -rpath [path] add directory to the runtime library search path\n" " --each-lib-rpath add rpath for each used dynamic library\n" @@ -141,7 +140,6 @@ int main(int argc, char **argv) { bool rdynamic = false; const char *mmacosx_version_min = nullptr; const char *mios_version_min = nullptr; - bool check_unused = false; const char *linker_script = nullptr; ZigList rpath_list = {0}; bool each_lib_rpath = false; @@ -166,8 +164,6 @@ int main(int argc, char **argv) { municode = true; } else if (strcmp(arg, "-rdynamic") == 0) { rdynamic = true; - } else if (strcmp(arg, "--check-unused") == 0) { - check_unused = true; } else if (strcmp(arg, "--each-lib-rpath") == 0) { each_lib_rpath = true; } else if (arg[1] == 'L' && arg[2] != 0) { @@ -354,7 +350,6 @@ int main(int argc, char **argv) { codegen_set_is_release(g, is_release_build); codegen_set_is_test(g, cmd == CmdTest); codegen_set_linker_script(g, linker_script); - codegen_set_check_unused(g, check_unused); if (each_lib_rpath) codegen_set_each_lib_rpath(g, each_lib_rpath); diff --git a/src/parser.cpp b/src/parser.cpp index b55eefe6ac980ad45894c976b9c998e1e12afa4a..2ae51047e5ab84f09913284f9b55028d104f363b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2417,6 +2417,27 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, size_t *token_index return node; } +/* +TestDecl = "test" String Block +*/ +static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index, VisibMod visib_mod) { + Token *first_token = &pc->tokens->at(*token_index); + + if (first_token->id != TokenIdKeywordTest) { + return nullptr; + } + *token_index += 1; + + Token *name_tok = ast_eat_token(pc, token_index, TokenIdStringLiteral); + + AstNode *node = ast_create_node(pc, NodeTypeTestDecl, first_token); + node->data.test_decl.visib_mod = visib_mod; + node->data.test_decl.name = token_buf(name_tok); + node->data.test_decl.body = ast_parse_block(pc, token_index, true); + + return node; +} + /* TypeDecl = "type" "Symbol" "=" TypeExpr ";" */ @@ -2443,7 +2464,7 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index, Visib } /* -TopLevelItem = ErrorValueDecl | Block | TopLevelDecl +TopLevelItem = ErrorValueDecl | Block | TopLevelDecl | TestDecl TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | TypeDecl | UseDecl) */ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList *top_level_decls) { @@ -2491,6 +2512,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig continue; } + AstNode *test_decl_node = ast_parse_test_decl_node(pc, token_index, visib_mod); + if (test_decl_node) { + top_level_decls->append(test_decl_node); + continue; + } + AstNode *type_decl_node = ast_parse_type_decl(pc, token_index, visib_mod); if (type_decl_node) { top_level_decls->append(type_decl_node); @@ -2585,6 +2612,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont case NodeTypeErrorValueDecl: // none break; + case NodeTypeTestDecl: + visit_field(&node->data.test_decl.body, visit, context); + break; case NodeTypeBinOpExpr: visit_field(&node->data.bin_op_expr.op1, visit, context); visit_field(&node->data.bin_op_expr.op2, visit, context); diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index deaa2a6ef40e2d1f3fc243ecfc0de5ad3324476f..640cd1ffeaca754ef2c2b8fe3924ee6e64828d43 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -133,6 +133,7 @@ static const struct ZigKeyword zig_keywords[] = { {"return", TokenIdKeywordReturn}, {"struct", TokenIdKeywordStruct}, {"switch", TokenIdKeywordSwitch}, + {"test", TokenIdKeywordTest}, {"this", TokenIdKeywordThis}, {"true", TokenIdKeywordTrue}, {"try", TokenIdKeywordTry}, @@ -1508,6 +1509,7 @@ const char * token_name(TokenId id) { case TokenIdKeywordReturn: return "return"; case TokenIdKeywordStruct: return "struct"; case TokenIdKeywordSwitch: return "switch"; + case TokenIdKeywordTest: return "test"; case TokenIdKeywordThis: return "this"; case TokenIdKeywordTrue: return "true"; case TokenIdKeywordTry: return "try"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index a5cbe4cdea231f4f16103501a95c70edd4eb8c7a..008bcde8539ae0d5af8ecfec4b0184275459407f 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -74,6 +74,7 @@ enum TokenId { TokenIdKeywordReturn, TokenIdKeywordStruct, TokenIdKeywordSwitch, + TokenIdKeywordTest, TokenIdKeywordThis, TokenIdKeywordTrue, TokenIdKeywordTry, diff --git a/std/compiler_rt.zig b/std/compiler_rt.zig index 2e05de91253526347fee6279d34c2141dd356b3e..255631a61f3fe4b41fa211d4917e7e4d7edbd351 100644 --- a/std/compiler_rt.zig +++ b/std/compiler_rt.zig @@ -322,9 +322,7 @@ export fn __udivsi3(n: su_int, d: su_int) -> su_int { return q; } -fn test_umoddi3() { - @setFnTest(this); - +test "test_umoddi3" { test_one_umoddi3(0, 1, 0); test_one_umoddi3(2, 1, 0); test_one_umoddi3(0x8000000000000000, 1, 0x0); @@ -337,9 +335,7 @@ fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) { assert(r == expected_r); } -fn test_udivmoddi4() { - @setFnTest(this); - +test "test_udivmoddi4" { const cases = [][4]du_int { []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000}, []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000}, @@ -367,9 +363,7 @@ fn test_one_udivmoddi4(a: du_int, b: du_int, expected_q: du_int, expected_r: du_ assert(r == expected_r); } -fn test_udivsi3() { - @setFnTest(this); - +test "test_udivsi3" { const cases = [][3]su_int { []su_int{0x00000000, 0x00000001, 0x00000000}, []su_int{0x00000000, 0x00000002, 0x00000000}, diff --git a/std/cstr.zig b/std/cstr.zig index a34f3155c24f6a4523d21f5bc9bf5c49519b22c2..ab250474df905e5012f95a409e53a05e40c9bf29 100644 --- a/std/cstr.zig +++ b/std/cstr.zig @@ -140,9 +140,7 @@ pub const Buffer0 = struct { } }; -fn testSimpleBuffer0() { - @setFnTest(this); - +test "simple Buffer0" { var buf = %%Buffer0.initEmpty(&debug.global_allocator); assert(buf.len() == 0); %%buf.appendCStr(c"hello"); @@ -162,9 +160,7 @@ fn testSimpleBuffer0() { assert(buf.startsWithOther(&buf2)); } -fn testCStrFns() { - @setFnTest(this); - +test "cstr fns" { comptime testCStrFnsImpl(); testCStrFnsImpl(); } diff --git a/std/fmt.zig b/std/fmt.zig index 0203954d70972a18dc8d52ffcd19e65b7a099759..104573703342915aa17bcd743f4e78458049a6f9 100644 --- a/std/fmt.zig +++ b/std/fmt.zig @@ -291,9 +291,7 @@ fn digitToChar(digit: u8, uppercase: bool) -> u8 { }; } -fn testBufPrintInt() { - @setFnTest(this); - +test "testBufPrintInt" { var buffer: [max_int_digits]u8 = undefined; const buf = buffer[0...]; assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110")); @@ -315,9 +313,7 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: u return buf[0...formatIntBuf(buf, value, base, uppercase, width)]; } -fn testParseU64DigitTooBig() { - @setFnTest(this); - +test "testParseU64DigitTooBig" { parseUnsigned(u64, "123a", 10) %% |err| { if (err == error.InvalidChar) return; @unreachable(); @@ -325,9 +321,7 @@ fn testParseU64DigitTooBig() { @unreachable(); } -fn testParseUnsignedComptime() { - @setFnTest(this); - +test "testParseUnsignedComptime" { comptime { assert(%%parseUnsigned(usize, "2", 10) == 2); } diff --git a/std/hash_map.zig b/std/hash_map.zig index 5cfe0743dbdf56297e102abdd30079eeb4be6a17..c22e3712a017d21b4dc34d8304e0413dc8e1b891 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -219,9 +219,7 @@ pub fn HashMap(comptime K: type, comptime V: type, } } -fn basicHashMapTest() { - @setFnTest(this); - +test "basicHashMapTest" { var map: HashMap(i32, i32, hash_i32, eql_i32) = undefined; map.init(&debug.global_allocator); defer map.deinit(); diff --git a/std/list.zig b/std/list.zig index 7758bd596b34fdb8c28dd09501edf79b2740a11c..c54332d9ef92db0fdd06ebd60d708900ba99fab1 100644 --- a/std/list.zig +++ b/std/list.zig @@ -64,9 +64,7 @@ pub fn List(comptime T: type) -> type{ } } -fn basicListTest() { - @setFnTest(this); - +test "basicListTest" { var list = List(i32).init(&debug.global_allocator); defer list.deinit(); diff --git a/std/math.zig b/std/math.zig index cc2eb44795d7670334c4f1618014765bc0bbb31e..711e1de453fb66ab8ecdd6d529d6e35b64e2cdfa 100644 --- a/std/math.zig +++ b/std/math.zig @@ -68,9 +68,7 @@ fn getReturnTypeForAbs(comptime T: type) -> type { } } -fn testMath() { - @setFnTest(this); - +test "testMath" { testMathImpl(); comptime testMathImpl(); } diff --git a/std/mem.zig b/std/mem.zig index dba0422081042d644d70f2ef691e21a2eed94049..c67cf11db62a7c1c24405ca0a6f3851d5d110cf2 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -117,17 +117,13 @@ pub fn writeInt(buf: []u8, value: var, big_endian: bool) { assert(bits == 0); } -fn testStringEquality() { - @setFnTest(this); - +test "testStringEquality" { assert(eql(u8, "abcd", "abcd")); assert(!eql(u8, "abcdef", "abZdef")); assert(!eql(u8, "abcdefg", "abcdef")); } -fn testReadInt() { - @setFnTest(this); - +test "testReadInt" { testReadIntImpl(); comptime testReadIntImpl(); } @@ -149,9 +145,7 @@ fn testReadIntImpl() { } } -fn testWriteInt() { - @setFnTest(this); - +test "testWriteInt" { testWriteIntImpl(); comptime testWriteIntImpl(); } diff --git a/std/rand.zig b/std/rand.zig index a36ca4a9ca93b563e2ab332487f2c335d093c1f2..dab451b725c550333a22eaff19ac8232cf10c334 100644 --- a/std/rand.zig +++ b/std/rand.zig @@ -158,9 +158,7 @@ fn MersenneTwister( } } -fn testFloat32() { - @setFnTest(this); - +test "testFloat32" { var r: Rand = undefined; r.init(42); @@ -171,9 +169,7 @@ fn testFloat32() { }} } -fn testMT19937_64() { - @setFnTest(this); - +test "testMT19937_64" { var rng: MT19937_64 = undefined; rng.init(rand_test.mt64_seed); for (rand_test.mt64_data) |value| { @@ -181,9 +177,7 @@ fn testMT19937_64() { } } -fn testMT19937_32() { - @setFnTest(this); - +test "testMT19937_32" { var rng: MT19937_32 = undefined; rng.init(rand_test.mt32_seed); for (rand_test.mt32_data) |value| { diff --git a/std/sort.zig b/std/sort.zig index 23fd1eba3472b870a419e6b5e12fea477e2dd420..ca1481ca17ecf669e157bc1803cecc10a8816515 100644 --- a/std/sort.zig +++ b/std/sort.zig @@ -58,9 +58,7 @@ fn reverse(was: Cmp) -> Cmp { // --------------------------------------- // tests -fn testSort() { - @setFnTest(this); - +test "testSort" { const u8cases = [][]const []const u8 { [][]const u8{"", ""}, [][]const u8{"a", "a"}, @@ -96,9 +94,7 @@ fn testSort() { } } -fn testSortDesc() { - @setFnTest(this); - +test "testSortDesc" { const rev_cases = [][]const []const i32 { [][]const i32{[]i32{}, []i32{}}, [][]const i32{[]i32{1}, []i32{1}}, diff --git a/test/cases/array.zig b/test/cases/array.zig index 3b91efbc203e2f3419fe2bd2acfe3e299e8f6c6a..789e549c55b1bef2a801a715a8bf03cc01e1d294 100644 --- a/test/cases/array.zig +++ b/test/cases/array.zig @@ -1,9 +1,7 @@ const assert = @import("std").debug.assert; const mem = @import("std").mem; -fn arrays() { - @setFnTest(this); - +test "arrays" { var array : [5]u32 = undefined; var i : u32 = 0; @@ -27,9 +25,7 @@ fn getArrayLen(a: []const u32) -> usize { a.len } -fn voidArrays() { - @setFnTest(this); - +test "voidArrays" { var array: [4]void = undefined; array[0] = void{}; array[1] = array[2]; @@ -37,18 +33,14 @@ fn voidArrays() { assert(array.len == 4); } -fn arrayLiteral() { - @setFnTest(this); - +test "arrayLiteral" { const hex_mult = []u16{4096, 256, 16, 1}; assert(hex_mult.len == 4); assert(hex_mult[1] == 256); } -fn arrayDotLenConstExpr() { - @setFnTest(this); - +test "arrayDotLenConstExpr" { assert(comptime {some_array.len == 4}); } @@ -58,9 +50,7 @@ const ArrayDotLenConstExpr = struct { const some_array = []u8 {0, 1, 2, 3}; -fn nestedArrays() { - @setFnTest(this); - +test "nestedArrays" { const array_of_strings = [][]const u8 {"hello", "this", "is", "my", "thing"}; for (array_of_strings) |s, i| { if (i == 0) assert(mem.eql(u8, s, "hello")); @@ -79,9 +69,7 @@ const Sub = struct { const Str = struct { a: []Sub, }; -fn setGlobalVarArrayViaSliceEmbeddedInStruct() { - @setFnTest(this); - +test "setGlobalVarArrayViaSliceEmbeddedInStruct" { var s = Str { .a = s_array[0...]}; s.a[0].b = 1; diff --git a/test/cases/atomics.zig b/test/cases/atomics.zig index 2b232bbf6923eb8b13a3fe6e16bd22606b64b571..b11c5229c05cb978549942aa591b0036c3591ec9 100644 --- a/test/cases/atomics.zig +++ b/test/cases/atomics.zig @@ -1,16 +1,12 @@ const assert = @import("std").debug.assert; -fn cmpxchg() { - @setFnTest(this); - +test "cmpxchg" { var x: i32 = 1234; while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.SeqCst, AtomicOrder.SeqCst)) {} assert(x == 5678); } -fn fence() { - @setFnTest(this); - +test "fence" { var x: i32 = 1234; @fence(AtomicOrder.SeqCst); x = 5678; diff --git a/test/cases/bool.zig b/test/cases/bool.zig index fce22d86ae1d006cda4b47df01a7f4cb1882748f..c05387ef9f5486d953e2a6efb6974ec3332296dd 100644 --- a/test/cases/bool.zig +++ b/test/cases/bool.zig @@ -1,15 +1,11 @@ const assert = @import("std").debug.assert; -fn boolLiterals() { - @setFnTest(this); - +test "boolLiterals" { assert(true); assert(!false); } -fn castBoolToInt() { - @setFnTest(this); - +test "castBoolToInt" { const t = true; const f = false; assert(i32(t) == i32(1)); @@ -22,18 +18,14 @@ fn nonConstCastBoolToInt(t: bool, f: bool) { assert(i32(f) == i32(0)); } -fn boolCmp() { - @setFnTest(this); - +test "boolCmp" { assert(testBoolCmp(true, false) == false); } fn testBoolCmp(a: bool, b: bool) -> bool { a == b } -fn shortCircuitAndOr() { - @setFnTest(this); - +test "shortCircuitAndOr" { var a = true; a &&= false; assert(!a); @@ -49,9 +41,7 @@ const global_f = false; const global_t = true; const not_global_f = !global_f; const not_global_t = !global_t; -fn compileTimeBoolnot() { - @setFnTest(this); - +test "compileTimeBoolnot" { assert(not_global_f); assert(!not_global_t); } diff --git a/test/cases/cast.zig b/test/cases/cast.zig index a7bef9ded5cf87e6d708e381c06d5ae3c1d41ac6..928b6313397e583e82b4b51ae40557601e0ae370 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -1,24 +1,18 @@ const assert = @import("std").debug.assert; -fn intToPtrCast() { - @setFnTest(this); - +test "intToPtrCast" { const x = isize(13); const y = (&u8)(x); const z = usize(y); assert(z == 13); } -fn numLitIntToPtrCast() { - @setFnTest(this); - +test "numLitIntToPtrCast" { const vga_mem = (&u16)(0xB8000); assert(usize(vga_mem) == 0xB8000); } -fn pointerReinterpretConstFloatToInt() { - @setFnTest(this); - +test "pointerReinterpretConstFloatToInt" { const float: f64 = 5.99999999999994648725e-01; const float_ptr = &float; const int_ptr = (&i32)(float_ptr); diff --git a/test/cases/const_slice_child.zig b/test/cases/const_slice_child.zig index 21c9d03e5055930da592710796a61980f872b239..8a022307c3485db0be74fa8335d19f7fe899c462 100644 --- a/test/cases/const_slice_child.zig +++ b/test/cases/const_slice_child.zig @@ -2,9 +2,7 @@ const assert = @import("std").debug.assert; var argv: &const &const u8 = undefined; -fn constSliceChild() { - @setFnTest(this); - +test "constSliceChild" { const strs = ([]&const u8) { c"one", c"two", diff --git a/test/cases/defer.zig b/test/cases/defer.zig index 4bff9fab811e307d25b9ea7c8f90c0957e777627..ecee63bf89c84a3bab916e7053010b438877a62c 100644 --- a/test/cases/defer.zig +++ b/test/cases/defer.zig @@ -21,9 +21,7 @@ fn runSomeMaybeDefers(x: bool) -> ?bool { return if (x) x else null; } -fn mixingNormalAndErrorDefers() { - @setFnTest(this); - +test "mixingNormalAndErrorDefers" { assert(%%runSomeErrorDefers(true)); assert(result[0] == 'c'); assert(result[1] == 'a'); @@ -38,9 +36,7 @@ fn mixingNormalAndErrorDefers() { assert(result[2] == 'a'); } -fn mixingNormalAndMaybeDefers() { - @setFnTest(this); - +test "mixingNormalAndMaybeDefers" { assert(??runSomeMaybeDefers(true)); assert(result[0] == 'c'); assert(result[1] == 'a'); diff --git a/test/cases/enum.zig b/test/cases/enum.zig index 37ba0fe4ecf8b07a9ac5cdecbb1a525e1a5f6524..d3534115b594756ef04909e5d5e3f496c8a5ac84 100644 --- a/test/cases/enum.zig +++ b/test/cases/enum.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn enumType() { - @setFnTest(this); - +test "enumType" { const foo1 = Foo.One {13}; const foo2 = Foo.Two { Point { .x = 1234, .y = 5678, }}; const bar = Bar.B; @@ -15,9 +13,7 @@ fn enumType() { assert(@sizeOf(Bar) == 1); } -fn enumAsReturnValue () { - @setFnTest(this); - +test "enumAsReturnValue" { switch (returnAnInt(13)) { Foo.One => |value| assert(value == 13), else => @unreachable(), @@ -45,9 +41,7 @@ fn returnAnInt(x: i32) -> Foo { } -fn constantEnumWithPayload() { - @setFnTest(this); - +test "constantEnumWithPayload" { var empty = AnEnumWithPayload.Empty; var full = AnEnumWithPayload.Full {13}; shouldBeEmpty(empty); @@ -83,9 +77,7 @@ const Number = enum { Four, }; -fn enumToInt() { - @setFnTest(this); - +test "enumToInt" { shouldEqual(Number.Zero, 0); shouldEqual(Number.One, 1); shouldEqual(Number.Two, 2); @@ -98,9 +90,7 @@ fn shouldEqual(n: Number, expected: usize) { } -fn intToEnum() { - @setFnTest(this); - +test "intToEnum" { testIntToEnumEval(3); } fn testIntToEnumEval(x: i32) { diff --git a/test/cases/enum_with_members.zig b/test/cases/enum_with_members.zig index 36c7b5d175c873ee9a18abdeb6c716f9473fc061..865400c537166e0f6729153cc7b317dc668cc5ef 100644 --- a/test/cases/enum_with_members.zig +++ b/test/cases/enum_with_members.zig @@ -14,9 +14,7 @@ const ET = enum { } }; -fn enumWithMembers() { - @setFnTest(this); - +test "enumWithMembers" { const a = ET.SINT { -42 }; const b = ET.UINT { 42 }; var buf: [20]u8 = undefined; diff --git a/test/cases/error.zig b/test/cases/error.zig index eeed33714125af1318bb686419b92b0c33034621..27e45e9996105bbab9a1fbbf89d85e2afc9a1f97 100644 --- a/test/cases/error.zig +++ b/test/cases/error.zig @@ -15,9 +15,7 @@ pub fn baz() -> %i32 { return y + 1; } -fn errorWrapping() { - @setFnTest(this); - +test "errorWrapping" { assert(%%baz() == 15); } @@ -26,8 +24,7 @@ fn gimmeItBroke() -> []const u8 { @errorName(error.ItBroke) } -fn errorName() { - @setFnTest(this); +test "errorName" { assert(mem.eql(u8, @errorName(error.AnError), "AnError")); assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); } @@ -35,9 +32,7 @@ error AnError; error ALongerErrorName; -fn errorValues() { - @setFnTest(this); - +test "errorValues" { const a = i32(error.err1); const b = i32(error.err2); assert(a != b); @@ -46,9 +41,7 @@ error err1; error err2; -fn redefinitionOfErrorValuesAllowed() { - @setFnTest(this); - +test "redefinitionOfErrorValuesAllowed" { shouldBeNotEqual(error.AnError, error.SecondError); } error AnError; @@ -59,9 +52,7 @@ fn shouldBeNotEqual(a: error, b: error) { } -fn errBinaryOperator() { - @setFnTest(this); - +test "errBinaryOperator" { const a = errBinaryOperatorG(true) %% 3; const b = errBinaryOperatorG(false) %% 3; assert(a == 3); @@ -77,18 +68,14 @@ fn errBinaryOperatorG(x: bool) -> %isize { } -fn unwrapSimpleValueFromError() { - @setFnTest(this); - +test "unwrapSimpleValueFromError" { const i = %%unwrapSimpleValueFromErrorDo(); assert(i == 13); } fn unwrapSimpleValueFromErrorDo() -> %isize { 13 } -fn errReturnInAssignment() { - @setFnTest(this); - +test "errReturnInAssignment" { %%doErrReturnInAssignment(); } diff --git a/test/cases/eval.zig b/test/cases/eval.zig index 4e7c94f2d3e8564b98e41086d79105fa1caeca58..f66bba09918ae75fe5ccbb3b7207286bf941ab81 100644 --- a/test/cases/eval.zig +++ b/test/cases/eval.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn compileTimeRecursion() { - @setFnTest(this); - +test "compileTimeRecursion" { assert(some_data.len == 21); } var some_data: [usize(fibonacci(7))]u8 = undefined; @@ -17,14 +15,11 @@ fn unwrapAndAddOne(blah: ?i32) -> i32 { return ??blah + 1; } const should_be_1235 = unwrapAndAddOne(1234); -fn testStaticAddOne() { - @setFnTest(this); +test "testStaticAddOne" { assert(should_be_1235 == 1235); } -fn inlinedLoop() { - @setFnTest(this); - +test "inlinedLoop" { comptime var i = 0; comptime var sum = 0; inline while (i <= 5; i += 1) @@ -38,25 +33,20 @@ fn gimme1or2(comptime a: bool) -> i32 { comptime var z: i32 = if (a) x else y; return z; } -fn inlineVariableGetsResultOfConstIf() { - @setFnTest(this); +test "inlineVariableGetsResultOfConstIf" { assert(gimme1or2(true) == 1); assert(gimme1or2(false) == 2); } -fn staticFunctionEvaluation() { - @setFnTest(this); - +test "staticFunctionEvaluation" { assert(statically_added_number == 3); } const statically_added_number = staticAdd(1, 2); fn staticAdd(a: i32, b: i32) -> i32 { a + b } -fn constExprEvalOnSingleExprBlocks() { - @setFnTest(this); - +test "constExprEvalOnSingleExprBlocks" { assert(constExprEvalOnSingleExprBlocksFn(1, true) == 3); } @@ -75,9 +65,7 @@ fn constExprEvalOnSingleExprBlocksFn(x: i32, b: bool) -> i32 { -fn staticallyInitalizedList() { - @setFnTest(this); - +test "staticallyInitalizedList" { assert(static_point_list[0].x == 1); assert(static_point_list[0].y == 2); assert(static_point_list[1].x == 3); @@ -96,9 +84,7 @@ fn makePoint(x: i32, y: i32) -> Point { } -fn staticEvalListInit() { - @setFnTest(this); - +test "staticEvalListInit" { assert(static_vec3.data[2] == 1.0); assert(vec3(0.0, 0.0, 3.0).data[2] == 3.0); } @@ -113,18 +99,14 @@ pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 { } -fn constantExpressions() { - @setFnTest(this); - +test "constantExpressions" { var array : [array_size]u8 = undefined; assert(@sizeOf(@typeOf(array)) == 20); } const array_size : u8 = 20; -fn constantStructWithNegation() { - @setFnTest(this); - +test "constantStructWithNegation" { assert(vertices[0].x == -0.6); } const Vertex = struct { @@ -141,9 +123,7 @@ const vertices = []Vertex { }; -fn staticallyInitalizedStruct() { - @setFnTest(this); - +test "staticallyInitalizedStruct" { st_init_str_foo.x += 1; assert(st_init_str_foo.x == 14); } @@ -154,18 +134,14 @@ const StInitStrFoo = struct { var st_init_str_foo = StInitStrFoo { .x = 13, .y = true, }; -fn staticallyInitializedArrayLiteral() { - @setFnTest(this); - +test "staticallyInitializedArrayLiteral" { const y : [4]u8 = st_init_arr_lit_x; assert(y[3] == 4); } const st_init_arr_lit_x = []u8{1,2,3,4}; -fn constSlice() { - @setFnTest(this); - +test "constSlice" { comptime { const a = "1234567890"; assert(a.len == 10); @@ -175,9 +151,7 @@ fn constSlice() { } } -fn tryToTrickEvalWithRuntimeIf() { - @setFnTest(this); - +test "tryToTrickEvalWithRuntimeIf" { assert(testTryToTrickEvalWithRuntimeIf(true) == 10); } @@ -203,9 +177,7 @@ fn max(comptime T: type, a: T, b: T) -> T { fn letsTryToCompareBools(a: bool, b: bool) -> bool { max(bool, a, b) } -fn inlinedBlockAndRuntimeBlockPhi() { - @setFnTest(this); - +test "inlinedBlockAndRuntimeBlockPhi" { assert(letsTryToCompareBools(true, true)); assert(letsTryToCompareBools(true, false)); assert(letsTryToCompareBools(false, true)); @@ -244,17 +216,13 @@ fn performFn(comptime prefix_char: u8, start_value: i32) -> i32 { return result; } -fn comptimeIterateOverFnPtrList() { - @setFnTest(this); - +test "comptimeIterateOverFnPtrList" { assert(performFn('t', 1) == 6); assert(performFn('o', 0) == 1); assert(performFn('w', 99) == 99); } -fn evalSetDebugSafetyAtCompileTime() { - @setFnTest(this); - +test "evalSetDebugSafetyAtCompileTime" { const result = comptime fnWithSetDebugSafety(); assert(result == 1234); } @@ -278,17 +246,13 @@ var simple_struct = SimpleStruct{ .field = 1234, }; const bound_fn = simple_struct.method; -fn callMethodOnBoundFnReferringToVarInstance() { - @setFnTest(this); - +test "callMethodOnBoundFnReferringToVarInstance" { assert(bound_fn() == 1237); } -fn ptrToLocalArrayArgumentAtComptime() { - @setFnTest(this); - +test "ptrToLocalArrayArgumentAtComptime" { comptime { var bytes: [10]u8 = undefined; modifySomeBytes(bytes[0...]); diff --git a/test/cases/fn.zig b/test/cases/fn.zig index b8d801824e2c9d5dbac416c15974a50b0925e984..a58bf614f333c20b7af93cf42271c0b4edda90f4 100644 --- a/test/cases/fn.zig +++ b/test/cases/fn.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn params() { - @setFnTest(this); - +test "params" { assert(testParamsAdd(22, 11) == 33); } fn testParamsAdd(a: i32, b: i32) -> i32 { @@ -10,9 +8,7 @@ fn testParamsAdd(a: i32, b: i32) -> i32 { } -fn localVariables() { - @setFnTest(this); - +test "localVariables" { testLocVars(2); } fn testLocVars(b: i32) { @@ -21,9 +17,7 @@ fn testLocVars(b: i32) { } -fn voidParameters() { - @setFnTest(this); - +test "voidParameters" { voidFun(1, void{}, 2, {}); } fn voidFun(a: i32, b: void, c: i32, d: void) { @@ -34,9 +28,7 @@ fn voidFun(a: i32, b: void, c: i32, d: void) { } -fn mutableLocalVariables() { - @setFnTest(this); - +test "mutableLocalVariables" { var zero : i32 = 0; assert(zero == 0); @@ -47,9 +39,7 @@ fn mutableLocalVariables() { assert(i == 3); } -fn separateBlockScopes() { - @setFnTest(this); - +test "separateBlockScopes" { { const no_conflict : i32 = 5; assert(no_conflict == 5); @@ -62,22 +52,21 @@ fn separateBlockScopes() { assert(c == 10); } -fn callFnWithEmptyString() { - @setFnTest(this); - +test "callFnWithEmptyString" { acceptsString(""); } fn acceptsString(foo: []u8) { } -fn @"weird function name"() { - @setFnTest(this); +fn @"weird function name"() -> i32 { + return 1234; +} +test "weird function name" { + assert(@"weird function name"() == 1234); } -fn implicitCastFnUnreachableReturn() { - @setFnTest(this); - +test "implicitCastFnUnreachableReturn" { wantsFnWithVoid(fnWithUnreachable); } @@ -88,9 +77,7 @@ fn fnWithUnreachable() -> unreachable { } -fn functionPointers() { - @setFnTest(this); - +test "functionPointers" { const fns = []@typeOf(fn1) { fn1, fn2, fn3, fn4, }; for (fns) |f, i| { assert(f() == u32(i) + 5); diff --git a/test/cases/for.zig b/test/cases/for.zig index b7e9fba295a1bf1e8f023b1ea211292fc50c4554..f18b342fa2bf44f65312632a6070ff7d9b02adb5 100644 --- a/test/cases/for.zig +++ b/test/cases/for.zig @@ -2,9 +2,7 @@ const std = @import("std"); const assert = std.debug.assert; const mem = std.mem; -fn continueInForLoop() { - @setFnTest(this); - +test "continueInForLoop" { const array = []i32 {1, 2, 3, 4, 5}; var sum : i32 = 0; for (array) |x| { @@ -17,9 +15,7 @@ fn continueInForLoop() { if (sum != 6) @unreachable() } -fn forLoopWithPointerElemVar() { - @setFnTest(this); - +test "forLoopWithPointerElemVar" { const source = "abcdefg"; var target: [source.len]u8 = undefined; mem.copy(u8, target[0...], source); @@ -32,9 +28,7 @@ fn mangleString(s: []u8) { } } -fn basicForLoop() { - @setFnTest(this); - +test "basicForLoop" { const expected_result = []u8{9, 8, 7, 6, 0, 1, 2, 3, 9, 8, 7, 6, 0, 1, 2, 3 }; var buffer: [expected_result.len]u8 = undefined; diff --git a/test/cases/generics.zig b/test/cases/generics.zig index dcdb5086e16e9126d174a7ea2e250db7a0c68252..c23b189dc313b8117e4c8298314d5842b2e5c535 100644 --- a/test/cases/generics.zig +++ b/test/cases/generics.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn simpleGenericFn() { - @setFnTest(this); - +test "simpleGenericFn" { assert(max(i32, 3, -1) == 3); assert(max(f32, 0.123, 0.456) == 0.456); assert(add(2, 3) == 5); @@ -17,8 +15,7 @@ fn add(comptime a: i32, b: i32) -> i32 { } const the_max = max(u32, 1234, 5678); -fn compileTimeGenericEval() { - @setFnTest(this); +test "compileTimeGenericEval" { assert(the_max == 5678); } @@ -34,18 +31,14 @@ fn sameButWithFloats(a: f64, b: f64) -> f64 { max(f64, a, b) } -fn fnWithInlineArgs() { - @setFnTest(this); - +test "fnWithInlineArgs" { assert(gimmeTheBigOne(1234, 5678) == 5678); assert(shouldCallSameInstance(34, 12) == 34); assert(sameButWithFloats(0.43, 0.49) == 0.49); } -fn varParams() { - @setFnTest(this); - +test "varParams" { assert(max_i32(12, 34) == 34); assert(max_f64(1.2, 3.4) == 3.4); } @@ -79,9 +72,7 @@ pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type { } } -fn functionWithReturnTypeType() { - @setFnTest(this); - +test "functionWithReturnTypeType" { var list: List(i32) = undefined; var list2: List(i32) = undefined; list.length = 10; @@ -91,9 +82,7 @@ fn functionWithReturnTypeType() { } -fn genericStruct() { - @setFnTest(this); - +test "genericStruct" { var a1 = GenNode(i32) {.value = 13, .next = null,}; var b1 = GenNode(bool) {.value = true, .next = null,}; assert(a1.value == 13); @@ -108,9 +97,7 @@ fn GenNode(comptime T: type) -> type { } } -fn constDeclsInStruct() { - @setFnTest(this); - +test "constDeclsInStruct" { assert(GenericDataThing(3).count_plus_one == 4); } fn GenericDataThing(comptime count: isize) -> type { @@ -120,9 +107,7 @@ fn GenericDataThing(comptime count: isize) -> type { } -fn useGenericParamInGenericParam() { - @setFnTest(this); - +test "useGenericParamInGenericParam" { assert(aGenericFn(i32, 3, 4) == 7); } fn aGenericFn(comptime T: type, comptime a: T, b: T) -> T { @@ -130,9 +115,7 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) -> T { } -fn genericFnWithImplicitCast() { - @setFnTest(this); - +test "genericFnWithImplicitCast" { assert(getFirstByte(u8, []u8 {13}) == 13); assert(getFirstByte(u16, []u16 {0, 13}) == 0); } diff --git a/test/cases/goto.zig b/test/cases/goto.zig index 155aa5cdbe3ebb4f686a87dfbc7712647c10e50f..b4a3af8adbfd3cbf3c042061f19f2ef687fbead4 100644 --- a/test/cases/goto.zig +++ b/test/cases/goto.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn gotoAndLabels() { - @setFnTest(this); - +test "gotoAndLabels" { gotoLoop(); assert(goto_counter == 10); } @@ -21,9 +19,7 @@ var goto_counter: i32 = 0; -fn gotoLeaveDeferScope() { - @setFnTest(this); - +test "gotoLeaveDeferScope" { testGotoLeaveDeferScope(true); } fn testGotoLeaveDeferScope(b: bool) { diff --git a/test/cases/if.zig b/test/cases/if.zig index a3681a463478b65b01c3b3376272df937b9ce016..7cff1c1a5685b455f9d8ceadc9aeaef7bfd33193 100644 --- a/test/cases/if.zig +++ b/test/cases/if.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn ifStatements() { - @setFnTest(this); - +test "ifStatements" { shouldBeEqual(1, 1); firstEqlThird(2, 1, 2); } @@ -26,9 +24,7 @@ fn firstEqlThird(a: i32, b: i32, c: i32) { } -fn elseIfExpression() { - @setFnTest(this); - +test "elseIfExpression" { assert(elseIfExpressionF(1) == 1); } fn elseIfExpressionF(c: u8) -> u8 { diff --git a/test/cases/import.zig b/test/cases/import.zig index 6787afecf939a68042fca7470124204bf39683a4..b5bbbc211423663233d0508decf0e305d6ab67e8 100644 --- a/test/cases/import.zig +++ b/test/cases/import.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; const a_namespace = @import("cases/import/a_namespace.zig"); -fn callFnViaNamespaceLookup() { - @setFnTest(this); - +test "callFnViaNamespaceLookup" { assert(a_namespace.foo() == 1234); } diff --git a/test/cases/ir_block_deps.zig b/test/cases/ir_block_deps.zig index 9ba03b803134b5a265cb76319b4d195fc3b89d07..ab3ea2b0defb895d4cae5d6ff040fc8211d28505 100644 --- a/test/cases/ir_block_deps.zig +++ b/test/cases/ir_block_deps.zig @@ -15,9 +15,7 @@ fn getErrInt() -> %i32 { 0 } error ItBroke; -fn irBlockDeps() { - @setFnTest(this); - +test "irBlockDeps" { assert(%%foo(1) == 0); assert(%%foo(2) == 0); } diff --git a/test/cases/math.zig b/test/cases/math.zig index fc1555ef14e69e73952feddc50f9e3036d382ac7..3171c526d81ff2ffd00eb3140816b57a01123831 100644 --- a/test/cases/math.zig +++ b/test/cases/math.zig @@ -1,60 +1,46 @@ const assert = @import("std").debug.assert; -fn exactDivision() { - @setFnTest(this); - +test "exactDivision" { assert(divExact(55, 11) == 5); } fn divExact(a: u32, b: u32) -> u32 { @divExact(a, b) } -fn floatDivision() { - @setFnTest(this); - +test "floatDivision" { assert(fdiv32(12.0, 3.0) == 4.0); } fn fdiv32(a: f32, b: f32) -> f32 { a / b } -fn overflowIntrinsics() { - @setFnTest(this); - +test "overflowIntrinsics" { var result: u8 = undefined; assert(@addWithOverflow(u8, 250, 100, &result)); assert(!@addWithOverflow(u8, 100, 150, &result)); assert(result == 250); } -fn shlWithOverflow() { - @setFnTest(this); - +test "shlWithOverflow" { var result: u16 = undefined; assert(@shlWithOverflow(u16, 0b0010111111111111, 3, &result)); assert(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result)); assert(result == 0b1011111111111100); } -fn countLeadingZeroes() { - @setFnTest(this); - +test "countLeadingZeroes" { assert(@clz(u8(0b00001010)) == 4); assert(@clz(u8(0b10001010)) == 0); assert(@clz(u8(0b00000000)) == 8); } -fn countTrailingZeroes() { - @setFnTest(this); - +test "countTrailingZeroes" { assert(@ctz(u8(0b10100000)) == 5); assert(@ctz(u8(0b10001010)) == 1); assert(@ctz(u8(0b00000000)) == 8); } -fn modifyOperators() { - @setFnTest(this); - +test "modifyOperators" { var i : i32 = 0; i += 5; assert(i == 5); i -= 2; assert(i == 3); @@ -70,9 +56,7 @@ fn modifyOperators() { i |= 3; assert(i == 7); } -fn threeExprInARow() { - @setFnTest(this); - testThreeExprInARow(false, true); +test "threeExprInARow" { } fn testThreeExprInARow(f: bool, t: bool) { assertFalse(f || f || f); @@ -94,9 +78,7 @@ fn assertFalse(b: bool) { } -fn constNumberLiteral() { - @setFnTest(this); - +test "constNumberLiteral" { const one = 1; const eleven = ten + one; @@ -106,9 +88,7 @@ const ten = 10; -fn unsignedWrapping() { - @setFnTest(this); - +test "unsignedWrapping" { testUnsignedWrappingEval(@maxValue(u32)); } fn testUnsignedWrappingEval(x: u32) { @@ -118,9 +98,7 @@ fn testUnsignedWrappingEval(x: u32) { assert(orig == @maxValue(u32)); } -fn signedWrapping() { - @setFnTest(this); - +test "signedWrapping" { testSignedWrappingEval(@maxValue(i32)); } fn testSignedWrappingEval(x: i32) { @@ -130,9 +108,7 @@ fn testSignedWrappingEval(x: i32) { assert(max_val == @maxValue(i32)); } -fn negationWrapping() { - @setFnTest(this); - +test "negationWrapping" { testNegationWrappingEval(@minValue(i16)); } fn testNegationWrappingEval(x: i16) { @@ -141,9 +117,7 @@ fn testNegationWrappingEval(x: i16) { assert(neg == -32768); } -fn shlWrapping() { - @setFnTest(this); - +test "shlWrapping" { testShlWrappingEval(@maxValue(u16)); } fn testShlWrappingEval(x: u16) { @@ -151,9 +125,7 @@ fn testShlWrappingEval(x: u16) { assert(shifted == 65534); } -fn unsigned64BitDivision() { - @setFnTest(this); - +test "unsigned64BitDivision" { const result = div(1152921504606846976, 34359738365); assert(result.quotient == 33554432); assert(result.remainder == 100663296); @@ -169,9 +141,7 @@ const DivResult = struct { remainder: u64, }; -fn binaryNot() { - @setFnTest(this); - +test "binaryNot" { assert(comptime {~u16(0b1010101010101010) == 0b0101010101010101}); assert(comptime {~u64(2147483647) == 18446744071562067968}); testBinaryNot(0b1010101010101010); @@ -181,9 +151,7 @@ fn testBinaryNot(x: u16) { assert(~x == 0b0101010101010101); } -fn smallIntAddition() { - @setFnTest(this); - +test "smallIntAddition" { var x: @intType(false, 2) = 0; assert(x == 0); @@ -202,9 +170,7 @@ fn smallIntAddition() { assert(result == 0); } -fn testFloatEquality() { - @setFnTest(this); - +test "testFloatEquality" { const x: f64 = 0.012; const y: f64 = x + 1.0; diff --git a/test/cases/misc.zig b/test/cases/misc.zig index 601194dd3f8f77664cf3d1422e73c3f7ba339e12..28a5fcd9c7372ba2014faa36055ff41e858b0d54 100644 --- a/test/cases/misc.zig +++ b/test/cases/misc.zig @@ -5,23 +5,21 @@ const cstr = @import("std").cstr; // normal comment /// this is a documentation comment /// doc comment line 2 -fn emptyFunctionWithComments() { - @setFnTest(this); +fn emptyFunctionWithComments() {} + +test "emptyFunctionWithComments" { + emptyFunctionWithComments(); } export fn disabledExternFn() { @setFnVisible(this, false); } -fn callDisabledExternFn() { - @setFnTest(this); - +test "callDisabledExternFn" { disabledExternFn(); } -fn intTypeBuiltin() { - @setFnTest(this); - +test "intTypeBuiltin" { assert(@intType(true, 8) == i8); assert(@intType(true, 16) == i16); assert(@intType(true, 32) == i32); @@ -55,9 +53,7 @@ const u63 = @intType(false, 63); const i1 = @intType(true, 1); const i63 = @intType(true, 63); -fn minValueAndMaxValue() { - @setFnTest(this); - +test "minValueAndMaxValue" { assert(@maxValue(u1) == 1); assert(@maxValue(u8) == 255); assert(@maxValue(u16) == 65535); @@ -86,9 +82,7 @@ fn minValueAndMaxValue() { assert(@minValue(i64) == -9223372036854775808); } -fn maxValueType() { - @setFnTest(this); - +test "maxValueType" { // If the type of @maxValue(i32) was i32 then this implicit cast to // u32 would not work. But since the value is a number literal, // it works fine. @@ -96,8 +90,7 @@ fn maxValueType() { assert(x == 2147483647); } -fn shortCircuit() { - @setFnTest(this); +test "shortCircuit" { testShortCircuit(false, true); } @@ -128,18 +121,14 @@ fn testShortCircuit(f: bool, t: bool) { assert(hit_4); } -fn truncate() { - @setFnTest(this); - +test "truncate" { assert(testTruncate(0x10fd) == 0xfd); } fn testTruncate(x: u32) -> u8 { @truncate(u8, x) } -fn assignToIfVarPtr() { - @setFnTest(this); - +test "assignToIfVarPtr" { var maybe_bool: ?bool = true; if (const *b ?= maybe_bool) { @@ -153,27 +142,21 @@ fn first4KeysOfHomeRow() -> []const u8 { "aoeu" } -fn ReturnStringFromFunction() { - @setFnTest(this); - +test "ReturnStringFromFunction" { assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); } const g1 : i32 = 1233 + 1; var g2 : i32 = 0; -fn globalVariables() { - @setFnTest(this); - +test "globalVariables" { assert(g2 == 0); g2 = g1; assert(g2 == 1234); } -fn memcpyAndMemsetIntrinsics() { - @setFnTest(this); - +test "memcpyAndMemsetIntrinsics" { var foo : [20]u8 = undefined; var bar : [20]u8 = undefined; @@ -183,16 +166,12 @@ fn memcpyAndMemsetIntrinsics() { if (bar[11] != 'A') @unreachable(); } -fn builtinStaticEval() { - @setFnTest(this); - +test "builtinStaticEval" { const x : i32 = comptime {1 + 2 + 3}; assert(x == comptime 6); } -fn slicing() { - @setFnTest(this); - +test "slicing" { var array : [20]i32 = undefined; array[5] = 1234; @@ -209,9 +188,7 @@ fn slicing() { } -fn constantEqualFunctionPointers() { - @setFnTest(this); - +test "constantEqualFunctionPointers" { const alias = emptyFn; assert(comptime {emptyFn == alias}); } @@ -219,27 +196,19 @@ fn constantEqualFunctionPointers() { fn emptyFn() {} -fn hexEscape() { - @setFnTest(this); - +test "hexEscape" { assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); } -fn stringConcatenation() { - @setFnTest(this); - +test "stringConcatenation" { assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); } -fn arrayMultOperator() { - @setFnTest(this); - +test "arrayMultOperator" { assert(mem.eql(u8, "ab" ** 5, "ababababab")); } -fn stringEscapes() { - @setFnTest(this); - +test "stringEscapes" { assert(mem.eql(u8, "\"", "\x22")); assert(mem.eql(u8, "\'", "\x27")); assert(mem.eql(u8, "\n", "\x0a")); @@ -249,9 +218,7 @@ fn stringEscapes() { assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69")); } -fn multilineString() { - @setFnTest(this); - +test "multilineString" { const s1 = \\one \\two) @@ -261,9 +228,7 @@ fn multilineString() { assert(mem.eql(u8, s1, s2)); } -fn multilineCString() { - @setFnTest(this); - +test "multilineCString" { const s1 = c\\one c\\two) @@ -274,9 +239,7 @@ fn multilineCString() { } -fn typeEquality() { - @setFnTest(this); - +test "typeEquality" { assert(&const u8 != &u8); } @@ -284,22 +247,17 @@ fn typeEquality() { const global_a: i32 = 1234; const global_b: &const i32 = &global_a; const global_c: &const f32 = (&const f32)(global_b); -fn compileTimeGlobalReinterpret() { - @setFnTest(this); +test "compileTimeGlobalReinterpret" { const d = (&const i32)(global_c); assert(*d == 1234); } -fn explicitCastMaybePointers() { - @setFnTest(this); - +test "explicitCastMaybePointers" { const a: ?&i32 = undefined; const b: ?&f32 = (?&f32)(a); } -fn genericMallocFree() { - @setFnTest(this); - +test "genericMallocFree" { const a = %%memAlloc(u8, 10); memFree(u8, a); } @@ -310,9 +268,7 @@ fn memAlloc(comptime T: type, n: usize) -> %[]T { fn memFree(comptime T: type, memory: []T) { } -fn castUndefined() { - @setFnTest(this); - +test "castUndefined" { const array: [100]u8 = undefined; const slice = ([]const u8)(array); testCastUndefined(slice); @@ -320,9 +276,7 @@ fn castUndefined() { fn testCastUndefined(x: []const u8) {} -fn castSmallUnsignedToLargerSigned() { - @setFnTest(this); - +test "castSmallUnsignedToLargerSigned" { assert(castSmallUnsignedToLargerSigned1(200) == i16(200)); assert(castSmallUnsignedToLargerSigned2(9999) == i64(9999)); } @@ -330,9 +284,7 @@ fn castSmallUnsignedToLargerSigned1(x: u8) -> i16 { x } fn castSmallUnsignedToLargerSigned2(x: u16) -> i64 { x } -fn implicitCastAfterUnreachable() { - @setFnTest(this); - +test "implicitCastAfterUnreachable" { assert(outer() == 1234); } fn inner() -> i32 { 1234 } @@ -341,9 +293,7 @@ fn outer() -> i64 { } -fn pointerDereferencing() { - @setFnTest(this); - +test "pointerDereferencing" { var x = i32(3); const y = &x; @@ -353,9 +303,7 @@ fn pointerDereferencing() { assert(*y == 4); } -fn callResultOfIfElseExpression() { - @setFnTest(this); - +test "callResultOfIfElseExpression" { assert(mem.eql(u8, f2(true), "a")); assert(mem.eql(u8, f2(false), "b")); } @@ -366,9 +314,7 @@ fn fA() -> []const u8 { "a" } fn fB() -> []const u8 { "b" } -fn constExpressionEvalHandlingOfVariables() { - @setFnTest(this); - +test "constExpressionEvalHandlingOfVariables" { var x = true; while (x) { x = false; @@ -377,9 +323,7 @@ fn constExpressionEvalHandlingOfVariables() { -fn constantEnumInitializationWithDifferingSizes() { - @setFnTest(this); - +test "constantEnumInitializationWithDifferingSizes" { test3_1(test3_foo); test3_2(test3_bar); } @@ -413,18 +357,14 @@ fn test3_2(f: Test3Foo) { } -fn characterLiterals() { - @setFnTest(this); - +test "characterLiterals" { assert('\'' == single_quote); } const single_quote = '\''; -fn takeAddressOfParameter() { - @setFnTest(this); - +test "takeAddressOfParameter" { testTakeAddressOfParameter(12.34); } fn testTakeAddressOfParameter(f: f32) { @@ -433,9 +373,7 @@ fn testTakeAddressOfParameter(f: f32) { } -fn intToPtrCast() { - @setFnTest(this); - +test "intToPtrCast" { const x = isize(13); const y = (&u8)(x); const z = usize(y); @@ -443,9 +381,7 @@ fn intToPtrCast() { } -fn pointerComparison() { - @setFnTest(this); - +test "pointerComparison" { const a = ([]const u8)("a"); const b = &a; assert(ptrEql(b, b)); @@ -455,9 +391,7 @@ fn ptrEql(a: &const []const u8, b: &const []const u8) -> bool { } -fn cStringConcatenation() { - @setFnTest(this); - +test "cStringConcatenation" { const a = c"OK" ++ c" IT " ++ c"WORKED"; const b = c"OK IT WORKED"; @@ -470,9 +404,7 @@ fn cStringConcatenation() { assert(b[len] == 0); } -fn castSliceToU8Slice() { - @setFnTest(this); - +test "castSliceToU8Slice" { assert(@sizeOf(i32) == 4); var big_thing_array = []i32{1, 2, 3, 4}; const big_thing_slice: []i32 = big_thing_array[0...]; @@ -492,9 +424,7 @@ fn castSliceToU8Slice() { assert(bytes[11] == @maxValue(u8)); } -fn pointerToVoidReturnType() { - @setFnTest(this); - +test "pointerToVoidReturnType" { %%testPointerToVoidReturnType(); } fn testPointerToVoidReturnType() -> %void { @@ -507,17 +437,14 @@ fn testPointerToVoidReturnType2() -> &const void { } -fn nonConstPtrToAliasedType() { - @setFnTest(this); +test "nonConstPtrToAliasedType" { const int = i32; assert(?&int == ?&i32); } -fn array2DConstDoublePtr() { - @setFnTest(this); - +test "array2DConstDoublePtr" { const rect_2d_vertexes = [][1]f32 { []f32{1.0}, []f32{2.0}, @@ -530,9 +457,7 @@ fn testArray2DConstDoublePtr(ptr: &const f32) { assert(ptr[1] == 2.0); } -fn isInteger() { - @setFnTest(this); - +test "isInteger" { comptime { assert(@isInteger(i8)); assert(@isInteger(u8)); @@ -545,9 +470,7 @@ fn isInteger() { } } -fn isFloat() { - @setFnTest(this); - +test "isFloat" { comptime { assert(!@isFloat(i8)); assert(!@isFloat(u8)); @@ -560,9 +483,7 @@ fn isFloat() { } } -fn canImplicitCast() { - @setFnTest(this); - +test "canImplicitCast" { comptime { assert(@canImplicitCast(i64, i32(3))); assert(!@canImplicitCast(i32, f32(1.234))); @@ -570,18 +491,14 @@ fn canImplicitCast() { } } -fn typeName() { - @setFnTest(this); - +test "typeName" { comptime { assert(mem.eql(u8, @typeName(i64), "i64")); assert(mem.eql(u8, @typeName(&usize), "&usize")); } } -fn volatileLoadAndStore() { - @setFnTest(this); - +test "volatileLoadAndStore" { var number: i32 = 1234; const ptr = &volatile number; *ptr += 1; diff --git a/test/cases/namespace_depends_on_compile_var/index.zig b/test/cases/namespace_depends_on_compile_var/index.zig index 9bc8f781e7182cf5b9c32272a9e8bd5e49273222..8c57d21946c79a7807ea04d94ce6b5b307485978 100644 --- a/test/cases/namespace_depends_on_compile_var/index.zig +++ b/test/cases/namespace_depends_on_compile_var/index.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn namespaceDependsOnCompileVar() { - @setFnTest(this); - +test "namespaceDependsOnCompileVar" { if (some_namespace.a_bool) { assert(some_namespace.a_bool); } else { diff --git a/test/cases/null.zig b/test/cases/null.zig index d2f65e1ae279f3555e26db56cd78fa25e9e189f5..c502afba6963b69b3370194119b31d4098ea7949 100644 --- a/test/cases/null.zig +++ b/test/cases/null.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn nullableType() { - @setFnTest(this); - +test "nullableType" { const x : ?bool = @generatedCode(true); if (const y ?= x) { @@ -28,9 +26,7 @@ fn nullableType() { assert(num == 13); } -fn assignToIfVarPtr() { - @setFnTest(this); - +test "assignToIfVarPtr" { var maybe_bool: ?bool = true; if (const *b ?= maybe_bool) { @@ -40,17 +36,13 @@ fn assignToIfVarPtr() { assert(??maybe_bool == false); } -fn rhsMaybeUnwrapReturn() { - @setFnTest(this); - +test "rhsMaybeUnwrapReturn" { const x: ?bool = @generatedCode(true); const y = x ?? return; } -fn maybeReturn() { - @setFnTest(this); - +test "maybeReturn" { maybeReturnImpl(); comptime maybeReturnImpl(); } @@ -67,9 +59,7 @@ fn foo(x: ?i32) -> ?bool { } -fn ifVarMaybePointer() { - @setFnTest(this); - +test "ifVarMaybePointer" { assert(shouldBeAPlus1(Particle {.a = 14, .b = 1, .c = 1, .d = 1}) == 15); } fn shouldBeAPlus1(p: Particle) -> u64 { @@ -90,9 +80,7 @@ const Particle = struct { }; -fn nullLiteralOutsideFunction() { - @setFnTest(this); - +test "nullLiteralOutsideFunction" { const is_null = here_is_a_null_literal.context == null; assert(is_null); @@ -107,9 +95,7 @@ const here_is_a_null_literal = SillyStruct { }; -fn testNullRuntime() { - @setFnTest(this); - +test "testNullRuntime" { testTestNullRuntime(null); } fn testTestNullRuntime(x: ?i32) { @@ -117,9 +103,7 @@ fn testTestNullRuntime(x: ?i32) { assert(!(x != null)); } -fn nullableVoid() { - @setFnTest(this); - +test "nullableVoid" { nullableVoidImpl(); comptime nullableVoidImpl(); } diff --git a/test/cases/pub_enum/index.zig b/test/cases/pub_enum/index.zig index 889ce30bba4f2f30eabcd855034a5cef2cb6a020..4935f210bac4bd01f8a640bb08f16bace8ec6b68 100644 --- a/test/cases/pub_enum/index.zig +++ b/test/cases/pub_enum/index.zig @@ -1,17 +1,13 @@ const other = @import("cases/pub_enum/other.zig"); const assert = @import("std").debug.assert; -fn pubEnum() { - @setFnTest(this); - +test "pubEnum" { pubEnumTest(other.APubEnum.Two); } fn pubEnumTest(foo: other.APubEnum) { assert(foo == other.APubEnum.Two); } -fn castWithImportedSymbol() { - @setFnTest(this); - +test "castWithImportedSymbol" { assert(other.size_t(42) == 42); } diff --git a/test/cases/sizeof_and_typeof.zig b/test/cases/sizeof_and_typeof.zig index 734406c7c2ccf1bbcf20c5aa60b4f2287f3522a5..702e0ecc224ba624cc3e32c3796649fc65922c98 100644 --- a/test/cases/sizeof_and_typeof.zig +++ b/test/cases/sizeof_and_typeof.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn sizeofAndTypeOf() { - @setFnTest(this); - +test "sizeofAndTypeOf" { const y: @typeOf(x) = 120; assert(@sizeOf(@typeOf(y)) == 2); } diff --git a/test/cases/struct.zig b/test/cases/struct.zig index 9bcd9fd9f64dc25dab2f4b9e9100771c05fa6cac..5d2c2ba60824a9f0db9aa6c90dceaeaac50f574e 100644 --- a/test/cases/struct.zig +++ b/test/cases/struct.zig @@ -5,27 +5,25 @@ const StructWithNoFields = struct { }; const empty_global_instance = StructWithNoFields {}; -fn callStructStaticMethod() { - @setFnTest(this); +test "callStructStaticMethod" { const result = StructWithNoFields.add(3, 4); assert(result == 7); } +test "returnEmptyStructInstance" { + _ = returnEmptyStructInstance(); +} fn returnEmptyStructInstance() -> StructWithNoFields { - @setFnTest(this); return empty_global_instance; } const should_be_11 = StructWithNoFields.add(5, 6); -fn invokeStaticMethodInGlobalScope() { - @setFnTest(this); +test "invokeStaticMethodInGlobalScope" { assert(should_be_11 == 11); } -fn voidStructFields() { - @setFnTest(this); - +test "voidStructFields" { const foo = VoidStructFieldsFoo { .a = void{}, .b = 1, @@ -41,9 +39,7 @@ const VoidStructFieldsFoo = struct { }; -pub fn structs() { - @setFnTest(this); - +test "fn" { var foo: StructFoo = undefined; @memset((&u8)(&foo), 0, @sizeOf(StructFoo)); foo.a += 1; @@ -74,9 +70,7 @@ const Val = struct { x: i32, }; -fn structPointToSelf() { - @setFnTest(this); - +test "structPointToSelf" { var root : Node = undefined; root.val.x = 1; @@ -89,9 +83,7 @@ fn structPointToSelf() { assert(node.next.next.next.val.x == 1); } -fn structByvalAssign() { - @setFnTest(this); - +test "structByvalAssign" { var foo1 : StructFoo = undefined; var foo2 : StructFoo = undefined; @@ -108,9 +100,7 @@ fn structInitializer() { } -fn fnCallOfStructField() { - @setFnTest(this); - +test "fnCallOfStructField" { assert(callStructField(Foo {.ptr = aFunc,}) == 13); } @@ -125,9 +115,7 @@ fn callStructField(foo: Foo) -> i32 { } -fn storeMemberFunctionInVariable() { - @setFnTest(this); - +test "storeMemberFunctionInVariable" { const instance = MemberFnTestFoo { .x = 1234, }; const memberFn = MemberFnTestFoo.member; const result = memberFn(instance); @@ -139,17 +127,13 @@ const MemberFnTestFoo = struct { }; -fn callMemberFunctionDirectly() { - @setFnTest(this); - +test "callMemberFunctionDirectly" { const instance = MemberFnTestFoo { .x = 1234, }; const result = MemberFnTestFoo.member(instance); assert(result == 1234); } -fn memberFunctions() { - @setFnTest(this); - +test "memberFunctions" { const r = MemberFnRand {.seed = 1234}; assert(r.getSeed() == 1234); } @@ -160,9 +144,7 @@ const MemberFnRand = struct { } }; -fn returnStructByvalFromFunction() { - @setFnTest(this); - +test "returnStructByvalFromFunction" { const bar = makeBar(1234, 5678); assert(bar.y == 5678); } @@ -177,9 +159,7 @@ fn makeBar(x: i32, y: i32) -> Bar { } } -fn emptyStructMethodCall() { - @setFnTest(this); - +test "emptyStructMethodCall" { const es = EmptyStruct{}; assert(es.method() == 1234); } @@ -190,9 +170,7 @@ const EmptyStruct = struct { }; -fn returnEmptyStructFromFn() { - @setFnTest(this); - +test "returnEmptyStructFromFn" { _ = testReturnEmptyStructFromFn(); } const EmptyStruct2 = struct {}; @@ -200,9 +178,7 @@ fn testReturnEmptyStructFromFn() -> EmptyStruct2 { EmptyStruct2 {} } -fn passSliceOfEmptyStructToFn() { - @setFnTest(this); - +test "passSliceOfEmptyStructToFn" { assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1); } fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) -> usize { @@ -214,9 +190,7 @@ const APackedStruct = packed struct { y: u8, }; -fn packedStruct() { - @setFnTest(this); - +test "packedStruct" { var foo = APackedStruct { .x = 1, .y = 2, @@ -242,9 +216,7 @@ const bit_field_1 = BitField1 { .c = 3, }; -fn bitFieldAccess() { - @setFnTest(this); - +test "bitFieldAccess" { var data = bit_field_1; assert(getA(&data) == 1); assert(getB(&data) == 2); @@ -282,9 +254,7 @@ const Foo96Bits = packed struct { d: u24, }; -fn packedStruct24Bits() { - @setFnTest(this); - +test "packedStruct24Bits" { comptime { assert(@sizeOf(Foo24Bits) == 3); assert(@sizeOf(Foo96Bits) == 12); @@ -327,9 +297,7 @@ const FooArray24Bits = packed struct { c: u16, }; -fn packedArray24Bits() { - @setFnTest(this); - +test "packedArray24Bits" { comptime { assert(@sizeOf([9]Foo24Bits) == 9 * 3); assert(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); @@ -379,9 +347,7 @@ const FooArrayOfAligned = packed struct { a: [2]FooStructAligned, }; -fn alignedArrayOfPackedStruct() { - @setFnTest(this); - +test "alignedArrayOfPackedStruct" { comptime { assert(@sizeOf(FooStructAligned) == 2); assert(@sizeOf(FooArrayOfAligned) == 2 * 2); diff --git a/test/cases/struct_contains_slice_of_itself.zig b/test/cases/struct_contains_slice_of_itself.zig index 4c4bf431ea34a620153e1e86108799e6322bbaca..6443b52725fa9e64d959576d3284c78e05bbb85c 100644 --- a/test/cases/struct_contains_slice_of_itself.zig +++ b/test/cases/struct_contains_slice_of_itself.zig @@ -5,9 +5,7 @@ const Node = struct { children: []Node, }; -fn structContainsSliceOfItself() { - @setFnTest(this); - +test "structContainsSliceOfItself" { var nodes = []Node { Node { .payload = 1, diff --git a/test/cases/switch.zig b/test/cases/switch.zig index 9d831bd356b04022585f84473f15213322a217bd..00046e38cef2b2b06eeb3e9c9a0dfe5748a6bedc 100644 --- a/test/cases/switch.zig +++ b/test/cases/switch.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn switchWithNumbers() { - @setFnTest(this); - +test "switchWithNumbers" { testSwitchWithNumbers(13); } @@ -15,9 +13,7 @@ fn testSwitchWithNumbers(x: u32) { assert(result); } -fn switchWithAllRanges() { - @setFnTest(this); - +test "switchWithAllRanges" { assert(testSwitchWithAllRanges(50, 3) == 1); assert(testSwitchWithAllRanges(101, 0) == 2); assert(testSwitchWithAllRanges(300, 5) == 3); @@ -33,9 +29,7 @@ fn testSwitchWithAllRanges(x: u32, y: u32) -> u32 { } } -fn implicitComptimeSwitch() { - @setFnTest(this); - +test "implicitComptimeSwitch" { const x = 3 + 4; const result = switch (x) { 3 => 10, @@ -50,9 +44,7 @@ fn implicitComptimeSwitch() { } } -fn switchOnEnum() { - @setFnTest(this); - +test "switchOnEnum" { const fruit = Fruit.Orange; nonConstSwitchOnEnum(fruit); } @@ -70,9 +62,7 @@ fn nonConstSwitchOnEnum(fruit: Fruit) { } -fn switchStatement() { - @setFnTest(this); - +test "switchStatement" { nonConstSwitch(SwitchStatmentFoo.C); } fn nonConstSwitch(foo: SwitchStatmentFoo) { @@ -92,9 +82,7 @@ const SwitchStatmentFoo = enum { }; -fn switchProngWithVar() { - @setFnTest(this); - +test "switchProngWithVar" { switchProngWithVarFn(SwitchProngWithVarEnum.One {13}); switchProngWithVarFn(SwitchProngWithVarEnum.Two {13.0}); switchProngWithVarFn(SwitchProngWithVarEnum.Meh); @@ -119,9 +107,7 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) { } -fn switchWithMultipleExpressions() { - @setFnTest(this); - +test "switchWithMultipleExpressions" { const x = switch (returnsFive()) { 1, 2, 3 => 1, 4, 5, 6 => 2, @@ -149,8 +135,6 @@ fn returnsFalse() -> bool { Number.Three => |x| return x > 12.34, } } -fn switchOnConstEnumWithVar() { - @setFnTest(this); - +test "switchOnConstEnumWithVar" { assert(!returnsFalse()); } diff --git a/test/cases/switch_prong_err_enum.zig b/test/cases/switch_prong_err_enum.zig index 7c7296166f652912a9169800134c2383961dffe2..d8b4a10fa3022dcb199b96f65d5ffbf17db78d15 100644 --- a/test/cases/switch_prong_err_enum.zig +++ b/test/cases/switch_prong_err_enum.zig @@ -21,9 +21,7 @@ fn doThing(form_id: u64) -> %FormValue { } } -fn switchProngReturnsErrorEnum() { - @setFnTest(this); - +test "switchProngReturnsErrorEnum" { %%doThing(17); assert(read_count == 1); } diff --git a/test/cases/switch_prong_implicit_cast.zig b/test/cases/switch_prong_implicit_cast.zig index 7ec047ca2f457ea349e9e1b4e79bb7108afa95e6..a13a8ac55d1293079d04cd2dd9c71cc99bb3440d 100644 --- a/test/cases/switch_prong_implicit_cast.zig +++ b/test/cases/switch_prong_implicit_cast.zig @@ -15,9 +15,7 @@ fn foo(id: u64) -> %FormValue { } } -fn switchProngImplicitCast() { - @setFnTest(this); - +test "switchProngImplicitCast" { const result = switch (%%foo(2)) { FormValue.One => false, FormValue.Two => |x| x, diff --git a/test/cases/this.zig b/test/cases/this.zig index f18215b66c1514e6ce1ce891ab48b4ce56633072..ded18d82b745bf1be7038aa0db9b052efd98d74d 100644 --- a/test/cases/this.zig +++ b/test/cases/this.zig @@ -28,15 +28,11 @@ fn factorial(x: i32) -> i32 { } } -fn thisReferToModuleCallPrivateFn() { - @setFnTest(this); - +test "thisReferToModuleCallPrivateFn" { assert(module.add(1, 2) == 3); } -fn thisReferToContainer() { - @setFnTest(this); - +test "thisReferToContainer" { var pt = Point(i32) { .x = 12, .y = 34, @@ -46,8 +42,6 @@ fn thisReferToContainer() { assert(pt.y == 35); } -fn thisReferToFn() { - @setFnTest(this); - +test "thisReferToFn" { assert(factorial(5) == 120); } diff --git a/test/cases/try.zig b/test/cases/try.zig index 894ee2dd16001d5c4123c66d5b15b95e4deafe76..e0c5793039cfc34fcf04e6333f4200868503811c 100644 --- a/test/cases/try.zig +++ b/test/cases/try.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn tryOnErrorUnion() { - @setFnTest(this); - +test "tryOnErrorUnion" { tryOnErrorUnionImpl(); comptime tryOnErrorUnionImpl(); @@ -25,9 +23,7 @@ fn returnsTen() -> %i32 { 10 } -fn tryWithoutVars() { - @setFnTest(this); - +test "tryWithoutVars" { const result1 = try (failIfTrue(true)) { 1 } else { diff --git a/test/cases/typedef.zig b/test/cases/typedef.zig index 4281e01c7729d135f8aff072342e5d6781ade1db..db6e77685360d5eb5071ddf225f1785948526f02 100644 --- a/test/cases/typedef.zig +++ b/test/cases/typedef.zig @@ -5,8 +5,6 @@ type int = u8; fn add(a: int, b: int) -> int { a + b } -fn typedef() { - @setFnTest(this); - +test "typedef" { assert(add(12, 34) == 46); } diff --git a/test/cases/undefined.zig b/test/cases/undefined.zig index 03e6cfb64f285c562856482fec8337475c308ea7..3b5100e39c6b670ebf32730a263980fb64e9fc39 100644 --- a/test/cases/undefined.zig +++ b/test/cases/undefined.zig @@ -9,9 +9,7 @@ fn initStaticArray() -> [10]i32 { return array; } const static_array = initStaticArray(); -fn initStaticArrayToUndefined() { - @setFnTest(this); - +test "initStaticArrayToUndefined" { assert(static_array[0] == 1); assert(static_array[4] == 2); assert(static_array[7] == 3); @@ -37,9 +35,7 @@ fn setFooX(foo: &Foo) { foo.x = 2; } -fn assignUndefinedToStruct() { - @setFnTest(this); - +test "assignUndefinedToStruct" { comptime { var foo: Foo = undefined; setFooX(&foo); @@ -52,9 +48,7 @@ fn assignUndefinedToStruct() { } } -fn assignUndefinedToStructWithMethod() { - @setFnTest(this); - +test "assignUndefinedToStructWithMethod" { comptime { var foo: Foo = undefined; foo.setFooXMethod(); diff --git a/test/cases/var_args.zig b/test/cases/var_args.zig index c0de342c382afa061d65aabd547a0eaf83286adc..0e61a0c56725a89411a5b302f9f1b4386ca563bc 100644 --- a/test/cases/var_args.zig +++ b/test/cases/var_args.zig @@ -8,9 +8,7 @@ fn add(args: ...) -> i32 { return sum; } -fn testAddArbitraryArgs() { - @setFnTest(this); - +test "testAddArbitraryArgs" { assert(add(i32(1), i32(2), i32(3), i32(4)) == 10); assert(add(i32(1234)) == 1234); assert(add() == 0); @@ -20,15 +18,11 @@ fn readFirstVarArg(args: ...) { const value = args[0]; } -fn sendVoidArgToVarArgs() { - @setFnTest(this); - +test "sendVoidArgToVarArgs" { readFirstVarArg({}); } -fn testPassArgsDirectly() { - @setFnTest(this); - +test "testPassArgsDirectly" { assert(addSomeStuff(i32(1), i32(2), i32(3), i32(4)) == 10); assert(addSomeStuff(i32(1234)) == 1234); assert(addSomeStuff() == 0); diff --git a/test/cases/void.zig b/test/cases/void.zig index 15b8276b0bc7e94c062d7bd85fa35011b814c87e..5085613e76aaa5eb5eadd6821b160f63304b7fc8 100644 --- a/test/cases/void.zig +++ b/test/cases/void.zig @@ -6,9 +6,7 @@ const Foo = struct { c: void, }; -fn compareVoidWithVoidCompileTimeKnown() { - @setFnTest(this); - +test "compareVoidWithVoidCompileTimeKnown" { comptime { const foo = Foo { .a = {}, diff --git a/test/cases/while.zig b/test/cases/while.zig index e5e10e556887450e3a877c4179cabdea98d702ba..c3b7a84722aec57d38ba77c535dbee73277748a2 100644 --- a/test/cases/while.zig +++ b/test/cases/while.zig @@ -1,8 +1,6 @@ const assert = @import("std").debug.assert; -fn whileLoop() { - @setFnTest(this); - +test "whileLoop" { var i : i32 = 0; while (i < 4) { i += 1; @@ -18,9 +16,7 @@ fn whileLoop2() -> i32 { return 1; } } -fn staticEvalWhile() { - @setFnTest(this); - +test "staticEvalWhile" { assert(static_eval_while_number == 1); } const static_eval_while_number = staticWhileLoop1(); @@ -33,9 +29,7 @@ fn staticWhileLoop2() -> i32 { } } -fn continueAndBreak() { - @setFnTest(this); - +test "continueAndBreak" { runContinueAndBreakTest(); assert(continue_and_break_counter == 8); } @@ -53,9 +47,7 @@ fn runContinueAndBreakTest() { assert(i == 4); } -fn returnWithImplicitCastFromWhileLoop() { - @setFnTest(this); - +test "returnWithImplicitCastFromWhileLoop" { %%returnWithImplicitCastFromWhileLoopTest(); } fn returnWithImplicitCastFromWhileLoopTest() -> %void { @@ -64,9 +56,7 @@ fn returnWithImplicitCastFromWhileLoopTest() -> %void { } } -fn whileWithContinueExpr() { - @setFnTest(this); - +test "whileWithContinueExpr" { var sum: i32 = 0; {var i: i32 = 0; while (i < 10; i += 1) { if (i == 5) continue; diff --git a/test/run_tests.cpp b/test/run_tests.cpp index cc951a2c112c2c3f76eff72089cd1b759a4ccd2e..823d04af94ca0c0072333046d1efbd6db122959e 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -14,6 +14,12 @@ #include #include +enum TestSpecial { + TestSpecialNone, + TestSpecialSelfHosted, + TestSpecialStd, +}; + struct TestSourceFile { const char *relative_path; const char *source_code; @@ -32,7 +38,7 @@ struct TestCase { ZigList compiler_args; ZigList program_args; bool is_parseh; - bool is_self_hosted; + TestSpecial special; bool is_release_mode; bool is_debug_safety; AllowWarnings allow_warnings; @@ -79,7 +85,6 @@ static TestCase *add_simple_case(const char *case_name, const char *source, cons test_case->compiler_args.append("--strip"); test_case->compiler_args.append("--color"); test_case->compiler_args.append("on"); - test_case->compiler_args.append("--check-unused"); test_cases.append(test_case); @@ -93,58 +98,39 @@ static TestCase *add_simple_case_libc(const char *case_name, const char *source, return tc; } -static TestCase *add_compile_fail_case_extra(const char *case_name, const char *source, bool check_unused, - size_t count, va_list ap) -{ - TestCase *test_case = allocate(1); - test_case->case_name = case_name; - test_case->source_files.resize(1); - test_case->source_files.at(0).relative_path = tmp_source_path; - test_case->source_files.at(0).source_code = source; - - for (size_t i = 0; i < count; i += 1) { - const char *arg = va_arg(ap, const char *); - test_case->compile_errors.append(arg); - } - - test_case->compiler_args.append("build"); - test_case->compiler_args.append(tmp_source_path); - - test_case->compiler_args.append("--name"); - test_case->compiler_args.append("test"); - - test_case->compiler_args.append("--export"); - test_case->compiler_args.append("obj"); - - test_case->compiler_args.append("--output"); - test_case->compiler_args.append(tmp_exe_path); - - test_case->compiler_args.append("--release"); - test_case->compiler_args.append("--strip"); - - if (check_unused) { - test_case->compiler_args.append("--check-unused"); - } - - test_cases.append(test_case); - - return test_case; -} - -static TestCase *add_compile_fail_case_no_check_unused(const char *case_name, const char *source, size_t count, ...) { - va_list ap; - va_start(ap, count); - TestCase *result = add_compile_fail_case_extra(case_name, source, false, count, ap); - va_end(ap); - return result; -} - static TestCase *add_compile_fail_case(const char *case_name, const char *source, size_t count, ...) { va_list ap; va_start(ap, count); - TestCase *result = add_compile_fail_case_extra(case_name, source, true, count, ap); - va_end(ap); - return result; + + TestCase *test_case = allocate(1); + test_case->case_name = case_name; + test_case->source_files.resize(1); + test_case->source_files.at(0).relative_path = tmp_source_path; + test_case->source_files.at(0).source_code = source; + + for (size_t i = 0; i < count; i += 1) { + const char *arg = va_arg(ap, const char *); + test_case->compile_errors.append(arg); + } + + test_case->compiler_args.append("build"); + test_case->compiler_args.append(tmp_source_path); + + test_case->compiler_args.append("--name"); + test_case->compiler_args.append("test"); + + test_case->compiler_args.append("--export"); + test_case->compiler_args.append("obj"); + + test_case->compiler_args.append("--output"); + test_case->compiler_args.append(tmp_exe_path); + + test_case->compiler_args.append("--release"); + test_case->compiler_args.append("--strip"); + + test_cases.append(test_case); + + return test_case; } static void add_debug_safety_case(const char *case_name, const char *source) { @@ -674,24 +660,27 @@ static void add_compile_failure_test_cases(void) { add_compile_fail_case("multiple function definitions", R"SOURCE( fn a() {} fn a() {} +export fn entry() { a(); } )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'"); add_compile_fail_case("unreachable with return", R"SOURCE( fn a() -> unreachable {return;} +export fn entry() { a(); } )SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', found 'void'"); add_compile_fail_case("control reaches end of non-void function", R"SOURCE( fn a() -> i32 {} +export fn entry() { _ = a(); } )SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', found 'void'"); add_compile_fail_case("undefined function call", R"SOURCE( -fn a() { +export fn a() { b(); } )SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'"); add_compile_fail_case("wrong number of arguments", R"SOURCE( -fn a() { +export fn a() { b(1); } fn b(a: i32, b: i32, c: i32) { } @@ -699,14 +688,16 @@ fn b(a: i32, b: i32, c: i32) { } add_compile_fail_case("invalid type", R"SOURCE( fn a() -> bogus {} +export fn entry() { _ = a(); } )SOURCE", 1, ".tmp_source.zig:2:11: error: use of undeclared identifier 'bogus'"); add_compile_fail_case("pointer to unreachable", R"SOURCE( fn a() -> &unreachable {} +export fn entry() { _ = a(); } )SOURCE", 1, ".tmp_source.zig:2:12: error: pointer to unreachable not allowed"); add_compile_fail_case("unreachable code", R"SOURCE( -fn a() { +export fn a() { return; b(); } @@ -716,10 +707,11 @@ fn b() {} add_compile_fail_case("bad import", R"SOURCE( const bogus = @import("bogus-does-not-exist.zig"); +export fn entry() { bogus.bogo(); } )SOURCE", 1, ".tmp_source.zig:2:15: error: unable to find 'bogus-does-not-exist.zig'"); add_compile_fail_case("undeclared identifier", R"SOURCE( -fn a() { +export fn a() { b + c } @@ -730,10 +722,11 @@ fn a() { add_compile_fail_case("parameter redeclaration", R"SOURCE( fn f(a : i32, a : i32) { } +export fn entry() { f(1, 2); } )SOURCE", 1, ".tmp_source.zig:2:15: error: redeclaration of variable 'a'"); add_compile_fail_case("local variable redeclaration", R"SOURCE( -fn f() { +export fn f() { const a : i32 = 0; const a = 0; } @@ -743,71 +736,73 @@ fn f() { fn f(a : i32) { const a = 0; } +export fn entry() { f(1); } )SOURCE", 1, ".tmp_source.zig:3:5: error: redeclaration of variable 'a'"); add_compile_fail_case("variable has wrong type", R"SOURCE( -fn f() -> i32 { +export fn f() -> i32 { const a = c"a"; a } )SOURCE", 1, ".tmp_source.zig:4:5: error: expected type 'i32', found '&const u8'"); add_compile_fail_case("if condition is bool, not int", R"SOURCE( -fn f() { +export fn f() { if (0) {} } )SOURCE", 1, ".tmp_source.zig:3:9: error: integer value 0 cannot be implicitly casted to type 'bool'"); add_compile_fail_case("assign unreachable", R"SOURCE( -fn f() { +export fn f() { const a = return; } )SOURCE", 1, ".tmp_source.zig:3:5: error: unreachable code"); add_compile_fail_case("unreachable variable", R"SOURCE( -fn f() { +export fn f() { const a : unreachable = {}; } )SOURCE", 1, ".tmp_source.zig:3:15: error: variable of type 'unreachable' not allowed"); add_compile_fail_case("unreachable parameter", R"SOURCE( fn f(a : unreachable) {} +export fn entry() { f(); } )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed"); add_compile_fail_case("bad assignment target", R"SOURCE( -fn f() { +export fn f() { 3 = 3; } )SOURCE", 1, ".tmp_source.zig:3:7: error: cannot assign to constant"); add_compile_fail_case("assign to constant variable", R"SOURCE( -fn f() { +export fn f() { const a = 3; a = 4; } )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant"); add_compile_fail_case("use of undeclared identifier", R"SOURCE( -fn f() { +export fn f() { b = 3; } )SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'"); add_compile_fail_case("const is a statement, not an expression", R"SOURCE( -fn f() { +export fn f() { (const a = 0); } )SOURCE", 1, ".tmp_source.zig:3:6: error: invalid token: 'const'"); add_compile_fail_case("array access of undeclared identifier", R"SOURCE( -fn f() { +export fn f() { i[i] = i[i]; } )SOURCE", 2, ".tmp_source.zig:3:5: error: use of undeclared identifier 'i'", ".tmp_source.zig:3:12: error: use of undeclared identifier 'i'"); add_compile_fail_case("array access of non array", R"SOURCE( -fn f() { +export fn f() { var bad : bool = undefined; bad[bad] = bad[bad]; } @@ -815,7 +810,7 @@ fn f() { ".tmp_source.zig:4:19: error: array access of non-array type 'bool'"); add_compile_fail_case("array access with non integer index", R"SOURCE( -fn f() { +export fn f() { var array = "aoeu"; var bad = false; array[bad] = array[bad]; @@ -828,6 +823,7 @@ const x : i32 = 99; fn f() { x = 1; } +export fn entry() { f(); } )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant"); @@ -836,22 +832,25 @@ fn f(b: bool) { const x : i32 = if (b) { 1 }; const y = if (b) { i32(1) }; } +export fn entry() { f(true); } )SOURCE", 2, ".tmp_source.zig:3:30: error: integer value 1 cannot be implicitly casted to type 'void'", ".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'"); add_compile_fail_case("direct struct loop", R"SOURCE( const A = struct { a : A, }; +export fn entry() -> usize { @sizeOf(A) } )SOURCE", 1, ".tmp_source.zig:2:11: error: struct 'A' contains itself"); add_compile_fail_case("indirect struct loop", R"SOURCE( const A = struct { b : B, }; const B = struct { c : C, }; const C = struct { a : A, }; +export fn entry() -> usize { @sizeOf(A) } )SOURCE", 1, ".tmp_source.zig:2:11: error: struct 'A' contains itself"); add_compile_fail_case("invalid struct field", R"SOURCE( const A = struct { x : i32, }; -fn f() { +export fn f() { var a : A = undefined; a.foo = 1; const y = a.bar; @@ -873,7 +872,9 @@ const A = enum {}; add_compile_fail_case("redefinition of global variables", R"SOURCE( var a : i32 = 1; var a : i32 = 2; - )SOURCE", 1, ".tmp_source.zig:3:1: error: redeclaration of variable 'a'"); + )SOURCE", 2, + ".tmp_source.zig:3:1: error: redefinition of 'a'", + ".tmp_source.zig:2:1: note: previous definition is here"); add_compile_fail_case("byvalue struct parameter in exported function", R"SOURCE( const A = struct { x : i32, }; @@ -893,7 +894,7 @@ const A = struct { y : i32, z : i32, }; -fn f() { +export fn f() { const a = A { .z = 1, .y = 2, @@ -909,7 +910,7 @@ const A = struct { y : i32, z : i32, }; -fn f() { +export fn f() { // we want the error on the '{' not the 'A' because // the A could be a complicated expression const a = A { @@ -925,7 +926,7 @@ const A = struct { y : i32, z : i32, }; -fn f() { +export fn f() { const a = A { .z = 4, .y = 2, @@ -935,19 +936,19 @@ fn f() { )SOURCE", 1, ".tmp_source.zig:11:9: error: no member named 'foo' in 'A'"); add_compile_fail_case("invalid break expression", R"SOURCE( -fn f() { +export fn f() { break; } )SOURCE", 1, ".tmp_source.zig:3:5: error: 'break' expression outside loop"); add_compile_fail_case("invalid continue expression", R"SOURCE( -fn f() { +export fn f() { continue; } )SOURCE", 1, ".tmp_source.zig:3:5: error: 'continue' expression outside loop"); add_compile_fail_case("invalid maybe type", R"SOURCE( -fn f() { +export fn f() { if (const x ?= true) { } } )SOURCE", 1, ".tmp_source.zig:3:20: error: expected nullable type, found 'bool'"); @@ -956,43 +957,40 @@ fn f() { fn f() -> i32 { i32(return 1) } +export fn entry() { _ = f(); } )SOURCE", 1, ".tmp_source.zig:3:8: error: unreachable code"); add_compile_fail_case("invalid builtin fn", R"SOURCE( fn f() -> @bogus(foo) { } +export fn entry() { _ = f(); } )SOURCE", 1, ".tmp_source.zig:2:11: error: invalid builtin function: 'bogus'"); add_compile_fail_case("top level decl dependency loop", R"SOURCE( const a : @typeOf(b) = 0; const b : @typeOf(a) = 0; +export fn entry() { + const c = a + b; +} )SOURCE", 1, ".tmp_source.zig:2:1: error: 'a' depends on itself"); add_compile_fail_case("noalias on non pointer param", R"SOURCE( fn f(noalias x: i32) {} +export fn entry() { f(1234); } )SOURCE", 1, ".tmp_source.zig:2:6: error: noalias on non-pointer parameter"); add_compile_fail_case("struct init syntax for array", R"SOURCE( const foo = []u16{.x = 1024,}; +export fn entry() -> usize { @sizeOf(@typeOf(foo)) } )SOURCE", 1, ".tmp_source.zig:2:18: error: type '[]u16' does not support struct initialization syntax"); add_compile_fail_case("type variables must be constant", R"SOURCE( var foo = u8; +export fn entry() -> foo { + return 1; +} )SOURCE", 1, ".tmp_source.zig:2:1: error: variable of type 'type' must be constant"); - add_compile_fail_case("variables shadowing types", R"SOURCE( -const Foo = struct {}; -const Bar = struct {}; - -fn f(Foo: i32) { - var Bar : i32 = undefined; -} - )SOURCE", 4, - ".tmp_source.zig:5:6: error: redeclaration of variable 'Foo'", - ".tmp_source.zig:2:1: note: previous declaration is here", - ".tmp_source.zig:6:5: error: redeclaration of variable 'Bar'", - ".tmp_source.zig:3:1: note: previous declaration is here"); - add_compile_fail_case("multiple else prongs in a switch", R"SOURCE( fn f(x: u32) { const value: bool = switch (x) { @@ -1000,28 +998,36 @@ fn f(x: u32) { else => true, else => true, }; +} +export fn entry() { + f(1234); } )SOURCE", 1, ".tmp_source.zig:6:9: error: multiple else prongs in switch expression"); add_compile_fail_case("global variable initializer must be constant expression", R"SOURCE( extern fn foo() -> i32; const x = foo(); +export fn entry() -> i32 { x } )SOURCE", 1, ".tmp_source.zig:3:11: error: unable to evaluate constant expression"); add_compile_fail_case("array concatenation with wrong type", R"SOURCE( const src = "aoeu"; const derp = usize(1234); const a = derp ++ "foo"; + +export fn entry() -> usize { @sizeOf(@typeOf(a)) } )SOURCE", 1, ".tmp_source.zig:4:11: error: expected array or C string literal, found 'usize'"); add_compile_fail_case("non compile time array concatenation", R"SOURCE( fn f(s: [10]u8) -> []u8 { s ++ "foo" } +export fn entry() -> usize { @sizeOf(@typeOf(f)) } )SOURCE", 1, ".tmp_source.zig:3:5: error: unable to evaluate constant expression"); add_compile_fail_case("@cImport with bogus include", R"SOURCE( const c = @cImport(@cInclude("bogus.h")); +export fn entry() -> usize { @sizeOf(@typeOf(c.bogo)) } )SOURCE", 2, ".tmp_source.zig:2:11: error: C import failed", ".h:1:10: note: 'bogus.h' file not found"); @@ -1029,14 +1035,17 @@ const c = @cImport(@cInclude("bogus.h")); const x = 3; const y = &x; fn foo() -> &const i32 { y } +export fn entry() -> usize { @sizeOf(@typeOf(foo)) } )SOURCE", 1, ".tmp_source.zig:4:26: error: expected type '&const i32', found '&const (integer literal)'"); add_compile_fail_case("integer overflow error", R"SOURCE( const x : u8 = 300; +export fn entry() -> usize { @sizeOf(@typeOf(x)) } )SOURCE", 1, ".tmp_source.zig:2:16: error: integer value 300 cannot be implicitly casted to type 'u8'"); add_compile_fail_case("incompatible number literals", R"SOURCE( const x = 2 == 2.0; +export fn entry() -> usize { @sizeOf(@typeOf(x)) } )SOURCE", 1, ".tmp_source.zig:2:11: error: integer value 2 cannot be implicitly casted to type '(float literal)'"); add_compile_fail_case("missing function call param", R"SOURCE( @@ -1061,11 +1070,14 @@ const members = []member_fn_type { fn f(foo: Foo, index: usize) { const result = members[index](); } + +export fn entry() -> usize { @sizeOf(@typeOf(f)) } )SOURCE", 1, ".tmp_source.zig:21:34: error: expected 1 arguments, found 0"); add_compile_fail_case("missing function name and param name", R"SOURCE( fn () {} fn f(i32) {} +export fn entry() -> usize { @sizeOf(@typeOf(f)) } )SOURCE", 2, ".tmp_source.zig:2:1: error: missing function name", ".tmp_source.zig:3:6: error: missing parameter name"); @@ -1075,6 +1087,7 @@ const fns = []fn(){ a, b, c }; fn a() -> i32 {0} fn b() -> i32 {1} fn c() -> i32 {2} +export fn entry() -> usize { @sizeOf(@typeOf(fns)) } )SOURCE", 1, ".tmp_source.zig:2:21: error: expected type 'fn()', found 'fn() -> i32'"); add_compile_fail_case("extern function pointer mismatch", R"SOURCE( @@ -1082,18 +1095,23 @@ const fns = [](fn(i32)->i32){ a, b, c }; pub fn a(x: i32) -> i32 {x + 0} pub fn b(x: i32) -> i32 {x + 1} export fn c(x: i32) -> i32 {x + 2} + +export fn entry() -> usize { @sizeOf(@typeOf(fns)) } )SOURCE", 1, ".tmp_source.zig:2:37: error: expected type 'fn(i32) -> i32', found 'extern fn(i32) -> i32'"); add_compile_fail_case("implicit cast from f64 to f32", R"SOURCE( const x : f64 = 1.0; const y : f32 = x; + +export fn entry() -> usize { @sizeOf(@typeOf(y)) } )SOURCE", 1, ".tmp_source.zig:3:17: error: expected type 'f32', found 'f64'"); add_compile_fail_case("colliding invalid top level functions", R"SOURCE( fn func() -> bogus {} fn func() -> bogus {} +export fn entry() -> usize { @sizeOf(@typeOf(func)) } )SOURCE", 2, ".tmp_source.zig:3:1: error: redefinition of 'func'", ".tmp_source.zig:2:14: error: use of undeclared identifier 'bogus'"); @@ -1101,6 +1119,7 @@ fn func() -> bogus {} add_compile_fail_case("bogus compile var", R"SOURCE( const x = @compileVar("bogus"); +export fn entry() -> usize { @sizeOf(@typeOf(x)) } )SOURCE", 1, ".tmp_source.zig:2:23: error: unrecognized compile variable: 'bogus'"); @@ -1110,6 +1129,8 @@ const Foo = struct { }; var global_var: usize = 1; fn get() -> usize { global_var } + +export fn entry() -> usize { @sizeOf(@typeOf(Foo)) } )SOURCE", 3, ".tmp_source.zig:6:21: error: unable to evaluate constant expression", ".tmp_source.zig:3:12: note: called from here", @@ -1121,6 +1142,8 @@ const Foo = struct { field: i32, }; const x = Foo {.field = 1} + Foo {.field = 2}; + +export fn entry() -> usize { @sizeOf(@typeOf(x)) } )SOURCE", 1, ".tmp_source.zig:5:28: error: invalid operands to binary expression: 'Foo' and 'Foo'"); @@ -1129,6 +1152,11 @@ const lit_int_x = 1 / 0; const lit_float_x = 1.0 / 0.0; const int_x = i32(1) / i32(0); const float_x = f32(1.0) / f32(0.0); + +export fn entry1() -> usize { @sizeOf(@typeOf(lit_int_x)) } +export fn entry2() -> usize { @sizeOf(@typeOf(lit_float_x)) } +export fn entry3() -> usize { @sizeOf(@typeOf(int_x)) } +export fn entry4() -> usize { @sizeOf(@typeOf(float_x)) } )SOURCE", 4, ".tmp_source.zig:2:21: error: division by zero is undefined", ".tmp_source.zig:3:25: error: division by zero is undefined", @@ -1150,16 +1178,22 @@ fn f(n: Number) -> i32 { Number.Three => i32(3), } } + +export fn entry() -> usize { @sizeOf(@typeOf(f)) } )SOURCE", 1, ".tmp_source.zig:9:5: error: enumeration value 'Number.Four' not handled in switch"); add_compile_fail_case("normal string with newline", R"SOURCE( const foo = "a b"; + +export fn entry() -> usize { @sizeOf(@typeOf(foo)) } )SOURCE", 1, ".tmp_source.zig:2:13: error: newline not allowed in string literal"); add_compile_fail_case("invalid comparison for function pointers", R"SOURCE( fn foo() {} const invalid = foo > foo; + +export fn entry() -> usize { @sizeOf(@typeOf(invalid)) } )SOURCE", 1, ".tmp_source.zig:3:21: error: operator not allowed for type 'fn()'"); add_compile_fail_case("generic function instance with non-constant expression", R"SOURCE( @@ -1167,10 +1201,12 @@ fn foo(comptime x: i32, y: i32) -> i32 { return x + y; } fn test1(a: i32, b: i32) -> i32 { return foo(a, b); } + +export fn entry() -> usize { @sizeOf(@typeOf(test1)) } )SOURCE", 1, ".tmp_source.zig:4:16: error: unable to evaluate constant expression"); add_compile_fail_case("goto jumping into block", R"SOURCE( -fn f() { +export fn f() { { a_label: } @@ -1185,15 +1221,19 @@ fn f(b: bool) { label: } fn derp(){} + +export fn entry() -> usize { @sizeOf(@typeOf(f)) } )SOURCE", 1, ".tmp_source.zig:3:12: error: no label in scope named 'label'"); add_compile_fail_case("assign null to non-nullable pointer", R"SOURCE( const a: &u8 = null; + +export fn entry() -> usize { @sizeOf(@typeOf(a)) } )SOURCE", 1, ".tmp_source.zig:2:16: error: expected type '&u8', found '(null)'"); add_compile_fail_case("indexing an array of size zero", R"SOURCE( const array = []u8{}; -fn foo() { +export fn foo() { const pointer = &array[0]; } )SOURCE", 1, ".tmp_source.zig:4:27: error: index 0 outside array of size 0"); @@ -1203,12 +1243,16 @@ const y = foo(0); fn foo(x: i32) -> i32 { 1 / x } + +export fn entry() -> usize { @sizeOf(@typeOf(y)) } )SOURCE", 2, ".tmp_source.zig:4:7: error: division by zero is undefined", ".tmp_source.zig:2:14: note: called from here"); add_compile_fail_case("branch on undefined value", R"SOURCE( const x = if (undefined) true else false; + +export fn entry() -> usize { @sizeOf(@typeOf(x)) } )SOURCE", 1, ".tmp_source.zig:2:15: error: use of undefined value"); @@ -1217,12 +1261,16 @@ const seventh_fib_number = fibbonaci(7); fn fibbonaci(x: i32) -> i32 { return fibbonaci(x - 1) + fibbonaci(x - 2); } + +export fn entry() -> usize { @sizeOf(@typeOf(seventh_fib_number)) } )SOURCE", 2, ".tmp_source.zig:4:21: error: evaluation exceeded 1000 backwards branches", ".tmp_source.zig:4:21: note: called from here"); add_compile_fail_case("@embedFile with bogus file", R"SOURCE( const resource = @embedFile("bogus.txt"); + +export fn entry() -> usize { @sizeOf(@typeOf(resource)) } )SOURCE", 1, ".tmp_source.zig:2:29: error: unable to find './bogus.txt'"); @@ -1232,6 +1280,8 @@ const Foo = struct { }; const a = Foo {.x = get_it()}; extern fn get_it() -> i32; + +export fn entry() -> usize { @sizeOf(@typeOf(a)) } )SOURCE", 1, ".tmp_source.zig:5:21: error: unable to evaluate constant expression"); add_compile_fail_case("non-const expression function call with struct return value outside function", R"SOURCE( @@ -1245,12 +1295,13 @@ fn get_it() -> Foo { } var global_side_effect = false; +export fn entry() -> usize { @sizeOf(@typeOf(a)) } )SOURCE", 2, ".tmp_source.zig:7:24: error: unable to evaluate constant expression", ".tmp_source.zig:5:17: note: called from here"); add_compile_fail_case("undeclared identifier error should mark fn as impure", R"SOURCE( -fn foo() { +export fn foo() { test_a_thing(); } fn test_a_thing() { @@ -1269,12 +1320,15 @@ const EnumWithData = enum { fn bad_eql_2(a: EnumWithData, b: EnumWithData) -> bool { a == b } + +export fn entry1() -> usize { @sizeOf(@typeOf(bad_eql_1)) } +export fn entry2() -> usize { @sizeOf(@typeOf(bad_eql_2)) } )SOURCE", 2, ".tmp_source.zig:3:7: error: operator not allowed for type '[]u8'", ".tmp_source.zig:10:7: error: operator not allowed for type 'EnumWithData'"); add_compile_fail_case("non-const switch number literal", R"SOURCE( -fn foo() { +export fn foo() { const x = switch (bar()) { 1, 2 => 1, 3, 4 => 2, @@ -1284,18 +1338,17 @@ fn foo() { fn bar() -> i32 { 2 } - )SOURCE", 1, ".tmp_source.zig:3:15: error: unable to infer expression type"); add_compile_fail_case("atomic orderings of cmpxchg - failure stricter than success", R"SOURCE( -fn f() { +export fn f() { var x: i32 = 1234; while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {} } )SOURCE", 1, ".tmp_source.zig:4:72: error: failure atomic ordering must be no stricter than success"); add_compile_fail_case("atomic orderings of cmpxchg - success Monotonic or stricter", R"SOURCE( -fn f() { +export fn f() { var x: i32 = 1234; while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {} } @@ -1306,6 +1359,8 @@ const y = neg(-128); fn neg(x: i8) -> i8 { -x } + +export fn entry() -> usize { @sizeOf(@typeOf(y)) } )SOURCE", 2, ".tmp_source.zig:4:5: error: negation caused overflow", ".tmp_source.zig:2:14: note: called from here"); @@ -1315,6 +1370,8 @@ const y = add(65530, 10); fn add(a: u16, b: u16) -> u16 { a + b } + +export fn entry() -> usize { @sizeOf(@typeOf(y)) } )SOURCE", 2, ".tmp_source.zig:4:7: error: operation caused overflow", ".tmp_source.zig:2:14: note: called from here"); @@ -1325,6 +1382,8 @@ const y = sub(10, 20); fn sub(a: u16, b: u16) -> u16 { a - b } + +export fn entry() -> usize { @sizeOf(@typeOf(y)) } )SOURCE", 2, ".tmp_source.zig:4:7: error: operation caused overflow", ".tmp_source.zig:2:14: note: called from here"); @@ -1334,6 +1393,8 @@ const y = mul(300, 6000); fn mul(a: u16, b: u16) -> u16 { a * b } + +export fn entry() -> usize { @sizeOf(@typeOf(y)) } )SOURCE", 2, ".tmp_source.zig:4:7: error: operation caused overflow", ".tmp_source.zig:2:14: note: called from here"); @@ -1343,10 +1404,12 @@ fn f() -> i8 { const x: u32 = 10; @truncate(i8, x) } + +export fn entry() -> usize { @sizeOf(@typeOf(f)) } )SOURCE", 1, ".tmp_source.zig:4:19: error: expected signed integer type, found 'u32'"); add_compile_fail_case("%return in function with non error return type", R"SOURCE( -fn f() { +export fn f() { %return something(); } fn something() -> %void { } @@ -1361,7 +1424,7 @@ pub fn main(args: [][]u8) { } add_compile_fail_case("invalid pointer for var type", R"SOURCE( extern fn ext() -> usize; var bytes: [ext()]u8 = undefined; -fn f() { +export fn f() { for (bytes) |*b, i| { *b = u8(i); } @@ -1379,10 +1442,11 @@ extern fn foo(comptime x: i32, y: i32) -> i32; fn f() -> i32 { foo(1, 2) } +export fn entry() -> usize { @sizeOf(@typeOf(f)) } )SOURCE", 1, ".tmp_source.zig:2:15: error: comptime parameter not allowed in extern function"); add_compile_fail_case("convert fixed size array to slice with invalid size", R"SOURCE( -fn f() { +export fn f() { var array: [5]u8 = undefined; var foo = ([]const u32)(array)[0]; } @@ -1403,7 +1467,7 @@ pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type { } } -fn function_with_return_type_type() { +export fn function_with_return_type_type() { var list: List(i32) = undefined; list.length = 10; } @@ -1417,6 +1481,7 @@ var self = "aoeu"; fn f(m: []const u8) { m.copy(u8, self[0...], m); } +export fn entry() -> usize { @sizeOf(@typeOf(f)) } )SOURCE", 1, ".tmp_source.zig:4:6: error: no member named 'copy' in '[]const u8'"); add_compile_fail_case("wrong number of arguments for method fn call", R"SOURCE( @@ -1427,17 +1492,18 @@ fn f(foo: &const Foo) { foo.method(1, 2); } +export fn entry() -> usize { @sizeOf(@typeOf(f)) } )SOURCE", 1, ".tmp_source.zig:7:15: error: expected 2 arguments, found 3"); add_compile_fail_case("assign through constant pointer", R"SOURCE( -fn f() { +export fn f() { var cstr = c"Hat"; cstr[0] = 'W'; } )SOURCE", 1, ".tmp_source.zig:4:11: error: cannot assign to constant"); add_compile_fail_case("assign through constant slice", R"SOURCE( -pub fn f() { +export fn f() { var cstr: []const u8 = "Hat"; cstr[0] = 'W'; } @@ -1451,6 +1517,7 @@ pub fn main(args: [][]bogus) -> %void {} fn foo(blah: []u8) { for (blah) { } } +export fn entry() -> usize { @sizeOf(@typeOf(foo)) } )SOURCE", 1, ".tmp_source.zig:3:5: error: for loop expression missing element parameter"); add_compile_fail_case("misspelled type with pointer only reference", R"SOURCE( @@ -1482,6 +1549,8 @@ fn foo() { jll.init(1234); var jd = JsonNode {.kind = JsonType.JSONArray , .jobject = JsonOA.JSONArray {jll} }; } + +export fn entry() -> usize { @sizeOf(@typeOf(foo)) } )SOURCE", 1, ".tmp_source.zig:6:16: error: use of undeclared identifier 'JsonList'"); add_compile_fail_case("method call with first arg type primitive", R"SOURCE( @@ -1495,7 +1564,7 @@ const Foo = struct { } }; -fn f() { +export fn f() { const derp = Foo.init(3); derp.init(); @@ -1523,7 +1592,7 @@ pub const Allocator = struct { field: i32, }; -fn foo() { +export fn foo() { var x = List.init(&global_allocator); x.init(); } @@ -1533,13 +1602,15 @@ fn foo() { const TINY_QUANTUM_SHIFT = 4; const TINY_QUANTUM_SIZE = 1 << TINY_QUANTUM_SHIFT; var block_aligned_stuff: usize = (4 + TINY_QUANTUM_SIZE) & ~(TINY_QUANTUM_SIZE - 1); + +export fn entry() -> usize { @sizeOf(@typeOf(block_aligned_stuff)) } )SOURCE", 1, ".tmp_source.zig:4:60: error: unable to perform binary not operation on type '(integer literal)'"); { TestCase *tc = add_compile_fail_case("multiple files with private function error", R"SOURCE( const foo = @import("foo.zig"); -fn callPrivFunction() { +export fn callPrivFunction() { foo.privateFunction(); } )SOURCE", 2, @@ -1554,13 +1625,15 @@ fn privateFunction() { } add_compile_fail_case("container init with non-type", R"SOURCE( const zero: i32 = 0; const a = zero{1}; + +export fn entry() -> usize { @sizeOf(@typeOf(a)) } )SOURCE", 1, ".tmp_source.zig:3:11: error: expected type, found 'i32'"); add_compile_fail_case("assign to constant field", R"SOURCE( const Foo = struct { field: i32, }; -fn derp() { +export fn derp() { const f = Foo {.field = 1234,}; f.field = 0; } @@ -1580,6 +1653,8 @@ fn canFail() -> %void { } pub fn maybeInt() -> ?i32 { return 0; } + +export fn entry() -> usize { @sizeOf(@typeOf(testTrickyDefer)) } )SOURCE", 1, ".tmp_source.zig:5:11: error: cannot return from defer expression"); add_compile_fail_case("attempt to access var args out of bounds", R"SOURCE( @@ -1590,6 +1665,8 @@ fn add(args: ...) -> i32 { fn foo() -> i32 { add(i32(1234)) } + +export fn entry() -> usize { @sizeOf(@typeOf(foo)) } )SOURCE", 2, ".tmp_source.zig:3:19: error: index 1 outside argument list of size 1", ".tmp_source.zig:7:8: note: called from here"); @@ -1606,10 +1683,12 @@ fn add(args: ...) -> i32 { fn bar() -> i32 { add(1, 2, 3, 4) } + +export fn entry() -> usize { @sizeOf(@typeOf(bar)) } )SOURCE", 1, ".tmp_source.zig:11:9: error: parameter of type '(integer literal)' requires comptime"); add_compile_fail_case("assign too big number to u16", R"SOURCE( -fn foo() { +export fn foo() { var vga_mem: u16 = 0xB8000; } )SOURCE", 1, ".tmp_source.zig:3:24: error: integer value 753664 cannot be implicitly casted to type 'u16'"); @@ -1619,10 +1698,11 @@ const some_data: [100]u8 = { @setGlobalAlign(some_data, 3); undefined }; +export fn entry() -> usize { @sizeOf(@typeOf(some_data)) } )SOURCE", 1, ".tmp_source.zig:3:32: error: alignment value must be power of 2"); add_compile_fail_case("compile log", R"SOURCE( -fn foo() { +export fn foo() { comptime bar(12, "hi"); } fn bar(a: i32, b: []const u8) { @@ -1660,9 +1740,11 @@ fn foo(bit_field: &const BitField) -> u3 { fn bar(x: &const u3) -> u3 { return *x; } + +export fn entry() -> usize { @sizeOf(@typeOf(foo)) } )SOURCE", 1, ".tmp_source.zig:12:26: error: expected type '&const u3', found '&:3:6 const u3'"); - add_compile_fail_case_no_check_unused("referring to a struct that is invalid without --check-unused", R"SOURCE( + add_compile_fail_case("referring to a struct that is invalid", R"SOURCE( const UsbDeviceRequest = struct { Type: u8, }; @@ -1679,7 +1761,7 @@ fn assert(ok: bool) { ".tmp_source.zig:7:20: note: called from here"); add_compile_fail_case("control flow uses comptime var at runtime", R"SOURCE( -fn foo() { +export fn foo() { comptime var i = 0; while (i < 5; i += 1) { bar(); @@ -1692,14 +1774,14 @@ fn bar() { } ".tmp_source.zig:4:21: note: compile-time variable assigned here"); add_compile_fail_case("ignored return value", R"SOURCE( -fn foo() { +export fn foo() { bar(); } fn bar() -> i32 { 0 } )SOURCE", 1, ".tmp_source.zig:3:8: error: return value ignored"); add_compile_fail_case("integer literal on a non-comptime var", R"SOURCE( -fn foo() { +export fn foo() { var i = 0; while (i < 10; i += 1) { } } @@ -1712,6 +1794,8 @@ pub fn pass(in: []u8) -> []u8 { *out[0] = in[0]; return (*out)[0...1]; } + +export fn entry() -> usize { @sizeOf(@typeOf(pass)) } )SOURCE", 1, ".tmp_source.zig:5:5: error: attempt to dereference non pointer type '[10]u8'"); add_compile_fail_case("pass const ptr to mutable ptr fn", R"SOURCE( @@ -1723,6 +1807,8 @@ fn foo() -> bool { fn ptrEql(a: &[]const u8, b: &[]const u8) -> bool { return true; } + +export fn entry() -> usize { @sizeOf(@typeOf(foo)) } )SOURCE", 1, ".tmp_source.zig:5:19: error: expected type '&[]const u8', found '&const []const u8'"); } @@ -2159,23 +2245,69 @@ static void run_self_hosted_test(bool is_release_mode) { } } +static void run_std_lib_test(bool is_release_mode) { + Buf std_index_file = BUF_INIT; + os_path_join(buf_create_from_str(ZIG_STD_DIR), + buf_create_from_str("index.zig"), &std_index_file); + + Buf zig_stderr = BUF_INIT; + Buf zig_stdout = BUF_INIT; + ZigList args = {0}; + args.append("test"); + args.append(buf_ptr(&std_index_file)); + if (is_release_mode) { + args.append("--release"); + } + Termination term; + os_exec_process(zig_exe, args, &term, &zig_stderr, &zig_stdout); + + if (term.how != TerminationIdClean || term.code != 0) { + printf("\nstd lib tests failed:\n"); + printf("./zig"); + for (size_t i = 0; i < args.length; i += 1) { + printf(" %s", args.at(i)); + } + printf("\n%s\n", buf_ptr(&zig_stderr)); + exit(1); + } +} + + static void add_self_hosted_tests(void) { { TestCase *test_case = allocate(1); test_case->case_name = "self hosted tests (debug)"; - test_case->is_self_hosted = true; + test_case->special = TestSpecialSelfHosted; test_case->is_release_mode = false; test_cases.append(test_case); } { TestCase *test_case = allocate(1); test_case->case_name = "self hosted tests (release)"; - test_case->is_self_hosted = true; + test_case->special = TestSpecialSelfHosted; test_case->is_release_mode = true; test_cases.append(test_case); } } +static void add_std_lib_tests(void) { + { + TestCase *test_case = allocate(1); + test_case->case_name = "std (debug)"; + test_case->special = TestSpecialStd; + test_case->is_release_mode = false; + test_cases.append(test_case); + } + { + TestCase *test_case = allocate(1); + test_case->case_name = "std (release)"; + test_case->special = TestSpecialStd; + test_case->is_release_mode = true; + test_cases.append(test_case); + } +} + + static void print_compiler_invocation(TestCase *test_case) { printf("%s", zig_exe); for (size_t i = 0; i < test_case->compiler_args.length; i += 1) { @@ -2193,8 +2325,10 @@ static void print_exe_invocation(TestCase *test_case) { } static void run_test(TestCase *test_case) { - if (test_case->is_self_hosted) { + if (test_case->special == TestSpecialSelfHosted) { return run_self_hosted_test(test_case->is_release_mode); + } else if (test_case->special == TestSpecialStd) { + return run_std_lib_test(test_case->is_release_mode); } for (size_t i = 0; i < test_case->source_files.length; i += 1) { @@ -2366,6 +2500,7 @@ int main(int argc, char **argv) { add_compile_failure_test_cases(); add_parseh_test_cases(); add_self_hosted_tests(); + add_std_lib_tests(); run_all_tests(reverse); cleanup(); } -- 2.54.0