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 | 174 ++++++---- 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 | 311 +++++++++++++----- 58 files changed, 626 insertions(+), 889 deletions(-) diff --git a/doc/langref.md b/doc/langref.md index 9b806fc384..cf759ae3f5 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 3880120f37..a3e39415ec 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 8fe633460c..48777b6df0 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 4f806b9e1b..8e3c82822f 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")); - } - } - } - - 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); - - 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))); - } + 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")); } - } 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); } } + + 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->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; + + g->fn_protos.append(fn_table_entry); + g->fn_defs.append(fn_table_entry); + + } 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 8a17cc4cf5..c10844df46 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 fd2d8dd3a9..5456fbce3d 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 dc2fb99ed8..72dacf71c4 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 0539851454..79647cdb97 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 3c9e53662e..b5f5a16983 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 87d06ee7fe..2705dcbf4a 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 b55eefe6ac..2ae51047e5 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 deaa2a6ef4..640cd1ffea 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 a5cbe4cdea..008bcde853 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 2e05de9125..255631a61f 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 a34f3155c2..ab250474df 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 0203954d70..1045737033 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 5cfe0743db..c22e3712a0 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 7758bd596b..c54332d9ef 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 cc2eb44795..711e1de453 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 dba0422081..c67cf11db6 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 a36ca4a9ca..dab451b725 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 23fd1eba34..ca1481ca17 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 3b91efbc20..789e549c55 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 2b232bbf69..b11c5229c0 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 fce22d86ae..c05387ef9f 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 a7bef9ded5..928b631339 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 21c9d03e50..8a022307c3 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 4bff9fab81..ecee63bf89 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 37ba0fe4ec..d3534115b5 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 36c7b5d175..865400c537 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 eeed337141..27e45e9996 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 4e7c94f2d3..f66bba0991 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 b8d801824e..a58bf614f3 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 b7e9fba295..f18b342fa2 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 dcdb5086e1..c23b189dc3 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 155aa5cdbe..b4a3af8adb 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 a3681a4634..7cff1c1a56 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 6787afecf9..b5bbbc2114 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 9ba03b8031..ab3ea2b0de 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 fc1555ef14..3171c526d8 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 601194dd3f..28a5fcd9c7 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 9bc8f781e7..8c57d21946 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 d2f65e1ae2..c502afba69 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 889ce30bba..4935f210ba 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 734406c7c2..702e0ecc22 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 9bcd9fd9f6..5d2c2ba608 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 4c4bf431ea..6443b52725 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 9d831bd356..00046e38ce 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 7c7296166f..d8b4a10fa3 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 7ec047ca2f..a13a8ac55d 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 f18215b66c..ded18d82b7 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 894ee2dd16..e0c5793039 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 4281e01c77..db6e776853 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 03e6cfb64f..3b5100e39c 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 c0de342c38..0e61a0c567 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 15b8276b0b..5085613e76 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 e5e10e5568..c3b7a84722 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 cc951a2c11..823d04af94 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,9 +98,10 @@ 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) -{ +static TestCase *add_compile_fail_case(const char *case_name, const char *source, size_t count, ...) { + va_list ap; + va_start(ap, count); + TestCase *test_case = allocate(1); test_case->case_name = case_name; test_case->source_files.resize(1); @@ -122,31 +128,11 @@ static TestCase *add_compile_fail_case_extra(const char *case_name, const char * 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; -} - static void add_debug_safety_case(const char *case_name, const char *source) { { TestCase *test_case = allocate(1); @@ -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,42 +957,39 @@ 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; - )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; +export fn entry() -> foo { + return 1; } - )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"); + )SOURCE", 1, ".tmp_source.zig:2:1: error: variable of type 'type' must be constant"); add_compile_fail_case("multiple else prongs in a switch", R"SOURCE( fn f(x: u32) { @@ -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(); }