authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-03-27 11:14:02+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-04-17 12:10:37+02:00
log7ea8f842bc65cdaf046483b2bfe7948ebad16516
tree59efc2b3a0dea8ee5bc2070110d95f85bae8a64c
parent3e1e625814165d9d9282f3cd89bc117cf1b6d61c
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

libzigc: move all unit tests from lib/c/ to test/c/

Before: * test-zigc: run libzigc unit tests (part of test-modules) * test-libc: run libc-test cases Now: * test-libc: run libc API unit tests (part of test-modules) * test-libc-nsz: run libc-test cases libc API unit tests (previously referred to as libzigc unit tests) now run for all supported targets, even those we don't provide libzigc for. The idea is that this will help us catch bad assumptions in the unit tests, as well as bugs in other libcs. I considered this setup: * test-c: run libc API unit tests (part of test-modules) * test-libc-nsz: run libc-test cases * test-libc: both of the above However, I do not like it because it gives a false sense of security; the full module and C ABI test suites are still liable to catch libzigc bugs that test-c and test-libc-nsz might not. So contributors should just run the test steps outlined in https://codeberg.org/ziglang/zig/issues/30978. Co-authored-by: rpkak <rpkak@noreply.codeberg.org>

21 files changed, 530 insertions(+), 430 deletions(-)

build.zig+16-16
......@@ -526,16 +526,16 @@ pub fn build(b: *std.Build) !void {
526526 .test_filters = test_filters,
527527 .test_target_filters = test_target_filters,
528528 .test_extra_targets = test_extra_targets,
529 .root_src = "lib/c.zig",
530 .name = "zigc",
531 .desc = "Run the zig libc implementation unit tests",
529 .root_src = "lib/std/std.zig",
530 .name = "std",
531 .desc = "Run the standard library tests",
532532 .optimize_modes = optimization_modes,
533533 .include_paths = &.{},
534534 .sanitize_thread = sanitize_thread,
535 .skip_single_threaded = true,
535 .skip_single_threaded = skip_single_threaded,
536536 .skip_non_native = skip_non_native,
537537 .test_only = test_only,
538 .skip_spirv = skip_spirv,
538 .skip_spirv = true,
539539 .skip_wasm = skip_wasm,
540540 .skip_freebsd = skip_freebsd,
541541 .skip_netbsd = skip_netbsd,
......@@ -544,25 +544,24 @@ pub fn build(b: *std.Build) !void {
544544 .skip_darwin = skip_darwin,
545545 .skip_linux = skip_linux,
546546 .skip_llvm = skip_llvm,
547 .skip_libc = true,
548 .no_builtin = true,
549 .max_rss = 4_000_000_000,
547 .skip_libc = skip_libc,
548 .max_rss = 9_300_000_000,
550549 }));
551550
552551 test_modules_step.dependOn(tests.addModuleTests(b, .{
553552 .test_filters = test_filters,
554553 .test_target_filters = test_target_filters,
555554 .test_extra_targets = test_extra_targets,
556 .root_src = "lib/std/std.zig",
557 .name = "std",
558 .desc = "Run the standard library tests",
555 .root_src = "test/c.zig",
556 .name = "libc",
557 .desc = "Run the libc API tests",
559558 .optimize_modes = optimization_modes,
560559 .include_paths = &.{},
561560 .sanitize_thread = sanitize_thread,
562 .skip_single_threaded = skip_single_threaded,
561 .skip_single_threaded = true,
563562 .skip_non_native = skip_non_native,
564563 .test_only = test_only,
565 .skip_spirv = skip_spirv,
564 .skip_spirv = true,
566565 .skip_wasm = skip_wasm,
567566 .skip_freebsd = skip_freebsd,
568567 .skip_netbsd = skip_netbsd,
......@@ -572,7 +571,8 @@ pub fn build(b: *std.Build) !void {
572571 .skip_linux = skip_linux,
573572 .skip_llvm = skip_llvm,
574573 .skip_libc = skip_libc,
575 .max_rss = 9_300_000_000,
574 .no_builtin = true,
575 .max_rss = 4_000_000_000,
576576 }));
577577
578578 const unit_tests_step = b.step("test-unit", "Run the compiler source unit tests");
......@@ -662,13 +662,13 @@ pub fn build(b: *std.Build) !void {
662662 try tests.addIncrementalTests(b, test_incremental_step, test_filters);
663663 if (!skip_test_incremental) test_step.dependOn(test_incremental_step);
664664
665 if (tests.addLibcTests(b, .{
665 if (tests.addLibcTestNszTests(b, .{
666666 .optimize_modes = optimization_modes,
667667 .test_filters = test_filters,
668668 .test_target_filters = test_target_filters,
669669 .skip_wasm = skip_wasm,
670670 .max_rss = 3_500_000_000,
671 })) |test_libc_step| test_step.dependOn(test_libc_step);
671 })) |test_libc_nsz_step| test_step.dependOn(test_libc_nsz_step);
672672}
673673
674674fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
lib/c.zig+1-2
......@@ -2,8 +2,7 @@
22//! bundled libcs.
33//!
44//! mingw-w64 libc is not fully statically linked, so some symbols don't need
5//! to be exported. However, a future enhancement could be eliminating Zig's
6//! dependency on msvcrt dll even when linking libc and targeting Windows.
5//! to be exported.
76
87const builtin = @import("builtin");
98const std = @import("std");
lib/c/inttypes.zig-10
......@@ -24,13 +24,3 @@ fn imaxdiv(a: intmax_t, b: intmax_t) callconv(.c) imaxdiv_t {
2424 .rem = @rem(a, b),
2525 };
2626}
27
28test imaxabs {
29 const val: intmax_t = -10;
30 try std.testing.expectEqual(10, imaxabs(val));
31}
32
33test imaxdiv {
34 const expected: imaxdiv_t = .{ .quot = 9, .rem = 0 };
35 try std.testing.expectEqual(expected, imaxdiv(9, 1));
36}
lib/c/math.zig-100
......@@ -2,10 +2,6 @@ const builtin = @import("builtin");
22
33const std = @import("std");
44const math = std.math;
5const expect = std.testing.expect;
6const expectEqual = std.testing.expectEqual;
7const expectApproxEqAbs = std.testing.expectApproxEqAbs;
8const expectApproxEqRel = std.testing.expectApproxEqRel;
95
106const symbol = @import("../c.zig").symbol;
117
......@@ -304,59 +300,6 @@ fn modfl(x: c_longdouble, iptr: *c_longdouble) callconv(.c) c_longdouble {
304300 };
305301}
306302
307fn testModf(comptime T: type) !void {
308 // Choose the appropriate `modf` impl to test based on type
309 const f = switch (T) {
310 f32 => modff,
311 f64 => modf,
312 c_longdouble => modfl,
313 else => @compileError("modf not implemented for " ++ @typeName(T)),
314 };
315
316 var int: T = undefined;
317 const iptr = &int;
318 const eps_val: comptime_float = @max(1e-6, math.floatEps(T));
319
320 const normal_frac = f(@as(T, 1234.567), iptr);
321 // Account for precision error
322 const expected = 1234.567 - @as(T, 1234);
323 try expectApproxEqAbs(expected, normal_frac, eps_val);
324 try expectApproxEqRel(@as(T, 1234.0), iptr.*, eps_val);
325
326 // When `x` is a NaN, NaN is returned and `*iptr` is set to NaN
327 const nan_frac = f(math.nan(T), iptr);
328 try expect(math.isNan(nan_frac));
329 try expect(math.isNan(iptr.*));
330
331 // When `x` is positive infinity, +0 is returned and `*iptr` is set to
332 // positive infinity
333 const pos_zero_frac = f(math.inf(T), iptr);
334 try expect(math.isPositiveZero(pos_zero_frac));
335 try expect(math.isPositiveInf(iptr.*));
336
337 // When `x` is negative infinity, -0 is returned and `*iptr` is set to
338 // negative infinity
339 const neg_zero_frac = f(-math.inf(T), iptr);
340 try expect(math.isNegativeZero(neg_zero_frac));
341 try expect(math.isNegativeInf(iptr.*));
342
343 // Return -0 when `x` is a negative integer
344 const nz_frac = f(@as(T, -1000.0), iptr);
345 try expect(math.isNegativeZero(nz_frac));
346 try expectEqual(@as(T, -1000.0), iptr.*);
347
348 // Return +0 when `x` is a positive integer
349 const pz_frac = f(@as(T, 1000.0), iptr);
350 try expect(math.isPositiveZero(pz_frac));
351 try expectEqual(@as(T, 1000.0), iptr.*);
352}
353
354test "modf" {
355 try testModf(f32);
356 try testModf(f64);
357 try testModf(c_longdouble);
358}
359
360303fn nan(_: [*:0]const c_char) callconv(.c) f64 {
361304 return math.nan(f64);
362305}
......@@ -421,49 +364,6 @@ fn rintf(x: f32) callconv(.c) f32 {
421364 return y;
422365}
423366
424fn testRint(comptime T: type) !void {
425 const f = switch (T) {
426 f32 => rintf,
427 f64 => rint,
428 else => @compileError("rint not implemented for" ++ @typeName(T)),
429 };
430
431 // Positive numbers round correctly
432 try expectEqual(@as(T, 42.0), f(42.2));
433 try expectEqual(@as(T, 42.0), f(41.8));
434
435 // Negative numbers round correctly
436 try expectEqual(@as(T, -6.0), f(-5.9));
437 try expectEqual(@as(T, -6.0), f(-6.1));
438
439 // No rounding needed test
440 try expectEqual(@as(T, 5.0), f(5.0));
441 try expectEqual(@as(T, -10.0), f(-10.0));
442 try expectEqual(@as(T, 0.0), f(0.0));
443
444 // Very large numbers return unchanged
445 const large: T = 9007199254740992.0; // 2^53
446 try expectEqual(large, f(large));
447 try expectEqual(-large, f(-large));
448
449 // Small positive numbers round to zero
450 const pos_result = f(0.3);
451 try expect(math.isPositiveZero(pos_result));
452
453 // Small negative numbers round to negative zero
454 const neg_result = f(-0.3);
455 try expect(math.isNegativeZero(neg_result));
456
457 // Exact half rounds to nearest even (banker's rounding)
458 try expectEqual(@as(T, 2.0), f(2.5));
459 try expectEqual(@as(T, 4.0), f(3.5));
460}
461
462test "rint" {
463 try testRint(f32);
464 try testRint(f64);
465}
466
467367fn tanh(x: f64) callconv(.c) f64 {
468368 return math.tanh(x);
469369}
lib/c/search.zig+1-27
......@@ -9,6 +9,7 @@ comptime {
99 }
1010}
1111
12/// Not defined in `std.c` because C headers don't either.
1213const Node = extern struct {
1314 next: ?*Node,
1415 prev: ?*Node,
......@@ -38,30 +39,3 @@ fn remque(element: *anyopaque) callconv(.c) void {
3839 if (e.next) |next| next.prev = e.prev;
3940 if (e.prev) |prev| prev.next = e.next;
4041}
41
42test "insque and remque" {
43 var first = Node{ .next = null, .prev = null };
44 var second = Node{ .next = null, .prev = null };
45 var third = Node{ .next = null, .prev = null };
46
47 insque(&first, null);
48 try std.testing.expectEqual(@as(?*Node, null), first.next);
49 try std.testing.expectEqual(@as(?*Node, null), first.prev);
50
51 insque(&second, &first);
52 try std.testing.expectEqual(@as(?*Node, &second), first.next);
53 try std.testing.expectEqual(@as(?*Node, &first), second.prev);
54
55 insque(&third, &first);
56 try std.testing.expectEqual(@as(?*Node, &third), first.next);
57 try std.testing.expectEqual(@as(?*Node, &second), third.next);
58 try std.testing.expectEqual(@as(?*Node, &first), third.prev);
59 try std.testing.expectEqual(@as(?*Node, &third), second.prev);
60
61 remque(&third);
62 try std.testing.expectEqual(@as(?*Node, &second), first.next);
63 try std.testing.expectEqual(@as(?*Node, &first), second.prev);
64
65 remque(&second);
66 try std.testing.expectEqual(@as(?*Node, null), first.next);
67}
lib/c/stdlib.zig-100
......@@ -294,103 +294,3 @@ fn bsearch(key: *const anyopaque, base: *const anyopaque, n: usize, size: usize,
294294 }
295295 return null;
296296}
297
298test abs {
299 const val: c_int = -10;
300 try std.testing.expectEqual(10, abs(val));
301}
302
303test labs {
304 const val: c_long = -10;
305 try std.testing.expectEqual(10, labs(val));
306}
307
308test llabs {
309 const val: c_longlong = -10;
310 try std.testing.expectEqual(10, llabs(val));
311}
312
313test div {
314 const expected: div_t = .{ .quot = 5, .rem = 5 };
315 try std.testing.expectEqual(expected, div(55, 10));
316}
317
318test ldiv {
319 const expected: ldiv_t = .{ .quot = -6, .rem = 2 };
320 try std.testing.expectEqual(expected, ldiv(38, -6));
321}
322
323test lldiv {
324 const expected: lldiv_t = .{ .quot = 1, .rem = 2 };
325 try std.testing.expectEqual(expected, lldiv(5, 3));
326}
327
328test atoi {
329 try std.testing.expectEqual(0, atoi(@ptrCast("stop42true")));
330 try std.testing.expectEqual(42, atoi(@ptrCast("42true")));
331 try std.testing.expectEqual(-1, atoi(@ptrCast("-01")));
332 try std.testing.expectEqual(1, atoi(@ptrCast("+001")));
333 try std.testing.expectEqual(100, atoi(@ptrCast(" 100")));
334 try std.testing.expectEqual(500, atoi(@ptrCast("000000000000500")));
335 try std.testing.expectEqual(1111, atoi(@ptrCast("0000000000001111_0000")));
336 try std.testing.expectEqual(0, atoi(@ptrCast("0xAA")));
337 try std.testing.expectEqual(700, atoi(@ptrCast("700B")));
338 try std.testing.expectEqual(32453, atoi(@ptrCast("+32453more")));
339 try std.testing.expectEqual(std.math.maxInt(c_int), atoi(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.maxInt(c_int)}))));
340 try std.testing.expectEqual(std.math.minInt(c_int), atoi(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.minInt(c_int)}))));
341}
342
343test atol {
344 try std.testing.expectEqual(0, atol(@ptrCast("stop42true")));
345 try std.testing.expectEqual(42, atol(@ptrCast("42true")));
346 try std.testing.expectEqual(-1, atol(@ptrCast("-01")));
347 try std.testing.expectEqual(1, atol(@ptrCast("+001")));
348 try std.testing.expectEqual(100, atol(@ptrCast(" 100")));
349 try std.testing.expectEqual(500, atol(@ptrCast("000000000000500")));
350 try std.testing.expectEqual(1111, atol(@ptrCast("0000000000001111_0000")));
351 try std.testing.expectEqual(0, atol(@ptrCast("0xAA")));
352 try std.testing.expectEqual(700, atol(@ptrCast("700B")));
353 try std.testing.expectEqual(32453, atol(@ptrCast("+32453more")));
354 try std.testing.expectEqual(std.math.maxInt(c_long), atol(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.maxInt(c_long)}))));
355 try std.testing.expectEqual(std.math.minInt(c_long), atol(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.minInt(c_long)}))));
356}
357
358test atoll {
359 try std.testing.expectEqual(0, atoll(@ptrCast("stop42true")));
360 try std.testing.expectEqual(42, atoll(@ptrCast("42true")));
361 try std.testing.expectEqual(-1, atoll(@ptrCast("-01")));
362 try std.testing.expectEqual(1, atoll(@ptrCast("+001")));
363 try std.testing.expectEqual(100, atoll(@ptrCast(" 100")));
364 try std.testing.expectEqual(500, atoll(@ptrCast("000000000000500")));
365 try std.testing.expectEqual(1111, atoll(@ptrCast("0000000000001111_0000")));
366 try std.testing.expectEqual(0, atoll(@ptrCast("0xAA")));
367 try std.testing.expectEqual(700, atoll(@ptrCast("700B")));
368 try std.testing.expectEqual(32453, atoll(@ptrCast(" +32453more")));
369 try std.testing.expectEqual(std.math.maxInt(c_longlong), atoll(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.maxInt(c_longlong)}))));
370 try std.testing.expectEqual(std.math.minInt(c_longlong), atoll(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.minInt(c_longlong)}))));
371}
372
373// FIXME: We cannot test strtol, strtoll, strtoul, etc.. here as it must modify errno and libc is not linked in tests
374
375test bsearch {
376 const Comparison = struct {
377 pub fn compare(a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int {
378 const a_u16: *const u16 = @ptrCast(@alignCast(a));
379 const b_u16: *const u16 = @ptrCast(@alignCast(b));
380
381 return switch (std.math.order(a_u16.*, b_u16.*)) {
382 .gt => 1,
383 .eq => 0,
384 .lt => -1,
385 };
386 }
387 };
388
389 const items: []const u16 = &.{ 0, 5, 7, 9, 10, 200, 512, 768 };
390
391 try std.testing.expectEqual(@as(?*anyopaque, null), bsearch(&@as(u16, 2000), items.ptr, items.len, @sizeOf(u16), Comparison.compare));
392
393 for (items) |*value| {
394 try std.testing.expectEqual(@as(*const anyopaque, value), bsearch(value, items.ptr, items.len, @sizeOf(u16), Comparison.compare));
395 }
396}
lib/c/stdlib/drand48.zig-57
......@@ -90,60 +90,3 @@ fn srand48(seedval: c_long) callconv(.c) void {
9090 const xi = (@as(u32, @truncate(@as(c_ulong, @bitCast(seedval)))) << 16) | 0x330E;
9191 lcg = .init(xi, default_multiplier, default_addend);
9292}
93
94test erand48 {
95 var xsubi: [3]c_ushort = .{ 37174, 64810, 11603 };
96
97 try std.testing.expectApproxEqAbs(0.8965, erand48(&xsubi), 0.0005);
98 try std.testing.expectEqualSlices(c_ushort, &.{ 22537, 47966, 58735 }, &xsubi);
99
100 try std.testing.expectApproxEqAbs(0.3375, erand48(&xsubi), 0.0005);
101 try std.testing.expectEqualSlices(c_ushort, &.{ 37344, 32911, 22119 }, &xsubi);
102
103 try std.testing.expectApproxEqAbs(0.6475, erand48(&xsubi), 0.0005);
104 try std.testing.expectEqualSlices(c_ushort, &.{ 23659, 29872, 42445 }, &xsubi);
105
106 try std.testing.expectApproxEqAbs(0.5005, erand48(&xsubi), 0.0005);
107 try std.testing.expectEqualSlices(c_ushort, &.{ 31642, 7875, 32802 }, &xsubi);
108
109 try std.testing.expectApproxEqAbs(0.5065, erand48(&xsubi), 0.0005);
110 try std.testing.expectEqualSlices(c_ushort, &.{ 64669, 14399, 33170 }, &xsubi);
111}
112
113test jrand48 {
114 var xsubi: [3]c_ushort = .{ 25175, 11052, 45015 };
115
116 try std.testing.expectEqual(1699503220, jrand48(&xsubi));
117 try std.testing.expectEqualSlices(c_ushort, &.{ 2326, 23668, 25932 }, &xsubi);
118
119 try std.testing.expectEqual(-992276007, jrand48(&xsubi));
120 try std.testing.expectEqualSlices(c_ushort, &.{ 41577, 4569, 50395 }, &xsubi);
121
122 try std.testing.expectEqual(-19535776, jrand48(&xsubi));
123 try std.testing.expectEqualSlices(c_ushort, &.{ 31936, 59488, 65237 }, &xsubi);
124
125 try std.testing.expectEqual(79438377, jrand48(&xsubi));
126 try std.testing.expectEqualSlices(c_ushort, &.{ 40395, 8745, 1212 }, &xsubi);
127
128 try std.testing.expectEqual(-1258917728, jrand48(&xsubi));
129 try std.testing.expectEqualSlices(c_ushort, &.{ 37242, 28832, 46326 }, &xsubi);
130}
131
132test nrand48 {
133 var xsubi: [3]c_ushort = .{ 546, 33817, 23389 };
134
135 try std.testing.expectEqual(914920692, nrand48(&xsubi));
136 try std.testing.expectEqualSlices(c_ushort, &.{ 29829, 10728, 27921 }, &xsubi);
137
138 try std.testing.expectEqual(754104482, nrand48(&xsubi));
139 try std.testing.expectEqualSlices(c_ushort, &.{ 6828, 28997, 23013 }, &xsubi);
140
141 try std.testing.expectEqual(609453945, nrand48(&xsubi));
142 try std.testing.expectEqualSlices(c_ushort, &.{ 58183, 3826, 18599 }, &xsubi);
143
144 try std.testing.expectEqual(1878644360, nrand48(&xsubi));
145 try std.testing.expectEqualSlices(c_ushort, &.{ 36678, 44304, 57331 }, &xsubi);
146
147 try std.testing.expectEqual(2114923686, nrand48(&xsubi));
148 try std.testing.expectEqualSlices(c_ushort, &.{ 58585, 22861, 64542 }, &xsubi);
149}
lib/c/string.zig-7
......@@ -290,10 +290,3 @@ fn mempcpy(noalias dst: *anyopaque, noalias src: *const anyopaque, len: usize) c
290290 @memcpy(dst_bytes[0..len], src_bytes[0..len]);
291291 return dst_bytes + len;
292292}
293
294test strncmp {
295 try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
296 try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("c"), 1) < 0);
297 try std.testing.expect(strncmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
298 try std.testing.expect(strncmp(@ptrCast("\xff"), @ptrCast("\x02"), 1) > 0);
299}
lib/c/strings.zig-38
......@@ -81,41 +81,3 @@ fn __strncasecmp_l(a: [*:0]const c_char, b: [*:0]const c_char, n: usize, locale:
8181 _ = locale;
8282 return strncasecmp(a, b, n);
8383}
84
85test bzero {
86 var array: [10]u8 = [_]u8{ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
87 var a = std.mem.zeroes([array.len]u8);
88 a[9] = '0';
89 bzero(&array[0], 9);
90 try std.testing.expect(std.mem.eql(u8, &array, &a));
91}
92
93test firstBitSet {
94 try std.testing.expectEqual(0, firstBitSet(usize, 0));
95
96 for (0..@bitSizeOf(usize)) |i| {
97 const bit = @as(usize, 1) << @intCast(i);
98
99 try std.testing.expectEqual(i + 1, firstBitSet(usize, bit));
100 }
101}
102
103test strcasecmp {
104 try std.testing.expect(strcasecmp(@ptrCast("a"), @ptrCast("b")) < 0);
105 try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("a")) > 0);
106 try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("b")) < 0);
107 try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("A")) > 0);
108 try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("A")) == 0);
109 try std.testing.expect(strcasecmp(@ptrCast("B"), @ptrCast("b")) == 0);
110 try std.testing.expect(strcasecmp(@ptrCast("bb"), @ptrCast("AA")) > 0);
111}
112
113test strncasecmp {
114 try std.testing.expect(strncasecmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
115 try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
116 try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("b"), 1) < 0);
117 try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("A"), 1) > 0);
118 try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("A"), 1) == 0);
119 try std.testing.expect(strncasecmp(@ptrCast("B"), @ptrCast("b"), 1) == 0);
120 try std.testing.expect(strncasecmp(@ptrCast("bb"), @ptrCast("AA"), 2) > 0);
121}
lib/c/unistd.zig-26
......@@ -206,32 +206,6 @@ fn swab(noalias src_ptr: *const anyopaque, noalias dest_ptr: *anyopaque, n: isiz
206206 }
207207}
208208
209test swab {
210 var a: [4]u8 = undefined;
211 @memset(a[0..], '\x00');
212 swab("abcd", &a, 4);
213 try std.testing.expectEqualSlices(u8, "badc", &a);
214
215 // Partial copy
216 @memset(a[0..], '\x00');
217 swab("abcd", &a, 2);
218 try std.testing.expectEqualSlices(u8, "ba\x00\x00", &a);
219
220 // n < 1
221 @memset(a[0..], '\x00');
222 swab("abcd", &a, 0);
223 try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a);
224 swab("abcd", &a, -1);
225 try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a);
226
227 // Odd n
228 @memset(a[0..], '\x00');
229 swab("abcd", &a, 1);
230 try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a);
231 swab("abcd", &a, 3);
232 try std.testing.expectEqualSlices(u8, "ba\x00\x00", &a);
233}
234
235209fn close(fd: std.c.fd_t) callconv(.c) c_int {
236210 const signed: isize = @bitCast(linux.close(fd));
237211 if (signed < 0) {
lib/std/c.zig+53-6
......@@ -11102,13 +11102,60 @@ pub const ioctl = switch (native_os) {
1110211102 else => private.ioctl,
1110311103};
1110411104
11105pub extern "c" fn bzero(s: *anyopaque, n: usize) void;
11106
11107pub extern "c" fn swab(noalias from: *const anyopaque, noalias to: *anyopaque, n: isize) void;
11108
11109pub extern "c" fn strncmp(a: [*:0]const c_char, b: [*:0]const c_char, max: usize) c_int;
11110pub extern "c" fn strcasecmp(a: [*:0]const c_char, b: [*:0]const c_char) c_int;
11111pub extern "c" fn strncasecmp(a: [*:0]const c_char, b: [*:0]const c_char, max: usize) c_int;
11112
11113pub extern "c" fn ffs(i: c_int) c_int;
11114pub extern "c" fn ffsl(i: c_long) c_long;
11115pub extern "c" fn ffsll(i: c_longlong) c_longlong;
11116
11117pub extern "c" fn erand48(xsubi: *[3]c_ushort) f64;
11118pub extern "c" fn jrand48(xsubi: *[3]c_ushort) c_long;
11119pub extern "c" fn nrand48(xsubi: *[3]c_ushort) c_long;
11120
11121pub extern "c" fn insque(element: *anyopaque, pred: ?*anyopaque) void;
11122pub extern "c" fn remque(element: *anyopaque) void;
11123
11124pub extern "c" fn imaxabs(a: intmax_t) intmax_t;
11125pub extern "c" fn imaxdiv(a: intmax_t, b: intmax_t) imaxdiv_t;
11126
11127pub extern "c" fn abs(a: c_int) c_int;
11128pub extern "c" fn labs(a: c_long) c_long;
11129pub extern "c" fn llabs(a: c_longlong) c_longlong;
11130
11131pub extern "c" fn div(a: c_int, b: c_int) div_t;
11132pub extern "c" fn ldiv(a: c_long, b: c_long) ldiv_t;
11133pub extern "c" fn lldiv(a: c_longlong, b: c_longlong) lldiv_t;
11134
11135pub extern "c" fn atoi(str: [*:0]const c_char) c_int;
11136pub extern "c" fn atol(str: [*:0]const c_char) c_long;
11137pub extern "c" fn atoll(str: [*:0]const c_char) c_longlong;
11138
11139pub extern "c" fn bsearch(
11140 key: *const anyopaque,
11141 base: *const anyopaque,
11142 n: usize,
11143 size: usize,
11144 compare: *const fn (a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int,
11145) ?*anyopaque;
11146
1110511147// Math
11106pub extern "c" fn atan(x: f64) callconv(.c) f64;
11107pub extern "c" fn copysign(x: f64, y: f64) callconv(.c) f64;
11108pub extern "c" fn fdim(x: f64, y: f64) callconv(.c) f64;
11109pub extern "c" fn frexp(x: f64, e: *c_int) callconv(.c) f64;
11110pub extern "c" fn hypot(x: f64, y: f64) callconv(.c) f64;
11111pub extern "c" fn modf(x: f64, iptr: *f64) callconv(.c) f64;
11148pub extern "c" fn atan(x: f64) f64;
11149pub extern "c" fn copysign(x: f64, y: f64) f64;
11150pub extern "c" fn fdim(x: f64, y: f64) f64;
11151pub extern "c" fn frexp(x: f64, e: *c_int) f64;
11152pub extern "c" fn hypot(x: f64, y: f64) f64;
11153pub extern "c" fn modff(x: f32, iptr: *f32) f32;
11154pub extern "c" fn modf(x: f64, iptr: *f64) f64;
11155pub extern "c" fn modfl(x: c_longdouble, iptr: *c_longdouble) c_longdouble;
11156pub extern "c" fn rintf(x: f32) f32;
11157pub extern "c" fn rint(x: f64) f64;
11158pub extern "c" fn rintl(x: c_longdouble) c_longdouble;
1111211159
1111311160// OS-specific bits. These are protected from being used on the wrong OS by
1111411161// comptime assertions inside each OS-specific file.
test/c.zig created+12
......@@ -0,0 +1,12 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4test {
5 _ = @import("c/inttypes.zig");
6 _ = @import("c/math.zig");
7 _ = @import("c/search.zig");
8 _ = @import("c/stdlib.zig");
9 _ = @import("c/string.zig");
10 _ = @import("c/strings.zig");
11 _ = @import("c/unistd.zig");
12}
test/c/inttypes.zig created+15
......@@ -0,0 +1,15 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const c = std.c;
5const testing = std.testing;
6
7test "imaxabs" {
8 const val: c.intmax_t = -10;
9 try testing.expectEqual(10, c.imaxabs(val));
10}
11
12test "imaxdiv" {
13 const expected: c.imaxdiv_t = .{ .quot = 9, .rem = 0 };
14 try testing.expectEqual(expected, c.imaxdiv(9, 1));
15}
test/c/math.zig created+101
......@@ -0,0 +1,101 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const c = std.c;
5const math = std.math;
6const testing = std.testing;
7
8fn testModf(comptime T: type) !void {
9 const f = switch (T) {
10 f32 => c.modff,
11 f64 => c.modf,
12 c_longdouble => c.modfl,
13 else => unreachable,
14 };
15
16 var int: T = undefined;
17 const iptr = &int;
18 const eps_val: comptime_float = @max(1e-6, math.floatEps(T));
19
20 const normal_frac = f(@as(T, 1234.567), iptr);
21 // Account for precision error
22 const expected = 1234.567 - @as(T, 1234);
23 try testing.expectApproxEqAbs(expected, normal_frac, eps_val);
24 try testing.expectApproxEqRel(@as(T, 1234.0), iptr.*, eps_val);
25
26 // When `x` is a NaN, NaN is returned and `*iptr` is set to NaN
27 const nan_frac = f(math.nan(T), iptr);
28 try testing.expect(math.isNan(nan_frac));
29 try testing.expect(math.isNan(iptr.*));
30
31 // When `x` is positive infinity, +0 is returned and `*iptr` is set to
32 // positive infinity
33 const pos_zero_frac = f(math.inf(T), iptr);
34 try testing.expect(math.isPositiveZero(pos_zero_frac));
35 try testing.expect(math.isPositiveInf(iptr.*));
36
37 // When `x` is negative infinity, -0 is returned and `*iptr` is set to
38 // negative infinity
39 const neg_zero_frac = f(-math.inf(T), iptr);
40 try testing.expect(math.isNegativeZero(neg_zero_frac));
41 try testing.expect(math.isNegativeInf(iptr.*));
42
43 // Return -0 when `x` is a negative integer
44 const nz_frac = f(@as(T, -1000.0), iptr);
45 try testing.expect(math.isNegativeZero(nz_frac));
46 try testing.expectEqual(@as(T, -1000.0), iptr.*);
47
48 // Return +0 when `x` is a positive integer
49 const pz_frac = f(@as(T, 1000.0), iptr);
50 try testing.expect(math.isPositiveZero(pz_frac));
51 try testing.expectEqual(@as(T, 1000.0), iptr.*);
52}
53
54test "modf" {
55 try testModf(f32);
56 try testModf(f64);
57 try testModf(c_longdouble);
58}
59
60fn testRint(comptime T: type) !void {
61 const f = switch (T) {
62 f32 => c.rintf,
63 f64 => c.rint,
64 else => @compileError("rint not implemented for" ++ @typeName(T)),
65 };
66
67 // Positive numbers round correctly
68 try testing.expectEqual(@as(T, 42.0), f(42.2));
69 try testing.expectEqual(@as(T, 42.0), f(41.8));
70
71 // Negative numbers round correctly
72 try testing.expectEqual(@as(T, -6.0), f(-5.9));
73 try testing.expectEqual(@as(T, -6.0), f(-6.1));
74
75 // No rounding needed test
76 try testing.expectEqual(@as(T, 5.0), f(5.0));
77 try testing.expectEqual(@as(T, -10.0), f(-10.0));
78 try testing.expectEqual(@as(T, 0.0), f(0.0));
79
80 // Very large numbers return unchanged
81 const large: T = 9007199254740992.0; // 2^53
82 try testing.expectEqual(large, f(large));
83 try testing.expectEqual(-large, f(-large));
84
85 // Small positive numbers round to zero
86 const pos_result = f(0.3);
87 try testing.expect(math.isPositiveZero(pos_result));
88
89 // Small negative numbers round to negative zero
90 const neg_result = f(-0.3);
91 try testing.expect(math.isNegativeZero(neg_result));
92
93 // Exact half rounds to nearest even (banker's rounding)
94 try testing.expectEqual(@as(T, 2.0), f(2.5));
95 try testing.expectEqual(@as(T, 4.0), f(3.5));
96}
97
98test "rint" {
99 try testRint(f32);
100 try testRint(f64);
101}
test/c/search.zig created+38
......@@ -0,0 +1,38 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const c = std.c;
5const testing = std.testing;
6
7/// Not defined in `std.c` because C headers don't either.
8const Node = extern struct {
9 next: ?*Node,
10 prev: ?*Node,
11};
12
13test "insque and remque" {
14 var first: Node = .{ .next = null, .prev = null };
15 var second: Node = .{ .next = null, .prev = null };
16 var third: Node = .{ .next = null, .prev = null };
17
18 c.insque(&first, null);
19 try testing.expectEqual(@as(?*Node, null), first.next);
20 try testing.expectEqual(@as(?*Node, null), first.prev);
21
22 c.insque(&second, &first);
23 try testing.expectEqual(@as(?*Node, &second), first.next);
24 try testing.expectEqual(@as(?*Node, &first), second.prev);
25
26 c.insque(&third, &first);
27 try testing.expectEqual(@as(?*Node, &third), first.next);
28 try testing.expectEqual(@as(?*Node, &second), third.next);
29 try testing.expectEqual(@as(?*Node, &first), third.prev);
30 try testing.expectEqual(@as(?*Node, &third), second.prev);
31
32 c.remque(&third);
33 try testing.expectEqual(@as(?*Node, &second), first.next);
34 try testing.expectEqual(@as(?*Node, &first), second.prev);
35
36 c.remque(&second);
37 try testing.expectEqual(@as(?*Node, null), first.next);
38}
test/c/stdlib.zig created+109
......@@ -0,0 +1,109 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const c = std.c;
5const fmt = std.fmt;
6const math = std.math;
7const testing = std.testing;
8
9test "abs" {
10 const val: c_int = -10;
11 try testing.expectEqual(10, c.abs(val));
12}
13
14test "labs" {
15 const val: c_long = -10;
16 try testing.expectEqual(10, c.labs(val));
17}
18
19test "llabs" {
20 const val: c_longlong = -10;
21 try testing.expectEqual(10, c.llabs(val));
22}
23
24test "div" {
25 const expected: c.div_t = .{ .quot = 5, .rem = 5 };
26 try testing.expectEqual(expected, c.div(55, 10));
27}
28
29test "ldiv" {
30 const expected: c.ldiv_t = .{ .quot = -6, .rem = 2 };
31 try testing.expectEqual(expected, c.ldiv(38, -6));
32}
33
34test "lldiv" {
35 const expected: c.lldiv_t = .{ .quot = 1, .rem = 2 };
36 try testing.expectEqual(expected, c.lldiv(5, 3));
37}
38
39test "atoi" {
40 try testing.expectEqual(0, c.atoi(@ptrCast("stop42true")));
41 try testing.expectEqual(42, c.atoi(@ptrCast("42true")));
42 try testing.expectEqual(-1, c.atoi(@ptrCast("-01")));
43 try testing.expectEqual(1, c.atoi(@ptrCast("+001")));
44 try testing.expectEqual(100, c.atoi(@ptrCast(" 100")));
45 try testing.expectEqual(500, c.atoi(@ptrCast("000000000000500")));
46 try testing.expectEqual(1111, c.atoi(@ptrCast("0000000000001111_0000")));
47 try testing.expectEqual(0, c.atoi(@ptrCast("0xAA")));
48 try testing.expectEqual(700, c.atoi(@ptrCast("700B")));
49 try testing.expectEqual(32453, c.atoi(@ptrCast("+32453more")));
50 try testing.expectEqual(math.maxInt(c_int), c.atoi(@ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_int)}))));
51 try testing.expectEqual(math.minInt(c_int), c.atoi(@ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_int)}))));
52}
53
54test "atol" {
55 try testing.expectEqual(0, c.atol(@ptrCast("stop42true")));
56 try testing.expectEqual(42, c.atol(@ptrCast("42true")));
57 try testing.expectEqual(-1, c.atol(@ptrCast("-01")));
58 try testing.expectEqual(1, c.atol(@ptrCast("+001")));
59 try testing.expectEqual(100, c.atol(@ptrCast(" 100")));
60 try testing.expectEqual(500, c.atol(@ptrCast("000000000000500")));
61 try testing.expectEqual(1111, c.atol(@ptrCast("0000000000001111_0000")));
62 try testing.expectEqual(0, c.atol(@ptrCast("0xAA")));
63 try testing.expectEqual(700, c.atol(@ptrCast("700B")));
64 try testing.expectEqual(32453, c.atol(@ptrCast("+32453more")));
65 try testing.expectEqual(math.maxInt(c_long), c.atol(@ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_long)}))));
66 try testing.expectEqual(math.minInt(c_long), c.atol(@ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_long)}))));
67}
68
69test "atoll" {
70 try testing.expectEqual(0, c.atoll(@ptrCast("stop42true")));
71 try testing.expectEqual(42, c.atoll(@ptrCast("42true")));
72 try testing.expectEqual(-1, c.atoll(@ptrCast("-01")));
73 try testing.expectEqual(1, c.atoll(@ptrCast("+001")));
74 try testing.expectEqual(100, c.atoll(@ptrCast(" 100")));
75 try testing.expectEqual(500, c.atoll(@ptrCast("000000000000500")));
76 try testing.expectEqual(1111, c.atoll(@ptrCast("0000000000001111_0000")));
77 try testing.expectEqual(0, c.atoll(@ptrCast("0xAA")));
78 try testing.expectEqual(700, c.atoll(@ptrCast("700B")));
79 try testing.expectEqual(32453, c.atoll(@ptrCast(" +32453more")));
80 try testing.expectEqual(math.maxInt(c_longlong), c.atoll(@ptrCast(fmt.comptimePrint("{d}", .{math.maxInt(c_longlong)}))));
81 try testing.expectEqual(math.minInt(c_longlong), c.atoll(@ptrCast(fmt.comptimePrint("{d}", .{math.minInt(c_longlong)}))));
82}
83
84test "bsearch" {
85 const Comparison = struct {
86 pub fn compare(a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int {
87 const a_u16: *const u16 = @ptrCast(@alignCast(a));
88 const b_u16: *const u16 = @ptrCast(@alignCast(b));
89
90 return switch (math.order(a_u16.*, b_u16.*)) {
91 .gt => 1,
92 .eq => 0,
93 .lt => -1,
94 };
95 }
96 };
97
98 const items: []const u16 = &.{ 0, 5, 7, 9, 10, 200, 512, 768 };
99
100 try testing.expectEqual(@as(?*anyopaque, null), c.bsearch(&@as(u16, 2000), items.ptr, items.len, @sizeOf(u16), Comparison.compare));
101
102 for (items) |*value| {
103 try testing.expectEqual(@as(*const anyopaque, value), c.bsearch(value, items.ptr, items.len, @sizeOf(u16), Comparison.compare));
104 }
105}
106
107test {
108 _ = @import("stdlib/drand48.zig");
109}
test/c/stdlib/drand48.zig created+62
......@@ -0,0 +1,62 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const c = std.c;
5const testing = std.testing;
6
7test "erand48" {
8 var xsubi: [3]c_ushort = .{ 37174, 64810, 11603 };
9
10 try testing.expectApproxEqAbs(0.8965, c.erand48(&xsubi), 0.0005);
11 try testing.expectEqualSlices(c_ushort, &.{ 22537, 47966, 58735 }, &xsubi);
12
13 try testing.expectApproxEqAbs(0.3375, c.erand48(&xsubi), 0.0005);
14 try testing.expectEqualSlices(c_ushort, &.{ 37344, 32911, 22119 }, &xsubi);
15
16 try testing.expectApproxEqAbs(0.6475, c.erand48(&xsubi), 0.0005);
17 try testing.expectEqualSlices(c_ushort, &.{ 23659, 29872, 42445 }, &xsubi);
18
19 try testing.expectApproxEqAbs(0.5005, c.erand48(&xsubi), 0.0005);
20 try testing.expectEqualSlices(c_ushort, &.{ 31642, 7875, 32802 }, &xsubi);
21
22 try testing.expectApproxEqAbs(0.5065, c.erand48(&xsubi), 0.0005);
23 try testing.expectEqualSlices(c_ushort, &.{ 64669, 14399, 33170 }, &xsubi);
24}
25
26test "jrand48" {
27 var xsubi: [3]c_ushort = .{ 25175, 11052, 45015 };
28
29 try testing.expectEqual(1699503220, c.jrand48(&xsubi));
30 try testing.expectEqualSlices(c_ushort, &.{ 2326, 23668, 25932 }, &xsubi);
31
32 try testing.expectEqual(-992276007, c.jrand48(&xsubi));
33 try testing.expectEqualSlices(c_ushort, &.{ 41577, 4569, 50395 }, &xsubi);
34
35 try testing.expectEqual(-19535776, c.jrand48(&xsubi));
36 try testing.expectEqualSlices(c_ushort, &.{ 31936, 59488, 65237 }, &xsubi);
37
38 try testing.expectEqual(79438377, c.jrand48(&xsubi));
39 try testing.expectEqualSlices(c_ushort, &.{ 40395, 8745, 1212 }, &xsubi);
40
41 try testing.expectEqual(-1258917728, c.jrand48(&xsubi));
42 try testing.expectEqualSlices(c_ushort, &.{ 37242, 28832, 46326 }, &xsubi);
43}
44
45test "nrand48" {
46 var xsubi: [3]c_ushort = .{ 546, 33817, 23389 };
47
48 try testing.expectEqual(914920692, c.nrand48(&xsubi));
49 try testing.expectEqualSlices(c_ushort, &.{ 29829, 10728, 27921 }, &xsubi);
50
51 try testing.expectEqual(754104482, c.nrand48(&xsubi));
52 try testing.expectEqualSlices(c_ushort, &.{ 6828, 28997, 23013 }, &xsubi);
53
54 try testing.expectEqual(609453945, c.nrand48(&xsubi));
55 try testing.expectEqualSlices(c_ushort, &.{ 58183, 3826, 18599 }, &xsubi);
56
57 try testing.expectEqual(1878644360, c.nrand48(&xsubi));
58 try testing.expectEqualSlices(c_ushort, &.{ 36678, 44304, 57331 }, &xsubi);
59
60 try testing.expectEqual(2114923686, c.nrand48(&xsubi));
61 try testing.expectEqualSlices(c_ushort, &.{ 58585, 22861, 64542 }, &xsubi);
62}
test/c/string.zig created+12
......@@ -0,0 +1,12 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const c = std.c;
5const testing = std.testing;
6
7test "strncmp" {
8 try testing.expect(c.strncmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
9 try testing.expect(c.strncmp(@ptrCast("a"), @ptrCast("c"), 1) < 0);
10 try testing.expect(c.strncmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
11 try testing.expect(c.strncmp(@ptrCast("\xff"), @ptrCast("\x02"), 1) > 0);
12}
test/c/strings.zig created+57
......@@ -0,0 +1,57 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const c = std.c;
5const mem = std.mem;
6const testing = std.testing;
7
8test "bzero" {
9 var array: [10]u8 = [_]u8{ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
10 var a = mem.zeroes([array.len]u8);
11 a[9] = '0';
12 c.bzero(&array[0], 9);
13 try testing.expect(mem.eql(u8, &array, &a));
14}
15
16fn testFfs(comptime T: type) !void {
17 const ffs = switch (T) {
18 c_int => c.ffs,
19 c_long => c.ffsl,
20 c_longlong => c.ffsll,
21 else => unreachable,
22 };
23
24 try testing.expectEqual(0, ffs(0));
25
26 for (0..@bitSizeOf(T)) |i| {
27 const bit = @as(T, 1) << @intCast(i);
28
29 try testing.expectEqual(@as(T, @intCast(i + 1)), ffs(bit));
30 }
31}
32
33test "ffs" {
34 try testFfs(c_int);
35 try testFfs(c_long);
36 try testFfs(c_longlong);
37}
38
39test "strcasecmp" {
40 try testing.expect(c.strcasecmp(@ptrCast("a"), @ptrCast("b")) < 0);
41 try testing.expect(c.strcasecmp(@ptrCast("b"), @ptrCast("a")) > 0);
42 try testing.expect(c.strcasecmp(@ptrCast("A"), @ptrCast("b")) < 0);
43 try testing.expect(c.strcasecmp(@ptrCast("b"), @ptrCast("A")) > 0);
44 try testing.expect(c.strcasecmp(@ptrCast("A"), @ptrCast("A")) == 0);
45 try testing.expect(c.strcasecmp(@ptrCast("B"), @ptrCast("b")) == 0);
46 try testing.expect(c.strcasecmp(@ptrCast("bb"), @ptrCast("AA")) > 0);
47}
48
49test "strncasecmp" {
50 try testing.expect(c.strncasecmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
51 try testing.expect(c.strncasecmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
52 try testing.expect(c.strncasecmp(@ptrCast("A"), @ptrCast("b"), 1) < 0);
53 try testing.expect(c.strncasecmp(@ptrCast("b"), @ptrCast("A"), 1) > 0);
54 try testing.expect(c.strncasecmp(@ptrCast("A"), @ptrCast("A"), 1) == 0);
55 try testing.expect(c.strncasecmp(@ptrCast("B"), @ptrCast("b"), 1) == 0);
56 try testing.expect(c.strncasecmp(@ptrCast("bb"), @ptrCast("AA"), 2) > 0);
57}
test/c/unistd.zig created+31
......@@ -0,0 +1,31 @@
1const builtin = @import("builtin");
2const std = @import("std");
3
4const c = std.c;
5const testing = std.testing;
6
7test "swab" {
8 var a: [4]u8 = undefined;
9 @memset(a[0..], '\x00');
10 c.swab("abcd", &a, 4);
11 try testing.expectEqualSlices(u8, "badc", &a);
12
13 // Partial copy
14 @memset(a[0..], '\x00');
15 c.swab("abcd", &a, 2);
16 try testing.expectEqualSlices(u8, "ba\x00\x00", &a);
17
18 // n < 1
19 @memset(a[0..], '\x00');
20 c.swab("abcd", &a, 0);
21 try testing.expectEqualSlices(u8, "\x00" ** 4, &a);
22 c.swab("abcd", &a, -1);
23 try testing.expectEqualSlices(u8, "\x00" ** 4, &a);
24
25 // Odd n
26 @memset(a[0..], '\x00');
27 c.swab("abcd", &a, 1);
28 try testing.expectEqualSlices(u8, "\x00" ** 4, &a);
29 c.swab("abcd", &a, 3);
30 try testing.expectEqualSlices(u8, "ba\x00\x00", &a);
31}
test/tests.zig+22-41
......@@ -18,7 +18,7 @@ pub const DebuggerContext = @import("src/Debugger.zig");
1818pub const LlvmIrContext = @import("src/LlvmIr.zig");
1919pub const LibcContext = @import("src/Libc.zig");
2020
21const TestTarget = struct {
21const ModuleTestTarget = struct {
2222 linkage: ?std.builtin.LinkMode = null,
2323 target: std.Target.Query = .{},
2424 optimize_mode: std.builtin.OptimizeMode = .Debug,
......@@ -36,33 +36,14 @@ const TestTarget = struct {
3636 // invocation. This could be because of a slow backend, requiring a newer LLVM version, being
3737 // too niche, etc.
3838 extra_target: bool = false,
39
40 pub fn supportsModule(
41 self: *const TestTarget,
42 target: *const std.Build.ResolvedTarget,
43 name: []const u8,
44 ) bool {
45 if (mem.eql(u8, name, "zigc")) {
46 if (target.result.isMuslLibC()) return self.linkage == .static or (self.linkage == null and !target.query.isNative());
47 if (target.result.isMinGW()) return true;
48 if (target.result.isWasiLibC()) return true;
49 return false;
50 }
51 if (mem.eql(u8, name, "std")) {
52 if (target.result.cpu.arch.isSpirV()) return false;
53 return true;
54 }
55
56 return true;
57 }
5839};
5940
60const test_targets = blk: {
41const module_test_targets = blk: {
6142 // getBaselineCpuFeatures calls populateDependencies which has a O(N ^ 2) algorithm
6243 // (where N is roughly 160, which technically makes it O(1), but it adds up to a
6344 // lot of branches)
6445 @setEvalBranchQuota(80_000);
65 break :blk [_]TestTarget{
46 break :blk [_]ModuleTestTarget{
6647 // Native Targets
6748
6849 .{}, // 0 index must be all defaults
......@@ -2475,24 +2456,21 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
24752456 const step = b.step(b.fmt("test-{s}", .{options.name}), options.desc);
24762457
24772458 if (options.test_only) |test_only| {
2478 const test_target: TestTarget = switch (test_only) {
2479 .default => test_targets[0],
2459 const test_target: ModuleTestTarget = switch (test_only) {
2460 .default => module_test_targets[0],
24802461 .fuzz => |optimize| .{
24812462 .optimize_mode = optimize,
24822463 .use_llvm = true,
24832464 },
24842465 };
24852466 const resolved_target = b.resolveTargetQuery(test_target.target);
2486
2487 if (test_target.supportsModule(&resolved_target, options.name)) {
2488 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
2489 addOneModuleTest(b, step, test_target, &resolved_target, triple_txt, options);
2490 }
2467 const triple_txt = resolved_target.query.zigTriple(b.allocator) catch @panic("OOM");
2468 addOneModuleTest(b, step, test_target, &resolved_target, triple_txt, options);
24912469
24922470 return step;
24932471 }
24942472
2495 for_targets: for (test_targets) |test_target| {
2473 for_targets: for (module_test_targets) |test_target| {
24962474 if (test_target.skip_modules.len > 0) {
24972475 for (test_target.skip_modules) |skip_mod| {
24982476 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 {
25012479
25022480 const resolved_target = b.resolveTargetQuery(test_target.target);
25032481
2504 if (!test_target.supportsModule(&resolved_target, options.name)) continue;
2505
25062482 if (!options.test_extra_targets and test_target.extra_target) continue;
25072483
25082484 if (options.skip_non_native and !test_target.target.isNative())
......@@ -2510,6 +2486,13 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
25102486
25112487 const target = &resolved_target.result;
25122488
2489 if (std.mem.eql(u8, options.name, "libc")) {
2490 // The libc API tests obviously need to link libc. So for test
2491 // target entries where we wouldn't link libc by default, skip the
2492 // libc API tests.
2493 if (test_target.link_libc == null and !std.os.targetRequiresLibC(target)) continue;
2494 }
2495
25132496 if (options.skip_spirv and target.cpu.arch.isSpirV()) continue;
25142497 if (options.skip_wasm and target.cpu.arch.isWasm()) continue;
25152498
......@@ -2544,8 +2527,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
25442527 if (!would_use_llvm and target.cpu.arch == .aarch64) {
25452528 // TODO get std tests passing for the aarch64 self-hosted backend.
25462529 if (mem.eql(u8, options.name, "std")) continue;
2547 // TODO get zigc tests passing for the aarch64 self-hosted backend.
2548 if (mem.eql(u8, options.name, "zigc")) continue;
25492530 }
25502531
25512532 const want_this_mode = for (options.optimize_modes) |m| {
......@@ -2561,7 +2542,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
25612542fn addOneModuleTest(
25622543 b: *std.Build,
25632544 step: *Step,
2564 test_target: TestTarget,
2545 test_target: ModuleTestTarget,
25652546 resolved_target: *const std.Build.ResolvedTarget,
25662547 triple_txt: []const u8,
25672548 options: ModuleTestOptions,
......@@ -2598,11 +2579,11 @@ fn addOneModuleTest(
25982579 });
25992580 these_tests.linkage = test_target.linkage;
26002581 // https://codeberg.org/ziglang/zig/issues/31701
2601 if (!(mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "zigc"))) {
2582 if (!(mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "libc"))) {
26022583 if (options.no_builtin) these_tests.root_module.no_builtin = true;
26032584 }
26042585 // https://codeberg.org/ziglang/zig/issues/31702
2605 if (mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "zigc")) {
2586 if (mem.eql(u8, options.name, "compiler-rt") or mem.eql(u8, options.name, "libc")) {
26062587 these_tests.root_module.stack_protector = false;
26072588 }
26082589 if (options.build_options) |build_options| {
......@@ -2992,7 +2973,7 @@ pub fn addLlvmIrTests(b: *std.Build, options: LlvmIrContext.Options) ?*Step {
29922973 return step;
29932974}
29942975
2995const libc_targets: []const std.Target.Query = &.{
2976const libc_test_nsz_targets: []const std.Target.Query = &.{
29962977 .{
29972978 .cpu_arch = .arm,
29982979 .os_tag = .linux,
......@@ -3155,8 +3136,8 @@ const libc_targets: []const std.Target.Query = &.{
31553136 },
31563137};
31573138
3158pub fn addLibcTests(b: *std.Build, options: LibcContext.Options) ?*Step {
3159 const step = b.step("test-libc", "Run libc-test test cases");
3139pub fn addLibcTestNszTests(b: *std.Build, options: LibcContext.Options) ?*Step {
3140 const step = b.step("test-libc-nsz", "Run external libc-test test cases");
31603141 const opt_libc_test_path = b.option(std.Build.LazyPath, "libc-test-path", "path to libc-test source directory");
31613142 if (opt_libc_test_path) |libc_test_path| {
31623143 var context: LibcContext = .{
......@@ -3168,7 +3149,7 @@ pub fn addLibcTests(b: *std.Build, options: LibcContext.Options) ?*Step {
31683149
31693150 libc.addCases(&context);
31703151
3171 for (libc_targets) |target_query| {
3152 for (libc_test_nsz_targets) |target_query| {
31723153 const target = b.resolveTargetQuery(target_query);
31733154 context.addTarget(target);
31743155 }