master
1const builtin = @import("builtin");
2const std = @import("std");
3const expect = std.testing.expect;
4const expectEqualStrings = std.testing.expectEqualStrings;
5const expectStringStartsWith = std.testing.expectStringStartsWith;
6
7// Most tests here can be comptime but use runtime so that a stacktrace
8// can show failure location.
9//
10// Note certain results of `@typeName()` expect `behavior.zig` to be the
11// root file. Running a test against this file as root will result in
12// failures.
13
14test "anon fn param" {
15 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
18
19 // https://github.com/ziglang/zig/issues/9339
20 try expectEqualStringsIgnoreDigits(
21 "behavior.typename.TypeFromFn(behavior.typename.test.anon fn param__struct_0)",
22 @typeName(TypeFromFn(struct {})),
23 );
24 try expectEqualStringsIgnoreDigits(
25 "behavior.typename.TypeFromFn(behavior.typename.test.anon fn param__union_0)",
26 @typeName(TypeFromFn(union { unused: u8 })),
27 );
28 try expectEqualStringsIgnoreDigits(
29 "behavior.typename.TypeFromFn(behavior.typename.test.anon fn param__enum_0)",
30 @typeName(TypeFromFn(enum { unused })),
31 );
32
33 try expectEqualStringsIgnoreDigits(
34 "behavior.typename.TypeFromFnB(behavior.typename.test.anon fn param__struct_0,behavior.typename.test.anon fn param__union_0,behavior.typename.test.anon fn param__enum_0)",
35 @typeName(TypeFromFnB(struct {}, union { unused: u8 }, enum { unused })),
36 );
37}
38
39test "anon field init" {
40 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
41 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
42 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
43
44 const Foo = .{
45 .T1 = struct {},
46 .T2 = union { unused: u8 },
47 .T3 = enum { unused },
48 };
49
50 try expectEqualStringsIgnoreDigits(
51 "behavior.typename.test.anon field init__struct_0",
52 @typeName(Foo.T1),
53 );
54 try expectEqualStringsIgnoreDigits(
55 "behavior.typename.test.anon field init__union_0",
56 @typeName(Foo.T2),
57 );
58 try expectEqualStringsIgnoreDigits(
59 "behavior.typename.test.anon field init__enum_0",
60 @typeName(Foo.T3),
61 );
62}
63
64test "basic" {
65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
66 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
67 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
68
69 try expectEqualStrings("i64", @typeName(i64));
70 try expectEqualStrings("*usize", @typeName(*usize));
71 try expectEqualStrings("[]u8", @typeName([]u8));
72
73 try expectEqualStrings("fn () void", @typeName(fn () void));
74 try expectEqualStrings("fn (u32) void", @typeName(fn (u32) void));
75 try expectEqualStrings("fn (u32) void", @typeName(fn (a: u32) void));
76
77 try expectEqualStrings("fn (comptime u32) void", @typeName(fn (comptime u32) void));
78 try expectEqualStrings("fn (noalias []u8) void", @typeName(fn (noalias []u8) void));
79
80 try expectEqualStrings("fn () callconv(.c) void", @typeName(fn () callconv(.c) void));
81 try expectEqualStrings("fn (...) callconv(.c) void", @typeName(fn (...) callconv(.c) void));
82 try expectEqualStrings("fn (u32, ...) callconv(.c) void", @typeName(fn (u32, ...) callconv(.c) void));
83}
84
85test "top level decl" {
86 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
87 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
89
90 try expectEqualStrings(
91 "behavior.typename.A_Struct",
92 @typeName(A_Struct),
93 );
94 try expectEqualStrings(
95 "behavior.typename.A_Union",
96 @typeName(A_Union),
97 );
98 try expectEqualStrings(
99 "behavior.typename.A_Enum",
100 @typeName(A_Enum),
101 );
102
103 // regular fn, without error
104 try expectEqualStrings(
105 "fn () void",
106 @typeName(@TypeOf(regular)),
107 );
108 // regular fn inside struct, with error
109 try expectEqualStrings(
110 "fn () @typeInfo(@typeInfo(@TypeOf(behavior.typename.B.doTest)).@\"fn\".return_type.?).error_union.error_set!void",
111 @typeName(@TypeOf(B.doTest)),
112 );
113 // generic fn
114 try expectEqualStrings(
115 "fn (comptime type) type",
116 @typeName(@TypeOf(TypeFromFn)),
117 );
118}
119
120const A_Struct = struct {};
121const A_Union = union {
122 unused: u8,
123};
124const A_Enum = enum {
125 unused,
126};
127
128fn regular() void {}
129
130const B = struct {
131 fn doTest() !void {}
132};
133
134test "fn param" {
135 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
136 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
137 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
138
139 // https://github.com/ziglang/zig/issues/675
140 try expectEqualStrings(
141 "behavior.typename.TypeFromFn(u8)",
142 @typeName(TypeFromFn(u8)),
143 );
144 try expectEqualStrings(
145 "behavior.typename.TypeFromFn(behavior.typename.A_Struct)",
146 @typeName(TypeFromFn(A_Struct)),
147 );
148 try expectEqualStrings(
149 "behavior.typename.TypeFromFn(behavior.typename.A_Union)",
150 @typeName(TypeFromFn(A_Union)),
151 );
152 try expectEqualStrings(
153 "behavior.typename.TypeFromFn(behavior.typename.A_Enum)",
154 @typeName(TypeFromFn(A_Enum)),
155 );
156
157 try expectEqualStrings(
158 "behavior.typename.TypeFromFn2(u8,bool)",
159 @typeName(TypeFromFn2(u8, bool)),
160 );
161}
162
163fn TypeFromFn(comptime T: type) type {
164 return struct {
165 comptime {
166 _ = T;
167 }
168 };
169}
170
171fn TypeFromFn2(comptime T1: type, comptime T2: type) type {
172 return struct {
173 comptime {
174 _ = T1;
175 _ = T2;
176 }
177 };
178}
179
180fn TypeFromFnB(comptime T1: type, comptime T2: type, comptime T3: type) type {
181 return struct {
182 comptime {
183 _ = T1;
184 _ = T2;
185 _ = T3;
186 }
187 };
188}
189
190/// Replaces integers in `actual` with '0' before doing the test.
191pub fn expectEqualStringsIgnoreDigits(expected: []const u8, actual: []const u8) !void {
192 var actual_buf: [1024]u8 = undefined;
193 var actual_i: usize = 0;
194 var last_digit = false;
195 for (actual) |byte| {
196 switch (byte) {
197 '0'...'9' => {
198 if (last_digit) continue;
199 last_digit = true;
200 actual_buf[actual_i] = '0';
201 actual_i += 1;
202 },
203 else => {
204 last_digit = false;
205 actual_buf[actual_i] = byte;
206 actual_i += 1;
207 },
208 }
209 }
210 return expectEqualStrings(expected, actual_buf[0..actual_i]);
211}
212
213test "local variable" {
214 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
215 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
216 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
217
218 const Foo = struct { a: u32 };
219 const Bar = union { a: u32 };
220 const Baz = enum { a, b };
221 const Qux = enum { a, b };
222 const Quux = enum { a, b };
223
224 try expectEqualStrings("behavior.typename.test.local variable.Foo", @typeName(Foo));
225 try expectEqualStrings("behavior.typename.test.local variable.Bar", @typeName(Bar));
226 try expectEqualStrings("behavior.typename.test.local variable.Baz", @typeName(Baz));
227 try expectEqualStrings("behavior.typename.test.local variable.Qux", @typeName(Qux));
228 try expectEqualStrings("behavior.typename.test.local variable.Quux", @typeName(Quux));
229}
230
231test "comptime parameters not converted to anytype in function type" {
232 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
233 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
234 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
235
236 const T = fn (comptime fn (comptime type) void, void) void;
237 try expectEqualStrings("fn (comptime fn (comptime type) void, void) void", @typeName(T));
238}
239
240test "anon name strategy used in sub expression" {
241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
242 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
243 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
244
245 const S = struct {
246 fn getTheName() []const u8 {
247 return struct {
248 const name = @typeName(@This());
249 }.name;
250 }
251 };
252 try expectEqualStringsIgnoreDigits(
253 "behavior.typename.test.anon name strategy used in sub expression.S.getTheName__struct_0",
254 S.getTheName(),
255 );
256}