authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-03 19:14:48-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-07 22:43:53-07:00
logf4720e14072fc4aa45fd2c985a676d4140ecc06a
treef4c261f8a3b0feb19dd44bddd7647391f88c1d37
parent87a7568a4437ab4e98ad32573548886529c6b10d

std.testing: update to new std.io API


2 files changed, 41 insertions(+), 36 deletions(-)

lib/std/testing.zig+32-27
...@@ -360,9 +360,6 @@ test expectApproxEqRel {...@@ -360,9 +360,6 @@ test expectApproxEqRel {
360/// The colorized output is optional and controlled by the return of `std.io.tty.detectConfig()`.360/// The colorized output is optional and controlled by the return of `std.io.tty.detectConfig()`.
361/// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead.361/// If your inputs are UTF-8 encoded strings, consider calling `expectEqualStrings` instead.
362pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void {362pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const T) !void {
363 if (expected.ptr == actual.ptr and expected.len == actual.len) {
364 return;
365 }
366 const diff_index: usize = diff_index: {363 const diff_index: usize = diff_index: {
367 const shortest = @min(expected.len, actual.len);364 const shortest = @min(expected.len, actual.len);
368 var index: usize = 0;365 var index: usize = 0;
...@@ -371,12 +368,21 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -371,12 +368,21 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
371 }368 }
372 break :diff_index if (expected.len == actual.len) return else shortest;369 break :diff_index if (expected.len == actual.len) return else shortest;
373 };370 };
371 if (!backend_can_print) return error.TestExpectedEqual;
372 const stderr_w = std.debug.lockStderrWriter(&.{});
373 defer std.debug.unlockStderrWriter();
374 failEqualSlices(T, expected, actual, diff_index, stderr_w) catch {};
375 return error.TestExpectedEqual;
376}
374377
375 if (!backend_can_print) {378fn failEqualSlices(
376 return error.TestExpectedEqual;379 comptime T: type,
377 }380 expected: []const T,
378381 actual: []const T,
379 print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });382 diff_index: usize,
383 w: *std.io.Writer,
384) !void {
385 try w.print("slices differ. first difference occurs at index {d} (0x{X})\n", .{ diff_index, diff_index });
380386
381 // TODO: Should this be configurable by the caller?387 // TODO: Should this be configurable by the caller?
382 const max_lines: usize = 16;388 const max_lines: usize = 16;
...@@ -394,8 +400,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -394,8 +400,7 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
394 const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)];400 const actual_window = actual[window_start..@min(actual.len, window_start + max_window_size)];
395 const actual_truncated = window_start + actual_window.len < actual.len;401 const actual_truncated = window_start + actual_window.len < actual.len;
396402
397 const stderr: std.fs.File = .stderr();403 const ttyconf = std.io.tty.detectConfig(.stderr());
398 const ttyconf = std.io.tty.detectConfig(stderr);
399 var differ = if (T == u8) BytesDiffer{404 var differ = if (T == u8) BytesDiffer{
400 .expected = expected_window,405 .expected = expected_window,
401 .actual = actual_window,406 .actual = actual_window,
...@@ -411,47 +416,47 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const...@@ -411,47 +416,47 @@ pub fn expectEqualSlices(comptime T: type, expected: []const T, actual: []const
411 // that is usually useful.416 // that is usually useful.
412 const index_fmt = if (T == u8) "0x{X}" else "{}";417 const index_fmt = if (T == u8) "0x{X}" else "{}";
413418
414 print("\n============ expected this output: ============= len: {} (0x{X})\n\n", .{ expected.len, expected.len });419 try w.print("\n============ expected this output: ============= len: {} (0x{X})\n\n", .{ expected.len, expected.len });
415 if (window_start > 0) {420 if (window_start > 0) {
416 if (T == u8) {421 if (T == u8) {
417 print("... truncated, start index: " ++ index_fmt ++ " ...\n", .{window_start});422 try w.print("... truncated, start index: " ++ index_fmt ++ " ...\n", .{window_start});
418 } else {423 } else {
419 print("... truncated ...\n", .{});424 try w.print("... truncated ...\n", .{});
420 }425 }
421 }426 }
422 differ.write(stderr.deprecatedWriter()) catch {};427 differ.write(w) catch {};
423 if (expected_truncated) {428 if (expected_truncated) {
424 const end_offset = window_start + expected_window.len;429 const end_offset = window_start + expected_window.len;
425 const num_missing_items = expected.len - (window_start + expected_window.len);430 const num_missing_items = expected.len - (window_start + expected_window.len);
426 if (T == u8) {431 if (T == u8) {
427 print("... truncated, indexes [" ++ index_fmt ++ "..] not shown, remaining bytes: " ++ index_fmt ++ " ...\n", .{ end_offset, num_missing_items });432 try w.print("... truncated, indexes [" ++ index_fmt ++ "..] not shown, remaining bytes: " ++ index_fmt ++ " ...\n", .{ end_offset, num_missing_items });
428 } else {433 } else {
429 print("... truncated, remaining items: " ++ index_fmt ++ " ...\n", .{num_missing_items});434 try w.print("... truncated, remaining items: " ++ index_fmt ++ " ...\n", .{num_missing_items});
430 }435 }
431 }436 }
432437
433 // now reverse expected/actual and print again438 // now reverse expected/actual and print again
434 differ.expected = actual_window;439 differ.expected = actual_window;
435 differ.actual = expected_window;440 differ.actual = expected_window;
436 print("\n============= instead found this: ============== len: {} (0x{X})\n\n", .{ actual.len, actual.len });441 try w.print("\n============= instead found this: ============== len: {} (0x{X})\n\n", .{ actual.len, actual.len });
437 if (window_start > 0) {442 if (window_start > 0) {
438 if (T == u8) {443 if (T == u8) {
439 print("... truncated, start index: " ++ index_fmt ++ " ...\n", .{window_start});444 try w.print("... truncated, start index: " ++ index_fmt ++ " ...\n", .{window_start});
440 } else {445 } else {
441 print("... truncated ...\n", .{});446 try w.print("... truncated ...\n", .{});
442 }447 }
443 }448 }
444 differ.write(stderr.deprecatedWriter()) catch {};449 differ.write(w) catch {};
445 if (actual_truncated) {450 if (actual_truncated) {
446 const end_offset = window_start + actual_window.len;451 const end_offset = window_start + actual_window.len;
447 const num_missing_items = actual.len - (window_start + actual_window.len);452 const num_missing_items = actual.len - (window_start + actual_window.len);
448 if (T == u8) {453 if (T == u8) {
449 print("... truncated, indexes [" ++ index_fmt ++ "..] not shown, remaining bytes: " ++ index_fmt ++ " ...\n", .{ end_offset, num_missing_items });454 try w.print("... truncated, indexes [" ++ index_fmt ++ "..] not shown, remaining bytes: " ++ index_fmt ++ " ...\n", .{ end_offset, num_missing_items });
450 } else {455 } else {
451 print("... truncated, remaining items: " ++ index_fmt ++ " ...\n", .{num_missing_items});456 try w.print("... truncated, remaining items: " ++ index_fmt ++ " ...\n", .{num_missing_items});
452 }457 }
453 }458 }
454 print("\n================================================\n\n", .{});459 try w.print("\n================================================\n\n", .{});
455460
456 return error.TestExpectedEqual;461 return error.TestExpectedEqual;
457}462}
...@@ -465,7 +470,7 @@ fn SliceDiffer(comptime T: type) type {...@@ -465,7 +470,7 @@ fn SliceDiffer(comptime T: type) type {
465470
466 const Self = @This();471 const Self = @This();
467472
468 pub fn write(self: Self, writer: anytype) !void {473 pub fn write(self: Self, writer: *std.io.Writer) !void {
469 for (self.expected, 0..) |value, i| {474 for (self.expected, 0..) |value, i| {
470 const full_index = self.start_index + i;475 const full_index = self.start_index + i;
471 const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true;476 const diff = if (i < self.actual.len) !std.meta.eql(self.actual[i], value) else true;
...@@ -486,7 +491,7 @@ const BytesDiffer = struct {...@@ -486,7 +491,7 @@ const BytesDiffer = struct {
486 actual: []const u8,491 actual: []const u8,
487 ttyconf: std.io.tty.Config,492 ttyconf: std.io.tty.Config,
488493
489 pub fn write(self: BytesDiffer, writer: anytype) !void {494 pub fn write(self: BytesDiffer, writer: *std.io.Writer) !void {
490 var expected_iterator = std.mem.window(u8, self.expected, 16, 16);495 var expected_iterator = std.mem.window(u8, self.expected, 16, 16);
491 var row: usize = 0;496 var row: usize = 0;
492 while (expected_iterator.next()) |chunk| {497 while (expected_iterator.next()) |chunk| {
...@@ -503,7 +508,7 @@ const BytesDiffer = struct {...@@ -503,7 +508,7 @@ const BytesDiffer = struct {
503 if (chunk.len < 16) {508 if (chunk.len < 16) {
504 var missing_columns = (16 - chunk.len) * 3;509 var missing_columns = (16 - chunk.len) * 3;
505 if (chunk.len < 8) missing_columns += 1;510 if (chunk.len < 8) missing_columns += 1;
506 try writer.writeByteNTimes(' ', missing_columns);511 try writer.splatByteAll(' ', missing_columns);
507 }512 }
508 for (chunk, 0..) |byte, col| {513 for (chunk, 0..) |byte, col| {
509 const diff = diffs.isSet(col);514 const diff = diffs.isSet(col);
...@@ -532,7 +537,7 @@ const BytesDiffer = struct {...@@ -532,7 +537,7 @@ const BytesDiffer = struct {
532 }537 }
533 }538 }
534539
535 fn writeDiff(self: BytesDiffer, writer: anytype, comptime fmt: []const u8, args: anytype, diff: bool) !void {540 fn writeDiff(self: BytesDiffer, writer: *std.io.Writer, comptime fmt: []const u8, args: anytype, diff: bool) !void {
536 if (diff) try self.ttyconf.setColor(writer, .red);541 if (diff) try self.ttyconf.setColor(writer, .red);
537 try writer.print(fmt, args);542 try writer.print(fmt, args);
538 if (diff) try self.ttyconf.setColor(writer, .reset);543 if (diff) try self.ttyconf.setColor(writer, .reset);
lib/std/zip.zig+9-9
...@@ -124,7 +124,7 @@ pub fn findEndRecord(seekable_stream: anytype, stream_len: u64) !EndRecord {...@@ -124,7 +124,7 @@ pub fn findEndRecord(seekable_stream: anytype, stream_len: u64) !EndRecord {
124124
125 try seekable_stream.seekTo(stream_len - @as(u64, new_loaded_len));125 try seekable_stream.seekTo(stream_len - @as(u64, new_loaded_len));
126 const read_buf: []u8 = buf[buf.len - new_loaded_len ..][0..read_len];126 const read_buf: []u8 = buf[buf.len - new_loaded_len ..][0..read_len];
127 const len = try seekable_stream.context.deprecatedReader().readAll(read_buf);127 const len = try seekable_stream.context.reader().readAll(read_buf);
128 if (len != read_len)128 if (len != read_len)
129 return error.ZipTruncated;129 return error.ZipTruncated;
130 loaded_len = new_loaded_len;130 loaded_len = new_loaded_len;
...@@ -295,7 +295,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -295,7 +295,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
295 if (locator_end_offset > stream_len)295 if (locator_end_offset > stream_len)
296 return error.ZipTruncated;296 return error.ZipTruncated;
297 try stream.seekTo(stream_len - locator_end_offset);297 try stream.seekTo(stream_len - locator_end_offset);
298 const locator = try stream.context.deprecatedReader().readStructEndian(EndLocator64, .little);298 const locator = try stream.context.reader().readStructEndian(EndLocator64, .little);
299 if (!std.mem.eql(u8, &locator.signature, &end_locator64_sig))299 if (!std.mem.eql(u8, &locator.signature, &end_locator64_sig))
300 return error.ZipBadLocatorSig;300 return error.ZipBadLocatorSig;
301 if (locator.zip64_disk_count != 0)301 if (locator.zip64_disk_count != 0)
...@@ -305,7 +305,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -305,7 +305,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
305305
306 try stream.seekTo(locator.record_file_offset);306 try stream.seekTo(locator.record_file_offset);
307307
308 const record64 = try stream.context.deprecatedReader().readStructEndian(EndRecord64, .little);308 const record64 = try stream.context.reader().readStructEndian(EndRecord64, .little);
309309
310 if (!std.mem.eql(u8, &record64.signature, &end_record64_sig))310 if (!std.mem.eql(u8, &record64.signature, &end_record64_sig))
311 return error.ZipBadEndRecord64Sig;311 return error.ZipBadEndRecord64Sig;
...@@ -357,7 +357,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -357,7 +357,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
357357
358 const header_zip_offset = self.cd_zip_offset + self.cd_record_offset;358 const header_zip_offset = self.cd_zip_offset + self.cd_record_offset;
359 try self.stream.seekTo(header_zip_offset);359 try self.stream.seekTo(header_zip_offset);
360 const header = try self.stream.context.deprecatedReader().readStructEndian(CentralDirectoryFileHeader, .little);360 const header = try self.stream.context.reader().readStructEndian(CentralDirectoryFileHeader, .little);
361 if (!std.mem.eql(u8, &header.signature, &central_file_header_sig))361 if (!std.mem.eql(u8, &header.signature, &central_file_header_sig))
362 return error.ZipBadCdOffset;362 return error.ZipBadCdOffset;
363363
...@@ -386,7 +386,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -386,7 +386,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
386386
387 {387 {
388 try self.stream.seekTo(header_zip_offset + @sizeOf(CentralDirectoryFileHeader) + header.filename_len);388 try self.stream.seekTo(header_zip_offset + @sizeOf(CentralDirectoryFileHeader) + header.filename_len);
389 const len = try self.stream.context.deprecatedReader().readAll(extra);389 const len = try self.stream.context.reader().readAll(extra);
390 if (len != extra.len)390 if (len != extra.len)
391 return error.ZipTruncated;391 return error.ZipTruncated;
392 }392 }
...@@ -449,7 +449,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -449,7 +449,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
449 try stream.seekTo(self.header_zip_offset + @sizeOf(CentralDirectoryFileHeader));449 try stream.seekTo(self.header_zip_offset + @sizeOf(CentralDirectoryFileHeader));
450450
451 {451 {
452 const len = try stream.context.deprecatedReader().readAll(filename);452 const len = try stream.context.reader().readAll(filename);
453 if (len != filename.len)453 if (len != filename.len)
454 return error.ZipBadFileOffset;454 return error.ZipBadFileOffset;
455 }455 }
...@@ -457,7 +457,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -457,7 +457,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
457 const local_data_header_offset: u64 = local_data_header_offset: {457 const local_data_header_offset: u64 = local_data_header_offset: {
458 const local_header = blk: {458 const local_header = blk: {
459 try stream.seekTo(self.file_offset);459 try stream.seekTo(self.file_offset);
460 break :blk try stream.context.deprecatedReader().readStructEndian(LocalFileHeader, .little);460 break :blk try stream.context.reader().readStructEndian(LocalFileHeader, .little);
461 };461 };
462 if (!std.mem.eql(u8, &local_header.signature, &local_file_header_sig))462 if (!std.mem.eql(u8, &local_header.signature, &local_file_header_sig))
463 return error.ZipBadFileOffset;463 return error.ZipBadFileOffset;
...@@ -483,7 +483,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -483,7 +483,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
483483
484 {484 {
485 try stream.seekTo(self.file_offset + @sizeOf(LocalFileHeader) + local_header.filename_len);485 try stream.seekTo(self.file_offset + @sizeOf(LocalFileHeader) + local_header.filename_len);
486 const len = try stream.context.deprecatedReader().readAll(extra);486 const len = try stream.context.reader().readAll(extra);
487 if (len != extra.len)487 if (len != extra.len)
488 return error.ZipTruncated;488 return error.ZipTruncated;
489 }489 }
...@@ -552,7 +552,7 @@ pub fn Iterator(comptime SeekableStream: type) type {...@@ -552,7 +552,7 @@ pub fn Iterator(comptime SeekableStream: type) type {
552 @as(u64, @sizeOf(LocalFileHeader)) +552 @as(u64, @sizeOf(LocalFileHeader)) +
553 local_data_header_offset;553 local_data_header_offset;
554 try stream.seekTo(local_data_file_offset);554 try stream.seekTo(local_data_file_offset);
555 var limited_reader = std.io.limitedReader(stream.context.deprecatedReader(), self.compressed_size);555 var limited_reader = std.io.limitedReader(stream.context.reader(), self.compressed_size);
556 const crc = try decompress(556 const crc = try decompress(
557 self.compression_method,557 self.compression_method,
558 self.uncompressed_size,558 self.uncompressed_size,