mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
Merge pull request 'libzigc: move all unit tests from lib/c/ to test/c/' (#31923) from alexrp/zig:libc-test-refactor into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31923 Reviewed-by: Andrew Kelley <andrew@ziglang.org>
This commit is contained in:
@@ -522,33 +522,6 @@ pub fn build(b: *std.Build) !void {
|
||||
.max_rss = 4_000_000_000,
|
||||
}));
|
||||
|
||||
test_modules_step.dependOn(tests.addModuleTests(b, .{
|
||||
.test_filters = test_filters,
|
||||
.test_target_filters = test_target_filters,
|
||||
.test_extra_targets = test_extra_targets,
|
||||
.root_src = "lib/c.zig",
|
||||
.name = "zigc",
|
||||
.desc = "Run the zig libc implementation unit tests",
|
||||
.optimize_modes = optimization_modes,
|
||||
.include_paths = &.{},
|
||||
.sanitize_thread = sanitize_thread,
|
||||
.skip_single_threaded = true,
|
||||
.skip_non_native = skip_non_native,
|
||||
.test_only = test_only,
|
||||
.skip_spirv = skip_spirv,
|
||||
.skip_wasm = skip_wasm,
|
||||
.skip_freebsd = skip_freebsd,
|
||||
.skip_netbsd = skip_netbsd,
|
||||
.skip_openbsd = skip_openbsd,
|
||||
.skip_windows = skip_windows,
|
||||
.skip_darwin = skip_darwin,
|
||||
.skip_linux = skip_linux,
|
||||
.skip_llvm = skip_llvm,
|
||||
.skip_libc = true,
|
||||
.no_builtin = true,
|
||||
.max_rss = 4_000_000_000,
|
||||
}));
|
||||
|
||||
test_modules_step.dependOn(tests.addModuleTests(b, .{
|
||||
.test_filters = test_filters,
|
||||
.test_target_filters = test_target_filters,
|
||||
@@ -562,7 +535,7 @@ pub fn build(b: *std.Build) !void {
|
||||
.skip_single_threaded = skip_single_threaded,
|
||||
.skip_non_native = skip_non_native,
|
||||
.test_only = test_only,
|
||||
.skip_spirv = skip_spirv,
|
||||
.skip_spirv = true,
|
||||
.skip_wasm = skip_wasm,
|
||||
.skip_freebsd = skip_freebsd,
|
||||
.skip_netbsd = skip_netbsd,
|
||||
@@ -575,6 +548,33 @@ pub fn build(b: *std.Build) !void {
|
||||
.max_rss = 9_300_000_000,
|
||||
}));
|
||||
|
||||
test_modules_step.dependOn(tests.addModuleTests(b, .{
|
||||
.test_filters = test_filters,
|
||||
.test_target_filters = test_target_filters,
|
||||
.test_extra_targets = test_extra_targets,
|
||||
.root_src = "test/c.zig",
|
||||
.name = "libc",
|
||||
.desc = "Run the libc API tests",
|
||||
.optimize_modes = optimization_modes,
|
||||
.include_paths = &.{},
|
||||
.sanitize_thread = sanitize_thread,
|
||||
.skip_single_threaded = true,
|
||||
.skip_non_native = skip_non_native,
|
||||
.test_only = test_only,
|
||||
.skip_spirv = true,
|
||||
.skip_wasm = skip_wasm,
|
||||
.skip_freebsd = skip_freebsd,
|
||||
.skip_netbsd = skip_netbsd,
|
||||
.skip_openbsd = skip_openbsd,
|
||||
.skip_windows = skip_windows,
|
||||
.skip_darwin = skip_darwin,
|
||||
.skip_linux = skip_linux,
|
||||
.skip_llvm = skip_llvm,
|
||||
.skip_libc = skip_libc,
|
||||
.no_builtin = true,
|
||||
.max_rss = 4_000_000_000,
|
||||
}));
|
||||
|
||||
const unit_tests_step = b.step("test-unit", "Run the compiler source unit tests");
|
||||
test_step.dependOn(unit_tests_step);
|
||||
|
||||
@@ -662,13 +662,13 @@ pub fn build(b: *std.Build) !void {
|
||||
try tests.addIncrementalTests(b, test_incremental_step, test_filters);
|
||||
if (!skip_test_incremental) test_step.dependOn(test_incremental_step);
|
||||
|
||||
if (tests.addLibcTests(b, .{
|
||||
if (tests.addLibcTestNszTests(b, .{
|
||||
.optimize_modes = optimization_modes,
|
||||
.test_filters = test_filters,
|
||||
.test_target_filters = test_target_filters,
|
||||
.skip_wasm = skip_wasm,
|
||||
.max_rss = 3_500_000_000,
|
||||
})) |test_libc_step| test_step.dependOn(test_libc_step);
|
||||
})) |test_libc_nsz_step| test_step.dependOn(test_libc_nsz_step);
|
||||
}
|
||||
|
||||
fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
//! bundled libcs.
|
||||
//!
|
||||
//! mingw-w64 libc is not fully statically linked, so some symbols don't need
|
||||
//! to be exported. However, a future enhancement could be eliminating Zig's
|
||||
//! dependency on msvcrt dll even when linking libc and targeting Windows.
|
||||
//! to be exported.
|
||||
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
@@ -24,13 +24,3 @@ fn imaxdiv(a: intmax_t, b: intmax_t) callconv(.c) imaxdiv_t {
|
||||
.rem = @rem(a, b),
|
||||
};
|
||||
}
|
||||
|
||||
test imaxabs {
|
||||
const val: intmax_t = -10;
|
||||
try std.testing.expectEqual(10, imaxabs(val));
|
||||
}
|
||||
|
||||
test imaxdiv {
|
||||
const expected: imaxdiv_t = .{ .quot = 9, .rem = 0 };
|
||||
try std.testing.expectEqual(expected, imaxdiv(9, 1));
|
||||
}
|
||||
|
||||
-100
@@ -2,10 +2,6 @@ const builtin = @import("builtin");
|
||||
|
||||
const std = @import("std");
|
||||
const math = std.math;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
const expectApproxEqAbs = std.testing.expectApproxEqAbs;
|
||||
const expectApproxEqRel = std.testing.expectApproxEqRel;
|
||||
|
||||
const symbol = @import("../c.zig").symbol;
|
||||
|
||||
@@ -304,59 +300,6 @@ fn modfl(x: c_longdouble, iptr: *c_longdouble) callconv(.c) c_longdouble {
|
||||
};
|
||||
}
|
||||
|
||||
fn testModf(comptime T: type) !void {
|
||||
// Choose the appropriate `modf` impl to test based on type
|
||||
const f = switch (T) {
|
||||
f32 => modff,
|
||||
f64 => modf,
|
||||
c_longdouble => modfl,
|
||||
else => @compileError("modf not implemented for " ++ @typeName(T)),
|
||||
};
|
||||
|
||||
var int: T = undefined;
|
||||
const iptr = ∫
|
||||
const eps_val: comptime_float = @max(1e-6, math.floatEps(T));
|
||||
|
||||
const normal_frac = f(@as(T, 1234.567), iptr);
|
||||
// Account for precision error
|
||||
const expected = 1234.567 - @as(T, 1234);
|
||||
try expectApproxEqAbs(expected, normal_frac, eps_val);
|
||||
try expectApproxEqRel(@as(T, 1234.0), iptr.*, eps_val);
|
||||
|
||||
// When `x` is a NaN, NaN is returned and `*iptr` is set to NaN
|
||||
const nan_frac = f(math.nan(T), iptr);
|
||||
try expect(math.isNan(nan_frac));
|
||||
try expect(math.isNan(iptr.*));
|
||||
|
||||
// When `x` is positive infinity, +0 is returned and `*iptr` is set to
|
||||
// positive infinity
|
||||
const pos_zero_frac = f(math.inf(T), iptr);
|
||||
try expect(math.isPositiveZero(pos_zero_frac));
|
||||
try expect(math.isPositiveInf(iptr.*));
|
||||
|
||||
// When `x` is negative infinity, -0 is returned and `*iptr` is set to
|
||||
// negative infinity
|
||||
const neg_zero_frac = f(-math.inf(T), iptr);
|
||||
try expect(math.isNegativeZero(neg_zero_frac));
|
||||
try expect(math.isNegativeInf(iptr.*));
|
||||
|
||||
// Return -0 when `x` is a negative integer
|
||||
const nz_frac = f(@as(T, -1000.0), iptr);
|
||||
try expect(math.isNegativeZero(nz_frac));
|
||||
try expectEqual(@as(T, -1000.0), iptr.*);
|
||||
|
||||
// Return +0 when `x` is a positive integer
|
||||
const pz_frac = f(@as(T, 1000.0), iptr);
|
||||
try expect(math.isPositiveZero(pz_frac));
|
||||
try expectEqual(@as(T, 1000.0), iptr.*);
|
||||
}
|
||||
|
||||
test "modf" {
|
||||
try testModf(f32);
|
||||
try testModf(f64);
|
||||
try testModf(c_longdouble);
|
||||
}
|
||||
|
||||
fn nan(_: [*:0]const c_char) callconv(.c) f64 {
|
||||
return math.nan(f64);
|
||||
}
|
||||
@@ -421,49 +364,6 @@ fn rintf(x: f32) callconv(.c) f32 {
|
||||
return y;
|
||||
}
|
||||
|
||||
fn testRint(comptime T: type) !void {
|
||||
const f = switch (T) {
|
||||
f32 => rintf,
|
||||
f64 => rint,
|
||||
else => @compileError("rint not implemented for" ++ @typeName(T)),
|
||||
};
|
||||
|
||||
// Positive numbers round correctly
|
||||
try expectEqual(@as(T, 42.0), f(42.2));
|
||||
try expectEqual(@as(T, 42.0), f(41.8));
|
||||
|
||||
// Negative numbers round correctly
|
||||
try expectEqual(@as(T, -6.0), f(-5.9));
|
||||
try expectEqual(@as(T, -6.0), f(-6.1));
|
||||
|
||||
// No rounding needed test
|
||||
try expectEqual(@as(T, 5.0), f(5.0));
|
||||
try expectEqual(@as(T, -10.0), f(-10.0));
|
||||
try expectEqual(@as(T, 0.0), f(0.0));
|
||||
|
||||
// Very large numbers return unchanged
|
||||
const large: T = 9007199254740992.0; // 2^53
|
||||
try expectEqual(large, f(large));
|
||||
try expectEqual(-large, f(-large));
|
||||
|
||||
// Small positive numbers round to zero
|
||||
const pos_result = f(0.3);
|
||||
try expect(math.isPositiveZero(pos_result));
|
||||
|
||||
// Small negative numbers round to negative zero
|
||||
const neg_result = f(-0.3);
|
||||
try expect(math.isNegativeZero(neg_result));
|
||||
|
||||
// Exact half rounds to nearest even (banker's rounding)
|
||||
try expectEqual(@as(T, 2.0), f(2.5));
|
||||
try expectEqual(@as(T, 4.0), f(3.5));
|
||||
}
|
||||
|
||||
test "rint" {
|
||||
try testRint(f32);
|
||||
try testRint(f64);
|
||||
}
|
||||
|
||||
fn tanh(x: f64) callconv(.c) f64 {
|
||||
return math.tanh(x);
|
||||
}
|
||||
|
||||
+1
-27
@@ -9,6 +9,7 @@ comptime {
|
||||
}
|
||||
}
|
||||
|
||||
/// Not defined in `std.c` because C headers don't either.
|
||||
const Node = extern struct {
|
||||
next: ?*Node,
|
||||
prev: ?*Node,
|
||||
@@ -38,30 +39,3 @@ fn remque(element: *anyopaque) callconv(.c) void {
|
||||
if (e.next) |next| next.prev = e.prev;
|
||||
if (e.prev) |prev| prev.next = e.next;
|
||||
}
|
||||
|
||||
test "insque and remque" {
|
||||
var first = Node{ .next = null, .prev = null };
|
||||
var second = Node{ .next = null, .prev = null };
|
||||
var third = Node{ .next = null, .prev = null };
|
||||
|
||||
insque(&first, null);
|
||||
try std.testing.expectEqual(@as(?*Node, null), first.next);
|
||||
try std.testing.expectEqual(@as(?*Node, null), first.prev);
|
||||
|
||||
insque(&second, &first);
|
||||
try std.testing.expectEqual(@as(?*Node, &second), first.next);
|
||||
try std.testing.expectEqual(@as(?*Node, &first), second.prev);
|
||||
|
||||
insque(&third, &first);
|
||||
try std.testing.expectEqual(@as(?*Node, &third), first.next);
|
||||
try std.testing.expectEqual(@as(?*Node, &second), third.next);
|
||||
try std.testing.expectEqual(@as(?*Node, &first), third.prev);
|
||||
try std.testing.expectEqual(@as(?*Node, &third), second.prev);
|
||||
|
||||
remque(&third);
|
||||
try std.testing.expectEqual(@as(?*Node, &second), first.next);
|
||||
try std.testing.expectEqual(@as(?*Node, &first), second.prev);
|
||||
|
||||
remque(&second);
|
||||
try std.testing.expectEqual(@as(?*Node, null), first.next);
|
||||
}
|
||||
|
||||
@@ -294,103 +294,3 @@ fn bsearch(key: *const anyopaque, base: *const anyopaque, n: usize, size: usize,
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
test abs {
|
||||
const val: c_int = -10;
|
||||
try std.testing.expectEqual(10, abs(val));
|
||||
}
|
||||
|
||||
test labs {
|
||||
const val: c_long = -10;
|
||||
try std.testing.expectEqual(10, labs(val));
|
||||
}
|
||||
|
||||
test llabs {
|
||||
const val: c_longlong = -10;
|
||||
try std.testing.expectEqual(10, llabs(val));
|
||||
}
|
||||
|
||||
test div {
|
||||
const expected: div_t = .{ .quot = 5, .rem = 5 };
|
||||
try std.testing.expectEqual(expected, div(55, 10));
|
||||
}
|
||||
|
||||
test ldiv {
|
||||
const expected: ldiv_t = .{ .quot = -6, .rem = 2 };
|
||||
try std.testing.expectEqual(expected, ldiv(38, -6));
|
||||
}
|
||||
|
||||
test lldiv {
|
||||
const expected: lldiv_t = .{ .quot = 1, .rem = 2 };
|
||||
try std.testing.expectEqual(expected, lldiv(5, 3));
|
||||
}
|
||||
|
||||
test atoi {
|
||||
try std.testing.expectEqual(0, atoi(@ptrCast("stop42true")));
|
||||
try std.testing.expectEqual(42, atoi(@ptrCast("42true")));
|
||||
try std.testing.expectEqual(-1, atoi(@ptrCast("-01")));
|
||||
try std.testing.expectEqual(1, atoi(@ptrCast("+001")));
|
||||
try std.testing.expectEqual(100, atoi(@ptrCast(" 100")));
|
||||
try std.testing.expectEqual(500, atoi(@ptrCast("000000000000500")));
|
||||
try std.testing.expectEqual(1111, atoi(@ptrCast("0000000000001111_0000")));
|
||||
try std.testing.expectEqual(0, atoi(@ptrCast("0xAA")));
|
||||
try std.testing.expectEqual(700, atoi(@ptrCast("700B")));
|
||||
try std.testing.expectEqual(32453, atoi(@ptrCast("+32453more")));
|
||||
try std.testing.expectEqual(std.math.maxInt(c_int), atoi(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.maxInt(c_int)}))));
|
||||
try std.testing.expectEqual(std.math.minInt(c_int), atoi(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.minInt(c_int)}))));
|
||||
}
|
||||
|
||||
test atol {
|
||||
try std.testing.expectEqual(0, atol(@ptrCast("stop42true")));
|
||||
try std.testing.expectEqual(42, atol(@ptrCast("42true")));
|
||||
try std.testing.expectEqual(-1, atol(@ptrCast("-01")));
|
||||
try std.testing.expectEqual(1, atol(@ptrCast("+001")));
|
||||
try std.testing.expectEqual(100, atol(@ptrCast(" 100")));
|
||||
try std.testing.expectEqual(500, atol(@ptrCast("000000000000500")));
|
||||
try std.testing.expectEqual(1111, atol(@ptrCast("0000000000001111_0000")));
|
||||
try std.testing.expectEqual(0, atol(@ptrCast("0xAA")));
|
||||
try std.testing.expectEqual(700, atol(@ptrCast("700B")));
|
||||
try std.testing.expectEqual(32453, atol(@ptrCast("+32453more")));
|
||||
try std.testing.expectEqual(std.math.maxInt(c_long), atol(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.maxInt(c_long)}))));
|
||||
try std.testing.expectEqual(std.math.minInt(c_long), atol(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.minInt(c_long)}))));
|
||||
}
|
||||
|
||||
test atoll {
|
||||
try std.testing.expectEqual(0, atoll(@ptrCast("stop42true")));
|
||||
try std.testing.expectEqual(42, atoll(@ptrCast("42true")));
|
||||
try std.testing.expectEqual(-1, atoll(@ptrCast("-01")));
|
||||
try std.testing.expectEqual(1, atoll(@ptrCast("+001")));
|
||||
try std.testing.expectEqual(100, atoll(@ptrCast(" 100")));
|
||||
try std.testing.expectEqual(500, atoll(@ptrCast("000000000000500")));
|
||||
try std.testing.expectEqual(1111, atoll(@ptrCast("0000000000001111_0000")));
|
||||
try std.testing.expectEqual(0, atoll(@ptrCast("0xAA")));
|
||||
try std.testing.expectEqual(700, atoll(@ptrCast("700B")));
|
||||
try std.testing.expectEqual(32453, atoll(@ptrCast(" +32453more")));
|
||||
try std.testing.expectEqual(std.math.maxInt(c_longlong), atoll(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.maxInt(c_longlong)}))));
|
||||
try std.testing.expectEqual(std.math.minInt(c_longlong), atoll(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.minInt(c_longlong)}))));
|
||||
}
|
||||
|
||||
// FIXME: We cannot test strtol, strtoll, strtoul, etc.. here as it must modify errno and libc is not linked in tests
|
||||
|
||||
test bsearch {
|
||||
const Comparison = struct {
|
||||
pub fn compare(a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int {
|
||||
const a_u16: *const u16 = @ptrCast(@alignCast(a));
|
||||
const b_u16: *const u16 = @ptrCast(@alignCast(b));
|
||||
|
||||
return switch (std.math.order(a_u16.*, b_u16.*)) {
|
||||
.gt => 1,
|
||||
.eq => 0,
|
||||
.lt => -1,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const items: []const u16 = &.{ 0, 5, 7, 9, 10, 200, 512, 768 };
|
||||
|
||||
try std.testing.expectEqual(@as(?*anyopaque, null), bsearch(&@as(u16, 2000), items.ptr, items.len, @sizeOf(u16), Comparison.compare));
|
||||
|
||||
for (items) |*value| {
|
||||
try std.testing.expectEqual(@as(*const anyopaque, value), bsearch(value, items.ptr, items.len, @sizeOf(u16), Comparison.compare));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,60 +90,3 @@ fn srand48(seedval: c_long) callconv(.c) void {
|
||||
const xi = (@as(u32, @truncate(@as(c_ulong, @bitCast(seedval)))) << 16) | 0x330E;
|
||||
lcg = .init(xi, default_multiplier, default_addend);
|
||||
}
|
||||
|
||||
test erand48 {
|
||||
var xsubi: [3]c_ushort = .{ 37174, 64810, 11603 };
|
||||
|
||||
try std.testing.expectApproxEqAbs(0.8965, erand48(&xsubi), 0.0005);
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 22537, 47966, 58735 }, &xsubi);
|
||||
|
||||
try std.testing.expectApproxEqAbs(0.3375, erand48(&xsubi), 0.0005);
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 37344, 32911, 22119 }, &xsubi);
|
||||
|
||||
try std.testing.expectApproxEqAbs(0.6475, erand48(&xsubi), 0.0005);
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 23659, 29872, 42445 }, &xsubi);
|
||||
|
||||
try std.testing.expectApproxEqAbs(0.5005, erand48(&xsubi), 0.0005);
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 31642, 7875, 32802 }, &xsubi);
|
||||
|
||||
try std.testing.expectApproxEqAbs(0.5065, erand48(&xsubi), 0.0005);
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 64669, 14399, 33170 }, &xsubi);
|
||||
}
|
||||
|
||||
test jrand48 {
|
||||
var xsubi: [3]c_ushort = .{ 25175, 11052, 45015 };
|
||||
|
||||
try std.testing.expectEqual(1699503220, jrand48(&xsubi));
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 2326, 23668, 25932 }, &xsubi);
|
||||
|
||||
try std.testing.expectEqual(-992276007, jrand48(&xsubi));
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 41577, 4569, 50395 }, &xsubi);
|
||||
|
||||
try std.testing.expectEqual(-19535776, jrand48(&xsubi));
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 31936, 59488, 65237 }, &xsubi);
|
||||
|
||||
try std.testing.expectEqual(79438377, jrand48(&xsubi));
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 40395, 8745, 1212 }, &xsubi);
|
||||
|
||||
try std.testing.expectEqual(-1258917728, jrand48(&xsubi));
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 37242, 28832, 46326 }, &xsubi);
|
||||
}
|
||||
|
||||
test nrand48 {
|
||||
var xsubi: [3]c_ushort = .{ 546, 33817, 23389 };
|
||||
|
||||
try std.testing.expectEqual(914920692, nrand48(&xsubi));
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 29829, 10728, 27921 }, &xsubi);
|
||||
|
||||
try std.testing.expectEqual(754104482, nrand48(&xsubi));
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 6828, 28997, 23013 }, &xsubi);
|
||||
|
||||
try std.testing.expectEqual(609453945, nrand48(&xsubi));
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 58183, 3826, 18599 }, &xsubi);
|
||||
|
||||
try std.testing.expectEqual(1878644360, nrand48(&xsubi));
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 36678, 44304, 57331 }, &xsubi);
|
||||
|
||||
try std.testing.expectEqual(2114923686, nrand48(&xsubi));
|
||||
try std.testing.expectEqualSlices(c_ushort, &.{ 58585, 22861, 64542 }, &xsubi);
|
||||
}
|
||||
|
||||
@@ -290,10 +290,3 @@ fn mempcpy(noalias dst: *anyopaque, noalias src: *const anyopaque, len: usize) c
|
||||
@memcpy(dst_bytes[0..len], src_bytes[0..len]);
|
||||
return dst_bytes + len;
|
||||
}
|
||||
|
||||
test strncmp {
|
||||
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
|
||||
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("c"), 1) < 0);
|
||||
try std.testing.expect(strncmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
|
||||
try std.testing.expect(strncmp(@ptrCast("\xff"), @ptrCast("\x02"), 1) > 0);
|
||||
}
|
||||
|
||||
@@ -81,41 +81,3 @@ fn __strncasecmp_l(a: [*:0]const c_char, b: [*:0]const c_char, n: usize, locale:
|
||||
_ = locale;
|
||||
return strncasecmp(a, b, n);
|
||||
}
|
||||
|
||||
test bzero {
|
||||
var array: [10]u8 = [_]u8{ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
|
||||
var a = std.mem.zeroes([array.len]u8);
|
||||
a[9] = '0';
|
||||
bzero(&array[0], 9);
|
||||
try std.testing.expect(std.mem.eql(u8, &array, &a));
|
||||
}
|
||||
|
||||
test firstBitSet {
|
||||
try std.testing.expectEqual(0, firstBitSet(usize, 0));
|
||||
|
||||
for (0..@bitSizeOf(usize)) |i| {
|
||||
const bit = @as(usize, 1) << @intCast(i);
|
||||
|
||||
try std.testing.expectEqual(i + 1, firstBitSet(usize, bit));
|
||||
}
|
||||
}
|
||||
|
||||
test strcasecmp {
|
||||
try std.testing.expect(strcasecmp(@ptrCast("a"), @ptrCast("b")) < 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("a")) > 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("b")) < 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("A")) > 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("A")) == 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("B"), @ptrCast("b")) == 0);
|
||||
try std.testing.expect(strcasecmp(@ptrCast("bb"), @ptrCast("AA")) > 0);
|
||||
}
|
||||
|
||||
test strncasecmp {
|
||||
try std.testing.expect(strncasecmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("b"), 1) < 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("A"), 1) > 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("A"), 1) == 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("B"), @ptrCast("b"), 1) == 0);
|
||||
try std.testing.expect(strncasecmp(@ptrCast("bb"), @ptrCast("AA"), 2) > 0);
|
||||
}
|
||||
|
||||
@@ -206,32 +206,6 @@ fn swab(noalias src_ptr: *const anyopaque, noalias dest_ptr: *anyopaque, n: isiz
|
||||
}
|
||||
}
|
||||
|
||||
test swab {
|
||||
var a: [4]u8 = undefined;
|
||||
@memset(a[0..], '\x00');
|
||||
swab("abcd", &a, 4);
|
||||
try std.testing.expectEqualSlices(u8, "badc", &a);
|
||||
|
||||
// Partial copy
|
||||
@memset(a[0..], '\x00');
|
||||
swab("abcd", &a, 2);
|
||||
try std.testing.expectEqualSlices(u8, "ba\x00\x00", &a);
|
||||
|
||||
// n < 1
|
||||
@memset(a[0..], '\x00');
|
||||
swab("abcd", &a, 0);
|
||||
try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a);
|
||||
swab("abcd", &a, -1);
|
||||
try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a);
|
||||
|
||||
// Odd n
|
||||
@memset(a[0..], '\x00');
|
||||
swab("abcd", &a, 1);
|
||||
try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a);
|
||||
swab("abcd", &a, 3);
|
||||
try std.testing.expectEqualSlices(u8, "ba\x00\x00", &a);
|
||||
}
|
||||
|
||||
fn close(fd: std.c.fd_t) callconv(.c) c_int {
|
||||
const signed: isize = @bitCast(linux.close(fd));
|
||||
if (signed < 0) {
|
||||
|
||||
+53
-6
@@ -11102,13 +11102,60 @@ pub const ioctl = switch (native_os) {
|
||||
else => private.ioctl,
|
||||
};
|
||||
|
||||
pub extern "c" fn bzero(s: *anyopaque, n: usize) void;
|
||||
|
||||
pub extern "c" fn swab(noalias from: *const anyopaque, noalias to: *anyopaque, n: isize) void;
|
||||
|
||||
pub extern "c" fn strncmp(a: [*:0]const c_char, b: [*:0]const c_char, max: usize) c_int;
|
||||
pub extern "c" fn strcasecmp(a: [*:0]const c_char, b: [*:0]const c_char) c_int;
|
||||
pub extern "c" fn strncasecmp(a: [*:0]const c_char, b: [*:0]const c_char, max: usize) c_int;
|
||||
|
||||
pub extern "c" fn ffs(i: c_int) c_int;
|
||||
pub extern "c" fn ffsl(i: c_long) c_long;
|
||||
pub extern "c" fn ffsll(i: c_longlong) c_longlong;
|
||||
|
||||
pub extern "c" fn erand48(xsubi: *[3]c_ushort) f64;
|
||||
pub extern "c" fn jrand48(xsubi: *[3]c_ushort) c_long;
|
||||
pub extern "c" fn nrand48(xsubi: *[3]c_ushort) c_long;
|
||||
|
||||
pub extern "c" fn insque(element: *anyopaque, pred: ?*anyopaque) void;
|
||||
pub extern "c" fn remque(element: *anyopaque) void;
|
||||
|
||||
pub extern "c" fn imaxabs(a: intmax_t) intmax_t;
|
||||
pub extern "c" fn imaxdiv(a: intmax_t, b: intmax_t) imaxdiv_t;
|
||||
|
||||
pub extern "c" fn abs(a: c_int) c_int;
|
||||
pub extern "c" fn labs(a: c_long) c_long;
|
||||
pub extern "c" fn llabs(a: c_longlong) c_longlong;
|
||||
|
||||
pub extern "c" fn div(a: c_int, b: c_int) div_t;
|
||||
pub extern "c" fn ldiv(a: c_long, b: c_long) ldiv_t;
|
||||
pub extern "c" fn lldiv(a: c_longlong, b: c_longlong) lldiv_t;
|
||||
|
||||
pub extern "c" fn atoi(str: [*:0]const c_char) c_int;
|
||||
pub extern "c" fn atol(str: [*:0]const c_char) c_long;
|
||||
pub extern "c" fn atoll(str: [*:0]const c_char) c_longlong;
|
||||
|
||||
pub extern "c" fn bsearch(
|
||||
key: *const anyopaque,
|
||||
base: *const anyopaque,
|
||||
n: usize,
|
||||
size: usize,
|
||||
compare: *const fn (a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int,
|
||||
) ?*anyopaque;
|
||||
|
||||
// Math
|
||||
pub extern "c" fn atan(x: f64) callconv(.c) f64;
|
||||
pub extern "c" fn copysign(x: f64, y: f64) callconv(.c) f64;
|
||||
pub extern "c" fn fdim(x: f64, y: f64) callconv(.c) f64;
|
||||
pub extern "c" fn frexp(x: f64, e: *c_int) callconv(.c) f64;
|
||||
pub extern "c" fn hypot(x: f64, y: f64) callconv(.c) f64;
|
||||
pub extern "c" fn modf(x: f64, iptr: *f64) callconv(.c) f64;
|
||||
pub extern "c" fn atan(x: f64) f64;
|
||||
pub extern "c" fn copysign(x: f64, y: f64) f64;
|
||||
pub extern "c" fn fdim(x: f64, y: f64) f64;
|
||||
pub extern "c" fn frexp(x: f64, e: *c_int) f64;
|
||||
pub extern "c" fn hypot(x: f64, y: f64) f64;
|
||||
pub extern "c" fn modff(x: f32, iptr: *f32) f32;
|
||||
pub extern "c" fn modf(x: f64, iptr: *f64) f64;
|
||||
pub extern "c" fn modfl(x: c_longdouble, iptr: *c_longdouble) c_longdouble;
|
||||
pub extern "c" fn rintf(x: f32) f32;
|
||||
pub extern "c" fn rint(x: f64) f64;
|
||||
pub extern "c" fn rintl(x: c_longdouble) c_longdouble;
|
||||
|
||||
// OS-specific bits. These are protected from being used on the wrong OS by
|
||||
// comptime assertions inside each OS-specific file.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std.zig");
|
||||
const native_os = builtin.os.tag;
|
||||
|
||||
pub const linux = @import("os/linux.zig");
|
||||
@@ -8,6 +9,46 @@ pub const wasi = @import("os/wasi.zig");
|
||||
pub const emscripten = @import("os/emscripten.zig");
|
||||
pub const windows = @import("os/windows.zig");
|
||||
|
||||
/// Returns whether the Zig standard library requires libc in order to interface
|
||||
/// with the operating system on the given target.
|
||||
pub fn targetRequiresLibC(target: *const std.Target) bool {
|
||||
if (target.requiresLibC()) return true;
|
||||
return switch (target.os.tag) {
|
||||
.linux => switch (target.cpu.arch) {
|
||||
// https://codeberg.org/ziglang/zig/issues/30940
|
||||
.alpha,
|
||||
// https://codeberg.org/ziglang/zig/issues/30942
|
||||
.csky,
|
||||
// https://codeberg.org/ziglang/zig/issues/30943
|
||||
.hppa,
|
||||
.hppa64,
|
||||
// https://codeberg.org/ziglang/zig/issues/30944
|
||||
.microblaze,
|
||||
.microblazeel,
|
||||
// https://codeberg.org/ziglang/zig/issues/30946
|
||||
.sh,
|
||||
.sheb,
|
||||
// https://codeberg.org/ziglang/zig/issues/30945
|
||||
.sparc,
|
||||
// https://codeberg.org/ziglang/zig/issues/30947
|
||||
.xtensa,
|
||||
.xtensaeb,
|
||||
=> true,
|
||||
else => false,
|
||||
},
|
||||
.freebsd => true, // https://codeberg.org/ziglang/zig/issues/30981
|
||||
.netbsd => true, // https://codeberg.org/ziglang/zig/issues/30980
|
||||
.openbsd => true, // https://codeberg.org/ziglang/zig/issues/30982
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns whether the Zig standard library requires libc in order to interface
|
||||
/// with the operating system on the current target.
|
||||
pub fn requiresLibC() bool {
|
||||
return targetRequiresLibC(&builtin.target);
|
||||
}
|
||||
|
||||
test {
|
||||
_ = linux;
|
||||
if (native_os == .uefi) _ = uefi;
|
||||
|
||||
@@ -234,19 +234,10 @@ pub fn resolve(options: Options) ResolveError!Config {
|
||||
break :b true;
|
||||
}
|
||||
if (options.link_libc) |x| break :b x;
|
||||
switch (target.os.tag) {
|
||||
// These targets don't require libc, but we don't yet have a syscall layer for them,
|
||||
// so we default to linking libc for now.
|
||||
.freebsd,
|
||||
.netbsd,
|
||||
.openbsd,
|
||||
=> break :b true,
|
||||
else => {},
|
||||
}
|
||||
if (options.ensure_libc_on_non_freestanding and target.os.tag != .freestanding)
|
||||
break :b true;
|
||||
|
||||
break :b target.requiresLibC();
|
||||
break :b std.os.targetRequiresLibC(target);
|
||||
};
|
||||
|
||||
const link_mode = b: {
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
test {
|
||||
_ = @import("c/inttypes.zig");
|
||||
_ = @import("c/math.zig");
|
||||
_ = @import("c/search.zig");
|
||||
_ = @import("c/stdlib.zig");
|
||||
_ = @import("c/string.zig");
|
||||
_ = @import("c/strings.zig");
|
||||
_ = @import("c/unistd.zig");
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
const c = std.c;
|
||||
const testing = std.testing;
|
||||
|
||||
test "imaxabs" {
|
||||
const val: c.intmax_t = -10;
|
||||
try testing.expectEqual(10, c.imaxabs(val));
|
||||
}
|
||||
|
||||
test "imaxdiv" {
|
||||
if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest; // TODO
|
||||
if (builtin.target.cpu.arch == .s390x) return error.SkipZigTest; // TODO
|
||||
|
||||
const expected: c.imaxdiv_t = .{ .quot = 9, .rem = 0 };
|
||||
try testing.expectEqual(expected, c.imaxdiv(9, 1));
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
const c = std.c;
|
||||
const math = std.math;
|
||||
const testing = std.testing;
|
||||
|
||||
fn testModf(comptime T: type) !void {
|
||||
const f = switch (T) {
|
||||
f32 => c.modff,
|
||||
f64 => c.modf,
|
||||
c_longdouble => c.modfl,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
var int: T = undefined;
|
||||
const iptr = ∫
|
||||
const eps_val: comptime_float = @max(1e-6, math.floatEps(T));
|
||||
|
||||
const normal_frac = f(@as(T, 1234.567), iptr);
|
||||
// Account for precision error
|
||||
const expected = 1234.567 - @as(T, 1234);
|
||||
try testing.expectApproxEqAbs(expected, normal_frac, eps_val);
|
||||
try testing.expectApproxEqRel(@as(T, 1234.0), iptr.*, eps_val);
|
||||
|
||||
// When `x` is a NaN, NaN is returned and `*iptr` is set to NaN
|
||||
const nan_frac = f(math.nan(T), iptr);
|
||||
try testing.expect(math.isNan(nan_frac));
|
||||
try testing.expect(math.isNan(iptr.*));
|
||||
|
||||
// When `x` is positive infinity, +0 is returned and `*iptr` is set to
|
||||
// positive infinity
|
||||
const pos_zero_frac = f(math.inf(T), iptr);
|
||||
try testing.expect(math.isPositiveZero(pos_zero_frac));
|
||||
try testing.expect(math.isPositiveInf(iptr.*));
|
||||
|
||||
// When `x` is negative infinity, -0 is returned and `*iptr` is set to
|
||||
// negative infinity
|
||||
const neg_zero_frac = f(-math.inf(T), iptr);
|
||||
try testing.expect(math.isNegativeZero(neg_zero_frac));
|
||||
try testing.expect(math.isNegativeInf(iptr.*));
|
||||
|
||||
// Return -0 when `x` is a negative integer
|
||||
const nz_frac = f(@as(T, -1000.0), iptr);
|
||||
try testing.expect(math.isNegativeZero(nz_frac));
|
||||
try testing.expectEqual(@as(T, -1000.0), iptr.*);
|
||||
|
||||
// Return +0 when `x` is a positive integer
|
||||
const pz_frac = f(@as(T, 1000.0), iptr);
|
||||
try testing.expect(math.isPositiveZero(pz_frac));
|
||||
try testing.expectEqual(@as(T, 1000.0), iptr.*);
|
||||
}
|
||||
|
||||
test "modf" {
|
||||
try testModf(f32);
|
||||
try testModf(f64);
|
||||
|
||||
if (builtin.target.cpu.arch.isPowerPC()) return error.SkipZigTest; // TODO
|
||||
|
||||
try testModf(c_longdouble);
|
||||
}
|
||||
|
||||
fn testRint(comptime T: type) !void {
|
||||
const f = switch (T) {
|
||||
f32 => c.rintf,
|
||||
f64 => c.rint,
|
||||
else => @compileError("rint not implemented for" ++ @typeName(T)),
|
||||
};
|
||||
|
||||
// Positive numbers round correctly
|
||||
try testing.expectEqual(@as(T, 42.0), f(42.2));
|
||||
try testing.expectEqual(@as(T, 42.0), f(41.8));
|
||||
|
||||
// Negative numbers round correctly
|
||||
try testing.expectEqual(@as(T, -6.0), f(-5.9));
|
||||
try testing.expectEqual(@as(T, -6.0), f(-6.1));
|
||||
|
||||
// No rounding needed test
|
||||
try testing.expectEqual(@as(T, 5.0), f(5.0));
|
||||
try testing.expectEqual(@as(T, -10.0), f(-10.0));
|
||||
try testing.expectEqual(@as(T, 0.0), f(0.0));
|
||||
|
||||
// Very large numbers return unchanged
|
||||
const large: T = 9007199254740992.0; // 2^53
|
||||
try testing.expectEqual(large, f(large));
|
||||
try testing.expectEqual(-large, f(-large));
|
||||
|
||||
// Small positive numbers round to zero
|
||||
const pos_result = f(0.3);
|
||||
try testing.expect(math.isPositiveZero(pos_result));
|
||||
|
||||
// Small negative numbers round to negative zero
|
||||
const neg_result = f(-0.3);
|
||||
try testing.expect(math.isNegativeZero(neg_result));
|
||||
|
||||
// Exact half rounds to nearest even (banker's rounding)
|
||||
try testing.expectEqual(@as(T, 2.0), f(2.5));
|
||||
try testing.expectEqual(@as(T, 4.0), f(3.5));
|
||||
}
|
||||
|
||||
test "rint" {
|
||||
try testRint(f32);
|
||||
try testRint(f64);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
const c = std.c;
|
||||
const testing = std.testing;
|
||||
|
||||
/// Not defined in `std.c` because C headers don't either.
|
||||
const Node = extern struct {
|
||||
next: ?*Node,
|
||||
prev: ?*Node,
|
||||
};
|
||||
|
||||
test "insque and remque" {
|
||||
if (builtin.target.os.tag == .windows) return; // no insque/remque
|
||||
|
||||
var first: Node = .{ .next = null, .prev = null };
|
||||
var second: Node = .{ .next = null, .prev = null };
|
||||
var third: Node = .{ .next = null, .prev = null };
|
||||
|
||||
c.insque(&first, null);
|
||||
try testing.expectEqual(@as(?*Node, null), first.next);
|
||||
try testing.expectEqual(@as(?*Node, null), first.prev);
|
||||
|
||||
c.insque(&second, &first);
|
||||
try testing.expectEqual(@as(?*Node, &second), first.next);
|
||||
try testing.expectEqual(@as(?*Node, &first), second.prev);
|
||||
|
||||
c.insque(&third, &first);
|
||||
try testing.expectEqual(@as(?*Node, &third), first.next);
|
||||
try testing.expectEqual(@as(?*Node, &second), third.next);
|
||||
try testing.expectEqual(@as(?*Node, &first), third.prev);
|
||||
try testing.expectEqual(@as(?*Node, &third), second.prev);
|
||||
|
||||
c.remque(&third);
|
||||
try testing.expectEqual(@as(?*Node, &second), first.next);
|
||||
try testing.expectEqual(@as(?*Node, &first), second.prev);
|
||||
|
||||
c.remque(&second);
|
||||
try testing.expectEqual(@as(?*Node, null), first.next);
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
const c = std.c;
|
||||
const fmt = std.fmt;
|
||||
const math = std.math;
|
||||
const testing = std.testing;
|
||||
|
||||
test "abs" {
|
||||
if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest; // TODO
|
||||
|
||||
const val: c_int = -10;
|
||||
try testing.expectEqual(10, c.abs(val));
|
||||
}
|
||||
|
||||
test "labs" {
|
||||
if (builtin.target.cpu.arch.isMIPS64() and @sizeOf(usize) == 4) return error.SkipZigTest; // TODO
|
||||
|
||||
const val: c_long = -10;
|
||||
try testing.expectEqual(10, c.labs(val));
|
||||
}
|
||||
|
||||
test "llabs" {
|
||||
const val: c_longlong = -10;
|
||||
try testing.expectEqual(10, c.llabs(val));
|
||||
}
|
||||
|
||||
test "div" {
|
||||
if (builtin.target.cpu.arch.isLoongArch()) return error.SkipZigTest; // TODO
|
||||
if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest; // TODO
|
||||
if (builtin.target.cpu.arch.isPowerPC()) return error.SkipZigTest; // TODO
|
||||
if (builtin.target.cpu.arch == .s390x) return error.SkipZigTest; // TODO
|
||||
|
||||
const expected: c.div_t = .{ .quot = 5, .rem = 5 };
|
||||
try testing.expectEqual(expected, c.div(55, 10));
|
||||
}
|
||||
|
||||
test "ldiv" {
|
||||
if (builtin.target.cpu.arch.isMIPS64() and @sizeOf(usize) == 4) return error.SkipZigTest; // TODO
|
||||
if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest; // TODO
|
||||
if (builtin.target.cpu.arch == .s390x) return error.SkipZigTest; // TODO
|
||||
|
||||
const expected: c.ldiv_t = .{ .quot = -6, .rem = 2 };
|
||||
try testing.expectEqual(expected, c.ldiv(38, -6));
|
||||
}
|
||||
|
||||
test "lldiv" {
|
||||
if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest; // TODO
|
||||
if (builtin.target.cpu.arch == .s390x) return error.SkipZigTest; // TODO
|
||||
|
||||
const expected: c.lldiv_t = .{ .quot = 1, .rem = 2 };
|
||||
try testing.expectEqual(expected, c.lldiv(5, 3));
|
||||
}
|
||||
|
||||
test "atoi" {
|
||||
try testing.expectEqual(0, c.atoi(@ptrCast("stop42true")));
|
||||
try testing.expectEqual(42, c.atoi(@ptrCast("42true")));
|
||||
try testing.expectEqual(-1, c.atoi(@ptrCast("-01")));
|
||||
try testing.expectEqual(1, c.atoi(@ptrCast("+001")));
|
||||
try testing.expectEqual(100, c.atoi(@ptrCast(" 100")));
|
||||
try testing.expectEqual(500, c.atoi(@ptrCast("000000000000500")));
|
||||
try testing.expectEqual(1111, c.atoi(@ptrCast("0000000000001111_0000")));
|
||||
try testing.expectEqual(0, c.atoi(@ptrCast("0xAA")));
|
||||
try testing.expectEqual(700, c.atoi(@ptrCast("700B")));
|
||||
try testing.expectEqual(32453, c.atoi(@ptrCast("+32453more")));
|
||||
try testing.expectEqual(math.maxInt(c_int), c.atoi(@ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_int)}))));
|
||||
try testing.expectEqual(math.minInt(c_int), c.atoi(@ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_int)}))));
|
||||
}
|
||||
|
||||
test "atol" {
|
||||
try testing.expectEqual(0, c.atol(@ptrCast("stop42true")));
|
||||
try testing.expectEqual(42, c.atol(@ptrCast("42true")));
|
||||
try testing.expectEqual(-1, c.atol(@ptrCast("-01")));
|
||||
try testing.expectEqual(1, c.atol(@ptrCast("+001")));
|
||||
try testing.expectEqual(100, c.atol(@ptrCast(" 100")));
|
||||
try testing.expectEqual(500, c.atol(@ptrCast("000000000000500")));
|
||||
try testing.expectEqual(1111, c.atol(@ptrCast("0000000000001111_0000")));
|
||||
try testing.expectEqual(0, c.atol(@ptrCast("0xAA")));
|
||||
try testing.expectEqual(700, c.atol(@ptrCast("700B")));
|
||||
try testing.expectEqual(32453, c.atol(@ptrCast("+32453more")));
|
||||
try testing.expectEqual(math.maxInt(c_long), c.atol(@ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_long)}))));
|
||||
try testing.expectEqual(math.minInt(c_long), c.atol(@ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_long)}))));
|
||||
}
|
||||
|
||||
test "atoll" {
|
||||
try testing.expectEqual(0, c.atoll(@ptrCast("stop42true")));
|
||||
try testing.expectEqual(42, c.atoll(@ptrCast("42true")));
|
||||
try testing.expectEqual(-1, c.atoll(@ptrCast("-01")));
|
||||
try testing.expectEqual(1, c.atoll(@ptrCast("+001")));
|
||||
try testing.expectEqual(100, c.atoll(@ptrCast(" 100")));
|
||||
try testing.expectEqual(500, c.atoll(@ptrCast("000000000000500")));
|
||||
try testing.expectEqual(1111, c.atoll(@ptrCast("0000000000001111_0000")));
|
||||
try testing.expectEqual(0, c.atoll(@ptrCast("0xAA")));
|
||||
try testing.expectEqual(700, c.atoll(@ptrCast("700B")));
|
||||
try testing.expectEqual(32453, c.atoll(@ptrCast(" +32453more")));
|
||||
try testing.expectEqual(math.maxInt(c_longlong), c.atoll(@ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_longlong)}))));
|
||||
try testing.expectEqual(math.minInt(c_longlong), c.atoll(@ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_longlong)}))));
|
||||
}
|
||||
|
||||
test "bsearch" {
|
||||
const Comparison = struct {
|
||||
pub fn compare(a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int {
|
||||
const a_u16: *const u16 = @ptrCast(@alignCast(a));
|
||||
const b_u16: *const u16 = @ptrCast(@alignCast(b));
|
||||
|
||||
return switch (math.order(a_u16.*, b_u16.*)) {
|
||||
.gt => 1,
|
||||
.eq => 0,
|
||||
.lt => -1,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const items: []const u16 = &.{ 0, 5, 7, 9, 10, 200, 512, 768 };
|
||||
|
||||
try testing.expectEqual(@as(?*anyopaque, null), c.bsearch(&@as(u16, 2000), items.ptr, items.len, @sizeOf(u16), Comparison.compare));
|
||||
|
||||
for (items) |*value| {
|
||||
try testing.expectEqual(@as(*const anyopaque, value), c.bsearch(value, items.ptr, items.len, @sizeOf(u16), Comparison.compare));
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
_ = @import("stdlib/drand48.zig");
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
const c = std.c;
|
||||
const testing = std.testing;
|
||||
|
||||
test "erand48" {
|
||||
if (builtin.target.os.tag == .windows) return; // no erand48
|
||||
|
||||
var xsubi: [3]c_ushort = .{ 37174, 64810, 11603 };
|
||||
|
||||
try testing.expectApproxEqAbs(0.8965, c.erand48(&xsubi), 0.0005);
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 22537, 47966, 58735 }, &xsubi);
|
||||
|
||||
try testing.expectApproxEqAbs(0.3375, c.erand48(&xsubi), 0.0005);
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 37344, 32911, 22119 }, &xsubi);
|
||||
|
||||
try testing.expectApproxEqAbs(0.6475, c.erand48(&xsubi), 0.0005);
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 23659, 29872, 42445 }, &xsubi);
|
||||
|
||||
try testing.expectApproxEqAbs(0.5005, c.erand48(&xsubi), 0.0005);
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 31642, 7875, 32802 }, &xsubi);
|
||||
|
||||
try testing.expectApproxEqAbs(0.5065, c.erand48(&xsubi), 0.0005);
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 64669, 14399, 33170 }, &xsubi);
|
||||
}
|
||||
|
||||
test "jrand48" {
|
||||
if (builtin.target.os.tag == .windows) return; // no jrand48
|
||||
|
||||
if (builtin.target.os.tag == .openbsd) return error.SkipZigTest; // TODO
|
||||
|
||||
var xsubi: [3]c_ushort = .{ 25175, 11052, 45015 };
|
||||
|
||||
try testing.expectEqual(1699503220, c.jrand48(&xsubi));
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 2326, 23668, 25932 }, &xsubi);
|
||||
|
||||
try testing.expectEqual(-992276007, c.jrand48(&xsubi));
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 41577, 4569, 50395 }, &xsubi);
|
||||
|
||||
try testing.expectEqual(-19535776, c.jrand48(&xsubi));
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 31936, 59488, 65237 }, &xsubi);
|
||||
|
||||
try testing.expectEqual(79438377, c.jrand48(&xsubi));
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 40395, 8745, 1212 }, &xsubi);
|
||||
|
||||
try testing.expectEqual(-1258917728, c.jrand48(&xsubi));
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 37242, 28832, 46326 }, &xsubi);
|
||||
}
|
||||
|
||||
test "nrand48" {
|
||||
if (builtin.target.os.tag == .windows) return; // no nrand48
|
||||
|
||||
var xsubi: [3]c_ushort = .{ 546, 33817, 23389 };
|
||||
|
||||
try testing.expectEqual(914920692, c.nrand48(&xsubi));
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 29829, 10728, 27921 }, &xsubi);
|
||||
|
||||
try testing.expectEqual(754104482, c.nrand48(&xsubi));
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 6828, 28997, 23013 }, &xsubi);
|
||||
|
||||
try testing.expectEqual(609453945, c.nrand48(&xsubi));
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 58183, 3826, 18599 }, &xsubi);
|
||||
|
||||
try testing.expectEqual(1878644360, c.nrand48(&xsubi));
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 36678, 44304, 57331 }, &xsubi);
|
||||
|
||||
try testing.expectEqual(2114923686, c.nrand48(&xsubi));
|
||||
try testing.expectEqualSlices(c_ushort, &.{ 58585, 22861, 64542 }, &xsubi);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
const c = std.c;
|
||||
const testing = std.testing;
|
||||
|
||||
test "strncmp" {
|
||||
try testing.expect(c.strncmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
|
||||
try testing.expect(c.strncmp(@ptrCast("a"), @ptrCast("c"), 1) < 0);
|
||||
try testing.expect(c.strncmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
|
||||
try testing.expect(c.strncmp(@ptrCast("\xff"), @ptrCast("\x02"), 1) > 0);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
const c = std.c;
|
||||
const mem = std.mem;
|
||||
const testing = std.testing;
|
||||
|
||||
test "bzero" {
|
||||
if (builtin.target.os.tag == .windows) return; // no bzero
|
||||
|
||||
var array: [10]u8 = [_]u8{ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
|
||||
var a = mem.zeroes([array.len]u8);
|
||||
a[9] = '0';
|
||||
c.bzero(&array[0], 9);
|
||||
try testing.expect(mem.eql(u8, &array, &a));
|
||||
}
|
||||
|
||||
fn testFfs(comptime T: type) !void {
|
||||
const ffs = switch (T) {
|
||||
c_int => c.ffs,
|
||||
c_long => c.ffsl,
|
||||
c_longlong => c.ffsll,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
try testing.expectEqual(0, ffs(0));
|
||||
|
||||
for (0..@bitSizeOf(T)) |i| {
|
||||
const bit = @as(T, 1) << @intCast(i);
|
||||
|
||||
try testing.expectEqual(@as(T, @intCast(i + 1)), ffs(bit));
|
||||
}
|
||||
}
|
||||
|
||||
test "ffs" {
|
||||
if (builtin.target.os.tag == .openbsd) return; // no ffsl/ffsll
|
||||
if (builtin.target.os.tag == .windows) return; // no ffs
|
||||
|
||||
try testFfs(c_int);
|
||||
|
||||
if (builtin.target.os.tag == .netbsd) return; // no ffsl/ffsll until 11
|
||||
|
||||
try testFfs(c_long);
|
||||
|
||||
if (@sizeOf(usize) == 4) return error.SkipZigTest; // TODO
|
||||
|
||||
try testFfs(c_longlong);
|
||||
}
|
||||
|
||||
test "strcasecmp" {
|
||||
try testing.expect(c.strcasecmp(@ptrCast("a"), @ptrCast("b")) < 0);
|
||||
try testing.expect(c.strcasecmp(@ptrCast("b"), @ptrCast("a")) > 0);
|
||||
try testing.expect(c.strcasecmp(@ptrCast("A"), @ptrCast("b")) < 0);
|
||||
try testing.expect(c.strcasecmp(@ptrCast("b"), @ptrCast("A")) > 0);
|
||||
try testing.expect(c.strcasecmp(@ptrCast("A"), @ptrCast("A")) == 0);
|
||||
try testing.expect(c.strcasecmp(@ptrCast("B"), @ptrCast("b")) == 0);
|
||||
try testing.expect(c.strcasecmp(@ptrCast("bb"), @ptrCast("AA")) > 0);
|
||||
}
|
||||
|
||||
test "strncasecmp" {
|
||||
try testing.expect(c.strncasecmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
|
||||
try testing.expect(c.strncasecmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
|
||||
try testing.expect(c.strncasecmp(@ptrCast("A"), @ptrCast("b"), 1) < 0);
|
||||
try testing.expect(c.strncasecmp(@ptrCast("b"), @ptrCast("A"), 1) > 0);
|
||||
try testing.expect(c.strncasecmp(@ptrCast("A"), @ptrCast("A"), 1) == 0);
|
||||
try testing.expect(c.strncasecmp(@ptrCast("B"), @ptrCast("b"), 1) == 0);
|
||||
try testing.expect(c.strncasecmp(@ptrCast("bb"), @ptrCast("AA"), 2) > 0);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
|
||||
const c = std.c;
|
||||
const testing = std.testing;
|
||||
|
||||
test "swab" {
|
||||
if (builtin.target.cpu.arch.isMIPS64() and @sizeOf(usize) == 4) return error.SkipZigTest; // TODO
|
||||
if (builtin.target.cpu.arch == .x86_64 and @sizeOf(usize) == 4) return error.SkipZigTest; // TODO
|
||||
if (builtin.target.os.tag == .netbsd) return error.SkipZigTest; // TODO
|
||||
|
||||
var a: [4]u8 = undefined;
|
||||
@memset(a[0..], '\x00');
|
||||
c.swab("abcd", &a, 4);
|
||||
try testing.expectEqualSlices(u8, "badc", &a);
|
||||
|
||||
// Partial copy
|
||||
@memset(a[0..], '\x00');
|
||||
c.swab("abcd", &a, 2);
|
||||
try testing.expectEqualSlices(u8, "ba\x00\x00", &a);
|
||||
|
||||
// n < 1
|
||||
@memset(a[0..], '\x00');
|
||||
c.swab("abcd", &a, 0);
|
||||
try testing.expectEqualSlices(u8, "\x00" ** 4, &a);
|
||||
c.swab("abcd", &a, -1);
|
||||
try testing.expectEqualSlices(u8, "\x00" ** 4, &a);
|
||||
|
||||
// Odd n
|
||||
@memset(a[0..], '\x00');
|
||||
c.swab("abcd", &a, 1);
|
||||
try testing.expectEqualSlices(u8, "\x00" ** 4, &a);
|
||||
c.swab("abcd", &a, 3);
|
||||
try testing.expectEqualSlices(u8, "ba\x00\x00", &a);
|
||||
}
|
||||
@@ -58,10 +58,7 @@ fn addCaseTarget(
|
||||
.fuchsia => false,
|
||||
else => true,
|
||||
};
|
||||
const both_libc = switch (target.result.os.tag) {
|
||||
.freebsd, .netbsd, .openbsd => false,
|
||||
else => !target.result.requiresLibC(),
|
||||
};
|
||||
const both_libc = !std.os.targetRequiresLibC(&target.result);
|
||||
|
||||
// See `std.debug.StackIterator.fp_usability` logic.
|
||||
const fp_usability: enum { useless, unsafe, safe, ideal } = switch (target.result.cpu.arch) {
|
||||
|
||||
+23
-42
@@ -18,7 +18,7 @@ pub const DebuggerContext = @import("src/Debugger.zig");
|
||||
pub const LlvmIrContext = @import("src/LlvmIr.zig");
|
||||
pub const LibcContext = @import("src/Libc.zig");
|
||||
|
||||
const TestTarget = struct {
|
||||
const ModuleTestTarget = struct {
|
||||
linkage: ?std.builtin.LinkMode = null,
|
||||
target: std.Target.Query = .{},
|
||||
optimize_mode: std.builtin.OptimizeMode = .Debug,
|
||||
@@ -36,33 +36,14 @@ const TestTarget = struct {
|
||||
// invocation. This could be because of a slow backend, requiring a newer LLVM version, being
|
||||
// too niche, etc.
|
||||
extra_target: bool = false,
|
||||
|
||||
pub fn supportsModule(
|
||||
self: *const TestTarget,
|
||||
target: *const std.Build.ResolvedTarget,
|
||||
name: []const u8,
|
||||
) bool {
|
||||
if (mem.eql(u8, name, "zigc")) {
|
||||
if (target.result.isMuslLibC()) return self.linkage == .static or (self.linkage == null and !target.query.isNative());
|
||||
if (target.result.isMinGW()) return true;
|
||||
if (target.result.isWasiLibC()) return true;
|
||||
return false;
|
||||
}
|
||||
if (mem.eql(u8, name, "std")) {
|
||||
if (target.result.cpu.arch.isSpirV()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const test_targets = blk: {
|
||||
const module_test_targets = blk: {
|
||||
// getBaselineCpuFeatures calls populateDependencies which has a O(N ^ 2) algorithm
|
||||
// (where N is roughly 160, which technically makes it O(1), but it adds up to a
|
||||
// lot of branches)
|
||||
@setEvalBranchQuota(80_000);
|
||||
break :blk [_]TestTarget{
|
||||
break :blk [_]ModuleTestTarget{
|
||||
// Native Targets
|
||||
|
||||
.{}, // 0 index must be all defaults
|
||||
@@ -2475,24 +2456,21 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
|
||||
const step = b.step(b.fmt("test-{s}", .{options.name}), options.desc);
|
||||
|
||||
if (options.test_only) |test_only| {
|
||||
const test_target: TestTarget = switch (test_only) {
|
||||
.default => test_targets[0],
|
||||
const test_target: ModuleTestTarget = switch (test_only) {
|
||||
.default => module_test_targets[0],
|
||||
.fuzz => |optimize| .{
|
||||
.optimize_mode = optimize,
|
||||
.use_llvm = true,
|
||||
},
|
||||
};
|
||||
const resolved_target = b.resolveTargetQuery(test_target.target);
|
||||
|
||||
if (test_target.supportsModule(&resolved_target, options.name)) {
|
||||
const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
|
||||
addOneModuleTest(b, step, test_target, &resolved_target, triple_txt, options);
|
||||
}
|
||||
const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
|
||||
addOneModuleTest(b, step, test_target, &resolved_target, triple_txt, options);
|
||||
|
||||
return step;
|
||||
}
|
||||
|
||||
for_targets: for (test_targets) |test_target| {
|
||||
for_targets: for (module_test_targets) |test_target| {
|
||||
if (test_target.skip_modules.len > 0) {
|
||||
for (test_target.skip_modules) |skip_mod| {
|
||||
if (std.mem.eql(u8, options.name, skip_mod)) continue :for_targets;
|
||||
@@ -2501,8 +2479,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
|
||||
|
||||
const resolved_target = b.resolveTargetQuery(test_target.target);
|
||||
|
||||
if (!test_target.supportsModule(&resolved_target, options.name)) continue;
|
||||
|
||||
if (!options.test_extra_targets and test_target.extra_target) continue;
|
||||
|
||||
if (options.skip_non_native and !test_target.target.isNative())
|
||||
@@ -2510,6 +2486,13 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
|
||||
|
||||
const target = &resolved_target.result;
|
||||
|
||||
if (std.mem.eql(u8, options.name, "libc")) {
|
||||
// The libc API tests obviously need to link libc. So for test
|
||||
// target entries where we wouldn't link libc by default, skip the
|
||||
// libc API tests.
|
||||
if (test_target.link_libc == null and !std.os.targetRequiresLibC(target)) continue;
|
||||
}
|
||||
|
||||
if (options.skip_spirv and target.cpu.arch.isSpirV()) continue;
|
||||
if (options.skip_wasm and target.cpu.arch.isWasm()) continue;
|
||||
|
||||
@@ -2531,7 +2514,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
|
||||
} else continue;
|
||||
}
|
||||
|
||||
if (options.skip_libc and test_target.link_libc == true)
|
||||
if (options.skip_libc and (test_target.link_libc == true or std.os.targetRequiresLibC(target)))
|
||||
continue;
|
||||
|
||||
// We can't provide MSVC libc when cross-compiling.
|
||||
@@ -2544,8 +2527,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
|
||||
if (!would_use_llvm and target.cpu.arch == .aarch64) {
|
||||
// TODO get std tests passing for the aarch64 self-hosted backend.
|
||||
if (mem.eql(u8, options.name, "std")) continue;
|
||||
// TODO get zigc tests passing for the aarch64 self-hosted backend.
|
||||
if (mem.eql(u8, options.name, "zigc")) continue;
|
||||
}
|
||||
|
||||
const want_this_mode = for (options.optimize_modes) |m| {
|
||||
@@ -2561,7 +2542,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
|
||||
fn addOneModuleTest(
|
||||
b: *std.Build,
|
||||
step: *Step,
|
||||
test_target: TestTarget,
|
||||
test_target: ModuleTestTarget,
|
||||
resolved_target: *const std.Build.ResolvedTarget,
|
||||
triple_txt: []const u8,
|
||||
options: ModuleTestOptions,
|
||||
@@ -2598,11 +2579,11 @@ fn addOneModuleTest(
|
||||
});
|
||||
these_tests.linkage = test_target.linkage;
|
||||
// https://codeberg.org/ziglang/zig/issues/31701
|
||||
if (!(mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "zigc"))) {
|
||||
if (!(mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "libc"))) {
|
||||
if (options.no_builtin) these_tests.root_module.no_builtin = true;
|
||||
}
|
||||
// https://codeberg.org/ziglang/zig/issues/31702
|
||||
if (mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "zigc")) {
|
||||
if (mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "libc")) {
|
||||
these_tests.root_module.stack_protector = false;
|
||||
}
|
||||
if (options.build_options) |build_options| {
|
||||
@@ -2992,7 +2973,7 @@ pub fn addLlvmIrTests(b: *std.Build, options: LlvmIrContext.Options) ?*Step {
|
||||
return step;
|
||||
}
|
||||
|
||||
const libc_targets: []const std.Target.Query = &.{
|
||||
const libc_test_nsz_targets: []const std.Target.Query = &.{
|
||||
.{
|
||||
.cpu_arch = .arm,
|
||||
.os_tag = .linux,
|
||||
@@ -3155,8 +3136,8 @@ const libc_targets: []const std.Target.Query = &.{
|
||||
},
|
||||
};
|
||||
|
||||
pub fn addLibcTests(b: *std.Build, options: LibcContext.Options) ?*Step {
|
||||
const step = b.step("test-libc", "Run libc-test test cases");
|
||||
pub fn addLibcTestNszTests(b: *std.Build, options: LibcContext.Options) ?*Step {
|
||||
const step = b.step("test-libc-nsz", "Run external libc-test test cases");
|
||||
const opt_libc_test_path = b.option(std.Build.LazyPath, "libc-test-path", "path to libc-test source directory");
|
||||
if (opt_libc_test_path) |libc_test_path| {
|
||||
var context: LibcContext = .{
|
||||
@@ -3168,7 +3149,7 @@ pub fn addLibcTests(b: *std.Build, options: LibcContext.Options) ?*Step {
|
||||
|
||||
libc.addCases(&context);
|
||||
|
||||
for (libc_targets) |target_query| {
|
||||
for (libc_test_nsz_targets) |target_query| {
|
||||
const target = b.resolveTargetQuery(target_query);
|
||||
context.addTarget(target);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user