organize behavior tests

check the set of passing tests; move towards the disabling logic being
inside each test rather than which files are included.

this enables a few more passing tests.
This commit is contained in:
Andrew Kelley 2022-01-26 20:59:20 -07:00
parent 82bd0ac572
commit 35423b0054
13 changed files with 1034 additions and 972 deletions

View File

@ -1,7 +1,6 @@
const builtin = @import("builtin");
test {
// Tests that pass for stage1, llvm backend, C backend, wasm backend, arm backend and x86_64 backend.
_ = @import("behavior/align.zig");
_ = @import("behavior/alignof.zig");
_ = @import("behavior/array.zig");
@ -26,7 +25,6 @@ test {
_ = @import("behavior/cast.zig");
_ = @import("behavior/comptime_memory.zig");
_ = @import("behavior/fn_in_struct_in_comptime.zig");
_ = @import("behavior/generics_llvm.zig");
_ = @import("behavior/hasdecl.zig");
_ = @import("behavior/hasfield.zig");
_ = @import("behavior/namespace_depends_on_compile_var.zig");
@ -43,6 +41,7 @@ test {
_ = @import("behavior/bitcast.zig");
_ = @import("behavior/bugs/624.zig");
_ = @import("behavior/bugs/704.zig");
_ = @import("behavior/bugs/1076.zig");
_ = @import("behavior/bugs/1486.zig");
_ = @import("behavior/bugs/2692.zig");
_ = @import("behavior/bugs/2889.zig");
@ -128,7 +127,6 @@ test {
_ = @import("behavior/bugs/726.zig");
_ = @import("behavior/bugs/828.zig");
_ = @import("behavior/bugs/920.zig");
_ = @import("behavior/bugs/1076.zig");
_ = @import("behavior/bugs/1120.zig");
_ = @import("behavior/bugs/1421.zig");
_ = @import("behavior/bugs/1442.zig");
@ -150,9 +148,7 @@ test {
_ = @import("behavior/bugs/7047.zig");
_ = @import("behavior/bugs/10147.zig");
_ = @import("behavior/byteswap.zig");
_ = @import("behavior/call_stage1.zig");
_ = @import("behavior/const_slice_child.zig");
_ = @import("behavior/error_stage1.zig");
_ = @import("behavior/field_parent_ptr.zig");
_ = @import("behavior/floatop_stage1.zig");
_ = @import("behavior/fn_delegation.zig");
@ -164,14 +160,12 @@ test {
_ = @import("behavior/optional_stage1.zig");
_ = @import("behavior/popcount_stage1.zig");
_ = @import("behavior/reflection.zig");
_ = @import("behavior/saturating_arithmetic_stage1.zig");
_ = @import("behavior/select.zig");
_ = @import("behavior/shuffle.zig");
_ = @import("behavior/sizeof_and_typeof_stage1.zig");
_ = @import("behavior/slice_stage1.zig");
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
_ = @import("behavior/struct_contains_slice_of_itself.zig");
_ = @import("behavior/struct_stage1.zig");
_ = @import("behavior/switch_prong_err_enum.zig");
_ = @import("behavior/switch_prong_implicit_cast.zig");
_ = @import("behavior/truncate_stage1.zig");
@ -185,7 +179,6 @@ test {
if (builtin.target.cpu.arch == .wasm32) {
_ = @import("behavior/wasm.zig");
}
_ = @import("behavior/translate_c_macros_stage1.zig");
}
}
}

View File

@ -1,3 +1,81 @@
const builtin = @import("builtin");
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
test "basic invocations" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const foo = struct {
fn foo() i32 {
return 1234;
}
}.foo;
try expect(@call(.{}, foo, .{}) == 1234);
comptime {
// modifiers that allow comptime calls
try expect(@call(.{}, foo, .{}) == 1234);
try expect(@call(.{ .modifier = .no_async }, foo, .{}) == 1234);
try expect(@call(.{ .modifier = .always_tail }, foo, .{}) == 1234);
try expect(@call(.{ .modifier = .always_inline }, foo, .{}) == 1234);
}
{
// comptime call without comptime keyword
const result = @call(.{ .modifier = .compile_time }, foo, .{}) == 1234;
comptime try expect(result);
}
{
// call of non comptime-known function
var alias_foo = foo;
try expect(@call(.{ .modifier = .no_async }, alias_foo, .{}) == 1234);
try expect(@call(.{ .modifier = .never_tail }, alias_foo, .{}) == 1234);
try expect(@call(.{ .modifier = .never_inline }, alias_foo, .{}) == 1234);
}
}
test "tuple parameters" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const add = struct {
fn add(a: i32, b: i32) i32 {
return a + b;
}
}.add;
var a: i32 = 12;
var b: i32 = 34;
try expect(@call(.{}, add, .{ a, 34 }) == 46);
try expect(@call(.{}, add, .{ 12, b }) == 46);
try expect(@call(.{}, add, .{ a, b }) == 46);
try expect(@call(.{}, add, .{ 12, 34 }) == 46);
comptime try expect(@call(.{}, add, .{ 12, 34 }) == 46);
{
const separate_args0 = .{ a, b };
const separate_args1 = .{ a, 34 };
const separate_args2 = .{ 12, 34 };
const separate_args3 = .{ 12, b };
try expect(@call(.{ .modifier = .always_inline }, add, separate_args0) == 46);
try expect(@call(.{ .modifier = .always_inline }, add, separate_args1) == 46);
try expect(@call(.{ .modifier = .always_inline }, add, separate_args2) == 46);
try expect(@call(.{ .modifier = .always_inline }, add, separate_args3) == 46);
}
}
test "comptime call with bound function as parameter" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
fn ReturnType(func: anytype) type {
return switch (@typeInfo(@TypeOf(func))) {
.BoundFn => |info| info,
else => unreachable,
}.return_type orelse void;
}
fn call_me_maybe() ?i32 {
return 123;
}
};
var inst: S = undefined;
try expectEqual(?i32, S.ReturnType(inst.call_me_maybe));
}

View File

@ -1,74 +0,0 @@
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
test "basic invocations" {
const foo = struct {
fn foo() i32 {
return 1234;
}
}.foo;
try expect(@call(.{}, foo, .{}) == 1234);
comptime {
// modifiers that allow comptime calls
try expect(@call(.{}, foo, .{}) == 1234);
try expect(@call(.{ .modifier = .no_async }, foo, .{}) == 1234);
try expect(@call(.{ .modifier = .always_tail }, foo, .{}) == 1234);
try expect(@call(.{ .modifier = .always_inline }, foo, .{}) == 1234);
}
{
// comptime call without comptime keyword
const result = @call(.{ .modifier = .compile_time }, foo, .{}) == 1234;
comptime try expect(result);
}
{
// call of non comptime-known function
var alias_foo = foo;
try expect(@call(.{ .modifier = .no_async }, alias_foo, .{}) == 1234);
try expect(@call(.{ .modifier = .never_tail }, alias_foo, .{}) == 1234);
try expect(@call(.{ .modifier = .never_inline }, alias_foo, .{}) == 1234);
}
}
test "tuple parameters" {
const add = struct {
fn add(a: i32, b: i32) i32 {
return a + b;
}
}.add;
var a: i32 = 12;
var b: i32 = 34;
try expect(@call(.{}, add, .{ a, 34 }) == 46);
try expect(@call(.{}, add, .{ 12, b }) == 46);
try expect(@call(.{}, add, .{ a, b }) == 46);
try expect(@call(.{}, add, .{ 12, 34 }) == 46);
comptime try expect(@call(.{}, add, .{ 12, 34 }) == 46);
{
const separate_args0 = .{ a, b };
const separate_args1 = .{ a, 34 };
const separate_args2 = .{ 12, 34 };
const separate_args3 = .{ 12, b };
try expect(@call(.{ .modifier = .always_inline }, add, separate_args0) == 46);
try expect(@call(.{ .modifier = .always_inline }, add, separate_args1) == 46);
try expect(@call(.{ .modifier = .always_inline }, add, separate_args2) == 46);
try expect(@call(.{ .modifier = .always_inline }, add, separate_args3) == 46);
}
}
test "comptime call with bound function as parameter" {
const S = struct {
fn ReturnType(func: anytype) type {
return switch (@typeInfo(@TypeOf(func))) {
.BoundFn => |info| info,
else => unreachable,
}.return_type orelse void;
}
fn call_me_maybe() ?i32 {
return 123;
}
};
var inst: S = undefined;
try expectEqual(?i32, S.ReturnType(inst.call_me_maybe));
}

View File

@ -132,3 +132,349 @@ fn foo2(f: fn () anyerror!void) void {
}
fn bar2() (error{}!void) {}
test "error union type " {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
try testErrorUnionType();
comptime try testErrorUnionType();
}
fn testErrorUnionType() !void {
const x: anyerror!i32 = 1234;
if (x) |value| try expect(value == 1234) else |_| unreachable;
try expect(@typeInfo(@TypeOf(x)) == .ErrorUnion);
try expect(@typeInfo(@typeInfo(@TypeOf(x)).ErrorUnion.error_set) == .ErrorSet);
try expect(@typeInfo(@TypeOf(x)).ErrorUnion.error_set == anyerror);
}
test "error set type" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
try testErrorSetType();
comptime try testErrorSetType();
}
const MyErrSet = error{
OutOfMemory,
FileNotFound,
};
fn testErrorSetType() !void {
try expect(@typeInfo(MyErrSet).ErrorSet.?.len == 2);
const a: MyErrSet!i32 = 5678;
const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
try expect(b catch error.OutOfMemory == error.OutOfMemory);
if (a) |value| try expect(value == 5678) else |err| switch (err) {
error.OutOfMemory => unreachable,
error.FileNotFound => unreachable,
}
}
test "explicit error set cast" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
try testExplicitErrorSetCast(Set1.A);
comptime try testExplicitErrorSetCast(Set1.A);
}
const Set1 = error{ A, B };
const Set2 = error{ A, C };
fn testExplicitErrorSetCast(set1: Set1) !void {
var x = @errSetCast(Set2, set1);
var y = @errSetCast(Set1, x);
try expect(y == error.A);
}
test "comptime test error for empty error set" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
try testComptimeTestErrorEmptySet(1234);
comptime try testComptimeTestErrorEmptySet(1234);
}
const EmptyErrorSet = error{};
fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) !void {
if (x) |v| try expect(v == 1234) else |err| {
_ = err;
@compileError("bad");
}
}
test "comptime err to int of error set with only 1 possible value" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
}
fn testErrToIntWithOnePossibleValue(
x: error{A},
comptime value: u32,
) void {
if (@errorToInt(x) != value) {
@compileError("bad");
}
}
test "error union peer type resolution" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
try testErrorUnionPeerTypeResolution(1);
}
fn testErrorUnionPeerTypeResolution(x: i32) !void {
const y = switch (x) {
1 => bar_1(),
2 => baz_1(),
else => quux_1(),
};
if (y) |_| {
@panic("expected error");
} else |e| {
try expect(e == error.A);
}
}
fn bar_1() anyerror {
return error.A;
}
fn baz_1() !i32 {
return error.B;
}
fn quux_1() !i32 {
return error.C;
}
test "error: Zero sized error set returned with value payload crash" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
_ = foo3(0) catch {};
_ = comptime foo3(0) catch {};
}
const Error = error{};
fn foo3(b: usize) Error!usize {
return b;
}
test "error: Infer error set from literals" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
_ = nullLiteral("n") catch |err| handleErrors(err);
_ = floatLiteral("n") catch |err| handleErrors(err);
_ = intLiteral("n") catch |err| handleErrors(err);
_ = comptime nullLiteral("n") catch |err| handleErrors(err);
_ = comptime floatLiteral("n") catch |err| handleErrors(err);
_ = comptime intLiteral("n") catch |err| handleErrors(err);
}
fn handleErrors(err: anytype) noreturn {
switch (err) {
error.T => {},
}
unreachable;
}
fn nullLiteral(str: []const u8) !?i64 {
if (str[0] == 'n') return null;
return error.T;
}
fn floatLiteral(str: []const u8) !?f64 {
if (str[0] == 'n') return 1.0;
return error.T;
}
fn intLiteral(str: []const u8) !?i64 {
if (str[0] == 'n') return 1;
return error.T;
}
test "nested error union function call in optional unwrap" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
const Foo = struct {
a: i32,
};
fn errorable() !i32 {
var x: Foo = (try getFoo()) orelse return error.Other;
return x.a;
}
fn errorable2() !i32 {
var x: Foo = (try getFoo2()) orelse return error.Other;
return x.a;
}
fn errorable3() !i32 {
var x: Foo = (try getFoo3()) orelse return error.Other;
return x.a;
}
fn getFoo() anyerror!?Foo {
return Foo{ .a = 1234 };
}
fn getFoo2() anyerror!?Foo {
return error.Failure;
}
fn getFoo3() anyerror!?Foo {
return null;
}
};
try expect((try S.errorable()) == 1234);
try expectError(error.Failure, S.errorable2());
try expectError(error.Other, S.errorable3());
comptime {
try expect((try S.errorable()) == 1234);
try expectError(error.Failure, S.errorable2());
try expectError(error.Other, S.errorable3());
}
}
test "return function call to error set from error union function" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
fn errorable() anyerror!i32 {
return fail();
}
fn fail() anyerror {
return error.Failure;
}
};
try expectError(error.Failure, S.errorable());
comptime try expectError(error.Failure, S.errorable());
}
test "optional error set is the same size as error set" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
comptime try expect(@sizeOf(?anyerror) == @sizeOf(anyerror));
const S = struct {
fn returnsOptErrSet() ?anyerror {
return null;
}
};
try expect(S.returnsOptErrSet() == null);
comptime try expect(S.returnsOptErrSet() == null);
}
test "nested catch" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
fn entry() !void {
try expectError(error.Bad, func());
}
fn fail() anyerror!Foo {
return error.Wrong;
}
fn func() anyerror!Foo {
_ = fail() catch
fail() catch
return error.Bad;
unreachable;
}
const Foo = struct {
field: i32,
};
};
try S.entry();
comptime try S.entry();
}
test "function pointer with return type that is error union with payload which is pointer of parent struct" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
const Foo = struct {
fun: fn (a: i32) (anyerror!*Foo),
};
const Err = error{UnspecifiedErr};
fn bar(a: i32) anyerror!*Foo {
_ = a;
return Err.UnspecifiedErr;
}
fn doTheTest() !void {
var x = Foo{ .fun = @This().bar };
try expectError(error.UnspecifiedErr, x.fun(1));
}
};
try S.doTheTest();
}
test "return result loc as peer result loc in inferred error set function" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {
if (quux(2)) |x| {
try expect(x.Two);
} else |e| switch (e) {
error.Whatever => @panic("fail"),
}
try expectError(error.Whatever, quux(99));
}
const FormValue = union(enum) {
One: void,
Two: bool,
};
fn quux(id: u64) !FormValue {
return switch (id) {
2 => FormValue{ .Two = true },
1 => FormValue{ .One = {} },
else => return error.Whatever,
};
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "error payload type is correctly resolved" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const MyIntWrapper = struct {
const Self = @This();
x: i32,
pub fn create() anyerror!Self {
return Self{ .x = 42 };
}
};
try expectEqual(MyIntWrapper{ .x = 42 }, try MyIntWrapper.create());
}
test "error union comptime caching" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
fn quux(comptime arg: anytype) void {
arg catch {};
}
};
S.quux(@as(anyerror!void, {}));
S.quux(@as(anyerror!void, {}));
}

View File

@ -1,319 +0,0 @@
const std = @import("std");
const expect = std.testing.expect;
const expectError = std.testing.expectError;
const expectEqual = std.testing.expectEqual;
const mem = std.mem;
test "error union type " {
try testErrorUnionType();
comptime try testErrorUnionType();
}
fn testErrorUnionType() !void {
const x: anyerror!i32 = 1234;
if (x) |value| try expect(value == 1234) else |_| unreachable;
try expect(@typeInfo(@TypeOf(x)) == .ErrorUnion);
try expect(@typeInfo(@typeInfo(@TypeOf(x)).ErrorUnion.error_set) == .ErrorSet);
try expect(@typeInfo(@TypeOf(x)).ErrorUnion.error_set == anyerror);
}
test "error set type" {
try testErrorSetType();
comptime try testErrorSetType();
}
const MyErrSet = error{
OutOfMemory,
FileNotFound,
};
fn testErrorSetType() !void {
try expect(@typeInfo(MyErrSet).ErrorSet.?.len == 2);
const a: MyErrSet!i32 = 5678;
const b: MyErrSet!i32 = MyErrSet.OutOfMemory;
try expect(b catch error.OutOfMemory == error.OutOfMemory);
if (a) |value| try expect(value == 5678) else |err| switch (err) {
error.OutOfMemory => unreachable,
error.FileNotFound => unreachable,
}
}
test "explicit error set cast" {
try testExplicitErrorSetCast(Set1.A);
comptime try testExplicitErrorSetCast(Set1.A);
}
const Set1 = error{ A, B };
const Set2 = error{ A, C };
fn testExplicitErrorSetCast(set1: Set1) !void {
var x = @errSetCast(Set2, set1);
var y = @errSetCast(Set1, x);
try expect(y == error.A);
}
test "comptime test error for empty error set" {
try testComptimeTestErrorEmptySet(1234);
comptime try testComptimeTestErrorEmptySet(1234);
}
const EmptyErrorSet = error{};
fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) !void {
if (x) |v| try expect(v == 1234) else |err| {
_ = err;
@compileError("bad");
}
}
test "comptime err to int of error set with only 1 possible value" {
testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
}
fn testErrToIntWithOnePossibleValue(
x: error{A},
comptime value: u32,
) void {
if (@errorToInt(x) != value) {
@compileError("bad");
}
}
test "error union peer type resolution" {
try testErrorUnionPeerTypeResolution(1);
}
fn testErrorUnionPeerTypeResolution(x: i32) !void {
const y = switch (x) {
1 => bar_1(),
2 => baz_1(),
else => quux_1(),
};
if (y) |_| {
@panic("expected error");
} else |e| {
try expect(e == error.A);
}
}
fn bar_1() anyerror {
return error.A;
}
fn baz_1() !i32 {
return error.B;
}
fn quux_1() !i32 {
return error.C;
}
test "error: Zero sized error set returned with value payload crash" {
_ = foo3(0) catch {};
_ = comptime foo3(0) catch {};
}
const Error = error{};
fn foo3(b: usize) Error!usize {
return b;
}
test "error: Infer error set from literals" {
_ = nullLiteral("n") catch |err| handleErrors(err);
_ = floatLiteral("n") catch |err| handleErrors(err);
_ = intLiteral("n") catch |err| handleErrors(err);
_ = comptime nullLiteral("n") catch |err| handleErrors(err);
_ = comptime floatLiteral("n") catch |err| handleErrors(err);
_ = comptime intLiteral("n") catch |err| handleErrors(err);
}
fn handleErrors(err: anytype) noreturn {
switch (err) {
error.T => {},
}
unreachable;
}
fn nullLiteral(str: []const u8) !?i64 {
if (str[0] == 'n') return null;
return error.T;
}
fn floatLiteral(str: []const u8) !?f64 {
if (str[0] == 'n') return 1.0;
return error.T;
}
fn intLiteral(str: []const u8) !?i64 {
if (str[0] == 'n') return 1;
return error.T;
}
test "nested error union function call in optional unwrap" {
const S = struct {
const Foo = struct {
a: i32,
};
fn errorable() !i32 {
var x: Foo = (try getFoo()) orelse return error.Other;
return x.a;
}
fn errorable2() !i32 {
var x: Foo = (try getFoo2()) orelse return error.Other;
return x.a;
}
fn errorable3() !i32 {
var x: Foo = (try getFoo3()) orelse return error.Other;
return x.a;
}
fn getFoo() anyerror!?Foo {
return Foo{ .a = 1234 };
}
fn getFoo2() anyerror!?Foo {
return error.Failure;
}
fn getFoo3() anyerror!?Foo {
return null;
}
};
try expect((try S.errorable()) == 1234);
try expectError(error.Failure, S.errorable2());
try expectError(error.Other, S.errorable3());
comptime {
try expect((try S.errorable()) == 1234);
try expectError(error.Failure, S.errorable2());
try expectError(error.Other, S.errorable3());
}
}
test "return function call to error set from error union function" {
const S = struct {
fn errorable() anyerror!i32 {
return fail();
}
fn fail() anyerror {
return error.Failure;
}
};
try expectError(error.Failure, S.errorable());
comptime try expectError(error.Failure, S.errorable());
}
test "optional error set is the same size as error set" {
comptime try expect(@sizeOf(?anyerror) == @sizeOf(anyerror));
const S = struct {
fn returnsOptErrSet() ?anyerror {
return null;
}
};
try expect(S.returnsOptErrSet() == null);
comptime try expect(S.returnsOptErrSet() == null);
}
test "nested catch" {
const S = struct {
fn entry() !void {
try expectError(error.Bad, func());
}
fn fail() anyerror!Foo {
return error.Wrong;
}
fn func() anyerror!Foo {
_ = fail() catch
fail() catch
return error.Bad;
unreachable;
}
const Foo = struct {
field: i32,
};
};
try S.entry();
comptime try S.entry();
}
test "function pointer with return type that is error union with payload which is pointer of parent struct" {
const S = struct {
const Foo = struct {
fun: fn (a: i32) (anyerror!*Foo),
};
const Err = error{UnspecifiedErr};
fn bar(a: i32) anyerror!*Foo {
_ = a;
return Err.UnspecifiedErr;
}
fn doTheTest() !void {
var x = Foo{ .fun = @This().bar };
try expectError(error.UnspecifiedErr, x.fun(1));
}
};
try S.doTheTest();
}
test "return result loc as peer result loc in inferred error set function" {
const S = struct {
fn doTheTest() !void {
if (quux(2)) |x| {
try expect(x.Two);
} else |e| switch (e) {
error.Whatever => @panic("fail"),
}
try expectError(error.Whatever, quux(99));
}
const FormValue = union(enum) {
One: void,
Two: bool,
};
fn quux(id: u64) !FormValue {
return switch (id) {
2 => FormValue{ .Two = true },
1 => FormValue{ .One = {} },
else => return error.Whatever,
};
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "error payload type is correctly resolved" {
const MyIntWrapper = struct {
const Self = @This();
x: i32,
pub fn create() anyerror!Self {
return Self{ .x = 42 };
}
};
try expectEqual(MyIntWrapper{ .x = 42 }, try MyIntWrapper.create());
}
test "error union comptime caching" {
const S = struct {
fn quux(comptime arg: anytype) void {
arg catch {};
}
};
S.quux(@as(anyerror!void, {}));
S.quux(@as(anyerror!void, {}));
}

View File

@ -163,3 +163,49 @@ test "generic fn keeps non-generic parameter types" {
var x: [16]u8 align(A) = undefined;
try S.f(u8, &x);
}
test "array of generic fns" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
try expect(foos[0](true));
try expect(!foos[1](true));
}
const foos = [_]fn (anytype) bool{
foo1,
foo2,
};
fn foo1(arg: anytype) bool {
return arg;
}
fn foo2(arg: anytype) bool {
return !arg;
}
test "generic struct" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
var a1 = GenNode(i32){
.value = 13,
.next = null,
};
var b1 = GenNode(bool){
.value = true,
.next = null,
};
try expect(a1.value == 13);
try expect(a1.value == a1.getVal());
try expect(b1.getVal());
}
fn GenNode(comptime T: type) type {
return struct {
value: T,
next: ?*GenNode(T),
fn getVal(n: *const GenNode(T)) T {
return n.value;
}
};
}

View File

@ -1,49 +0,0 @@
const std = @import("std");
const expect = std.testing.expect;
const builtin = @import("builtin");
const foos = [_]fn (anytype) bool{
foo1,
foo2,
};
fn foo1(arg: anytype) bool {
return arg;
}
fn foo2(arg: anytype) bool {
return !arg;
}
test "array of generic fns" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
try expect(foos[0](true));
try expect(!foos[1](true));
}
test "generic struct" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
var a1 = GenNode(i32){
.value = 13,
.next = null,
};
var b1 = GenNode(bool){
.value = true,
.next = null,
};
try expect(a1.value == 13);
try expect(a1.value == a1.getVal());
try expect(b1.getVal());
}
fn GenNode(comptime T: type) type {
return struct {
value: T,
next: ?*GenNode(T),
fn getVal(n: *const GenNode(T)) T {
return n.value;
}
};
}

View File

@ -118,3 +118,25 @@ test "saturating shift-left" {
try S.doTheTest();
comptime try S.doTheTest();
}
test "saturating shl uses the LHS type" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const lhs_const: u8 = 1;
var lhs_var: u8 = 1;
const rhs_const: usize = 8;
var rhs_var: usize = 8;
try expect((lhs_const <<| 8) == 255);
try expect((lhs_const <<| rhs_const) == 255);
try expect((lhs_const <<| rhs_var) == 255);
try expect((lhs_var <<| 8) == 255);
try expect((lhs_var <<| rhs_const) == 255);
try expect((lhs_var <<| rhs_var) == 255);
try expect((@as(u8, 1) <<| 8) == 255);
try expect((@as(u8, 1) <<| rhs_const) == 255);
try expect((@as(u8, 1) <<| rhs_var) == 255);
}

View File

@ -1,22 +0,0 @@
const std = @import("std");
const expect = std.testing.expect;
test "saturating shl uses the LHS type" {
const lhs_const: u8 = 1;
var lhs_var: u8 = 1;
const rhs_const: usize = 8;
var rhs_var: usize = 8;
try expect((lhs_const <<| 8) == 255);
try expect((lhs_const <<| rhs_const) == 255);
try expect((lhs_const <<| rhs_var) == 255);
try expect((lhs_var <<| 8) == 255);
try expect((lhs_var <<| rhs_const) == 255);
try expect((lhs_var <<| rhs_var) == 255);
try expect((@as(u8, 1) <<| 8) == 255);
try expect((@as(u8, 1) <<| rhs_const) == 255);
try expect((@as(u8, 1) <<| rhs_var) == 255);
}

View File

@ -305,3 +305,513 @@ test "default struct initialization fields" {
try expect(y.b == x.b);
try expect(1239 == x.a + x.b);
}
// TODO revisit this test when doing https://github.com/ziglang/zig/issues/1512
test "packed array 24bits" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
comptime {
try expect(@sizeOf([9]Foo32Bits) == 9 * 4);
try expect(@sizeOf(FooArray24Bits) == 2 + 2 * 4 + 2);
}
var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1);
bytes[bytes.len - 1] = 0xaa;
const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
try expect(ptr.a == 0);
try expect(ptr.b[0].field == 0);
try expect(ptr.b[1].field == 0);
try expect(ptr.c == 0);
ptr.a = maxInt(u16);
try expect(ptr.a == maxInt(u16));
try expect(ptr.b[0].field == 0);
try expect(ptr.b[1].field == 0);
try expect(ptr.c == 0);
ptr.b[0].field = maxInt(u24);
try expect(ptr.a == maxInt(u16));
try expect(ptr.b[0].field == maxInt(u24));
try expect(ptr.b[1].field == 0);
try expect(ptr.c == 0);
ptr.b[1].field = maxInt(u24);
try expect(ptr.a == maxInt(u16));
try expect(ptr.b[0].field == maxInt(u24));
try expect(ptr.b[1].field == maxInt(u24));
try expect(ptr.c == 0);
ptr.c = maxInt(u16);
try expect(ptr.a == maxInt(u16));
try expect(ptr.b[0].field == maxInt(u24));
try expect(ptr.b[1].field == maxInt(u24));
try expect(ptr.c == maxInt(u16));
try expect(bytes[bytes.len - 1] == 0xaa);
}
const Foo32Bits = packed struct {
field: u24,
pad: u8,
};
const FooArray24Bits = packed struct {
a: u16,
b: [2]Foo32Bits,
c: u16,
};
test "aligned array of packed struct" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
comptime {
try expect(@sizeOf(FooStructAligned) == 2);
try expect(@sizeOf(FooArrayOfAligned) == 2 * 2);
}
var bytes = [_]u8{0xbb} ** @sizeOf(FooArrayOfAligned);
const ptr = &std.mem.bytesAsSlice(FooArrayOfAligned, bytes[0..])[0];
try expect(ptr.a[0].a == 0xbb);
try expect(ptr.a[0].b == 0xbb);
try expect(ptr.a[1].a == 0xbb);
try expect(ptr.a[1].b == 0xbb);
}
const FooStructAligned = packed struct {
a: u8,
b: u8,
};
const FooArrayOfAligned = packed struct {
a: [2]FooStructAligned,
};
test "pointer to packed struct member in a stack variable" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = packed struct {
a: u2,
b: u2,
};
var s = S{ .a = 2, .b = 0 };
var b_ptr = &s.b;
try expect(s.b == 0);
b_ptr.* = 2;
try expect(s.b == 2);
}
test "non-byte-aligned array inside packed struct" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const Foo = packed struct {
a: bool,
b: [0x16]u8,
};
const S = struct {
fn bar(slice: []const u8) !void {
try expectEqualSlices(u8, slice, "abcdefghijklmnopqurstu");
}
fn doTheTest() !void {
var foo = Foo{
.a = true,
.b = "abcdefghijklmnopqurstu".*,
};
const value = foo.b;
try bar(&value);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "packed struct with u0 field access" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = packed struct {
f0: u0,
};
var s = S{ .f0 = 0 };
comptime try expect(s.f0 == 0);
}
test "access to global struct fields" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
g_foo.bar.value = 42;
try expect(g_foo.bar.value == 42);
}
const S0 = struct {
bar: S1,
pub const S1 = struct {
value: u8,
};
fn init() @This() {
return S0{ .bar = S1{ .value = 123 } };
}
};
var g_foo: S0 = S0.init();
test "packed struct with fp fields" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = packed struct {
data: [3]f32,
pub fn frob(self: *@This()) void {
self.data[0] += self.data[1] + self.data[2];
self.data[1] += self.data[0] + self.data[2];
self.data[2] += self.data[0] + self.data[1];
}
};
var s: S = undefined;
s.data[0] = 1.0;
s.data[1] = 2.0;
s.data[2] = 3.0;
s.frob();
try expectEqual(@as(f32, 6.0), s.data[0]);
try expectEqual(@as(f32, 11.0), s.data[1]);
try expectEqual(@as(f32, 20.0), s.data[2]);
}
test "fn with C calling convention returns struct by value" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
fn entry() !void {
var x = makeBar(10);
try expectEqual(@as(i32, 10), x.handle);
}
const ExternBar = extern struct {
handle: i32,
};
fn makeBar(t: i32) callconv(.C) ExternBar {
return ExternBar{
.handle = t,
};
}
};
try S.entry();
comptime try S.entry();
}
test "non-packed struct with u128 entry in union" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const U = union(enum) {
Num: u128,
Void,
};
const S = struct {
f1: U,
f2: U,
};
var sx: S = undefined;
var s = &sx;
try std.testing.expect(@ptrToInt(&s.f2) - @ptrToInt(&s.f1) == @offsetOf(S, "f2"));
var v2 = U{ .Num = 123 };
s.f2 = v2;
try std.testing.expect(s.f2.Num == 123);
}
test "packed struct field passed to generic function" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
const P = packed struct {
b: u5,
g: u5,
r: u5,
a: u1,
};
fn genericReadPackedField(ptr: anytype) u5 {
return ptr.*;
}
};
var p: S.P = undefined;
p.b = 29;
var loaded = S.genericReadPackedField(&p.b);
try expect(loaded == 29);
}
test "anonymous struct literal syntax" {
const S = struct {
const Point = struct {
x: i32,
y: i32,
};
fn doTheTest() !void {
var p: Point = .{
.x = 1,
.y = 2,
};
try expect(p.x == 1);
try expect(p.y == 2);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "fully anonymous struct" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {
try dump(.{
.int = @as(u32, 1234),
.float = @as(f64, 12.34),
.b = true,
.s = "hi",
});
}
fn dump(args: anytype) !void {
try expect(args.int == 1234);
try expect(args.float == 12.34);
try expect(args.b);
try expect(args.s[0] == 'h');
try expect(args.s[1] == 'i');
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "fully anonymous list literal" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {
try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });
}
fn dump(args: anytype) !void {
try expect(args.@"0" == 1234);
try expect(args.@"1" == 12.34);
try expect(args.@"2");
try expect(args.@"3"[0] == 'h');
try expect(args.@"3"[1] == 'i');
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "anonymous struct literal assigned to variable" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };
try expect(vec.@"0" == 22);
try expect(vec.@"1" == 55);
try expect(vec.@"2" == 99);
}
test "struct with var field" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const Point = struct {
x: anytype,
y: anytype,
};
const pt = Point{
.x = 1,
.y = 2,
};
try expect(pt.x == 1);
try expect(pt.y == 2);
}
test "comptime struct field" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const T = struct {
a: i32,
comptime b: i32 = 1234,
};
var foo: T = undefined;
comptime try expect(foo.b == 1234);
}
test "anon struct literal field value initialized with fn call" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
fn doTheTest() !void {
var x = .{foo()};
try expectEqualSlices(u8, x[0], "hi");
}
fn foo() []const u8 {
return "hi";
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "struct with union field" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const Value = struct {
ref: u32 = 2,
kind: union(enum) {
None: usize,
Bool: bool,
},
};
var True = Value{
.kind = .{ .Bool = true },
};
try expectEqual(@as(u32, 2), True.ref);
try expectEqual(true, True.kind.Bool);
}
test "type coercion of anon struct literal to struct" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
const S2 = struct {
A: u32,
B: []const u8,
C: void,
D: Foo = .{},
};
const Foo = struct {
field: i32 = 1234,
};
fn doTheTest() !void {
var y: u32 = 42;
const t0 = .{ .A = 123, .B = "foo", .C = {} };
const t1 = .{ .A = y, .B = "foo", .C = {} };
const y0: S2 = t0;
var y1: S2 = t1;
try expect(y0.A == 123);
try expect(std.mem.eql(u8, y0.B, "foo"));
try expect(y0.C == {});
try expect(y0.D.field == 1234);
try expect(y1.A == y);
try expect(std.mem.eql(u8, y1.B, "foo"));
try expect(y1.C == {});
try expect(y1.D.field == 1234);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "type coercion of pointer to anon struct literal to pointer to struct" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
const S2 = struct {
A: u32,
B: []const u8,
C: void,
D: Foo = .{},
};
const Foo = struct {
field: i32 = 1234,
};
fn doTheTest() !void {
var y: u32 = 42;
const t0 = &.{ .A = 123, .B = "foo", .C = {} };
const t1 = &.{ .A = y, .B = "foo", .C = {} };
const y0: *const S2 = t0;
var y1: *const S2 = t1;
try expect(y0.A == 123);
try expect(std.mem.eql(u8, y0.B, "foo"));
try expect(y0.C == {});
try expect(y0.D.field == 1234);
try expect(y1.A == y);
try expect(std.mem.eql(u8, y1.B, "foo"));
try expect(y1.C == {});
try expect(y1.D.field == 1234);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "packed struct with undefined initializers" {
const S = struct {
const P = packed struct {
a: u3,
_a: u3 = undefined,
b: u3,
_b: u3 = undefined,
c: u3,
_c: u3 = undefined,
};
fn doTheTest() !void {
var p: P = undefined;
p = P{ .a = 2, .b = 4, .c = 6 };
// Make sure the compiler doesn't touch the unprefixed fields.
// Use expect since i386-linux doesn't like expectEqual
try expect(p.a == 2);
try expect(p.b == 4);
try expect(p.c == 6);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "for loop over pointers to struct, getting field from struct pointer" {
// When enabling this test, be careful. I have observed it to pass when compiling
// stage2 alone, but when using stage1 with -fno-stage1 -fLLVM it fails.
// Maybe eyeball the LLVM that it generates and run in valgrind, both the compiler
// and the generated test at runtime.
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
const S = struct {
const Foo = struct {
name: []const u8,
};
var ok = true;
fn eql(a: []const u8) bool {
_ = a;
return true;
}
const ArrayList = struct {
fn toSlice(self: *ArrayList) []*Foo {
_ = self;
return @as([*]*Foo, undefined)[0..0];
}
};
fn doTheTest() !void {
var objects: ArrayList = undefined;
for (objects.toSlice()) |obj| {
if (eql(obj.name)) {
ok = false;
}
}
try expect(ok);
}
};
try S.doTheTest();
}

View File

@ -1,473 +0,0 @@
const std = @import("std");
const builtin = @import("builtin");
const native_endian = builtin.target.cpu.arch.endian();
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
const expectEqualSlices = std.testing.expectEqualSlices;
const maxInt = std.math.maxInt;
const Foo32Bits = packed struct {
field: u24,
pad: u8,
};
const FooArray24Bits = packed struct {
a: u16,
b: [2]Foo32Bits,
c: u16,
};
// TODO revisit this test when doing https://github.com/ziglang/zig/issues/1512
test "packed array 24bits" {
comptime {
try expect(@sizeOf([9]Foo32Bits) == 9 * 4);
try expect(@sizeOf(FooArray24Bits) == 2 + 2 * 4 + 2);
}
var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1);
bytes[bytes.len - 1] = 0xaa;
const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
try expect(ptr.a == 0);
try expect(ptr.b[0].field == 0);
try expect(ptr.b[1].field == 0);
try expect(ptr.c == 0);
ptr.a = maxInt(u16);
try expect(ptr.a == maxInt(u16));
try expect(ptr.b[0].field == 0);
try expect(ptr.b[1].field == 0);
try expect(ptr.c == 0);
ptr.b[0].field = maxInt(u24);
try expect(ptr.a == maxInt(u16));
try expect(ptr.b[0].field == maxInt(u24));
try expect(ptr.b[1].field == 0);
try expect(ptr.c == 0);
ptr.b[1].field = maxInt(u24);
try expect(ptr.a == maxInt(u16));
try expect(ptr.b[0].field == maxInt(u24));
try expect(ptr.b[1].field == maxInt(u24));
try expect(ptr.c == 0);
ptr.c = maxInt(u16);
try expect(ptr.a == maxInt(u16));
try expect(ptr.b[0].field == maxInt(u24));
try expect(ptr.b[1].field == maxInt(u24));
try expect(ptr.c == maxInt(u16));
try expect(bytes[bytes.len - 1] == 0xaa);
}
const FooStructAligned = packed struct {
a: u8,
b: u8,
};
const FooArrayOfAligned = packed struct {
a: [2]FooStructAligned,
};
test "aligned array of packed struct" {
comptime {
try expect(@sizeOf(FooStructAligned) == 2);
try expect(@sizeOf(FooArrayOfAligned) == 2 * 2);
}
var bytes = [_]u8{0xbb} ** @sizeOf(FooArrayOfAligned);
const ptr = &std.mem.bytesAsSlice(FooArrayOfAligned, bytes[0..])[0];
try expect(ptr.a[0].a == 0xbb);
try expect(ptr.a[0].b == 0xbb);
try expect(ptr.a[1].a == 0xbb);
try expect(ptr.a[1].b == 0xbb);
}
test "pointer to packed struct member in a stack variable" {
const S = packed struct {
a: u2,
b: u2,
};
var s = S{ .a = 2, .b = 0 };
var b_ptr = &s.b;
try expect(s.b == 0);
b_ptr.* = 2;
try expect(s.b == 2);
}
test "non-byte-aligned array inside packed struct" {
const Foo = packed struct {
a: bool,
b: [0x16]u8,
};
const S = struct {
fn bar(slice: []const u8) !void {
try expectEqualSlices(u8, slice, "abcdefghijklmnopqurstu");
}
fn doTheTest() !void {
var foo = Foo{
.a = true,
.b = "abcdefghijklmnopqurstu".*,
};
const value = foo.b;
try bar(&value);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "packed struct with u0 field access" {
const S = packed struct {
f0: u0,
};
var s = S{ .f0 = 0 };
comptime try expect(s.f0 == 0);
}
const S0 = struct {
bar: S1,
pub const S1 = struct {
value: u8,
};
fn init() @This() {
return S0{ .bar = S1{ .value = 123 } };
}
};
var g_foo: S0 = S0.init();
test "access to global struct fields" {
g_foo.bar.value = 42;
try expect(g_foo.bar.value == 42);
}
test "packed struct with fp fields" {
const S = packed struct {
data: [3]f32,
pub fn frob(self: *@This()) void {
self.data[0] += self.data[1] + self.data[2];
self.data[1] += self.data[0] + self.data[2];
self.data[2] += self.data[0] + self.data[1];
}
};
var s: S = undefined;
s.data[0] = 1.0;
s.data[1] = 2.0;
s.data[2] = 3.0;
s.frob();
try expectEqual(@as(f32, 6.0), s.data[0]);
try expectEqual(@as(f32, 11.0), s.data[1]);
try expectEqual(@as(f32, 20.0), s.data[2]);
}
test "fn with C calling convention returns struct by value" {
const S = struct {
fn entry() !void {
var x = makeBar(10);
try expectEqual(@as(i32, 10), x.handle);
}
const ExternBar = extern struct {
handle: i32,
};
fn makeBar(t: i32) callconv(.C) ExternBar {
return ExternBar{
.handle = t,
};
}
};
try S.entry();
comptime try S.entry();
}
test "non-packed struct with u128 entry in union" {
const U = union(enum) {
Num: u128,
Void,
};
const S = struct {
f1: U,
f2: U,
};
var sx: S = undefined;
var s = &sx;
try std.testing.expect(@ptrToInt(&s.f2) - @ptrToInt(&s.f1) == @offsetOf(S, "f2"));
var v2 = U{ .Num = 123 };
s.f2 = v2;
try std.testing.expect(s.f2.Num == 123);
}
test "packed struct field passed to generic function" {
const S = struct {
const P = packed struct {
b: u5,
g: u5,
r: u5,
a: u1,
};
fn genericReadPackedField(ptr: anytype) u5 {
return ptr.*;
}
};
var p: S.P = undefined;
p.b = 29;
var loaded = S.genericReadPackedField(&p.b);
try expect(loaded == 29);
}
test "anonymous struct literal syntax" {
const S = struct {
const Point = struct {
x: i32,
y: i32,
};
fn doTheTest() !void {
var p: Point = .{
.x = 1,
.y = 2,
};
try expect(p.x == 1);
try expect(p.y == 2);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "fully anonymous struct" {
const S = struct {
fn doTheTest() !void {
try dump(.{
.int = @as(u32, 1234),
.float = @as(f64, 12.34),
.b = true,
.s = "hi",
});
}
fn dump(args: anytype) !void {
try expect(args.int == 1234);
try expect(args.float == 12.34);
try expect(args.b);
try expect(args.s[0] == 'h');
try expect(args.s[1] == 'i');
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "fully anonymous list literal" {
const S = struct {
fn doTheTest() !void {
try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });
}
fn dump(args: anytype) !void {
try expect(args.@"0" == 1234);
try expect(args.@"1" == 12.34);
try expect(args.@"2");
try expect(args.@"3"[0] == 'h');
try expect(args.@"3"[1] == 'i');
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "anonymous struct literal assigned to variable" {
var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };
try expect(vec.@"0" == 22);
try expect(vec.@"1" == 55);
try expect(vec.@"2" == 99);
}
test "struct with var field" {
const Point = struct {
x: anytype,
y: anytype,
};
const pt = Point{
.x = 1,
.y = 2,
};
try expect(pt.x == 1);
try expect(pt.y == 2);
}
test "comptime struct field" {
const T = struct {
a: i32,
comptime b: i32 = 1234,
};
var foo: T = undefined;
comptime try expect(foo.b == 1234);
}
test "anon struct literal field value initialized with fn call" {
const S = struct {
fn doTheTest() !void {
var x = .{foo()};
try expectEqualSlices(u8, x[0], "hi");
}
fn foo() []const u8 {
return "hi";
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "struct with union field" {
const Value = struct {
ref: u32 = 2,
kind: union(enum) {
None: usize,
Bool: bool,
},
};
var True = Value{
.kind = .{ .Bool = true },
};
try expectEqual(@as(u32, 2), True.ref);
try expectEqual(true, True.kind.Bool);
}
test "type coercion of anon struct literal to struct" {
const S = struct {
const S2 = struct {
A: u32,
B: []const u8,
C: void,
D: Foo = .{},
};
const Foo = struct {
field: i32 = 1234,
};
fn doTheTest() !void {
var y: u32 = 42;
const t0 = .{ .A = 123, .B = "foo", .C = {} };
const t1 = .{ .A = y, .B = "foo", .C = {} };
const y0: S2 = t0;
var y1: S2 = t1;
try expect(y0.A == 123);
try expect(std.mem.eql(u8, y0.B, "foo"));
try expect(y0.C == {});
try expect(y0.D.field == 1234);
try expect(y1.A == y);
try expect(std.mem.eql(u8, y1.B, "foo"));
try expect(y1.C == {});
try expect(y1.D.field == 1234);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "type coercion of pointer to anon struct literal to pointer to struct" {
const S = struct {
const S2 = struct {
A: u32,
B: []const u8,
C: void,
D: Foo = .{},
};
const Foo = struct {
field: i32 = 1234,
};
fn doTheTest() !void {
var y: u32 = 42;
const t0 = &.{ .A = 123, .B = "foo", .C = {} };
const t1 = &.{ .A = y, .B = "foo", .C = {} };
const y0: *const S2 = t0;
var y1: *const S2 = t1;
try expect(y0.A == 123);
try expect(std.mem.eql(u8, y0.B, "foo"));
try expect(y0.C == {});
try expect(y0.D.field == 1234);
try expect(y1.A == y);
try expect(std.mem.eql(u8, y1.B, "foo"));
try expect(y1.C == {});
try expect(y1.D.field == 1234);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "packed struct with undefined initializers" {
const S = struct {
const P = packed struct {
a: u3,
_a: u3 = undefined,
b: u3,
_b: u3 = undefined,
c: u3,
_c: u3 = undefined,
};
fn doTheTest() !void {
var p: P = undefined;
p = P{ .a = 2, .b = 4, .c = 6 };
// Make sure the compiler doesn't touch the unprefixed fields.
// Use expect since i386-linux doesn't like expectEqual
try expect(p.a == 2);
try expect(p.b == 4);
try expect(p.c == 6);
}
};
try S.doTheTest();
comptime try S.doTheTest();
}
test "for loop over pointers to struct, getting field from struct pointer" {
const S = struct {
const Foo = struct {
name: []const u8,
};
var ok = true;
fn eql(a: []const u8) bool {
_ = a;
return true;
}
const ArrayList = struct {
fn toSlice(self: *ArrayList) []*Foo {
_ = self;
return @as([*]*Foo, undefined)[0..0];
}
};
fn doTheTest() !void {
var objects: ArrayList = undefined;
for (objects.toSlice()) |obj| {
if (eql(obj.name)) {
ok = false;
}
}
try expect(ok);
}
};
try S.doTheTest();
}

View File

@ -1,3 +1,4 @@
const builtin = @import("builtin");
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
@ -16,3 +17,33 @@ test "casting to void with a macro" {
h.IGNORE_ME_9(42);
h.IGNORE_ME_10(42);
}
test "initializer list expression" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
try expectEqual(h.Color{
.r = 200,
.g = 200,
.b = 200,
.a = 255,
}, h.LIGHTGRAY);
}
test "sizeof in macros" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
}
test "reference to a struct type" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
}
test "cast negative integer to pointer" {
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
try expectEqual(@intToPtr(?*anyopaque, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED);
}

View File

@ -1,27 +0,0 @@
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
const h = @cImport(@cInclude("behavior/translate_c_macros.h"));
test "initializer list expression" {
try expectEqual(h.Color{
.r = 200,
.g = 200,
.b = 200,
.a = 255,
}, h.LIGHTGRAY);
}
test "sizeof in macros" {
try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF(u32));
try expectEqual(@as(c_int, @sizeOf(u32)), h.MY_SIZEOF2(u32));
}
test "reference to a struct type" {
try expectEqual(@sizeOf(h.struct_Foo), h.SIZE_OF_FOO);
}
test "cast negative integer to pointer" {
try expectEqual(@intToPtr(?*anyopaque, @bitCast(usize, @as(isize, -1))), h.MAP_FAILED);
}