mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
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:
parent
82bd0ac572
commit
35423b0054
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
@ -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, {}));
|
||||
}
|
||||
|
||||
@ -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, {}));
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user