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" {...@@ -205,7 +205,7 @@ test "SemanticVersion format" {
205 "1.2.3----R-S.12.9.1--.12+meta",205 "1.2.3----R-S.12.9.1--.12+meta",
206 "1.2.3----RC-SNAPSHOT.12.9.1--.12",206 "1.2.3----RC-SNAPSHOT.12.9.1--.12",
207 "1.0.0+0.build.1-rc.10000aaa-kk-0.1",207 "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
210 // Invalid version strings should be rejected.210 // Invalid version strings should be rejected.
211 for ([_][]const u8{211 for ([_][]const u8{
...@@ -253,7 +253,9 @@ test "SemanticVersion format" {...@@ -253,7 +253,9 @@ test "SemanticVersion format" {
253253
254 // Valid version string that may overflow.254 // Valid version string that may overflow.
255 const big_valid = "99999999999999999999999.999999999999999999.99999999999999999";255 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
258 // Invalid version string that may overflow.260 // Invalid version string that may overflow.
259 const big_invalid = "99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12";261 const big_invalid = "99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..12";
...@@ -280,20 +282,6 @@ test "SemanticVersion precedence" {...@@ -280,20 +282,6 @@ test "SemanticVersion precedence" {
280 expect(order(try parse("1.0.0-rc.1"), try parse("1.0.0")) == .lt);282 expect(order(try parse("1.0.0-rc.1"), try parse("1.0.0")) == .lt);
281}283}
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
297test "zig_version" {285test "zig_version" {
298 // An approximate Zig build that predates this test.286 // An approximate Zig build that predates this test.
299 const older_version = .{ .major = 0, .minor = 8, .patch = 0, .pre = "dev.874" };287 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;...@@ -12,6 +12,7 @@ const meta = std.meta;
12const builtin = @import("builtin");12const builtin = @import("builtin");
13const errol = @import("fmt/errol.zig");13const errol = @import("fmt/errol.zig");
14const lossyCast = std.math.lossyCast;14const lossyCast = std.math.lossyCast;
15const expectFmt = std.testing.expectFmt;
1516
16pub const default_max_depth = 3;17pub const default_max_depth = 3;
1718
...@@ -1531,91 +1532,91 @@ test "parse unsigned comptime" {...@@ -1531,91 +1532,91 @@ test "parse unsigned comptime" {
1531}1532}
15321533
1533test "escaped braces" {1534test "escaped braces" {
1534 try testFmt("escaped: {{foo}}\n", "escaped: {{{{foo}}}}\n", .{});1535 try expectFmt("escaped: {{foo}}\n", "escaped: {{{{foo}}}}\n", .{});
1535 try testFmt("escaped: {foo}\n", "escaped: {{foo}}\n", .{});1536 try expectFmt("escaped: {foo}\n", "escaped: {{foo}}\n", .{});
1536}1537}
15371538
1538test "optional" {1539test "optional" {
1539 {1540 {
1540 const value: ?i32 = 1234;1541 const value: ?i32 = 1234;
1541 try testFmt("optional: 1234\n", "optional: {}\n", .{value});1542 try expectFmt("optional: 1234\n", "optional: {}\n", .{value});
1542 }1543 }
1543 {1544 {
1544 const value: ?i32 = null;1545 const value: ?i32 = null;
1545 try testFmt("optional: null\n", "optional: {}\n", .{value});1546 try expectFmt("optional: null\n", "optional: {}\n", .{value});
1546 }1547 }
1547 {1548 {
1548 const value = @intToPtr(?*i32, 0xf000d000);1549 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});
1550 }1551 }
1551}1552}
15521553
1553test "error" {1554test "error" {
1554 {1555 {
1555 const value: anyerror!i32 = 1234;1556 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});
1557 }1558 }
1558 {1559 {
1559 const value: anyerror!i32 = error.InvalidChar;1560 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});
1561 }1562 }
1562}1563}
15631564
1564test "int.small" {1565test "int.small" {
1565 {1566 {
1566 const value: u3 = 0b101;1567 const value: u3 = 0b101;
1567 try testFmt("u3: 5\n", "u3: {}\n", .{value});1568 try expectFmt("u3: 5\n", "u3: {}\n", .{value});
1568 }1569 }
1569}1570}
15701571
1571test "int.specifier" {1572test "int.specifier" {
1572 {1573 {
1573 const value: u8 = 'a';1574 const value: u8 = 'a';
1574 try testFmt("u8: a\n", "u8: {c}\n", .{value});1575 try expectFmt("u8: a\n", "u8: {c}\n", .{value});
1575 }1576 }
1576 {1577 {
1577 const value: u8 = 0b1100;1578 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});
1579 }1580 }
1580 {1581 {
1581 const value: u16 = 0o1234;1582 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});
1583 }1584 }
1584 {1585 {
1585 const value: u8 = 'a';1586 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});
1587 }1588 }
1588 {1589 {
1589 const value: u21 = 0x1F310;1590 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});
1591 }1592 }
1592 {1593 {
1593 const value: u21 = 0xD800;1594 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});
1595 }1596 }
1596 {1597 {
1597 const value: u21 = 0x110001;1598 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});
1599 }1600 }
1600}1601}
16011602
1602test "int.padded" {1603test "int.padded" {
1603 try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});1604 try expectFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
1604 try testFmt("u8: '1000'", "u8: '{:0<4}'", .{@as(u8, 1)});1605 try expectFmt("u8: '1000'", "u8: '{:0<4}'", .{@as(u8, 1)});
1605 try testFmt("u8: '0001'", "u8: '{:0>4}'", .{@as(u8, 1)});1606 try expectFmt("u8: '0001'", "u8: '{:0>4}'", .{@as(u8, 1)});
1606 try testFmt("u8: '0100'", "u8: '{:0^4}'", .{@as(u8, 1)});1607 try expectFmt("u8: '0100'", "u8: '{:0^4}'", .{@as(u8, 1)});
1607 try testFmt("i8: '-1 '", "i8: '{:<4}'", .{@as(i8, -1)});1608 try expectFmt("i8: '-1 '", "i8: '{:<4}'", .{@as(i8, -1)});
1608 try testFmt("i8: ' -1'", "i8: '{:>4}'", .{@as(i8, -1)});1609 try expectFmt("i8: ' -1'", "i8: '{:>4}'", .{@as(i8, -1)});
1609 try testFmt("i8: ' -1 '", "i8: '{:^4}'", .{@as(i8, -1)});1610 try expectFmt("i8: ' -1 '", "i8: '{:^4}'", .{@as(i8, -1)});
1610 try testFmt("i16: '-1234'", "i16: '{:4}'", .{@as(i16, -1234)});1611 try expectFmt("i16: '-1234'", "i16: '{:4}'", .{@as(i16, -1234)});
1611 try testFmt("i16: '+1234'", "i16: '{:4}'", .{@as(i16, 1234)});1612 try expectFmt("i16: '+1234'", "i16: '{:4}'", .{@as(i16, 1234)});
1612 try testFmt("i16: '-12345'", "i16: '{:4}'", .{@as(i16, -12345)});1613 try expectFmt("i16: '-12345'", "i16: '{:4}'", .{@as(i16, -12345)});
1613 try testFmt("i16: '+12345'", "i16: '{:4}'", .{@as(i16, 12345)});1614 try expectFmt("i16: '+12345'", "i16: '{:4}'", .{@as(i16, 12345)});
1614 try testFmt("u16: '12345'", "u16: '{:4}'", .{@as(u16, 12345)});1615 try expectFmt("u16: '12345'", "u16: '{:4}'", .{@as(u16, 12345)});
16151616
1616 try testFmt("UTF-8: 'ü '", "UTF-8: '{u:<4}'", .{'ü'});1617 try expectFmt("UTF-8: 'ü '", "UTF-8: '{u:<4}'", .{'ü'});
1617 try testFmt("UTF-8: ' ü'", "UTF-8: '{u:>4}'", .{'ü'});1618 try expectFmt("UTF-8: ' ü'", "UTF-8: '{u:>4}'", .{'ü'});
1618 try testFmt("UTF-8: ' ü '", "UTF-8: '{u:^4}'", .{'ü'});1619 try expectFmt("UTF-8: ' ü '", "UTF-8: '{u:^4}'", .{'ü'});
1619}1620}
16201621
1621test "buffer" {1622test "buffer" {
...@@ -1638,12 +1639,12 @@ test "buffer" {...@@ -1638,12 +1639,12 @@ test "buffer" {
1638test "array" {1639test "array" {
1639 {1640 {
1640 const value: [3]u8 = "abc".*;1641 const value: [3]u8 = "abc".*;
1641 try testFmt("array: abc\n", "array: {s}\n", .{value});1642 try expectFmt("array: abc\n", "array: {s}\n", .{value});
1642 try testFmt("array: abc\n", "array: {s}\n", .{&value});1643 try expectFmt("array: abc\n", "array: {s}\n", .{&value});
1643 try testFmt("array: { 97, 98, 99 }\n", "array: {d}\n", .{value});1644 try expectFmt("array: { 97, 98, 99 }\n", "array: {d}\n", .{value});
16441645
1645 var buf: [100]u8 = undefined;1646 var buf: [100]u8 = undefined;
1646 try testFmt(1647 try expectFmt(
1647 try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),1648 try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
1648 "array: {*}\n",1649 "array: {*}\n",
1649 .{&value},1650 .{&value},
...@@ -1654,60 +1655,60 @@ test "array" {...@@ -1654,60 +1655,60 @@ test "array" {
1654test "slice" {1655test "slice" {
1655 {1656 {
1656 const value: []const u8 = "abc";1657 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});
1658 }1659 }
1659 {1660 {
1660 var runtime_zero: usize = 0;1661 var runtime_zero: usize = 0;
1661 const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[runtime_zero..runtime_zero];1662 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});
1663 }1664 }
1664 {1665 {
1665 const null_term_slice: [:0]const u8 = "\x00hello\x00";1666 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});
1667 }1668 }
16681669
1669 try testFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"});1670 try expectFmt("buf: Test\n", "buf: {s:5}\n", .{"Test"});
1670 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});1671 try expectFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
16711672
1672 {1673 {
1673 var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };1674 var int_slice = [_]u32{ 1, 4096, 391891, 1111111111 };
1674 var runtime_zero: usize = 0;1675 var runtime_zero: usize = 0;
1675 try testFmt("int: { 1, 4096, 391891, 1111111111 }", "int: {}", .{int_slice[runtime_zero..]});1676 try expectFmt("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 expectFmt("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 expectFmt("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..]});1679 try expectFmt("int: { 00001, 01000, 5fad3, 423a35c7 }", "int: {x:0>5}", .{int_slice[runtime_zero..]});
1679 }1680 }
1680}1681}
16811682
1682test "escape non-printable" {1683test "escape non-printable" {
1683 try testFmt("abc", "{e}", .{"abc"});1684 try expectFmt("abc", "{e}", .{"abc"});
1684 try testFmt("ab\\xffc", "{e}", .{"ab\xffc"});1685 try expectFmt("ab\\xffc", "{e}", .{"ab\xffc"});
1685 try testFmt("ab\\xFFc", "{E}", .{"ab\xffc"});1686 try expectFmt("ab\\xFFc", "{E}", .{"ab\xffc"});
1686}1687}
16871688
1688test "pointer" {1689test "pointer" {
1689 {1690 {
1690 const value = @intToPtr(*align(1) i32, 0xdeadbeef);1691 const value = @intToPtr(*align(1) i32, 0xdeadbeef);
1691 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});1692 try expectFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
1692 try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});1693 try expectFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
1693 }1694 }
1694 {1695 {
1695 const value = @intToPtr(fn () void, 0xdeadbeef);1696 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});
1697 }1698 }
1698 {1699 {
1699 const value = @intToPtr(fn () void, 0xdeadbeef);1700 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});
1701 }1702 }
1702}1703}
17031704
1704test "cstr" {1705test "cstr" {
1705 try testFmt(1706 try expectFmt(
1706 "cstr: Test C\n",1707 "cstr: Test C\n",
1707 "cstr: {s}\n",1708 "cstr: {s}\n",
1708 .{@ptrCast([*c]const u8, "Test C")},1709 .{@ptrCast([*c]const u8, "Test C")},
1709 );1710 );
1710 try testFmt(1711 try expectFmt(
1711 "cstr: Test C\n",1712 "cstr: Test C\n",
1712 "cstr: {s:10}\n",1713 "cstr: {s:10}\n",
1713 .{@ptrCast([*c]const u8, "Test C")},1714 .{@ptrCast([*c]const u8, "Test C")},
...@@ -1715,8 +1716,8 @@ test "cstr" {...@@ -1715,8 +1716,8 @@ test "cstr" {
1715}1716}
17161717
1717test "filesize" {1718test "filesize" {
1718 try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});1719 try expectFmt("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)});1720 try expectFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
1720}1721}
17211722
1722test "struct" {1723test "struct" {
...@@ -1725,8 +1726,8 @@ test "struct" {...@@ -1725,8 +1726,8 @@ test "struct" {
1725 field: u8,1726 field: u8,
1726 };1727 };
1727 const value = Struct{ .field = 42 };1728 const value = Struct{ .field = 42 };
1728 try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});1729 try expectFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
1729 try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});1730 try expectFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
1730 }1731 }
1731 {1732 {
1732 const Struct = struct {1733 const Struct = struct {
...@@ -1734,7 +1735,7 @@ test "struct" {...@@ -1734,7 +1735,7 @@ test "struct" {
1734 b: u1,1735 b: u1,
1735 };1736 };
1736 const value = Struct{ .a = 0, .b = 1 };1737 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});
1738 }1739 }
1739}1740}
17401741
...@@ -1744,13 +1745,13 @@ test "enum" {...@@ -1744,13 +1745,13 @@ test "enum" {
1744 Two,1745 Two,
1745 };1746 };
1746 const value = Enum.Two;1747 const value = Enum.Two;
1747 try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});1748 try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
1748 try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});1749 try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
1749 try testFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One});1750 try expectFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One});
1750 try testFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two});1751 try expectFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two});
17511752
1752 // test very large enum to verify ct branch quota is large enough1753 // 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});
1754}1755}
17551756
1756test "non-exhaustive enum" {1757test "non-exhaustive enum" {
...@@ -1759,78 +1760,78 @@ test "non-exhaustive enum" {...@@ -1759,78 +1760,78 @@ test "non-exhaustive enum" {
1759 Two = 0xbeef,1760 Two = 0xbeef,
1760 _,1761 _,
1761 };1762 };
1762 try testFmt("enum: Enum.One\n", "enum: {}\n", .{Enum.One});1763 try expectFmt("enum: Enum.One\n", "enum: {}\n", .{Enum.One});
1763 try testFmt("enum: Enum.Two\n", "enum: {}\n", .{Enum.Two});1764 try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{Enum.Two});
1764 try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});1765 try expectFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
1765 try testFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One});1766 try expectFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One});
1766 try testFmt("enum: Enum.Two\n", "enum: {x}\n", .{Enum.Two});1767 try expectFmt("enum: Enum.Two\n", "enum: {x}\n", .{Enum.Two});
1767 try testFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two});1768 try expectFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two});
1768 try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});1769 try expectFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
1769}1770}
17701771
1771test "float.scientific" {1772test "float.scientific" {
1772 try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});1773 try expectFmt("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 expectFmt("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 expectFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
1775 try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});1776 try expectFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
1776}1777}
17771778
1778test "float.scientific.precision" {1779test "float.scientific.precision" {
1779 try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});1780 try expectFmt("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 expectFmt("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)))});1782 try expectFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
1782 // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.1783 // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
1783 // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.1784 // 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)))});
1785}1786}
17861787
1787test "float.special" {1788test "float.special" {
1788 try testFmt("f64: nan", "f64: {}", .{math.nan_f64});1789 try expectFmt("f64: nan", "f64: {}", .{math.nan_f64});
1789 // negative nan is not defined by IEE 754,1790 // negative nan is not defined by IEE 754,
1790 // and ARM thus normalizes it to positive nan1791 // and ARM thus normalizes it to positive nan
1791 if (builtin.arch != builtin.Arch.arm) {1792 if (builtin.arch != builtin.Arch.arm) {
1792 try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});1793 try expectFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
1793 }1794 }
1794 try testFmt("f64: inf", "f64: {}", .{math.inf_f64});1795 try expectFmt("f64: inf", "f64: {}", .{math.inf_f64});
1795 try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});1796 try expectFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
1796}1797}
17971798
1798test "float.decimal" {1799test "float.decimal" {
1799 try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});1800 try expectFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
1800 try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});1801 try expectFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
1801 try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});1802 try expectFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
1802 try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});1803 try expectFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
1803 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).1804 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
1804 // -11.12339... is rounded back up to -11.12341805 // -11.12339... is rounded back up to -11.1234
1805 try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});1806 try expectFmt("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 expectFmt("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 expectFmt("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 expectFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
1809 try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});1810 try expectFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
1810 try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});1811 try expectFmt("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 expectFmt("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 expectFmt("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 expectFmt("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)});1815 try expectFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
1815}1816}
18161817
1817test "float.libc.sanity" {1818test "float.libc.sanity" {
1818 try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});1819 try expectFmt("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 expectFmt("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 expectFmt("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 expectFmt("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)))});1823 try expectFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
18231824
1824 // libc differences1825 // libc differences
1825 //1826 //
1826 // This is 0.015625 exactly according to gdb. We thus round down,1827 // This is 0.015625 exactly according to gdb. We thus round down,
1827 // however glibc rounds up for some reason. This occurs for all1828 // however glibc rounds up for some reason. This occurs for all
1828 // floats of the form x.yyyy25 on a precision point.1829 // 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)))});
1830 // errol3 rounds to ... 630 but libc rounds to ...632. Grisu31831 // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
1831 // also rounds to 630 so I'm inclined to believe libc is not1832 // also rounds to 630 so I'm inclined to believe libc is not
1832 // optimal here.1833 // 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)))});
1834}1835}
18351836
1836test "custom" {1837test "custom" {
...@@ -1860,12 +1861,12 @@ test "custom" {...@@ -1860,12 +1861,12 @@ test "custom" {
1860 .x = 10.2,1861 .x = 10.2,
1861 .y = 2.22,1862 .y = 2.22,
1862 };1863 };
1863 try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});1864 try expectFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
1864 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});1865 try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
18651866
1866 // same thing but not passing a pointer1867 // same thing but not passing a pointer
1867 try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});1868 try expectFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
1868 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});1869 try expectFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
1869}1870}
18701871
1871test "struct" {1872test "struct" {
...@@ -1879,7 +1880,7 @@ test "struct" {...@@ -1879,7 +1880,7 @@ test "struct" {
1879 .b = error.Unused,1880 .b = error.Unused,
1880 };1881 };
18811882
1882 try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});1883 try expectFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
1883}1884}
18841885
1885test "union" {1886test "union" {
...@@ -1902,7 +1903,7 @@ test "union" {...@@ -1902,7 +1903,7 @@ test "union" {
1902 const uu_inst = UU{ .int = 456 };1903 const uu_inst = UU{ .int = 456 };
1903 const eu_inst = EU{ .float = 321.123 };1904 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
1907 var buf: [100]u8 = undefined;1908 var buf: [100]u8 = undefined;
1908 const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});1909 const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
...@@ -1921,7 +1922,7 @@ test "enum" {...@@ -1921,7 +1922,7 @@ test "enum" {
19211922
1922 const inst = E.Two;1923 const inst = E.Two;
19231924
1924 try testFmt("E.Two", "{}", .{inst});1925 try expectFmt("E.Two", "{}", .{inst});
1925}1926}
19261927
1927test "struct.self-referential" {1928test "struct.self-referential" {
...@@ -1935,7 +1936,7 @@ test "struct.self-referential" {...@@ -1935,7 +1936,7 @@ test "struct.self-referential" {
1935 };1936 };
1936 inst.a = &inst;1937 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});
1939}1940}
19401941
1941test "struct.zero-size" {1942test "struct.zero-size" {
...@@ -1950,31 +1951,18 @@ test "struct.zero-size" {...@@ -1950,31 +1951,18 @@ test "struct.zero-size" {
1950 const a = A{};1951 const a = A{};
1951 const b = B{ .a = a, .c = 0 };1952 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});
1954}1955}
19551956
1956test "bytes.hex" {1957test "bytes.hex" {
1957 const some_bytes = "\xCA\xFE\xBA\xBE";1958 const some_bytes = "\xCA\xFE\xBA\xBE";
1958 try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});1959 try expectFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
1959 try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});1960 try expectFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
1960 //Test Slices1961 //Test Slices
1961 try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});1962 try expectFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
1962 try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});1963 try expectFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
1963 const bytes_with_zeros = "\x00\x0E\xBA\xBE";1964 const bytes_with_zeros = "\x00\x0E\xBA\xBE";
1964 try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});1965 try expectFmt("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;
1978}1966}
19791967
1980pub const trim = @compileError("deprecated; use std.mem.trim with std.ascii.spaces instead");1968pub const trim = @compileError("deprecated; use std.mem.trim with std.ascii.spaces instead");
...@@ -1996,7 +1984,7 @@ test "hexToBytes" {...@@ -1996,7 +1984,7 @@ test "hexToBytes" {
1996 const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";1984 const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
1997 var pb: [32]u8 = undefined;1985 var pb: [32]u8 = undefined;
1998 try hexToBytes(pb[0..], test_hex_str);1986 try hexToBytes(pb[0..], test_hex_str);
1999 try testFmt(test_hex_str, "{X}", .{pb});1987 try expectFmt(test_hex_str, "{X}", .{pb});
2000}1988}
20011989
2002test "formatIntValue with comptime_int" {1990test "formatIntValue with comptime_int" {
...@@ -2016,8 +2004,8 @@ test "formatFloatValue with comptime_float" {...@@ -2016,8 +2004,8 @@ test "formatFloatValue with comptime_float" {
2016 try formatFloatValue(value, "", FormatOptions{}, fbs.writer());2004 try formatFloatValue(value, "", FormatOptions{}, fbs.writer());
2017 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1.0e+00"));2005 std.testing.expect(mem.eql(u8, fbs.getWritten(), "1.0e+00"));
20182006
2019 try testFmt("1.0e+00", "{}", .{value});2007 try expectFmt("1.0e+00", "{}", .{value});
2020 try testFmt("1.0e+00", "{}", .{1.0});2008 try expectFmt("1.0e+00", "{}", .{1.0});
2021}2009}
20222010
2023test "formatType max_depth" {2011test "formatType max_depth" {
...@@ -2086,19 +2074,19 @@ test "formatType max_depth" {...@@ -2086,19 +2074,19 @@ test "formatType max_depth" {
2086}2074}
20872075
2088test "positional" {2076test "positional" {
2089 try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });2077 try expectFmt("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) });2078 try expectFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
2091 try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});2079 try expectFmt("0 0", "{0} {0}", .{@as(usize, 0)});
2092 try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });2080 try expectFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
2093 try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });2081 try expectFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
2094}2082}
20952083
2096test "positional with specifier" {2084test "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)});
2098}2086}
20992087
2100test "positional/alignment/width/precision" {2088test "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)});
2102}2090}
21032091
2104test "vector" {2092test "vector" {
...@@ -2119,76 +2107,76 @@ test "vector" {...@@ -2119,76 +2107,76 @@ test "vector" {
2119 const vi64: std.meta.Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };2107 const vi64: std.meta.Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
2120 const vu64: std.meta.Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };2108 const vu64: std.meta.Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
21212109
2122 try testFmt("{ true, false, true, false }", "{}", .{vbool});2110 try expectFmt("{ true, false, true, false }", "{}", .{vbool});
2123 try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});2111 try expectFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
2124 try testFmt("{ -2, -1, +0, +1 }", "{d:5}", .{vi64});2112 try expectFmt("{ -2, -1, +0, +1 }", "{d:5}", .{vi64});
2125 try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});2113 try expectFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
2126 try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});2114 try expectFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
2127 try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});2115 try expectFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
2128 try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});2116 try expectFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
2129}2117}
21302118
2131test "enum-literal" {2119test "enum-literal" {
2132 try testFmt(".hello_world", "{s}", .{.hello_world});2120 try expectFmt(".hello_world", "{s}", .{.hello_world});
2133}2121}
21342122
2135test "padding" {2123test "padding" {
2136 try testFmt("Simple", "{s}", .{"Simple"});2124 try expectFmt("Simple", "{s}", .{"Simple"});
2137 try testFmt(" true", "{:10}", .{true});2125 try expectFmt(" true", "{:10}", .{true});
2138 try testFmt(" true", "{:>10}", .{true});2126 try expectFmt(" true", "{:>10}", .{true});
2139 try testFmt("======true", "{:=>10}", .{true});2127 try expectFmt("======true", "{:=>10}", .{true});
2140 try testFmt("true======", "{:=<10}", .{true});2128 try expectFmt("true======", "{:=<10}", .{true});
2141 try testFmt(" true ", "{:^10}", .{true});2129 try expectFmt(" true ", "{:^10}", .{true});
2142 try testFmt("===true===", "{:=^10}", .{true});2130 try expectFmt("===true===", "{:=^10}", .{true});
2143 try testFmt(" Minimum width", "{s:18} width", .{"Minimum"});2131 try expectFmt(" Minimum width", "{s:18} width", .{"Minimum"});
2144 try testFmt("==================Filled", "{s:=>24}", .{"Filled"});2132 try expectFmt("==================Filled", "{s:=>24}", .{"Filled"});
2145 try testFmt(" Centered ", "{s:^24}", .{"Centered"});2133 try expectFmt(" Centered ", "{s:^24}", .{"Centered"});
2146 try testFmt("-", "{s:-^1}", .{""});2134 try expectFmt("-", "{s:-^1}", .{""});
2147 try testFmt("==crêpe===", "{s:=^10}", .{"crêpe"});2135 try expectFmt("==crêpe===", "{s:=^10}", .{"crêpe"});
2148 try testFmt("=====crêpe", "{s:=>10}", .{"crêpe"});2136 try expectFmt("=====crêpe", "{s:=>10}", .{"crêpe"});
2149 try testFmt("crêpe=====", "{s:=<10}", .{"crêpe"});2137 try expectFmt("crêpe=====", "{s:=<10}", .{"crêpe"});
2150}2138}
21512139
2152test "decimal float padding" {2140test "decimal float padding" {
2153 var number: f32 = 3.1415;2141 var number: f32 = 3.1415;
2154 try testFmt("left-pad: **3.141\n", "left-pad: {d:*>7.3}\n", .{number});2142 try expectFmt("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});2143 try expectFmt("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});2144 try expectFmt("right-pad: 3.141**\n", "right-pad: {d:*<7.3}\n", .{number});
2157}2145}
21582146
2159test "sci float padding" {2147test "sci float padding" {
2160 var number: f32 = 3.1415;2148 var number: f32 = 3.1415;
2161 try testFmt("left-pad: **3.141e+00\n", "left-pad: {e:*>11.3}\n", .{number});2149 try expectFmt("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});2150 try expectFmt("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});2151 try expectFmt("right-pad: 3.141e+00**\n", "right-pad: {e:*<11.3}\n", .{number});
2164}2152}
21652153
2166test "null" {2154test "null" {
2167 const inst = null;2155 const inst = null;
2168 try testFmt("null", "{}", .{inst});2156 try expectFmt("null", "{}", .{inst});
2169}2157}
21702158
2171test "type" {2159test "type" {
2172 try testFmt("u8", "{}", .{u8});2160 try expectFmt("u8", "{}", .{u8});
2173 try testFmt("?f32", "{}", .{?f32});2161 try expectFmt("?f32", "{}", .{?f32});
2174 try testFmt("[]const u8", "{}", .{[]const u8});2162 try expectFmt("[]const u8", "{}", .{[]const u8});
2175}2163}
21762164
2177test "named arguments" {2165test "named arguments" {
2178 try testFmt("hello world!", "{s} world{c}", .{ "hello", '!' });2166 try expectFmt("hello world!", "{s} world{c}", .{ "hello", '!' });
2179 try testFmt("hello world!", "{[greeting]s} world{[punctuation]c}", .{ .punctuation = '!', .greeting = "hello" });2167 try expectFmt("hello world!", "{[greeting]s} world{[punctuation]c}", .{ .punctuation = '!', .greeting = "hello" });
2180 try testFmt("hello world!", "{[1]s} world{[0]c}", .{ '!', "hello" });2168 try expectFmt("hello world!", "{[1]s} world{[0]c}", .{ '!', "hello" });
2181}2169}
21822170
2183test "runtime width specifier" {2171test "runtime width specifier" {
2184 var width: usize = 9;2172 var width: usize = 9;
2185 try testFmt("~~hello~~", "{s:~^[1]}", .{ "hello", width });2173 try expectFmt("~~hello~~", "{s:~^[1]}", .{ "hello", width });
2186 try testFmt("~~hello~~", "{s:~^[width]}", .{ .string = "hello", .width = width });2174 try expectFmt("~~hello~~", "{s:~^[width]}", .{ .string = "hello", .width = width });
2187}2175}
21882176
2189test "runtime precision specifier" {2177test "runtime precision specifier" {
2190 var number: f32 = 3.1415;2178 var number: f32 = 3.1415;
2191 var precision: usize = 2;2179 var precision: usize = 2;
2192 try testFmt("3.14e+00", "{:1.[1]}", .{ number, precision });2180 try expectFmt("3.14e+00", "{:1.[1]}", .{ number, precision });
2193 try testFmt("3.14e+00", "{:1.[precision]}", .{ .number = number, .precision = precision });2181 try expectFmt("3.14e+00", "{:1.[precision]}", .{ .number = number, .precision = precision });
2194}2182}
lib/std/testing.zig+16
...@@ -184,6 +184,22 @@ test "expectEqual.union(enum)" {...@@ -184,6 +184,22 @@ test "expectEqual.union(enum)" {
184 expectEqual(a10, a10);184 expectEqual(a10, a10);
185}185}
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
187/// This function is intended to be used only in tests. When the actual value is not203/// This function is intended to be used only in tests. When the actual value is not
188/// within the margin of the expected value,204/// within the margin of the expected value,
189/// prints diagnostics to stderr to show exactly how they are not equal, then aborts.205/// 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) {...@@ -60,12 +60,13 @@ pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(formatEscapes) {
60}60}
6161
62test "escape invalid identifiers" {62test "escape invalid identifiers" {
63 try std.fmt.testFmt("@\"while\"", "{}", .{fmtId("while")});63 const expectFmt = std.testing.expectFmt;
64 try std.fmt.testFmt("hello", "{}", .{fmtId("hello")});64 try expectFmt("@\"while\"", "{}", .{fmtId("while")});
65 try std.fmt.testFmt("@\"11\\\"23\"", "{}", .{fmtId("11\"23")});65 try expectFmt("hello", "{}", .{fmtId("hello")});
66 try std.fmt.testFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});66 try expectFmt("@\"11\\\"23\"", "{}", .{fmtId("11\"23")});
67 try std.fmt.testFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});67 try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")});
68 try std.fmt.testFmt(68 try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")});
69 try expectFmt(
69 \\" \\ hi \x07 \x11 \" derp \'"70 \\" \\ hi \x07 \x11 \" derp \'"
70 , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});71 , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")});
71}72}