authorgravatar for benjamin.feng@glassdoor.comBenjamin Feng <benjamin.feng@glassdoor.com> 2020-02-29 13:22:27-06:00
committergravatar for benjamin.feng@glassdoor.comBenjamin Feng <benjamin.feng@glassdoor.com> 2020-03-12 09:15:49-05:00
log78d12762a9c78f9563a3cfd29541d0a04f78ab58
treeead5c72d8a5e94d4cce3dba9d70e373eabf388f5
parent8241b96f78fa8ee33f9a73d4d296509d49b6f351

Re-enable a bunch of tests


1 files changed, 405 insertions(+), 407 deletions(-)

lib/std/fmtstream.zig+405-407
......@@ -430,7 +430,7 @@ pub fn formatType(
430430 },
431431 .Many, .C => {
432432 if (ptr_info.sentinel) |sentinel| {
433 return formatType(mem.span(value), fmt, options, context, Errors, output, max_depth);
433 return formatType(mem.span(value), fmt, options, out_stream, max_depth);
434434 }
435435 if (ptr_info.child == u8) {
436436 if (fmt.len > 0 and fmt[0] == 's') {
......@@ -481,7 +481,7 @@ pub fn formatType(
481481 .Type => return out_stream.writeAll(@typeName(T)),
482482 .EnumLiteral => {
483483 const buffer = [_]u8{'.'} ++ @tagName(value);
484 return formatType(buffer, fmt, options, context, Errors, output, max_depth);
484 return formatType(buffer, fmt, options, out_stream, max_depth);
485485 },
486486 else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"),
487487 }
......@@ -1079,11 +1079,11 @@ pub const BufPrintError = error{
10791079 BufferTooSmall,
10801080};
10811081pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
1082 var os = std.io.SliceOutStream.init(buf);
1083 format(&os.stream, fmt, args) catch |err| switch (err) {
1084 error.OutOfMemory => return error.BufferTooSmall,
1082 var fbs = std.io.fixedBufferStream(buf);
1083 format(fbs.outStream(), fmt, args) catch |err| switch (err) {
1084 error.NoSpaceLeft => return error.BufferTooSmall,
10851085 };
1086 return buf[0..os.pos];
1086 return buf[0..fbs.pos];
10871087}
10881088
10891089// pub const AllocPrintError = error{OutOfMemory};
......@@ -1131,348 +1131,346 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options:
11311131 return buf[0..formatIntBuf(buf, value, base, uppercase, options)];
11321132}
11331133
1134// test "parse u64 digit too big" {
1135// _ = parseUnsigned(u64, "123a", 10) catch |err| {
1136// if (err == error.InvalidCharacter) return;
1137// unreachable;
1138// };
1139// unreachable;
1140// }
1134test "parse u64 digit too big" {
1135 _ = parseUnsigned(u64, "123a", 10) catch |err| {
1136 if (err == error.InvalidCharacter) return;
1137 unreachable;
1138 };
1139 unreachable;
1140}
11411141
1142// test "parse unsigned comptime" {
1143// comptime {
1144// std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
1145// }
1146// }
1142test "parse unsigned comptime" {
1143 comptime {
1144 std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
1145 }
1146}
11471147
1148// test "optional" {
1149// {
1150// const value: ?i32 = 1234;
1151// try testFmt("optional: 1234\n", "optional: {}\n", .{value});
1152// }
1153// {
1154// const value: ?i32 = null;
1155// try testFmt("optional: null\n", "optional: {}\n", .{value});
1156// }
1157// }
1148test "optional" {
1149 {
1150 const value: ?i32 = 1234;
1151 try testFmt("optional: 1234\n", "optional: {}\n", .{value});
1152 }
1153 {
1154 const value: ?i32 = null;
1155 try testFmt("optional: null\n", "optional: {}\n", .{value});
1156 }
1157}
11581158
1159// test "error" {
1160// {
1161// const value: anyerror!i32 = 1234;
1162// try testFmt("error union: 1234\n", "error union: {}\n", .{value});
1163// }
1164// {
1165// const value: anyerror!i32 = error.InvalidChar;
1166// try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
1167// }
1168// }
1159test "error" {
1160 {
1161 const value: anyerror!i32 = 1234;
1162 try testFmt("error union: 1234\n", "error union: {}\n", .{value});
1163 }
1164 {
1165 const value: anyerror!i32 = error.InvalidChar;
1166 try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
1167 }
1168}
11691169
1170// test "int.small" {
1171// {
1172// const value: u3 = 0b101;
1173// try testFmt("u3: 5\n", "u3: {}\n", .{value});
1174// }
1175// }
1170test "int.small" {
1171 {
1172 const value: u3 = 0b101;
1173 try testFmt("u3: 5\n", "u3: {}\n", .{value});
1174 }
1175}
11761176
1177// test "int.specifier" {
1178// {
1179// const value: u8 = 'a';
1180// try testFmt("u8: a\n", "u8: {c}\n", .{value});
1181// }
1182// {
1183// const value: u8 = 0b1100;
1184// try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
1185// }
1186// }
1177test "int.specifier" {
1178 {
1179 const value: u8 = 'a';
1180 try testFmt("u8: a\n", "u8: {c}\n", .{value});
1181 }
1182 {
1183 const value: u8 = 0b1100;
1184 try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
1185 }
1186}
11871187
1188// test "int.padded" {
1189// try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
1190// try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
1191// }
1188test "int.padded" {
1189 try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
1190 try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
1191}
11921192
1193// test "buffer" {
1194// {
1195// var buf1: [32]u8 = undefined;
1196// var context = BufPrintContext{ .remaining = buf1[0..] };
1197// try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1198// var res = buf1[0 .. buf1.len - context.remaining.len];
1199// std.testing.expect(mem.eql(u8, res, "1234"));
1200
1201// context = BufPrintContext{ .remaining = buf1[0..] };
1202// try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1203// res = buf1[0 .. buf1.len - context.remaining.len];
1204// std.testing.expect(mem.eql(u8, res, "a"));
1205
1206// context = BufPrintContext{ .remaining = buf1[0..] };
1207// try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1208// res = buf1[0 .. buf1.len - context.remaining.len];
1209// std.testing.expect(mem.eql(u8, res, "1100"));
1210// }
1211// }
1193test "buffer" {
1194 {
1195 var buf1: [32]u8 = undefined;
1196 var fbs = std.io.fixedBufferStream(&buf1);
1197 try formatType(1234, "", FormatOptions{}, fbs.outStream(), default_max_depth);
1198 var res = buf1[0..fbs.pos];
1199 std.testing.expect(mem.eql(u8, res, "1234"));
1200
1201 try fbs.seekTo(0);
1202 try formatType('a', "c", FormatOptions{}, fbs.outStream(), default_max_depth);
1203 res = buf1[0..fbs.pos];
1204 std.testing.expect(mem.eql(u8, res, "a"));
1205
1206 try fbs.seekTo(0);
1207 try formatType(0b1100, "b", FormatOptions{}, fbs.outStream(), default_max_depth);
1208 res = buf1[0..fbs.pos];
1209 std.testing.expect(mem.eql(u8, res, "1100"));
1210 }
1211}
12121212
1213// test "array" {
1214// {
1215// const value: [3]u8 = "abc".*;
1216// try testFmt("array: abc\n", "array: {}\n", .{value});
1217// try testFmt("array: abc\n", "array: {}\n", .{&value});
1218
1219// var buf: [100]u8 = undefined;
1220// try testFmt(
1221// try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
1222// "array: {*}\n",
1223// .{&value},
1224// );
1225// }
1226// }
1213test "array" {
1214 {
1215 const value: [3]u8 = "abc".*;
1216 try testFmt("array: abc\n", "array: {}\n", .{value});
1217 try testFmt("array: abc\n", "array: {}\n", .{&value});
1218
1219 var buf: [100]u8 = undefined;
1220 try testFmt(
1221 try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
1222 "array: {*}\n",
1223 .{&value},
1224 );
1225 }
1226}
12271227
1228// test "slice" {
1229// {
1230// const value: []const u8 = "abc";
1231// try testFmt("slice: abc\n", "slice: {}\n", .{value});
1232// }
1233// {
1234// const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
1235// try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
1236// }
1237
1238// try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
1239// try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
1240// }
1228test "slice" {
1229 {
1230 const value: []const u8 = "abc";
1231 try testFmt("slice: abc\n", "slice: {}\n", .{value});
1232 }
1233 {
1234 const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
1235 try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
1236 }
12411237
1242// test "pointer" {
1243// {
1244// const value = @intToPtr(*align(1) i32, 0xdeadbeef);
1245// try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
1246// try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
1247// }
1248// {
1249// const value = @intToPtr(fn () void, 0xdeadbeef);
1250// try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
1251// }
1252// {
1253// const value = @intToPtr(fn () void, 0xdeadbeef);
1254// try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
1255// }
1256// }
1238 try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
1239 try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
1240}
12571241
1258// test "cstr" {
1259// try testFmt(
1260// "cstr: Test C\n",
1261// "cstr: {s}\n",
1262// .{@ptrCast([*c]const u8, "Test C")},
1263// );
1264// try testFmt(
1265// "cstr: Test C \n",
1266// "cstr: {s:10}\n",
1267// .{@ptrCast([*c]const u8, "Test C")},
1268// );
1269// }
1242test "pointer" {
1243 {
1244 const value = @intToPtr(*align(1) i32, 0xdeadbeef);
1245 try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
1246 try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
1247 }
1248 {
1249 const value = @intToPtr(fn () void, 0xdeadbeef);
1250 try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
1251 }
1252 {
1253 const value = @intToPtr(fn () void, 0xdeadbeef);
1254 try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
1255 }
1256}
12701257
1271// test "filesize" {
1272// try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
1273// try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
1274// }
1258test "cstr" {
1259 try testFmt(
1260 "cstr: Test C\n",
1261 "cstr: {s}\n",
1262 .{@ptrCast([*c]const u8, "Test C")},
1263 );
1264 try testFmt(
1265 "cstr: Test C \n",
1266 "cstr: {s:10}\n",
1267 .{@ptrCast([*c]const u8, "Test C")},
1268 );
1269}
12751270
1276// test "struct" {
1277// {
1278// const Struct = struct {
1279// field: u8,
1280// };
1281// const value = Struct{ .field = 42 };
1282// try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
1283// try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
1284// }
1285// {
1286// const Struct = struct {
1287// a: u0,
1288// b: u1,
1289// };
1290// const value = Struct{ .a = 0, .b = 1 };
1291// try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
1292// }
1293// }
1271test "filesize" {
1272 try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
1273 try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
1274}
12941275
1295// test "enum" {
1296// const Enum = enum {
1297// One,
1298// Two,
1299// };
1300// const value = Enum.Two;
1301// try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
1302// try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
1303// }
1276test "struct" {
1277 {
1278 const Struct = struct {
1279 field: u8,
1280 };
1281 const value = Struct{ .field = 42 };
1282 try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
1283 try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
1284 }
1285 {
1286 const Struct = struct {
1287 a: u0,
1288 b: u1,
1289 };
1290 const value = Struct{ .a = 0, .b = 1 };
1291 try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
1292 }
1293}
13041294
1305// test "non-exhaustive enum" {
1306// const Enum = enum(u16) {
1307// One = 0x000f,
1308// Two = 0xbeef,
1309// _,
1310// };
1311// try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One});
1312// try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two});
1313// try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
1314// try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One});
1315// try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two});
1316// try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
1317// }
1295test "enum" {
1296 const Enum = enum {
1297 One,
1298 Two,
1299 };
1300 const value = Enum.Two;
1301 try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
1302 try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
1303}
13181304
1319// test "float.scientific" {
1320// try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
1321// try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
1322// try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
1323// try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
1324// }
1305test "non-exhaustive enum" {
1306 const Enum = enum(u16) {
1307 One = 0x000f,
1308 Two = 0xbeef,
1309 _,
1310 };
1311 try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One});
1312 try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two});
1313 try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
1314 try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One});
1315 try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two});
1316 try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
1317}
13251318
1326// test "float.scientific.precision" {
1327// try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
1328// try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
1329// try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
1330// // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
1331// // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
1332// try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
1333// }
1319test "float.scientific" {
1320 try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
1321 try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
1322 try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
1323 try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
1324}
13341325
1335// test "float.special" {
1336// try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
1337// // negative nan is not defined by IEE 754,
1338// // and ARM thus normalizes it to positive nan
1339// if (builtin.arch != builtin.Arch.arm) {
1340// try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
1341// }
1342// try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
1343// try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
1344// }
1326test "float.scientific.precision" {
1327 try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
1328 try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
1329 try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
1330 // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
1331 // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
1332 try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
1333}
13451334
1346// test "float.decimal" {
1347// try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
1348// try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
1349// try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
1350// try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
1351// // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
1352// // -11.12339... is rounded back up to -11.1234
1353// try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
1354// try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
1355// try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
1356// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
1357// try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
1358// try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
1359// try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
1360// try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
1361// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
1362// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
1363// }
1335test "float.special" {
1336 try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
1337 // negative nan is not defined by IEE 754,
1338 // and ARM thus normalizes it to positive nan
1339 if (builtin.arch != builtin.Arch.arm) {
1340 try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
1341 }
1342 try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
1343 try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
1344}
13641345
1365// test "float.libc.sanity" {
1366// try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
1367// try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
1368// try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
1369// try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
1370// try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
1371
1372// // libc differences
1373// //
1374// // This is 0.015625 exactly according to gdb. We thus round down,
1375// // however glibc rounds up for some reason. This occurs for all
1376// // floats of the form x.yyyy25 on a precision point.
1377// try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
1378// // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
1379// // also rounds to 630 so I'm inclined to believe libc is not
1380// // optimal here.
1381// try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
1382// }
1346test "float.decimal" {
1347 try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
1348 try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
1349 try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
1350 try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
1351 // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
1352 // -11.12339... is rounded back up to -11.1234
1353 try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
1354 try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
1355 try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
1356 try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
1357 try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
1358 try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
1359 try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
1360 try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
1361 try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
1362 try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
1363}
13831364
1384// test "custom" {
1385// const Vec2 = struct {
1386// const SelfType = @This();
1387// x: f32,
1388// y: f32,
1365test "float.libc.sanity" {
1366 try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
1367 try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
1368 try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
1369 try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
1370 try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
1371
1372 // libc differences
1373 //
1374 // This is 0.015625 exactly according to gdb. We thus round down,
1375 // however glibc rounds up for some reason. This occurs for all
1376 // floats of the form x.yyyy25 on a precision point.
1377 try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
1378 // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
1379 // also rounds to 630 so I'm inclined to believe libc is not
1380 // optimal here.
1381 try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
1382}
13891383
1390// pub fn format(
1391// self: SelfType,
1392// comptime fmt: []const u8,
1393// options: FormatOptions,
1394// context: var,
1395// comptime Errors: type,
1396// comptime output: fn (@TypeOf(context), []const u8) !void,
1397// ) !void {
1398// if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
1399// return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
1400// } else if (comptime std.mem.eql(u8, fmt, "d")) {
1401// return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
1402// } else {
1403// @compileError("Unknown format character: '" ++ fmt ++ "'");
1404// }
1405// }
1406// };
1384test "custom" {
1385 const Vec2 = struct {
1386 const SelfType = @This();
1387 x: f32,
1388 y: f32,
1389
1390 pub fn format(
1391 self: SelfType,
1392 comptime fmt: []const u8,
1393 options: FormatOptions,
1394 out_stream: var,
1395 ) !void {
1396 if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
1397 return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
1398 } else if (comptime std.mem.eql(u8, fmt, "d")) {
1399 return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
1400 } else {
1401 @compileError("Unknown format character: '" ++ fmt ++ "'");
1402 }
1403 }
1404 };
14071405
1408// var buf1: [32]u8 = undefined;
1409// var value = Vec2{
1410// .x = 10.2,
1411// .y = 2.22,
1412// };
1413// try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
1414// try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
1406 var buf1: [32]u8 = undefined;
1407 var value = Vec2{
1408 .x = 10.2,
1409 .y = 2.22,
1410 };
1411 try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
1412 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
14151413
1416// // same thing but not passing a pointer
1417// try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
1418// try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
1419// }
1414 // same thing but not passing a pointer
1415 try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
1416 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
1417}
14201418
1421// test "struct" {
1422// const S = struct {
1423// a: u32,
1424// b: anyerror,
1425// };
1419test "struct" {
1420 const S = struct {
1421 a: u32,
1422 b: anyerror,
1423 };
14261424
1427// const inst = S{
1428// .a = 456,
1429// .b = error.Unused,
1430// };
1425 const inst = S{
1426 .a = 456,
1427 .b = error.Unused,
1428 };
14311429
1432// try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
1433// }
1430 try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
1431}
14341432
1435// test "union" {
1436// const TU = union(enum) {
1437// float: f32,
1438// int: u32,
1439// };
1433test "union" {
1434 const TU = union(enum) {
1435 float: f32,
1436 int: u32,
1437 };
14401438
1441// const UU = union {
1442// float: f32,
1443// int: u32,
1444// };
1439 const UU = union {
1440 float: f32,
1441 int: u32,
1442 };
14451443
1446// const EU = extern union {
1447// float: f32,
1448// int: u32,
1449// };
1444 const EU = extern union {
1445 float: f32,
1446 int: u32,
1447 };
14501448
1451// const tu_inst = TU{ .int = 123 };
1452// const uu_inst = UU{ .int = 456 };
1453// const eu_inst = EU{ .float = 321.123 };
1449 const tu_inst = TU{ .int = 123 };
1450 const uu_inst = UU{ .int = 456 };
1451 const eu_inst = EU{ .float = 321.123 };
14541452
1455// try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
1453 try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
14561454
1457// var buf: [100]u8 = undefined;
1458// const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
1459// std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
1455 var buf: [100]u8 = undefined;
1456 const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
1457 std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
14601458
1461// const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
1462// std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
1463// }
1459 const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
1460 std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
1461}
14641462
1465// test "enum" {
1466// const E = enum {
1467// One,
1468// Two,
1469// Three,
1470// };
1463test "enum" {
1464 const E = enum {
1465 One,
1466 Two,
1467 Three,
1468 };
14711469
1472// const inst = E.Two;
1470 const inst = E.Two;
14731471
1474// try testFmt("E.Two", "{}", .{inst});
1475// }
1472 try testFmt("E.Two", "{}", .{inst});
1473}
14761474
14771475// test "struct.self-referential" {
14781476// const S = struct {
......@@ -1488,20 +1486,20 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options:
14881486// try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
14891487// }
14901488
1491// test "struct.zero-size" {
1492// const A = struct {
1493// fn foo() void {}
1494// };
1495// const B = struct {
1496// a: A,
1497// c: i32,
1498// };
1489test "struct.zero-size" {
1490 const A = struct {
1491 fn foo() void {}
1492 };
1493 const B = struct {
1494 a: A,
1495 c: i32,
1496 };
14991497
1500// const a = A{};
1501// const b = B{ .a = a, .c = 0 };
1498 const a = A{};
1499 const b = B{ .a = a, .c = 0 };
15021500
1503// try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
1504// }
1501 try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
1502}
15051503
15061504test "bytes.hex" {
15071505 const some_bytes = "\xCA\xFE\xBA\xBE";
......@@ -1527,66 +1525,66 @@ fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void
15271525 return error.TestFailed;
15281526}
15291527
1530// pub fn trim(buf: []const u8) []const u8 {
1531// var start: usize = 0;
1532// while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
1528pub fn trim(buf: []const u8) []const u8 {
1529 var start: usize = 0;
1530 while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
15331531
1534// var end: usize = buf.len;
1535// while (true) {
1536// if (end > start) {
1537// const new_end = end - 1;
1538// if (isWhiteSpace(buf[new_end])) {
1539// end = new_end;
1540// continue;
1541// }
1542// }
1543// break;
1544// }
1545// return buf[start..end];
1546// }
1532 var end: usize = buf.len;
1533 while (true) {
1534 if (end > start) {
1535 const new_end = end - 1;
1536 if (isWhiteSpace(buf[new_end])) {
1537 end = new_end;
1538 continue;
1539 }
1540 }
1541 break;
1542 }
1543 return buf[start..end];
1544}
15471545
1548// test "trim" {
1549// std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
1550// std.testing.expect(mem.eql(u8, "", trim(" ")));
1551// std.testing.expect(mem.eql(u8, "", trim("")));
1552// std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
1553// std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
1554// }
1546test "trim" {
1547 std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
1548 std.testing.expect(mem.eql(u8, "", trim(" ")));
1549 std.testing.expect(mem.eql(u8, "", trim("")));
1550 std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
1551 std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
1552}
15551553
1556// pub fn isWhiteSpace(byte: u8) bool {
1557// return switch (byte) {
1558// ' ', '\t', '\n', '\r' => true,
1559// else => false,
1560// };
1561// }
1554pub fn isWhiteSpace(byte: u8) bool {
1555 return switch (byte) {
1556 ' ', '\t', '\n', '\r' => true,
1557 else => false,
1558 };
1559}
15621560
1563// pub fn hexToBytes(out: []u8, input: []const u8) !void {
1564// if (out.len * 2 < input.len)
1565// return error.InvalidLength;
1561pub fn hexToBytes(out: []u8, input: []const u8) !void {
1562 if (out.len * 2 < input.len)
1563 return error.InvalidLength;
15661564
1567// var in_i: usize = 0;
1568// while (in_i != input.len) : (in_i += 2) {
1569// const hi = try charToDigit(input[in_i], 16);
1570// const lo = try charToDigit(input[in_i + 1], 16);
1571// out[in_i / 2] = (hi << 4) | lo;
1572// }
1573// }
1565 var in_i: usize = 0;
1566 while (in_i != input.len) : (in_i += 2) {
1567 const hi = try charToDigit(input[in_i], 16);
1568 const lo = try charToDigit(input[in_i + 1], 16);
1569 out[in_i / 2] = (hi << 4) | lo;
1570 }
1571}
15741572
1575// test "hexToBytes" {
1576// const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
1577// var pb: [32]u8 = undefined;
1578// try hexToBytes(pb[0..], test_hex_str);
1579// try testFmt(test_hex_str, "{X}", .{pb});
1580// }
1573test "hexToBytes" {
1574 const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
1575 var pb: [32]u8 = undefined;
1576 try hexToBytes(pb[0..], test_hex_str);
1577 try testFmt(test_hex_str, "{X}", .{pb});
1578}
15811579
1582// test "formatIntValue with comptime_int" {
1583// const value: comptime_int = 123456789123456789;
1580test "formatIntValue with comptime_int" {
1581 const value: comptime_int = 123456789123456789;
15841582
1585// var buf = std.ArrayList(u8).init(std.testing.allocator);
1586// defer buf.deinit();
1587// try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);
1588// std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));
1589// }
1583 var buf: [20]u8 = undefined;
1584 var fbs = std.io.fixedBufferStream(&buf);
1585 try formatIntValue(value, "", FormatOptions{}, fbs.outStream());
1586 std.testing.expect(mem.eql(u8, buf[0..fbs.pos], "123456789123456789"));
1587}
15901588
15911589// test "formatType max_depth" {
15921590// const Vec2 = struct {
......@@ -1658,39 +1656,39 @@ fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void
16581656// std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
16591657// }
16601658
1661// test "positional" {
1662// try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
1663// try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
1664// try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
1665// try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
1666// try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
1667// }
1659test "positional" {
1660 try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
1661 try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
1662 try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
1663 try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
1664 try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
1665}
16681666
1669// test "positional with specifier" {
1670// try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
1671// }
1667test "positional with specifier" {
1668 try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
1669}
16721670
1673// test "positional/alignment/width/precision" {
1674// try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
1675// }
1671test "positional/alignment/width/precision" {
1672 try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
1673}
16761674
1677// test "vector" {
1678// // https://github.com/ziglang/zig/issues/3317
1679// if (builtin.arch == .mipsel) return error.SkipZigTest;
1680
1681// const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false };
1682// const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
1683// const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
1684
1685// try testFmt("{ true, false, true, false }", "{}", .{vbool});
1686// try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
1687// try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64});
1688// try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
1689// try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
1690// try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
1691// try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
1692// }
1675test "vector" {
1676 // https://github.com/ziglang/zig/issues/3317
1677 if (builtin.arch == .mipsel) return error.SkipZigTest;
1678
1679 const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false };
1680 const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
1681 const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
1682
1683 try testFmt("{ true, false, true, false }", "{}", .{vbool});
1684 try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
1685 try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64});
1686 try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
1687 try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
1688 try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
1689 try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
1690}
16931691
1694// test "enum-literal" {
1695// try testFmt(".hello_world", "{}", .{.hello_world});
1696// }
1692test "enum-literal" {
1693 try testFmt(".hello_world", "{}", .{.hello_world});
1694}