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}