const std = @import("std"); const builtin = @import("builtin"); const mem = std.mem; const expect = std.testing.expect; const expectEqualStrings = std.testing.expectEqualStrings; // normal comment /// this is a documentation comment /// doc comment line 2 fn emptyFunctionWithComments() void {} test "empty function with comments" { emptyFunctionWithComments(); } test "truncate" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; try expect(testTruncate(0x10fd) == 0xfd); comptime try expect(testTruncate(0x10fd) == 0xfd); } fn testTruncate(x: u32) u8 { return @truncate(u8, x); } test "truncate to non-power-of-two integers" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; try testTrunc(u32, u1, 0b10101, 0b1); try testTrunc(u32, u1, 0b10110, 0b0); try testTrunc(u32, u2, 0b10101, 0b01); try testTrunc(u32, u2, 0b10110, 0b10); try testTrunc(i32, i5, -4, -4); try testTrunc(i32, i5, 4, 4); try testTrunc(i32, i5, -28, 4); try testTrunc(i32, i5, 28, -4); try testTrunc(i32, i5, std.math.maxInt(i32), -1); } fn testTrunc(comptime Big: type, comptime Little: type, big: Big, little: Little) !void { try expect(@truncate(Little, big) == little); } const g1: i32 = 1233 + 1; var g2: i32 = 0; test "global variables" { if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; try expect(g2 == 0); g2 = g1; try expect(g2 == 1234); } test "comptime keyword on expressions" { const x: i32 = comptime x: { break :x 1 + 2 + 3; }; try expect(x == comptime 6); } test "type equality" { try expect(*const u8 != *u8); } test "pointer dereferencing" { var x = @as(i32, 3); const y = &x; y.* += 1; try expect(x == 4); try expect(y.* == 4); } test "const expression eval handling of variables" { var x = true; while (x) { x = false; } } test "character literals" { try expect('\'' == single_quote); } const single_quote = '\''; test "non const ptr to aliased type" { const int = i32; try expect(?*int == ?*i32); } test "cold function" { thisIsAColdFn(); comptime thisIsAColdFn(); } fn thisIsAColdFn() void { @setCold(true); } test "unicode escape in character literal" { var a: u24 = '\u{01f4a9}'; try expect(a == 128169); } test "unicode character in character literal" { try expect('💩' == 128169); } fn first4KeysOfHomeRow() []const u8 { return "aoeu"; } test "return string from function" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); } test "hex escape" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; try expect(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); } test "multiline string" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const s1 = \\one \\two) \\three ; const s2 = "one\ntwo)\nthree"; try expect(mem.eql(u8, s1, s2)); } test "multiline string comments at start" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const s1 = //\\one \\two) \\three ; const s2 = "two)\nthree"; try expect(mem.eql(u8, s1, s2)); } test "multiline string comments at end" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const s1 = \\one \\two) //\\three ; const s2 = "one\ntwo)"; try expect(mem.eql(u8, s1, s2)); } test "multiline string comments in middle" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const s1 = \\one //\\two) \\three ; const s2 = "one\nthree"; try expect(mem.eql(u8, s1, s2)); } test "multiline string comments at multiple places" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const s1 = \\one //\\two \\three //\\four \\five ; const s2 = "one\nthree\nfive"; try expect(mem.eql(u8, s1, s2)); } test "string concatenation" { if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .macos) return error.SkipZigTest; try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); } test "array mult operator" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; try expect(mem.eql(u8, "ab" ** 5, "ababababab")); } const OpaqueA = opaque {}; const OpaqueB = opaque {}; test "opaque types" { try expect(*OpaqueA != *OpaqueB); if (builtin.zig_backend == .stage1) { // TODO make this pass for stage2 try expect(mem.eql(u8, @typeName(OpaqueA), "OpaqueA")); try expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB")); } } const global_a: i32 = 1234; const global_b: *const i32 = &global_a; const global_c: *const f32 = @ptrCast(*const f32, global_b); test "compile time global reinterpret" { const d = @ptrCast(*const i32, global_c); try expect(d.* == 1234); } test "cast undefined" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; const array: [100]u8 = undefined; const slice = @as([]const u8, &array); testCastUndefined(slice); } fn testCastUndefined(x: []const u8) void { _ = x; } test "implicit cast after unreachable" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; try expect(outer() == 1234); } fn inner() i32 { return 1234; } fn outer() i64 { return inner(); } test "comptime if inside runtime while which unconditionally breaks" { testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true); } fn testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(cond: bool) void { while (cond) { if (false) {} break; } } test "implicit comptime while" { while (false) { @compileError("bad"); } } fn fnThatClosesOverLocalConst() type { const c = 1; return struct { fn g() i32 { return c; } }; } test "function closes over local const" { const x = fnThatClosesOverLocalConst().g(); try expect(x == 1); } test "volatile load and store" { var number: i32 = 1234; const ptr = @as(*volatile i32, &number); ptr.* += 1; try expect(ptr.* == 1235); } fn fA() []const u8 { return "a"; } fn fB() []const u8 { return "b"; } test "call function pointer in struct" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest; try expect(mem.eql(u8, f3(true), "a")); try expect(mem.eql(u8, f3(false), "b")); } fn f3(x: bool) []const u8 { var wrapper: FnPtrWrapper = .{ .fn_ptr = fB, }; if (x) { wrapper.fn_ptr = fA; } return wrapper.fn_ptr(); } const FnPtrWrapper = struct { fn_ptr: *const fn () []const u8, }; test "const ptr from var variable" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; var x: u64 = undefined; var y: u64 = undefined; x = 78; copy(&x, &y); try expect(x == y); } fn copy(src: *const u64, dst: *u64) void { dst.* = src.*; } test "call result of if else expression" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO try expect(mem.eql(u8, f2(true), "a")); try expect(mem.eql(u8, f2(false), "b")); } fn f2(x: bool) []const u8 { return (if (x) fA else fB)(); } test "memcpy and memset intrinsics" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO try testMemcpyMemset(); // TODO add comptime test coverage //comptime try testMemcpyMemset(); } fn testMemcpyMemset() !void { var foo: [20]u8 = undefined; var bar: [20]u8 = undefined; @memset(&foo, 'A', foo.len); @memcpy(&bar, &foo, bar.len); try expect(bar[0] == 'A'); try expect(bar[11] == 'A'); try expect(bar[19] == 'A'); } test "variable is allowed to be a pointer to an opaque type" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO var x: i32 = 1234; _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x)); } fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA { var a = ptr; return a; } test "take address of parameter" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; try testTakeAddressOfParameter(12.34); } fn testTakeAddressOfParameter(f: f32) !void { const f_ptr = &f; try expect(f_ptr.* == 12.34); } test "pointer to void return type" { if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .macos) return error.SkipZigTest; try testPointerToVoidReturnType(); } fn testPointerToVoidReturnType() anyerror!void { const a = testPointerToVoidReturnType2(); return a.*; } const test_pointer_to_void_return_type_x = void{}; fn testPointerToVoidReturnType2() *const void { return &test_pointer_to_void_return_type_x; } test "array 2D const double ptr" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO const rect_2d_vertexes = [_][1]f32{ [_]f32{1.0}, [_]f32{2.0}, }; try testArray2DConstDoublePtr(&rect_2d_vertexes[0][0]); } test "array 2D const double ptr with offset" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; const rect_2d_vertexes = [_][2]f32{ [_]f32{ 3.0, 4.239 }, [_]f32{ 1.0, 2.0 }, }; try testArray2DConstDoublePtr(&rect_2d_vertexes[1][0]); } test "array 3D const double ptr with offset" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO const rect_3d_vertexes = [_][2][2]f32{ [_][2]f32{ [_]f32{ 3.0, 4.239 }, [_]f32{ 3.5, 7.2 }, }, [_][2]f32{ [_]f32{ 3.0, 4.239 }, [_]f32{ 1.0, 2.0 }, }, }; try testArray2DConstDoublePtr(&rect_3d_vertexes[1][1][0]); } fn testArray2DConstDoublePtr(ptr: *const f32) !void { const ptr2 = @ptrCast([*]const f32, ptr); try expect(ptr2[0] == 1.0); try expect(ptr2[1] == 2.0); } test "double implicit cast in same expression" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; var x = @as(i32, @as(u16, nine())); try expect(x == 9); } fn nine() u8 { return 9; } test "struct inside function" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; try testStructInFn(); comptime try testStructInFn(); } fn testStructInFn() !void { const BlockKind = u32; const Block = struct { kind: BlockKind, }; var block = Block{ .kind = 1234 }; block.kind += 1; try expect(block.kind == 1235); } test "fn call returning scalar optional in equality expression" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; try expect(getNull() == null); } fn getNull() ?*i32 { return null; } test "global variable assignment with optional unwrapping with var initialized to undefined" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const S = struct { var data: i32 = 1234; fn foo() ?*i32 { return &data; } }; global_foo = S.foo() orelse { @panic("bad"); }; try expect(global_foo.* == 1234); } var global_foo: *i32 = undefined; test "peer result location with typed parent, runtime condition, comptime prongs" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; const S = struct { fn doTheTest(arg: i32) i32 { const st = Structy{ .bleh = if (arg == 1) 1 else 1, }; if (st.bleh == 1) return 1234; return 0; } const Structy = struct { bleh: i32, }; }; try expect(S.doTheTest(0) == 1234); try expect(S.doTheTest(1) == 1234); } test "non-ambiguous reference of shadowed decls" { try expect(ZA().B().Self != ZA().Self); } fn ZA() type { return struct { b: B(), const Self = @This(); fn B() type { return struct { const Self = @This(); }; } }; } test "use of declaration with same name as primitive" { const S = struct { const @"u8" = u16; const alias = @"u8"; }; const a: S.u8 = 300; try expect(a == 300); const b: S.alias = 300; try expect(b == 300); const @"u8" = u16; const c: @"u8" = 300; try expect(c == 300); } test "constant equal function pointers" { const alias = emptyFn; try expect(comptime x: { break :x emptyFn == alias; }); } fn emptyFn() void {} const addr1 = @ptrCast(*const u8, &emptyFn); test "comptime cast fn to ptr" { if (builtin.zig_backend == .stage1) return error.SkipZigTest; const addr2 = @ptrCast(*const u8, &emptyFn); comptime try expect(addr1 == addr2); } test "equality compare fn ptrs" { if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest; var a = &emptyFn; try expect(a == a); } test "self reference through fn ptr field" { if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest; if (builtin.zig_backend == .stage1) return error.SkipZigTest; if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const S = struct { const A = struct { f: *const fn (A) u8, }; fn foo(a: A) u8 { _ = a; return 12; } }; var a: S.A = undefined; a.f = S.foo; try expect(a.f(a) == 12); } test "global variable initialized to global variable array element" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; try expect(global_ptr == &gdt[0]); } const GDTEntry = struct { field: i32, }; var gdt = [_]GDTEntry{ GDTEntry{ .field = 1 }, GDTEntry{ .field = 2 }, }; var global_ptr = &gdt[0]; test "global constant is loaded with a runtime-known index" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; const S = struct { fn doTheTest() !void { var index: usize = 1; const ptr = &pieces[index].field; try expect(ptr.* == 2); } const Piece = struct { field: i32, }; const pieces = [_]Piece{ Piece{ .field = 1 }, Piece{ .field = 2 }, Piece{ .field = 3 } }; }; try S.doTheTest(); } test "multiline string literal is null terminated" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; const s1 = \\one \\two) \\three ; const s2 = "one\ntwo)\nthree"; try expect(std.cstr.cmp(s1, s2) == 0); } test "string escapes" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO try expectEqualStrings("\"", "\x22"); try expectEqualStrings("\'", "\x27"); try expectEqualStrings("\n", "\x0a"); try expectEqualStrings("\r", "\x0d"); try expectEqualStrings("\t", "\x09"); try expectEqualStrings("\\", "\x5c"); try expectEqualStrings("\u{1234}\u{069}\u{1}", "\xe1\x88\xb4\x69\x01"); } test "explicit cast optional pointers" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const a: ?*i32 = undefined; const b: ?*f32 = @ptrCast(?*f32, a); _ = b; } test "pointer comparison" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; const a = @as([]const u8, "a"); const b = &a; try expect(ptrEql(b, b)); } fn ptrEql(a: *const []const u8, b: *const []const u8) bool { return a == b; } test "string concatenation" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; const a = "OK" ++ " IT " ++ "WORKED"; const b = "OK IT WORKED"; comptime try expect(@TypeOf(a) == *const [12:0]u8); comptime try expect(@TypeOf(b) == *const [12:0]u8); const len = mem.len(b); const len_with_null = len + 1; { var i: u32 = 0; while (i < len_with_null) : (i += 1) { try expect(a[i] == b[i]); } } try expect(a[len] == 0); try expect(b[len] == 0); } test "thread local variable" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const S = struct { threadlocal var t: i32 = 1234; }; S.t += 1; try expect(S.t == 1235); } test "result location is optional inside error union" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const x = maybe(true) catch unreachable; try expect(x.? == 42); } fn maybe(x: bool) anyerror!?u32 { return switch (x) { true => @as(u32, 42), else => null, }; } test "pointer to thread local array" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const s = "Hello world"; std.mem.copy(u8, buffer[0..], s); try std.testing.expectEqualSlices(u8, buffer[0..], s); } threadlocal var buffer: [11]u8 = undefined; test "auto created variables have correct alignment" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const S = struct { fn foo(str: [*]const u8) u32 { for (@ptrCast([*]align(1) const u32, str)[0..1]) |v| { return v; } return 0; } }; try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a); comptime try expect(S.foo("\x7a\x7a\x7a\x7a") == 0x7a7a7a7a); } test "extern variable with non-pointer opaque type" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO @export(var_to_export, .{ .name = "opaque_extern_var" }); try expect(@ptrCast(*align(1) u32, &opaque_extern_var).* == 42); } extern var opaque_extern_var: opaque {}; var var_to_export: u32 = 42; test "lazy typeInfo value as generic parameter" { if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO const S = struct { fn foo(args: anytype) void { _ = args; } }; S.foo(@typeInfo(@TypeOf(.{}))); } test "variable name containing underscores does not shadow int primitive" { const _u0 = 0; const i_8 = 0; const u16_ = 0; const i3_2 = 0; const u6__4 = 0; const i2_04_8 = 0; _ = _u0; _ = i_8; _ = u16_; _ = i3_2; _ = u6__4; _ = i2_04_8; } test "if expression type coercion" { var cond: bool = true; const x: u16 = if (cond) 1 else 0; try expect(@as(u16, x) == 1); }