1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4
5// Most tests here can be comptime but use runtime so that a stacktrace
6// can show failure location.
7//
8// Note certain results of `@typeName()` expect `behavior.zig` to be the
9// root file. Running a test against this file as root will result in
10// failures.
11
12// CAUTION: this test is source-location sensitive.
13test "anon fn param - source-location sensitive" {
14    // https://github.com/ziglang/zig/issues/9339
15    try expectEqualSlices(u8, @typeName(TypeFromFn(struct {})), "behavior.typename.TypeFromFn(behavior.typename.struct:15:52)");
16    try expectEqualSlices(u8, @typeName(TypeFromFn(union { unused: u8 })), "behavior.typename.TypeFromFn(behavior.typename.union:16:52)");
17    try expectEqualSlices(u8, @typeName(TypeFromFn(enum { unused })), "behavior.typename.TypeFromFn(behavior.typename.enum:17:52)");
18
19    try expectEqualSlices(
20        u8,
21        @typeName(TypeFromFn3(struct {}, union { unused: u8 }, enum { unused })),
22        "behavior.typename.TypeFromFn3(behavior.typename.struct:21:31,behavior.typename.union:21:42,behavior.typename.enum:21:64)",
23    );
24}
25
26// CAUTION: this test is source-location sensitive.
27test "anon field init" {
28    const Foo = .{
29        .T1 = struct {},
30        .T2 = union { unused: u8 },
31        .T3 = enum { unused },
32    };
33
34    try expectEqualSlices(u8, @typeName(Foo.T1), "behavior.typename.struct:29:15");
35    try expectEqualSlices(u8, @typeName(Foo.T2), "behavior.typename.union:30:15");
36    try expectEqualSlices(u8, @typeName(Foo.T3), "behavior.typename.enum:31:15");
37}
38
39test "basic" {
40    try expectEqualSlices(u8, @typeName(i64), "i64");
41    try expectEqualSlices(u8, @typeName(*usize), "*usize");
42    try expectEqualSlices(u8, @typeName([]u8), "[]u8");
43}
44
45test "top level decl" {
46    try expectEqualSlices(u8, @typeName(A_Struct), "A_Struct");
47    try expectEqualSlices(u8, @typeName(A_Union), "A_Union");
48    try expectEqualSlices(u8, @typeName(A_Enum), "A_Enum");
49
50    // regular fn, without error
51    try expectEqualSlices(u8, @typeName(@TypeOf(regular)), "fn() void");
52    // regular fn inside struct, with error
53    try expectEqualSlices(u8, @typeName(@TypeOf(B.doTest)), "fn() @typeInfo(@typeInfo(@TypeOf(behavior.typename.B.doTest)).Fn.return_type.?).ErrorUnion.error_set!void");
54    // generic fn
55    try expectEqualSlices(u8, @typeName(@TypeOf(TypeFromFn)), "fn(type) anytype");
56}
57
58const A_Struct = struct {};
59const A_Union = union {
60    unused: u8,
61};
62const A_Enum = enum {
63    unused,
64};
65
66fn regular() void {}
67
68test "fn body decl" {
69    try B.doTest();
70}
71
72const B = struct {
73    fn doTest() !void {
74        const B_Struct = struct {};
75        const B_Union = union {
76            unused: u8,
77        };
78        const B_Enum = enum {
79            unused,
80        };
81
82        try expectEqualSlices(u8, @typeName(B_Struct), "B_Struct");
83        try expectEqualSlices(u8, @typeName(B_Union), "B_Union");
84        try expectEqualSlices(u8, @typeName(B_Enum), "B_Enum");
85    }
86};
87
88test "fn param" {
89    // https://github.com/ziglang/zig/issues/675
90    try expectEqualSlices(u8, @typeName(TypeFromFn(u8)), "behavior.typename.TypeFromFn(u8)");
91    try expectEqualSlices(u8, @typeName(TypeFromFn(A_Struct)), "behavior.typename.TypeFromFn(behavior.typename.A_Struct)");
92    try expectEqualSlices(u8, @typeName(TypeFromFn(A_Union)), "behavior.typename.TypeFromFn(behavior.typename.A_Union)");
93    try expectEqualSlices(u8, @typeName(TypeFromFn(A_Enum)), "behavior.typename.TypeFromFn(behavior.typename.A_Enum)");
94
95    try expectEqualSlices(u8, @typeName(TypeFromFn2(u8, bool)), "behavior.typename.TypeFromFn2(u8,bool)");
96}
97
98fn TypeFromFn(comptime T: type) type {
99    _ = T;
100    return struct {};
101}
102
103fn TypeFromFn2(comptime T1: type, comptime T2: type) type {
104    _ = T1;
105    _ = T2;
106    return struct {};
107}
108
109fn TypeFromFn3(comptime T1: type, comptime T2: type, comptime T3: type) type {
110    _ = T1;
111    _ = T2;
112    _ = T3;
113    return struct {};
114}
115