mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
328 lines
12 KiB
Zig
Vendored
328 lines
12 KiB
Zig
Vendored
const std = @import("std");
|
|
const builtin = @import("builtin");
|
|
const testing = std.testing;
|
|
const math = std.math;
|
|
|
|
const helpers = @import("helpers");
|
|
|
|
const cast = helpers.cast;
|
|
|
|
test cast {
|
|
var i = @as(i64, 10);
|
|
|
|
try testing.expect(cast(*u8, 16) == @as(*u8, @ptrFromInt(16)));
|
|
try testing.expect(cast(*u64, &i).* == @as(u64, 10));
|
|
try testing.expect(cast(*i64, @as(?*align(1) i64, &i)) == &i);
|
|
|
|
try testing.expect(cast(?*u8, 2) == @as(*u8, @ptrFromInt(2)));
|
|
try testing.expect(cast(?*i64, @as(*align(1) i64, &i)) == &i);
|
|
try testing.expect(cast(?*i64, @as(?*align(1) i64, &i)) == &i);
|
|
|
|
try testing.expectEqual(@as(u32, 4), cast(u32, @as(*u32, @ptrFromInt(4))));
|
|
try testing.expectEqual(@as(u32, 4), cast(u32, @as(?*u32, @ptrFromInt(4))));
|
|
try testing.expectEqual(@as(u32, 10), cast(u32, @as(u64, 10)));
|
|
|
|
try testing.expectEqual(@as(i32, @bitCast(@as(u32, 0x8000_0000))), cast(i32, @as(u32, 0x8000_0000)));
|
|
|
|
try testing.expectEqual(@as(*u8, @ptrFromInt(2)), cast(*u8, @as(*const u8, @ptrFromInt(2))));
|
|
try testing.expectEqual(@as(*u8, @ptrFromInt(2)), cast(*u8, @as(*volatile u8, @ptrFromInt(2))));
|
|
|
|
try testing.expectEqual(@as(?*anyopaque, @ptrFromInt(2)), cast(?*anyopaque, @as(*u8, @ptrFromInt(2))));
|
|
|
|
var foo: c_int = -1;
|
|
_ = &foo;
|
|
try testing.expect(cast(*anyopaque, -1) == @as(*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))))));
|
|
try testing.expect(cast(*anyopaque, foo) == @as(*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))))));
|
|
try testing.expect(cast(?*anyopaque, -1) == @as(?*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))))));
|
|
try testing.expect(cast(?*anyopaque, foo) == @as(?*anyopaque, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))))));
|
|
|
|
const FnPtr = ?*align(1) const fn (*anyopaque) void;
|
|
try testing.expect(cast(FnPtr, 0) == @as(FnPtr, @ptrFromInt(@as(usize, 0))));
|
|
try testing.expect(cast(FnPtr, foo) == @as(FnPtr, @ptrFromInt(@as(usize, @bitCast(@as(isize, -1))))));
|
|
|
|
const complexFunction = struct {
|
|
fn f(_: ?*anyopaque, _: c_uint, _: ?*const fn (?*anyopaque) callconv(.c) c_uint, _: ?*anyopaque, _: c_uint, _: [*c]c_uint) callconv(.c) usize {
|
|
return 0;
|
|
}
|
|
}.f;
|
|
|
|
const SDL_FunctionPointer = ?*const fn () callconv(.c) void;
|
|
const fn_ptr = cast(SDL_FunctionPointer, complexFunction);
|
|
try testing.expect(fn_ptr != null);
|
|
}
|
|
|
|
const sizeof = helpers.sizeof;
|
|
|
|
test sizeof {
|
|
const S = extern struct { a: u32 };
|
|
|
|
const ptr_size = @sizeOf(*anyopaque);
|
|
|
|
try testing.expect(sizeof(u32) == 4);
|
|
try testing.expect(sizeof(@as(u32, 2)) == 4);
|
|
try testing.expect(sizeof(2) == @sizeOf(c_int));
|
|
|
|
try testing.expect(sizeof(2.0) == @sizeOf(f64));
|
|
|
|
try testing.expect(sizeof(S) == 4);
|
|
|
|
try testing.expect(sizeof([_]u32{ 4, 5, 6 }) == 12);
|
|
try testing.expect(sizeof([3]u32) == 12);
|
|
try testing.expect(sizeof([3:0]u32) == 16);
|
|
try testing.expect(sizeof(&[_]u32{ 4, 5, 6 }) == ptr_size);
|
|
|
|
try testing.expect(sizeof(*u32) == ptr_size);
|
|
try testing.expect(sizeof([*]u32) == ptr_size);
|
|
try testing.expect(sizeof([*c]u32) == ptr_size);
|
|
try testing.expect(sizeof(?*u32) == ptr_size);
|
|
try testing.expect(sizeof(?[*]u32) == ptr_size);
|
|
try testing.expect(sizeof(*anyopaque) == ptr_size);
|
|
try testing.expect(sizeof(*void) == ptr_size);
|
|
try testing.expect(sizeof(null) == ptr_size);
|
|
|
|
try testing.expect(sizeof("foobar") == 7);
|
|
try testing.expect(sizeof(&[_:0]u16{ 'f', 'o', 'o', 'b', 'a', 'r' }) == 14);
|
|
try testing.expect(sizeof(*const [4:0]u8) == 5);
|
|
try testing.expect(sizeof(*[4:0]u8) == ptr_size);
|
|
try testing.expect(sizeof([*]const [4:0]u8) == ptr_size);
|
|
try testing.expect(sizeof(*const *const [4:0]u8) == ptr_size);
|
|
try testing.expect(sizeof(*const [4]u8) == ptr_size);
|
|
|
|
if (false) { // TODO
|
|
try testing.expect(sizeof(&sizeof) == @sizeOf(@TypeOf(&sizeof)));
|
|
try testing.expect(sizeof(sizeof) == 1);
|
|
}
|
|
|
|
try testing.expect(sizeof(void) == 1);
|
|
try testing.expect(sizeof(anyopaque) == 1);
|
|
}
|
|
|
|
const promoteIntLiteral = helpers.promoteIntLiteral;
|
|
|
|
test promoteIntLiteral {
|
|
const signed_hex = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .hex);
|
|
try testing.expectEqual(c_uint, @TypeOf(signed_hex));
|
|
|
|
if (math.maxInt(c_longlong) == math.maxInt(c_int)) return;
|
|
|
|
const signed_decimal = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .decimal);
|
|
const unsigned = promoteIntLiteral(c_uint, math.maxInt(c_uint) + 1, .hex);
|
|
|
|
if (math.maxInt(c_long) > math.maxInt(c_int)) {
|
|
try testing.expectEqual(c_long, @TypeOf(signed_decimal));
|
|
try testing.expectEqual(c_ulong, @TypeOf(unsigned));
|
|
} else {
|
|
try testing.expectEqual(c_longlong, @TypeOf(signed_decimal));
|
|
try testing.expectEqual(c_ulonglong, @TypeOf(unsigned));
|
|
}
|
|
}
|
|
|
|
const shuffleVectorIndex = helpers.shuffleVectorIndex;
|
|
|
|
test shuffleVectorIndex {
|
|
const vector_len: usize = 4;
|
|
|
|
_ = shuffleVectorIndex(-1, vector_len);
|
|
|
|
try testing.expect(shuffleVectorIndex(0, vector_len) == 0);
|
|
try testing.expect(shuffleVectorIndex(1, vector_len) == 1);
|
|
try testing.expect(shuffleVectorIndex(2, vector_len) == 2);
|
|
try testing.expect(shuffleVectorIndex(3, vector_len) == 3);
|
|
|
|
try testing.expect(shuffleVectorIndex(4, vector_len) == -1);
|
|
try testing.expect(shuffleVectorIndex(5, vector_len) == -2);
|
|
try testing.expect(shuffleVectorIndex(6, vector_len) == -3);
|
|
try testing.expect(shuffleVectorIndex(7, vector_len) == -4);
|
|
}
|
|
|
|
const FlexibleArrayType = helpers.FlexibleArrayType;
|
|
|
|
test FlexibleArrayType {
|
|
const Container = extern struct {
|
|
size: usize,
|
|
};
|
|
|
|
try testing.expectEqual(FlexibleArrayType(*Container, c_int), [*c]c_int);
|
|
try testing.expectEqual(FlexibleArrayType(*const Container, c_int), [*c]const c_int);
|
|
try testing.expectEqual(FlexibleArrayType(*volatile Container, c_int), [*c]volatile c_int);
|
|
try testing.expectEqual(FlexibleArrayType(*const volatile Container, c_int), [*c]const volatile c_int);
|
|
}
|
|
|
|
const signedRemainder = helpers.signedRemainder;
|
|
|
|
test signedRemainder {
|
|
// TODO add test
|
|
return error.SkipZigTest;
|
|
}
|
|
|
|
const ArithmeticConversion = helpers.ArithmeticConversion;
|
|
|
|
test ArithmeticConversion {
|
|
// Promotions not necessarily the same for other platforms
|
|
if (builtin.target.cpu.arch != .x86_64 or builtin.target.os.tag != .linux) return error.SkipZigTest;
|
|
|
|
const Test = struct {
|
|
/// Order of operands should not matter for arithmetic conversions
|
|
fn checkPromotion(comptime A: type, comptime B: type, comptime Expected: type) !void {
|
|
try std.testing.expect(ArithmeticConversion(A, B) == Expected);
|
|
try std.testing.expect(ArithmeticConversion(B, A) == Expected);
|
|
}
|
|
};
|
|
|
|
try Test.checkPromotion(c_longdouble, c_int, c_longdouble);
|
|
try Test.checkPromotion(c_int, f64, f64);
|
|
try Test.checkPromotion(f32, bool, f32);
|
|
|
|
try Test.checkPromotion(bool, c_short, c_int);
|
|
try Test.checkPromotion(c_int, c_int, c_int);
|
|
try Test.checkPromotion(c_short, c_int, c_int);
|
|
|
|
try Test.checkPromotion(c_int, c_long, c_long);
|
|
|
|
try Test.checkPromotion(c_ulonglong, c_uint, c_ulonglong);
|
|
|
|
try Test.checkPromotion(c_uint, c_int, c_uint);
|
|
|
|
try Test.checkPromotion(c_uint, c_long, c_long);
|
|
|
|
try Test.checkPromotion(c_ulong, c_longlong, c_ulonglong);
|
|
|
|
// stdint.h
|
|
try Test.checkPromotion(u8, i8, c_int);
|
|
try Test.checkPromotion(u16, i16, c_int);
|
|
try Test.checkPromotion(i32, c_int, c_int);
|
|
try Test.checkPromotion(u32, c_int, c_uint);
|
|
try Test.checkPromotion(i64, c_int, c_long);
|
|
try Test.checkPromotion(u64, c_int, c_ulong);
|
|
try Test.checkPromotion(isize, c_int, c_long);
|
|
try Test.checkPromotion(usize, c_int, c_ulong);
|
|
}
|
|
|
|
const F_SUFFIX = helpers.F_SUFFIX;
|
|
|
|
test F_SUFFIX {
|
|
try testing.expect(@TypeOf(F_SUFFIX(1)) == f32);
|
|
}
|
|
|
|
const U_SUFFIX = helpers.U_SUFFIX;
|
|
|
|
test U_SUFFIX {
|
|
try testing.expect(@TypeOf(U_SUFFIX(1)) == c_uint);
|
|
if (math.maxInt(c_ulong) > math.maxInt(c_uint)) {
|
|
try testing.expect(@TypeOf(U_SUFFIX(math.maxInt(c_uint) + 1)) == c_ulong);
|
|
}
|
|
if (math.maxInt(c_ulonglong) > math.maxInt(c_ulong)) {
|
|
try testing.expect(@TypeOf(U_SUFFIX(math.maxInt(c_ulong) + 1)) == c_ulonglong);
|
|
}
|
|
}
|
|
|
|
const L_SUFFIX = helpers.L_SUFFIX;
|
|
|
|
test L_SUFFIX {
|
|
try testing.expect(@TypeOf(L_SUFFIX(1)) == c_long);
|
|
if (math.maxInt(c_long) > math.maxInt(c_int)) {
|
|
try testing.expect(@TypeOf(L_SUFFIX(math.maxInt(c_int) + 1)) == c_long);
|
|
}
|
|
if (math.maxInt(c_longlong) > math.maxInt(c_long)) {
|
|
try testing.expect(@TypeOf(L_SUFFIX(math.maxInt(c_long) + 1)) == c_longlong);
|
|
}
|
|
}
|
|
const UL_SUFFIX = helpers.UL_SUFFIX;
|
|
|
|
test UL_SUFFIX {
|
|
try testing.expect(@TypeOf(UL_SUFFIX(1)) == c_ulong);
|
|
if (math.maxInt(c_ulonglong) > math.maxInt(c_ulong)) {
|
|
try testing.expect(@TypeOf(UL_SUFFIX(math.maxInt(c_ulong) + 1)) == c_ulonglong);
|
|
}
|
|
}
|
|
const LL_SUFFIX = helpers.LL_SUFFIX;
|
|
|
|
test LL_SUFFIX {
|
|
try testing.expect(@TypeOf(LL_SUFFIX(1)) == c_longlong);
|
|
}
|
|
const ULL_SUFFIX = helpers.ULL_SUFFIX;
|
|
|
|
test ULL_SUFFIX {
|
|
try testing.expect(@TypeOf(ULL_SUFFIX(1)) == c_ulonglong);
|
|
}
|
|
|
|
test "Extended C ABI casting" {
|
|
if (math.maxInt(c_long) > math.maxInt(c_char)) {
|
|
try testing.expect(@TypeOf(L_SUFFIX(@as(c_char, math.maxInt(c_char) - 1))) == c_long); // c_char
|
|
}
|
|
if (math.maxInt(c_long) > math.maxInt(c_short)) {
|
|
try testing.expect(@TypeOf(L_SUFFIX(@as(c_short, math.maxInt(c_short) - 1))) == c_long); // c_short
|
|
}
|
|
|
|
if (math.maxInt(c_long) > math.maxInt(c_ushort)) {
|
|
try testing.expect(@TypeOf(L_SUFFIX(@as(c_ushort, math.maxInt(c_ushort) - 1))) == c_long); //c_ushort
|
|
}
|
|
|
|
if (math.maxInt(c_long) > math.maxInt(c_int)) {
|
|
try testing.expect(@TypeOf(L_SUFFIX(@as(c_int, math.maxInt(c_int) - 1))) == c_long); // c_int
|
|
}
|
|
|
|
if (math.maxInt(c_long) > math.maxInt(c_uint)) {
|
|
try testing.expect(@TypeOf(L_SUFFIX(@as(c_uint, math.maxInt(c_uint) - 1))) == c_long); // c_uint
|
|
try testing.expect(@TypeOf(L_SUFFIX(math.maxInt(c_uint) + 1)) == c_long); // comptime_int -> c_long
|
|
}
|
|
|
|
if (math.maxInt(c_longlong) > math.maxInt(c_long)) {
|
|
try testing.expect(@TypeOf(L_SUFFIX(@as(c_long, math.maxInt(c_long) - 1))) == c_long); // c_long
|
|
try testing.expect(@TypeOf(L_SUFFIX(math.maxInt(c_long) + 1)) == c_longlong); // comptime_int -> c_longlong
|
|
}
|
|
}
|
|
|
|
const WL_CONTAINER_OF = helpers.WL_CONTAINER_OF;
|
|
|
|
test WL_CONTAINER_OF {
|
|
const S = struct {
|
|
a: u32 = 0,
|
|
b: u32 = 0,
|
|
};
|
|
const x = S{};
|
|
const y = S{};
|
|
const ptr = WL_CONTAINER_OF(&x.b, &y, "b");
|
|
try testing.expectEqual(&x, ptr);
|
|
}
|
|
|
|
const CAST_OR_CALL = helpers.CAST_OR_CALL;
|
|
|
|
test "CAST_OR_CALL casting" {
|
|
const arg: c_int = 1000;
|
|
const casted = CAST_OR_CALL(u8, arg);
|
|
try testing.expectEqual(cast(u8, arg), casted);
|
|
|
|
const S = struct {
|
|
x: u32 = 0,
|
|
};
|
|
var s: S = .{};
|
|
const casted_ptr = CAST_OR_CALL(*u8, &s);
|
|
try testing.expectEqual(cast(*u8, &s), casted_ptr);
|
|
}
|
|
|
|
test "CAST_OR_CALL calling" {
|
|
const Helper = struct {
|
|
var last_val: bool = false;
|
|
fn returnsVoid(val: bool) void {
|
|
last_val = val;
|
|
}
|
|
fn returnsBool(f: f32) bool {
|
|
return f > 0;
|
|
}
|
|
fn identity(self: c_uint) c_uint {
|
|
return self;
|
|
}
|
|
};
|
|
|
|
CAST_OR_CALL(Helper.returnsVoid, true);
|
|
try testing.expectEqual(true, Helper.last_val);
|
|
CAST_OR_CALL(Helper.returnsVoid, false);
|
|
try testing.expectEqual(false, Helper.last_val);
|
|
|
|
try testing.expectEqual(Helper.returnsBool(1), CAST_OR_CALL(Helper.returnsBool, @as(f32, 1)));
|
|
try testing.expectEqual(Helper.returnsBool(-1), CAST_OR_CALL(Helper.returnsBool, @as(f32, -1)));
|
|
|
|
try testing.expectEqual(Helper.identity(@as(c_uint, 100)), CAST_OR_CALL(Helper.identity, @as(c_uint, 100)));
|
|
}
|