authorgravatar for jay@jayschwa.netJay Petacat <jay@jayschwa.net> 2021-01-11 20:30:43-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-12 18:13:29-08:00
loga021c7b1b2428ecda85e79e281d43fa1c92f8c94
tree069163111972ebb708431098f97b07fd91581a11
parent2c79d669a7ad802c795583cf66bca1fffc8ce23e

Move fmt.testFmt to testing.expectFmt


4 files changed, 194 insertions(+), 201 deletions(-)

lib/std/SemanticVersion.zig+4-16
......@@ -205,7 +205,7 @@ test "SemanticVersion format" {
205205 "1.2.3----R-S.12.9.1--.12+meta",
206206 "1.2.3----RC-SNAPSHOT.12.9.1--.12",
207207 "1.0.0+0.build.1-rc.10000aaa-kk-0.1",
208 }) |valid| try testFmt(valid, "{}", .{try parse(valid)});
208 }) |valid| try std.testing.expectFmt(valid, "{}", .{try parse(valid)});
209209
210210 // Invalid version strings should be rejected.
211211 for ([_][]const u8{
......@@ -253,7 +253,9 @@ test "SemanticVersion format" {
253253
254254 // Valid version string that may overflow.
255255 const big_valid = "99999999999999999999999.999999999999999999.99999999999999999";
256 if (parse(big_valid)) |ver| try testFmt(big_valid, "{}", .{ver}) else |err| expect(err == error.Overflow);
256 if (parse(big_valid)) |ver| {
257 try std.testing.expectFmt(big_valid, "{}", .{ver});
258 } else |err| expect(err == error.Overflow);
257259
258260 // Invalid version string that may overflow.
259261 const big_invalid = "99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12";
......@@ -280,20 +282,6 @@ test "SemanticVersion precedence" {
280282 expect(order(try parse("1.0.0-rc.1"), try parse("1.0.0")) == .lt);
281283}
282284
283// This is copy-pasted from fmt.zig since it is not public.
284fn testFmt(expected: []const u8, comptime template: []const u8, args: anytype) !void {
285 var buf: [100]u8 = undefined;
286 const result = try std.fmt.bufPrint(buf[0..], template, args);
287 if (std.mem.eql(u8, result, expected)) return;
288
289 std.debug.warn("\n====== expected this output: =========\n", .{});
290 std.debug.warn("{s}", .{expected});
291 std.debug.warn("\n======== instead found this: =========\n", .{});
292 std.debug.warn("{s}", .{result});
293 std.debug.warn("\n======================================\n", .{});
294 return error.TestFailed;
295}
296
297285test "zig_version" {
298286 // An approximate Zig build that predates this test.
299287 const older_version = .{ .major = 0, .minor = 8, .patch = 0, .pre = "dev.874" };
lib/std/fmt.zig+167-179
......@@ -12,6 +12,7 @@ const meta = std.meta;
1212const builtin = @import("builtin");
1313const errol = @import("fmt/errol.zig");
1414const lossyCast = std.math.lossyCast;
15const expectFmt = std.testing.expectFmt;
1516
1617pub const default_max_depth = 3;
1718
......@@ -1531,91 +1532,91 @@ test "parse unsigned comptime" {
15311532}
15321533
15331534test "escaped braces" {
1534 try testFmt("escaped: {{foo}}\n", "escaped: {{{{foo}}}}\n", .{});
1535 try testFmt("escaped: {foo}\n", "escaped: {{foo}}\n", .{});
1535 try expectFmt("escaped: {{foo}}\n", "escaped: {{{{foo}}}}\n", .{});
1536 try expectFmt("escaped: {foo}\n", "escaped: {{foo}}\n", .{});
15361537}
15371538
15381539test "optional" {
15391540 {
15401541 const value: ?i32 = 1234;
1541 try testFmt("optional: 1234\n", "optional: {}\n", .{value});
1542 try expectFmt("optional: 1234\n", "optional: {}\n", .{value});
15421543 }
15431544 {
15441545 const value: ?i32 = null;
1545 try testFmt("optional: null\n", "optional: {}\n", .{value});
1546 try expectFmt("optional: null\n", "optional: {}\n", .{value});
15461547 }
15471548 {
15481549 const value = @intToPtr(?*i32, 0xf000d000);
1549 try testFmt("optional: *i32@f000d000\n", "optional: {*}\n", .{value});
1550 try expectFmt("optional: *i32@f000d000\n", "optional: {*}\n", .{value});
15501551 }
15511552}
15521553
15531554test "error" {
15541555 {
15551556 const value: anyerror!i32 = 1234;
1556 try testFmt("error union: 1234\n", "error union: {}\n", .{value});
1557 try expectFmt("error union: 1234\n", "error union: {}\n", .{value});
15571558 }
15581559 {
15591560 const value: anyerror!i32 = error.InvalidChar;
1560 try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
1561 try expectFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
15611562 }
15621563}
15631564
15641565test "int.small" {
15651566 {
15661567 const value: u3 = 0b101;
1567 try testFmt("u3: 5\n", "u3: {}\n", .{value});
1568 try expectFmt("u3: 5\n", "u3: {}\n", .{value});
15681569 }
15691570}
15701571
15711572test "int.specifier" {
15721573 {
15731574 const value: u8 = 'a';
1574 try testFmt("u8: a\n", "u8: {c}\n", .{value});
1575 try expectFmt("u8: a\n", "u8: {c}\n", .{value});
15751576 }
15761577 {
15771578 const value: u8 = 0b1100;
1578 try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
1579 try expectFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
15791580 }
15801581 {
15811582 const value: u16 = 0o1234;
1582 try testFmt("u16: 0o1234\n", "u16: 0o{o}\n", .{value});
1583 try expectFmt("u16: 0o1234\n", "u16: 0o{o}\n", .{value});
15831584 }
15841585 {
15851586 const value: u8 = 'a';
1586 try testFmt("UTF-8: a\n", "UTF-8: {u}\n", .{value});
1587 try expectFmt("UTF-8: a\n", "UTF-8: {u}\n", .{value});
15871588 }
15881589 {
15891590 const value: u21 = 0x1F310;
1590 try testFmt("UTF-8: 🌐\n", "UTF-8: {u}\n", .{value});
1591 try expectFmt("UTF-8: 🌐\n", "UTF-8: {u}\n", .{value});
15911592 }
15921593 {
15931594 const value: u21 = 0xD800;
1594 try testFmt("UTF-8: �\n", "UTF-8: {u}\n", .{value});
1595 try expectFmt("UTF-8: �\n", "UTF-8: {u}\n", .{value});
15951596 }
15961597 {
15971598 const value: u21 = 0x110001;
1598 try testFmt("UTF-8: �\n", "UTF-8: {u}\n", .{value});
1599 try expectFmt("UTF-8: �\n", "UTF-8: {u}\n", .{value});
15991600 }
16001601}
16011602
16021603test "int.padded" {
1603 try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
1604 try testFmt("u8: '1000'", "u8: '{:0<4}'", .{@as(u8, 1)});
1605 try testFmt("u8: '0001'", "u8: '{:0>4}'", .{@as(u8, 1)});
1606 try testFmt("u8: '0100'", "u8: '{:0^4}'", .{@as(u8, 1)});
1607 try testFmt("i8: '-1 '", "i8: '{:<4}'", .{@as(i8, -1)});
1608 try testFmt("i8: ' -1'", "i8: '{:>4}'", .{@as(i8, -1)});
1609 try testFmt("i8: ' -1 '", "i8: '{:^4}'", .{@as(i8, -1)});
1610 try testFmt("i16: '-1234'", "i16: '{:4}'", .{@as(i16, -1234)});
1611 try testFmt("i16: '+1234'", "i16: '{:4}'", .{@as(i16, 1234)});
1612 try testFmt("i16: '-12345'", "i16: '{:4}'", .{@as(i16, -12345)});
1613 try testFmt("i16: '+12345'", "i16: '{:4}'", .{@as(i16, 12345)});
1614 try testFmt("u16: '12345'", "u16: '{:4}'", .{@as(u16, 12345)});
1615
1616 try testFmt("UTF-8: 'ü '", "UTF-8: '{u:<4}'", .{'ü'});
1617 try testFmt("UTF-8: ' ü'", "UTF-8: '{u:>4}'", .{'ü'});
1618 try testFmt("UTF-8: ' ü '", "UTF-8: '{u:^4}'", .{'ü'});
1604 try expectFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
1605 try expectFmt("u8: '1000'", "u8: '{:0<4}'", .{@as(u8, 1)});
1606 try expectFmt("u8: '0001'", "u8: '{:0>4}'", .{@as(u8, 1)});
1607 try expectFmt("u8: '0100'", "u8: '{:0^4}'", .{@as(u8, 1)});
1608 try expectFmt("i8: '-1 '", "i8: '{:<4}'", .{@as(i8, -1)});
1609 try expectFmt("i8: ' -1'", "i8: '{:>4}'", .{@as(i8, -1)});
1610 try expectFmt("i8: ' -1 '", "i8: '{:^4}'", .{@as(i8, -1)});
1611 try expectFmt("i16: '-1234'", "i16: '{:4}'", .{@as(i16, -1234)});
1612 try expectFmt("i16: '+1234'", "i16: '{:4}'", .{@as(i16, 1234)});
1613 try expectFmt("i16: '-12345'", "i16: '{:4}'", .{@as(i16, -12345)});
1614 try expectFmt("i16: '+12345'", "i16: '{:4}'", .{@as(i16, 12345)});
1615 try expectFmt("u16: '12345'", "u16: '{:4}'", .{@as(u16, 12345)});
1616
1617 try expectFmt("UTF-8: 'ü '", "UTF-8: '{u:<4}'", .{'ü'});
1618 try expectFmt("UTF-8: ' ü'", "UTF-8: '{u:>4}'", .{'ü'});
1619 try expectFmt("UTF-8: ' ü '", "UTF-8: '{u:^4}'", .{'ü'});
16191620}
16201621
16211622test "buffer" {
......@@ -1638,12 +1639,12 @@ test "buffer" {
16381639test "array" {
16391640 {
16401641 const value: [3]u8 = "abc".*;
1641 try testFmt("array: abc\n", "array: {s}\n", .{value});
1642 try testFmt("array: abc\n", "array: {s}\n", .{&value});
1643 try testFmt("array: { 97, 98, 99 }\n", "array: {d}\n", .{value});
1642 try expectFmt("array: abc\n", "array: {s}\n", .{value});
1643 try expectFmt("array: abc\n", "array: {s}\n", .{&value});
1644 try expectFmt("array: { 97, 98, 99 }\n", "array: {d}\n", .{value});
16441645
16451646 var buf: [100]u8 = undefined;
1646 try testFmt(
1647 try expectFmt(
16471648 try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
16481649 "array: {*}\n",
16491650 .{&value},
......@@ -1654,60 +1655,60 @@ test "array" {
16541655test "slice" {
16551656 {
16561657 const value: []const u8 = "abc";
1657 try testFmt("slice: abc\n", "slice: {s}\n", .{value});
1658 try expectFmt("slice: abc\n", "slice: {s}\n", .{value});
16581659 }
16591660 {
16601661 var runtime_zero: usize = 0;
16611662 const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[runtime_zero..runtime_zero];
1662 try testFmt("slice: []const u8@deadbeef\n", "slice: {*}\n", .{value});
1663 try expectFmt("slice: []const u8@deadbeef\n", "slice: {*}\n", .{value});
16631664 }
16641665 {
16651666 const null_term_slice: [:0]const u8 = "\x00hello\x00";
1666 try testFmt("buf: \x00hello\x00\n", "buf: {s}\n", .{null_term_slice});
1667 try expectFmt("buf: \x00hello\x00\n", "buf: {s}\n", .{null_term_slice});
16671668 }
16681669
1669 try testFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"});
1670 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
1670 try expectFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"});
1671 try expectFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
16711672
16721673 {
16731674 var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };
16741675 var runtime_zero: usize = 0;
1675 try testFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {}", .{int_slice[runtime_zero..]});
1676 try testFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {d}", .{int_slice[runtime_zero..]});
1677 try testFmt("int: { 1, 1000, 5fad3, 423a35c7 }", "int: {x}", .{int_slice[runtime_zero..]});
1678 try testFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]});
1676 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {}", .{int_slice[runtime_zero..]});
1677 try expectFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {d}", .{int_slice[runtime_zero..]});
1678 try expectFmt("int: { 1, 1000, 5fad3, 423a35c7 }", "int: {x}", .{int_slice[runtime_zero..]});
1679 try expectFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]});
16791680 }
16801681}
16811682
16821683test "escape non-printable" {
1683 try testFmt("abc", "{e}", .{"abc"});
1684 try testFmt("ab\\xffc", "{e}", .{"ab\xffc"});
1685 try testFmt("ab\\xFFc", "{E}", .{"ab\xffc"});
1684 try expectFmt("abc", "{e}", .{"abc"});
1685 try expectFmt("ab\\xffc", "{e}", .{"ab\xffc"});
1686 try expectFmt("ab\\xFFc", "{E}", .{"ab\xffc"});
16861687}
16871688
16881689test "pointer" {
16891690 {
16901691 const value = @intToPtr(*align(1) i32, 0xdeadbeef);
1691 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
1692 try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
1692 try expectFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
1693 try expectFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
16931694 }
16941695 {
16951696 const value = @intToPtr(fn () void, 0xdeadbeef);
1696 try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
1697 try expectFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
16971698 }
16981699 {
16991700 const value = @intToPtr(fn () void, 0xdeadbeef);
1700 try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
1701 try expectFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
17011702 }
17021703}
17031704
17041705test "cstr" {
1705 try testFmt(
1706 try expectFmt(
17061707 "cstr: Test C\n",
17071708 "cstr: {s}\n",
17081709 .{@ptrCast([*c]const u8, "Test C")},
17091710 );
1710 try testFmt(
1711 try expectFmt(
17111712 "cstr: Test C\n",
17121713 "cstr: {s:10}\n",
17131714 .{@ptrCast([*c]const u8, "Test C")},
......@@ -1715,8 +1716,8 @@ test "cstr" {
17151716}
17161717
17171718test "filesize" {
1718 try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
1719 try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
1719 try expectFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
1720 try expectFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
17201721}
17211722
17221723test "struct" {
......@@ -1725,8 +1726,8 @@ test "struct" {
17251726 field: u8,
17261727 };
17271728 const value = Struct{ .field = 42 };
1728 try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
1729 try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
1729 try expectFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
1730 try expectFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
17301731 }
17311732 {
17321733 const Struct = struct {
......@@ -1734,7 +1735,7 @@ test "struct" {
17341735 b: u1,
17351736 };
17361737 const value = Struct{ .a = 0, .b = 1 };
1737 try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
1738 try expectFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
17381739 }
17391740}
17401741
......@@ -1744,13 +1745,13 @@ test "enum" {
17441745 Two,
17451746 };
17461747 const value = Enum.Two;
1747 try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
1748 try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
1749 try testFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One});
1750 try testFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two});
1748 try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
1749 try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
1750 try expectFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One});
1751 try expectFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two});
17511752
17521753 // test very large enum to verify ct branch quota is large enough
1753 try testFmt("enum: Win32Error.INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION});
1754 try expectFmt("enum: Win32Error.INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION});
17541755}
17551756
17561757test "non-exhaustive enum" {
......@@ -1759,78 +1760,78 @@ test "non-exhaustive enum" {
17591760 Two = 0xbeef,
17601761 _,
17611762 };
1762 try testFmt("enum: Enum.One\n", "enum: {}\n", .{Enum.One});
1763 try testFmt("enum: Enum.Two\n", "enum: {}\n", .{Enum.Two});
1764 try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
1765 try testFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One});
1766 try testFmt("enum: Enum.Two\n", "enum: {x}\n", .{Enum.Two});
1767 try testFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two});
1768 try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
1763 try expectFmt("enum: Enum.One\n", "enum: {}\n", .{Enum.One});
1764 try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{Enum.Two});
1765 try expectFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
1766 try expectFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One});
1767 try expectFmt("enum: Enum.Two\n", "enum: {x}\n", .{Enum.Two});
1768 try expectFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two});
1769 try expectFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
17691770}
17701771
17711772test "float.scientific" {
1772 try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
1773 try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
1774 try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
1775 try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
1773 try expectFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
1774 try expectFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
1775 try expectFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
1776 try expectFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
17761777}
17771778
17781779test "float.scientific.precision" {
1779 try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
1780 try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
1781 try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
1780 try expectFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
1781 try expectFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
1782 try expectFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
17821783 // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
17831784 // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
1784 try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
1785 try expectFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
17851786}
17861787
17871788test "float.special" {
1788 try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
1789 try expectFmt("f64: nan", "f64: {}", .{math.nan_f64});
17891790 // negative nan is not defined by IEE 754,
17901791 // and ARM thus normalizes it to positive nan
17911792 if (builtin.arch != builtin.Arch.arm) {
1792 try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
1793 try expectFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
17931794 }
1794 try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
1795 try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
1795 try expectFmt("f64: inf", "f64: {}", .{math.inf_f64});
1796 try expectFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
17961797}
17971798
17981799test "float.decimal" {
1799 try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
1800 try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
1801 try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
1802 try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
1800 try expectFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
1801 try expectFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
1802 try expectFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
1803 try expectFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
18031804 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
18041805 // -11.12339... is rounded back up to -11.1234
1805 try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
1806 try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
1807 try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
1808 try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
1809 try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
1810 try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
1811 try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
1812 try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
1813 try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
1814 try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
1806 try expectFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
1807 try expectFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
1808 try expectFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
1809 try expectFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
1810 try expectFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
1811 try expectFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
1812 try expectFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
1813 try expectFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
1814 try expectFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
1815 try expectFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
18151816}
18161817
18171818test "float.libc.sanity" {
1818 try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
1819 try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
1820 try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
1821 try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
1822 try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
1819 try expectFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
1820 try expectFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
1821 try expectFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
1822 try expectFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
1823 try expectFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
18231824
18241825 // libc differences
18251826 //
18261827 // This is 0.015625 exactly according to gdb. We thus round down,
18271828 // however glibc rounds up for some reason. This occurs for all
18281829 // floats of the form x.yyyy25 on a precision point.
1829 try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
1830 try expectFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
18301831 // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
18311832 // also rounds to 630 so I'm inclined to believe libc is not
18321833 // optimal here.
1833 try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
1834 try expectFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
18341835}
18351836
18361837test "custom" {
......@@ -1860,12 +1861,12 @@ test "custom" {
18601861 .x = 10.2,
18611862 .y = 2.22,
18621863 };
1863 try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
1864 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
1864 try expectFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
1865 try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
18651866
18661867 // same thing but not passing a pointer
1867 try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
1868 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
1868 try expectFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
1869 try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
18691870}
18701871
18711872test "struct" {
......@@ -1879,7 +1880,7 @@ test "struct" {
18791880 .b = error.Unused,
18801881 };
18811882
1882 try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
1883 try expectFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
18831884}
18841885
18851886test "union" {
......@@ -1902,7 +1903,7 @@ test "union" {
19021903 const uu_inst = UU{ .int = 456 };
19031904 const eu_inst = EU{ .float = 321.123 };
19041905
1905 try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
1906 try expectFmt("TU{ .int = 123 }", "{}", .{tu_inst});
19061907
19071908 var buf: [100]u8 = undefined;
19081909 const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
......@@ -1921,7 +1922,7 @@ test "enum" {
19211922
19221923 const inst = E.Two;
19231924
1924 try testFmt("E.Two", "{}", .{inst});
1925 try expectFmt("E.Two", "{}", .{inst});
19251926}
19261927
19271928test "struct.self-referential" {
......@@ -1935,7 +1936,7 @@ test "struct.self-referential" {
19351936 };
19361937 inst.a = &inst;
19371938
1938 try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
1939 try expectFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
19391940}
19401941
19411942test "struct.zero-size" {
......@@ -1950,31 +1951,18 @@ test "struct.zero-size" {
19501951 const a = A{};
19511952 const b = B{ .a = a, .c = 0 };
19521953
1953 try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
1954 try expectFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
19541955}
19551956
19561957test "bytes.hex" {
19571958 const some_bytes = "\xCA\xFE\xBA\xBE";
1958 try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
1959 try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
1959 try expectFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
1960 try expectFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
19601961 //Test Slices
1961 try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
1962 try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
1962 try expectFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
1963 try expectFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
19631964 const bytes_with_zeros = "\x00\x0E\xBA\xBE";
1964 try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
1965}
1966
1967pub fn testFmt(expected: []const u8, comptime template: []const u8, args: anytype) !void {
1968 var buf: [100]u8 = undefined;
1969 const result = try bufPrint(buf[0..], template, args);
1970 if (mem.eql(u8, result, expected)) return;
1971
1972 std.debug.warn("\n====== expected this output: =========\n", .{});
1973 std.debug.warn("{s}", .{expected});
1974 std.debug.warn("\n======== instead found this: =========\n", .{});
1975 std.debug.warn("{s}", .{result});
1976 std.debug.warn("\n======================================\n", .{});
1977 return error.TestFailed;
1965 try expectFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
19781966}
19791967
19801968pub const trim = @compileError("deprecated; use std.mem.trim with std.ascii.spaces instead");
......@@ -1996,7 +1984,7 @@ test "hexToBytes" {
19961984 const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
19971985 var pb: [32]u8 = undefined;
19981986 try hexToBytes(pb[0..], test_hex_str);
1999 try testFmt(test_hex_str, "{X}", .{pb});
1987 try expectFmt(test_hex_str, "{X}", .{pb});
20001988}
20011989
20021990test "formatIntValue with comptime_int" {
......@@ -2016,8 +2004,8 @@ test "formatFloatValue with comptime_float" {
20162004 try formatFloatValue(value, "", FormatOptions{}, fbs.writer());
20172005 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1.0e+00"));
20182006
2019 try testFmt("1.0e+00", "{}", .{value});
2020 try testFmt("1.0e+00", "{}", .{1.0});
2007 try expectFmt("1.0e+00", "{}", .{value});
2008 try expectFmt("1.0e+00", "{}", .{1.0});
20212009}
20222010
20232011test "formatType max_depth" {
......@@ -2086,19 +2074,19 @@ test "formatType max_depth" {
20862074}
20872075
20882076test "positional" {
2089 try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
2090 try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
2091 try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
2092 try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
2093 try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
2077 try expectFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
2078 try expectFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
2079 try expectFmt("0 0", "{0} {0}", .{@as(usize, 0)});
2080 try expectFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
2081 try expectFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
20942082}
20952083
20962084test "positional with specifier" {
2097 try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
2085 try expectFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
20982086}
20992087
21002088test "positional/alignment/width/precision" {
2101 try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
2089 try expectFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
21022090}
21032091
21042092test "vector" {
......@@ -2119,76 +2107,76 @@ test "vector" {
21192107 const vi64: std.meta.Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
21202108 const vu64: std.meta.Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
21212109
2122 try testFmt("{ true, false, true, false }", "{}", .{vbool});
2123 try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
2124 try testFmt("{ -2, -1, +0, +1 }", "{d:5}", .{vi64});
2125 try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
2126 try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
2127 try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
2128 try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
2110 try expectFmt("{ true, false, true, false }", "{}", .{vbool});
2111 try expectFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
2112 try expectFmt("{ -2, -1, +0, +1 }", "{d:5}", .{vi64});
2113 try expectFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
2114 try expectFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
2115 try expectFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
2116 try expectFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
21292117}
21302118
21312119test "enum-literal" {
2132 try testFmt(".hello_world", "{s}", .{.hello_world});
2120 try expectFmt(".hello_world", "{s}", .{.hello_world});
21332121}
21342122
21352123test "padding" {
2136 try testFmt("Simple", "{s}", .{"Simple"});
2137 try testFmt(" true", "{:10}", .{true});
2138 try testFmt(" true", "{:>10}", .{true});
2139 try testFmt("======true", "{:=>10}", .{true});
2140 try testFmt("true======", "{:=<10}", .{true});
2141 try testFmt(" true ", "{:^10}", .{true});
2142 try testFmt("===true===", "{:=^10}", .{true});
2143 try testFmt(" Minimum width", "{s:18} width", .{"Minimum"});
2144 try testFmt("==================Filled", "{s:=>24}", .{"Filled"});
2145 try testFmt(" Centered ", "{s:^24}", .{"Centered"});
2146 try testFmt("-", "{s:-^1}", .{""});
2147 try testFmt("==crêpe===", "{s:=^10}", .{"crêpe"});
2148 try testFmt("=====crêpe", "{s:=>10}", .{"crêpe"});
2149 try testFmt("crêpe=====", "{s:=<10}", .{"crêpe"});
2124 try expectFmt("Simple", "{s}", .{"Simple"});
2125 try expectFmt(" true", "{:10}", .{true});
2126 try expectFmt(" true", "{:>10}", .{true});
2127 try expectFmt("======true", "{:=>10}", .{true});
2128 try expectFmt("true======", "{:=<10}", .{true});
2129 try expectFmt(" true ", "{:^10}", .{true});
2130 try expectFmt("===true===", "{:=^10}", .{true});
2131 try expectFmt(" Minimum width", "{s:18} width", .{"Minimum"});
2132 try expectFmt("==================Filled", "{s:=>24}", .{"Filled"});
2133 try expectFmt(" Centered ", "{s:^24}", .{"Centered"});
2134 try expectFmt("-", "{s:-^1}", .{""});
2135 try expectFmt("==crêpe===", "{s:=^10}", .{"crêpe"});
2136 try expectFmt("=====crêpe", "{s:=>10}", .{"crêpe"});
2137 try expectFmt("crêpe=====", "{s:=<10}", .{"crêpe"});
21502138}
21512139
21522140test "decimal float padding" {
21532141 var number: f32 = 3.1415;
2154 try testFmt("left-pad: **3.141\n", "left-pad: {d:*>7.3}\n", .{number});
2155 try testFmt("center-pad: *3.141*\n", "center-pad: {d:*^7.3}\n", .{number});
2156 try testFmt("right-pad: 3.141**\n", "right-pad: {d:*<7.3}\n", .{number});
2142 try expectFmt("left-pad: **3.141\n", "left-pad: {d:*>7.3}\n", .{number});
2143 try expectFmt("center-pad: *3.141*\n", "center-pad: {d:*^7.3}\n", .{number});
2144 try expectFmt("right-pad: 3.141**\n", "right-pad: {d:*<7.3}\n", .{number});
21572145}
21582146
21592147test "sci float padding" {
21602148 var number: f32 = 3.1415;
2161 try testFmt("left-pad: **3.141e+00\n", "left-pad: {e:*>11.3}\n", .{number});
2162 try testFmt("center-pad: *3.141e+00*\n", "center-pad: {e:*^11.3}\n", .{number});
2163 try testFmt("right-pad: 3.141e+00**\n", "right-pad: {e:*<11.3}\n", .{number});
2149 try expectFmt("left-pad: **3.141e+00\n", "left-pad: {e:*>11.3}\n", .{number});
2150 try expectFmt("center-pad: *3.141e+00*\n", "center-pad: {e:*^11.3}\n", .{number});
2151 try expectFmt("right-pad: 3.141e+00**\n", "right-pad: {e:*<11.3}\n", .{number});
21642152}
21652153
21662154test "null" {
21672155 const inst = null;
2168 try testFmt("null", "{}", .{inst});
2156 try expectFmt("null", "{}", .{inst});
21692157}
21702158
21712159test "type" {
2172 try testFmt("u8", "{}", .{u8});
2173 try testFmt("?f32", "{}", .{?f32});
2174 try testFmt("[]const u8", "{}", .{[]const u8});
2160 try expectFmt("u8", "{}", .{u8});
2161 try expectFmt("?f32", "{}", .{?f32});
2162 try expectFmt("[]const u8", "{}", .{[]const u8});
21752163}
21762164
21772165test "named arguments" {
2178 try testFmt("hello world!", "{s} world{c}", .{ "hello", '!' });
2179 try testFmt("hello world!", "{[greeting]s} world{[punctuation]c}", .{ .punctuation = '!', .greeting = "hello" });
2180 try testFmt("hello world!", "{[1]s} world{[0]c}", .{ '!', "hello" });
2166 try expectFmt("hello world!", "{s} world{c}", .{ "hello", '!' });
2167 try expectFmt("hello world!", "{[greeting]s} world{[punctuation]c}", .{ .punctuation = '!', .greeting = "hello" });
2168 try expectFmt("hello world!", "{[1]s} world{[0]c}", .{ '!', "hello" });
21812169}
21822170
21832171test "runtime width specifier" {
21842172 var width: usize = 9;
2185 try testFmt("~~hello~~", "{s:~^[1]}", .{ "hello", width });
2186 try testFmt("~~hello~~", "{s:~^[width]}", .{ .string = "hello", .width = width });
2173 try expectFmt("~~hello~~", "{s:~^[1]}", .{ "hello", width });
2174 try expectFmt("~~hello~~", "{s:~^[width]}", .{ .string = "hello", .width = width });
21872175}
21882176
21892177test "runtime precision specifier" {
21902178 var number: f32 = 3.1415;
21912179 var precision: usize = 2;
2192 try testFmt("3.14e+00", "{:1.[1]}", .{ number, precision });
2193 try testFmt("3.14e+00", "{:1.[precision]}", .{ .number = number, .precision = precision });
2180 try expectFmt("3.14e+00", "{:1.[1]}", .{ number, precision });
2181 try expectFmt("3.14e+00", "{:1.[precision]}", .{ .number = number, .precision = precision });
21942182}
lib/std/testing.zig+16
......@@ -184,6 +184,22 @@ test "expectEqual.union(enum)" {
184184 expectEqual(a10, a10);
185185}
186186
187/// This function is intended to be used only in tests. When the formatted result of the template
188/// and its arguments does not equal the expected text, it prints diagnostics to stderr to show how
189/// they are not equal, then returns an error.
190pub fn expectFmt(expected: []const u8, comptime template: []const u8, args: anytype) !void {
191 const result = try std.fmt.allocPrint(allocator, template, args);
192 defer allocator.free(result);
193 if (std.mem.eql(u8, result, expected)) return;
194
195 print("\n====== expected this output: =========\n", .{});
196 print("{s}", .{expected});
197 print("\n======== instead found this: =========\n", .{});
198 print("{s}", .{result});
199 print("\n======================================\n", .{});
200 return error.TestFailed;
201}
202
187203/// This function is intended to be used only in tests. When the actual value is not
188204/// within the margin of the expected value,
189205/// prints diagnostics to stderr to show exactly how they are not equal, then aborts.
lib/std/zig/fmt.zig+7-6
......@@ -60,12 +60,13 @@ pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(formatEscapes) {
6060}
6161
6262test "escape invalid identifiers" {
63 try std.fmt.testFmt("@\"while\"", "{}", .{fmtId("while")});
64 try std.fmt.testFmt("hello", "{}", .{fmtId("hello")});
65 try std.fmt.testFmt("@\"11\\\"23\"", "{}", .{fmtId("11\"23")});
66 try std.fmt.testFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});
67 try std.fmt.testFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});
68 try std.fmt.testFmt(
63 const expectFmt = std.testing.expectFmt;
64 try expectFmt("@\"while\"", "{}", .{fmtId("while")});
65 try expectFmt("hello", "{}", .{fmtId("hello")});
66 try expectFmt("@\"11\\\"23\"", "{}", .{fmtId("11\"23")});
67 try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});
68 try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});
69 try expectFmt(
6970 \\" \\ hi \x07 \x11 \" derp \'"
7071 , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
7172}