mirror of
https://github.com/ziglang/zig.git
synced 2025-12-26 16:13:07 +00:00
* make it always return a fully qualified name. stage1 is inconsistent about this. * AstGen: fix anon_name_strategy to correctly be `func` when anon type creation happens in the operand of the return expression. * Sema: implement type names for the "function" naming strategy. * Put "enum", "union", "opaque", or "struct" in place of "anon" when creating respective anonymous Decl names. * std.testing: add `expectStringStartsWith`. Didn't end up using it after all. Also this enables the real test runner for stage2 LLVM backend (sans wasm32) since it works now.
869 lines
23 KiB
Zig
869 lines
23 KiB
Zig
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;
|
|
|
|
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;
|
|
|
|
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" {
|
|
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;
|
|
|
|
try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
|
|
}
|
|
|
|
test "hex escape" {
|
|
if (builtin.zig_backend == .stage2_aarch64) 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;
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
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;
|
|
|
|
const s1 =
|
|
\\one
|
|
//\\two
|
|
\\three
|
|
//\\four
|
|
\\five
|
|
;
|
|
const s2 = "one\nthree\nfive";
|
|
try expect(mem.eql(u8, s1, s2));
|
|
}
|
|
|
|
test "string concatenation" {
|
|
try expect(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
|
|
}
|
|
|
|
test "array mult operator" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
|
|
|
try expect(mem.eql(u8, "ab" ** 5, "ababababab"));
|
|
}
|
|
|
|
const OpaqueA = opaque {};
|
|
const OpaqueB = opaque {};
|
|
|
|
test "opaque types" {
|
|
if (builtin.zig_backend == .stage1) {
|
|
// stage1 gets the type names wrong
|
|
return error.SkipZigTest;
|
|
}
|
|
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
try expect(*OpaqueA != *OpaqueB);
|
|
|
|
try expect(mem.eql(u8, @typeName(OpaqueA), "behavior.basic.OpaqueA"));
|
|
try expect(mem.eql(u8, @typeName(OpaqueB), "behavior.basic.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;
|
|
|
|
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 == .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;
|
|
|
|
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_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
|
|
|
|
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;
|
|
|
|
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 == .stage1) return error.SkipZigTest;
|
|
|
|
var a = &emptyFn;
|
|
try expect(a == a);
|
|
}
|
|
|
|
test "self reference through fn ptr field" {
|
|
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 == .stage2_wasm) return error.SkipZigTest;
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
|
|
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 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" {
|
|
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_c) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch != .x86_64) 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 == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) 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_c) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch != .x86_64) 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 == .stage2_arm) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_aarch64) 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" {
|
|
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);
|
|
}
|
|
|
|
test "discarding the result of various expressions" {
|
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
|
|
|
const S = struct {
|
|
fn foo() !u32 {
|
|
return 1;
|
|
}
|
|
fn bar() ?u32 {
|
|
return 1;
|
|
}
|
|
};
|
|
_ = S.bar() orelse {
|
|
// do nothing
|
|
};
|
|
_ = S.foo() catch {
|
|
// do nothing
|
|
};
|
|
_ = switch (1) {
|
|
1 => 1,
|
|
2 => {},
|
|
else => return,
|
|
};
|
|
_ = try S.foo();
|
|
_ = if (S.bar()) |some| some else {};
|
|
_ = blk: {
|
|
if (S.bar()) |some| break :blk some;
|
|
break :blk;
|
|
};
|
|
_ = while (S.bar()) |some| break some else {};
|
|
_ = for ("foo") |char| break char else {};
|
|
}
|
|
|
|
test "labeled block implicitly ends in a break" {
|
|
var a = false;
|
|
blk: {
|
|
if (a) break :blk;
|
|
}
|
|
}
|