master
1const std = @import("std");
2const builtin = @import("builtin");
3const testing = std.testing;
4const math = std.math;
5
6const helpers = @import("helpers");
7
8const cast = helpers.cast;
9
10test cast {
11 var i = @as(i64, 10);
12
13 try testing.expect(cast(*u8, 16) == @as(*u8, @ptrFromInt(16)));
14 try testing.expect(cast(*u64, &i).* == @as(u64, 10));
15 try testing.expect(cast(*i64, @as(?*align(1) i64, &i)) == &i);
16
17 try testing.expect(cast(?*u8, 2) == @as(*u8, @ptrFromInt(2)));
18 try testing.expect(cast(?*i64, @as(*align(1) i64, &i)) == &i);
19 try testing.expect(cast(?*i64, @as(?*align(1) i64, &i)) == &i);
20
21 try testing.expectEqual(@as(u32, 4), cast(u32, @as(*u32, @ptrFromInt(4))));
22 try testing.expectEqual(@as(u32, 4), cast(u32, @as(?*u32, @ptrFromInt(4))));
23 try testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10)));
24
25 try testing.expectEqual(@as(i32, @bitCast(@as(u32, 0x8000_0000))), cast(i32, @as(u32, 0x8000_0000)));
26
27 try testing.expectEqual(@as(*u8, @ptrFromInt(2)), cast(*u8, @as(*const u8, @ptrFromInt(2))));
28 try testing.expectEqual(@as(*u8, @ptrFromInt(2)), cast(*u8, @as(*volatile u8, @ptrFromInt(2))));
29
30 try testing.expectEqual(@as(?*anyopaque, @ptrFromInt(2)), cast(?*anyopaque, @as(*u8, @ptrFromInt(2))));
31
32 var foo: c_int = -1;
33 _ = &foo;
34 try testing.expect(cast(*anyopaque, -1) == @as(*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))))));
35 try testing.expect(cast(*anyopaque, foo) == @as(*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))))));
36 try testing.expect(cast(?*anyopaque, -1) == @as(?*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))))));
37 try testing.expect(cast(?*anyopaque, foo) == @as(?*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))))));
38
39 const FnPtr = ?*align(1) const fn (*anyopaque) void;
40 try testing.expect(cast(FnPtr, 0) == @as(FnPtr, @ptrFromInt(@as(usize, 0))));
41 try testing.expect(cast(FnPtr, foo) == @as(FnPtr, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))))));
42
43 const complexFunction = struct {
44 fn f(_: ?*anyopaque, _: c_uint, _: ?*const fn (?*anyopaque) callconv(.c) c_uint, _: ?*anyopaque, _: c_uint, _: [*c]c_uint) callconv(.c) usize {
45 return 0;
46 }
47 }.f;
48
49 const SDL_FunctionPointer = ?*const fn () callconv(.c) void;
50 const fn_ptr = cast(SDL_FunctionPointer, complexFunction);
51 try testing.expect(fn_ptr != null);
52}
53
54const sizeof = helpers.sizeof;
55
56test sizeof {
57 const S = extern struct { a: u32 };
58
59 const ptr_size = @sizeOf(*anyopaque);
60
61 try testing.expect(sizeof(u32) == 4);
62 try testing.expect(sizeof(@as(u32, 2)) == 4);
63 try testing.expect(sizeof(2) == @sizeOf(c_int));
64
65 try testing.expect(sizeof(2.0) == @sizeOf(f64));
66
67 try testing.expect(sizeof(S) == 4);
68
69 try testing.expect(sizeof([_]u32{ 4, 5, 6 }) == 12);
70 try testing.expect(sizeof([3]u32) == 12);
71 try testing.expect(sizeof([3:0]u32) == 16);
72 try testing.expect(sizeof(&[_]u32{ 4, 5, 6 }) == ptr_size);
73
74 try testing.expect(sizeof(*u32) == ptr_size);
75 try testing.expect(sizeof([*]u32) == ptr_size);
76 try testing.expect(sizeof([*c]u32) == ptr_size);
77 try testing.expect(sizeof(?*u32) == ptr_size);
78 try testing.expect(sizeof(?[*]u32) == ptr_size);
79 try testing.expect(sizeof(*anyopaque) == ptr_size);
80 try testing.expect(sizeof(*void) == ptr_size);
81 try testing.expect(sizeof(null) == ptr_size);
82
83 try testing.expect(sizeof("foobar") == 7);
84 try testing.expect(sizeof(&[_:0]u16{ 'f', 'o', 'o', 'b', 'a', 'r' }) == 14);
85 try testing.expect(sizeof(*const [4:0]u8) == 5);
86 try testing.expect(sizeof(*[4:0]u8) == ptr_size);
87 try testing.expect(sizeof([*]const [4:0]u8) == ptr_size);
88 try testing.expect(sizeof(*const *const [4:0]u8) == ptr_size);
89 try testing.expect(sizeof(*const [4]u8) == ptr_size);
90
91 if (false) { // TODO
92 try testing.expect(sizeof(&sizeof) == @sizeOf(@TypeOf(&sizeof)));
93 try testing.expect(sizeof(sizeof) == 1);
94 }
95
96 try testing.expect(sizeof(void) == 1);
97 try testing.expect(sizeof(anyopaque) == 1);
98}
99
100const promoteIntLiteral = helpers.promoteIntLiteral;
101
102test promoteIntLiteral {
103 const signed_hex = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .hex);
104 try testing.expectEqual(c_uint, @TypeOf(signed_hex));
105
106 if (math.maxInt(c_longlong) == math.maxInt(c_int)) return;
107
108 const signed_decimal = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .decimal);
109 const unsigned = promoteIntLiteral(c_uint, math.maxInt(c_uint) + 1, .hex);
110
111 if (math.maxInt(c_long) > math.maxInt(c_int)) {
112 try testing.expectEqual(c_long, @TypeOf(signed_decimal));
113 try testing.expectEqual(c_ulong, @TypeOf(unsigned));
114 } else {
115 try testing.expectEqual(c_longlong, @TypeOf(signed_decimal));
116 try testing.expectEqual(c_ulonglong, @TypeOf(unsigned));
117 }
118}
119
120const shuffleVectorIndex = helpers.shuffleVectorIndex;
121
122test shuffleVectorIndex {
123 const vector_len: usize = 4;
124
125 _ = shuffleVectorIndex(-1, vector_len);
126
127 try testing.expect(shuffleVectorIndex(0, vector_len) == 0);
128 try testing.expect(shuffleVectorIndex(1, vector_len) == 1);
129 try testing.expect(shuffleVectorIndex(2, vector_len) == 2);
130 try testing.expect(shuffleVectorIndex(3, vector_len) == 3);
131
132 try testing.expect(shuffleVectorIndex(4, vector_len) == -1);
133 try testing.expect(shuffleVectorIndex(5, vector_len) == -2);
134 try testing.expect(shuffleVectorIndex(6, vector_len) == -3);
135 try testing.expect(shuffleVectorIndex(7, vector_len) == -4);
136}
137
138const FlexibleArrayType = helpers.FlexibleArrayType;
139
140test FlexibleArrayType {
141 const Container = extern struct {
142 size: usize,
143 };
144
145 try testing.expectEqual(FlexibleArrayType(*Container, c_int), [*c]c_int);
146 try testing.expectEqual(FlexibleArrayType(*const Container, c_int), [*c]const c_int);
147 try testing.expectEqual(FlexibleArrayType(*volatile Container, c_int), [*c]volatile c_int);
148 try testing.expectEqual(FlexibleArrayType(*const volatile Container, c_int), [*c]const volatile c_int);
149}
150
151const signedRemainder = helpers.signedRemainder;
152
153test signedRemainder {
154 // TODO add test
155 return error.SkipZigTest;
156}
157
158const ArithmeticConversion = helpers.ArithmeticConversion;
159
160test ArithmeticConversion {
161 // Promotions not necessarily the same for other platforms
162 if (builtin.target.cpu.arch != .x86_64 or builtin.target.os.tag != .linux) return error.SkipZigTest;
163
164 const Test = struct {
165 /// Order of operands should not matter for arithmetic conversions
166 fn checkPromotion(comptime A: type, comptime B: type, comptime Expected: type) !void {
167 try std.testing.expect(ArithmeticConversion(A, B) == Expected);
168 try std.testing.expect(ArithmeticConversion(B, A) == Expected);
169 }
170 };
171
172 try Test.checkPromotion(c_longdouble, c_int, c_longdouble);
173 try Test.checkPromotion(c_int, f64, f64);
174 try Test.checkPromotion(f32, bool, f32);
175
176 try Test.checkPromotion(bool, c_short, c_int);
177 try Test.checkPromotion(c_int, c_int, c_int);
178 try Test.checkPromotion(c_short, c_int, c_int);
179
180 try Test.checkPromotion(c_int, c_long, c_long);
181
182 try Test.checkPromotion(c_ulonglong, c_uint, c_ulonglong);
183
184 try Test.checkPromotion(c_uint, c_int, c_uint);
185
186 try Test.checkPromotion(c_uint, c_long, c_long);
187
188 try Test.checkPromotion(c_ulong, c_longlong, c_ulonglong);
189
190 // stdint.h
191 try Test.checkPromotion(u8, i8, c_int);
192 try Test.checkPromotion(u16, i16, c_int);
193 try Test.checkPromotion(i32, c_int, c_int);
194 try Test.checkPromotion(u32, c_int, c_uint);
195 try Test.checkPromotion(i64, c_int, c_long);
196 try Test.checkPromotion(u64, c_int, c_ulong);
197 try Test.checkPromotion(isize, c_int, c_long);
198 try Test.checkPromotion(usize, c_int, c_ulong);
199}
200
201const F_SUFFIX = helpers.F_SUFFIX;
202
203test F_SUFFIX {
204 try testing.expect(@TypeOf(F_SUFFIX(1)) == f32);
205}
206
207const U_SUFFIX = helpers.U_SUFFIX;
208
209test U_SUFFIX {
210 try testing.expect(@TypeOf(U_SUFFIX(1)) == c_uint);
211 if (math.maxInt(c_ulong) > math.maxInt(c_uint)) {
212 try testing.expect(@TypeOf(U_SUFFIX(math.maxInt(c_uint) + 1)) == c_ulong);
213 }
214 if (math.maxInt(c_ulonglong) > math.maxInt(c_ulong)) {
215 try testing.expect(@TypeOf(U_SUFFIX(math.maxInt(c_ulong) + 1)) == c_ulonglong);
216 }
217}
218
219const L_SUFFIX = helpers.L_SUFFIX;
220
221test L_SUFFIX {
222 try testing.expect(@TypeOf(L_SUFFIX(1)) == c_long);
223 if (math.maxInt(c_long) > math.maxInt(c_int)) {
224 try testing.expect(@TypeOf(L_SUFFIX(math.maxInt(c_int) + 1)) == c_long);
225 }
226 if (math.maxInt(c_longlong) > math.maxInt(c_long)) {
227 try testing.expect(@TypeOf(L_SUFFIX(math.maxInt(c_long) + 1)) == c_longlong);
228 }
229}
230const UL_SUFFIX = helpers.UL_SUFFIX;
231
232test UL_SUFFIX {
233 try testing.expect(@TypeOf(UL_SUFFIX(1)) == c_ulong);
234 if (math.maxInt(c_ulonglong) > math.maxInt(c_ulong)) {
235 try testing.expect(@TypeOf(UL_SUFFIX(math.maxInt(c_ulong) + 1)) == c_ulonglong);
236 }
237}
238const LL_SUFFIX = helpers.LL_SUFFIX;
239
240test LL_SUFFIX {
241 try testing.expect(@TypeOf(LL_SUFFIX(1)) == c_longlong);
242}
243const ULL_SUFFIX = helpers.ULL_SUFFIX;
244
245test ULL_SUFFIX {
246 try testing.expect(@TypeOf(ULL_SUFFIX(1)) == c_ulonglong);
247}
248
249test "Extended C ABI casting" {
250 if (math.maxInt(c_long) > math.maxInt(c_char)) {
251 try testing.expect(@TypeOf(L_SUFFIX(@as(c_char, math.maxInt(c_char) - 1))) == c_long); // c_char
252 }
253 if (math.maxInt(c_long) > math.maxInt(c_short)) {
254 try testing.expect(@TypeOf(L_SUFFIX(@as(c_short, math.maxInt(c_short) - 1))) == c_long); // c_short
255 }
256
257 if (math.maxInt(c_long) > math.maxInt(c_ushort)) {
258 try testing.expect(@TypeOf(L_SUFFIX(@as(c_ushort, math.maxInt(c_ushort) - 1))) == c_long); //c_ushort
259 }
260
261 if (math.maxInt(c_long) > math.maxInt(c_int)) {
262 try testing.expect(@TypeOf(L_SUFFIX(@as(c_int, math.maxInt(c_int) - 1))) == c_long); // c_int
263 }
264
265 if (math.maxInt(c_long) > math.maxInt(c_uint)) {
266 try testing.expect(@TypeOf(L_SUFFIX(@as(c_uint, math.maxInt(c_uint) - 1))) == c_long); // c_uint
267 try testing.expect(@TypeOf(L_SUFFIX(math.maxInt(c_uint) + 1)) == c_long); // comptime_int -> c_long
268 }
269
270 if (math.maxInt(c_longlong) > math.maxInt(c_long)) {
271 try testing.expect(@TypeOf(L_SUFFIX(@as(c_long, math.maxInt(c_long) - 1))) == c_long); // c_long
272 try testing.expect(@TypeOf(L_SUFFIX(math.maxInt(c_long) + 1)) == c_longlong); // comptime_int -> c_longlong
273 }
274}
275
276const WL_CONTAINER_OF = helpers.WL_CONTAINER_OF;
277
278test WL_CONTAINER_OF {
279 const S = struct {
280 a: u32 = 0,
281 b: u32 = 0,
282 };
283 const x = S{};
284 const y = S{};
285 const ptr = WL_CONTAINER_OF(&x.b, &y, "b");
286 try testing.expectEqual(&x, ptr);
287}
288
289const CAST_OR_CALL = helpers.CAST_OR_CALL;
290
291test "CAST_OR_CALL casting" {
292 const arg: c_int = 1000;
293 const casted = CAST_OR_CALL(u8, arg);
294 try testing.expectEqual(cast(u8, arg), casted);
295
296 const S = struct {
297 x: u32 = 0,
298 };
299 var s: S = .{};
300 const casted_ptr = CAST_OR_CALL(*u8, &s);
301 try testing.expectEqual(cast(*u8, &s), casted_ptr);
302}
303
304test "CAST_OR_CALL calling" {
305 const Helper = struct {
306 var last_val: bool = false;
307 fn returnsVoid(val: bool) void {
308 last_val = val;
309 }
310 fn returnsBool(f: f32) bool {
311 return f > 0;
312 }
313 fn identity(self: c_uint) c_uint {
314 return self;
315 }
316 };
317
318 CAST_OR_CALL(Helper.returnsVoid, true);
319 try testing.expectEqual(true, Helper.last_val);
320 CAST_OR_CALL(Helper.returnsVoid, false);
321 try testing.expectEqual(false, Helper.last_val);
322
323 try testing.expectEqual(Helper.returnsBool(1), CAST_OR_CALL(Helper.returnsBool, @as(f32, 1)));
324 try testing.expectEqual(Helper.returnsBool(-1), CAST_OR_CALL(Helper.returnsBool, @as(f32, -1)));
325
326 try testing.expectEqual(Helper.identity(@as(c_uint, 100)), CAST_OR_CALL(Helper.identity, @as(c_uint, 100)));
327}