Skip to content

Commit 8339ee2

Browse files
committed
uucore: format: num_format: add fmt function tests
All the other tests directly called format_float_* functions, bypassing the additional logic in `fmt` (negative numbers, padding, etc.). This also tests the `parse` function in `mod.rs`, which calls back into `try_from_spec` here. This also makes it easier to test a lot of different format combinations without having to do end-to-end tests in `test_printf.rs`. Also add broken tests for the issues in #7509 and #7510.
1 parent 383c8a3 commit 8339ee2

File tree

1 file changed

+166
-2
lines changed

1 file changed

+166
-2
lines changed

src/uucore/src/lib/features/format/num_format.rs

Lines changed: 166 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -662,10 +662,12 @@ mod test {
662662
use std::str::FromStr;
663663

664664
use crate::format::{
665-
ExtendedBigDecimal,
666-
num_format::{Case, ForceDecimal},
665+
ExtendedBigDecimal, Format,
666+
num_format::{Case, Float, ForceDecimal, UnsignedInt},
667667
};
668668

669+
use super::{Formatter, SignedInt};
670+
669671
#[test]
670672
fn unsigned_octal() {
671673
use super::{Formatter, NumberAlignment, Prefix, UnsignedInt, UnsignedIntVariant};
@@ -1025,4 +1027,166 @@ mod test {
10251027
assert_eq!(f(0.00001), "1e-05");
10261028
assert_eq!(f(0.000001), "1e-06");
10271029
}
1030+
1031+
// Wrapper function to get a string out of Format.fmt()
1032+
fn fmt<U, T>(format: &Format<U, T>, n: T) -> String
1033+
where
1034+
U: Formatter<T>,
1035+
{
1036+
let mut v = Vec::<u8>::new();
1037+
format.fmt(&mut v, n as T).unwrap();
1038+
String::from_utf8_lossy(&v).to_string()
1039+
}
1040+
1041+
// Some end-to-end tests, `printf` will also test some of those but it's easier to add more
1042+
// tests here. We mostly focus on padding, negative numbers, and format specifiers that are not
1043+
// covered above.
1044+
#[test]
1045+
fn format_signed_int() {
1046+
let format = Format::<SignedInt, i64>::parse("%d").unwrap();
1047+
assert_eq!(fmt(&format, 123i64), "123");
1048+
assert_eq!(fmt(&format, -123i64), "-123");
1049+
1050+
let format = Format::<SignedInt, i64>::parse("%i").unwrap();
1051+
assert_eq!(fmt(&format, 123i64), "123");
1052+
assert_eq!(fmt(&format, -123i64), "-123");
1053+
1054+
let format = Format::<SignedInt, i64>::parse("%6d").unwrap();
1055+
assert_eq!(fmt(&format, 123i64), " 123");
1056+
assert_eq!(fmt(&format, -123i64), " -123");
1057+
1058+
let format = Format::<SignedInt, i64>::parse("%06d").unwrap();
1059+
assert_eq!(fmt(&format, 123i64), "000123");
1060+
assert_eq!(fmt(&format, -123i64), "-00123");
1061+
1062+
let format = Format::<SignedInt, i64>::parse("%+6d").unwrap();
1063+
assert_eq!(fmt(&format, 123i64), " +123");
1064+
assert_eq!(fmt(&format, -123i64), " -123");
1065+
1066+
let format = Format::<SignedInt, i64>::parse("% d").unwrap();
1067+
assert_eq!(fmt(&format, 123i64), " 123");
1068+
assert_eq!(fmt(&format, -123i64), "-123");
1069+
}
1070+
1071+
#[test]
1072+
#[ignore = "Need issue #7509 to be fixed"]
1073+
fn format_signed_int_precision_zero() {
1074+
let format = Format::<SignedInt, i64>::parse("%.0d").unwrap();
1075+
assert_eq!(fmt(&format, 123i64), "123");
1076+
// From cppreference.com: "If both the converted value and the precision are ​0​ the conversion results in no characters."
1077+
assert_eq!(fmt(&format, 0i64), "");
1078+
}
1079+
1080+
#[test]
1081+
fn format_unsigned_int() {
1082+
let f = |fmt_str: &str, n: u64| {
1083+
let format = Format::<UnsignedInt, u64>::parse(fmt_str).unwrap();
1084+
fmt(&format, n)
1085+
};
1086+
1087+
assert_eq!(f("%u", 123u64), "123");
1088+
assert_eq!(f("%o", 123u64), "173");
1089+
assert_eq!(f("%#o", 123u64), "0173");
1090+
assert_eq!(f("%6x", 123u64), " 7b");
1091+
assert_eq!(f("%#6x", 123u64), " 0x7b");
1092+
assert_eq!(f("%06X", 123u64), "00007B");
1093+
assert_eq!(f("%+6u", 123u64), " 123"); // '+' is ignored for unsigned numbers.
1094+
assert_eq!(f("% u", 123u64), "123"); // ' ' is ignored for unsigned numbers.
1095+
assert_eq!(f("%#x", 0), "0"); // No prefix for 0
1096+
}
1097+
1098+
#[test]
1099+
#[ignore = "Need issues #7509 and #7510 to be fixed"]
1100+
fn format_unsigned_int_broken() {
1101+
// TODO: Merge this back into format_unsigned_int.
1102+
let f = |fmt_str: &str, n: u64| {
1103+
let format = Format::<UnsignedInt, u64>::parse(fmt_str).unwrap();
1104+
fmt(&format, n)
1105+
};
1106+
1107+
// #7509
1108+
assert_eq!(f("%.0o", 0), "");
1109+
assert_eq!(f("%#0o", 0), "0"); // Already correct, but probably an accident.
1110+
assert_eq!(f("%.0x", 0), "");
1111+
// #7510
1112+
assert_eq!(f("%#06x", 123u64), "0x007b");
1113+
}
1114+
1115+
#[test]
1116+
fn format_float_decimal() {
1117+
let format = Format::<Float, &ExtendedBigDecimal>::parse("%f").unwrap();
1118+
assert_eq!(fmt(&format, &123.0.into()), "123.000000");
1119+
assert_eq!(fmt(&format, &(-123.0).into()), "-123.000000");
1120+
assert_eq!(fmt(&format, &123.15e-8.into()), "0.000001");
1121+
assert_eq!(fmt(&format, &(-123.15e8).into()), "-12315000000.000000");
1122+
let zero_exp = |exp| ExtendedBigDecimal::BigDecimal(BigDecimal::from_bigint(0.into(), exp));
1123+
// We've had issues with "0e10"/"0e-10" formatting, and our current workaround is in Format.fmt function.
1124+
assert_eq!(fmt(&format, &zero_exp(0)), "0.000000");
1125+
assert_eq!(fmt(&format, &zero_exp(10)), "0.000000");
1126+
assert_eq!(fmt(&format, &zero_exp(-10)), "0.000000");
1127+
1128+
let format = Format::<Float, &ExtendedBigDecimal>::parse("%12f").unwrap();
1129+
assert_eq!(fmt(&format, &123.0.into()), " 123.000000");
1130+
assert_eq!(fmt(&format, &(-123.0).into()), " -123.000000");
1131+
assert_eq!(fmt(&format, &123.15e-8.into()), " 0.000001");
1132+
assert_eq!(fmt(&format, &(-123.15e8).into()), "-12315000000.000000");
1133+
assert_eq!(
1134+
fmt(&format, &(ExtendedBigDecimal::Infinity)),
1135+
" inf"
1136+
);
1137+
assert_eq!(
1138+
fmt(&format, &(ExtendedBigDecimal::MinusInfinity)),
1139+
" -inf"
1140+
);
1141+
assert_eq!(fmt(&format, &(ExtendedBigDecimal::Nan)), " nan");
1142+
assert_eq!(
1143+
fmt(&format, &(ExtendedBigDecimal::MinusNan)),
1144+
" -nan"
1145+
);
1146+
1147+
let format = Format::<Float, &ExtendedBigDecimal>::parse("%+#.0f").unwrap();
1148+
assert_eq!(fmt(&format, &123.0.into()), "+123.");
1149+
assert_eq!(fmt(&format, &(-123.0).into()), "-123.");
1150+
assert_eq!(fmt(&format, &123.15e-8.into()), "+0.");
1151+
assert_eq!(fmt(&format, &(-123.15e8).into()), "-12315000000.");
1152+
assert_eq!(fmt(&format, &(ExtendedBigDecimal::Infinity)), "+inf");
1153+
assert_eq!(fmt(&format, &(ExtendedBigDecimal::Nan)), "+nan");
1154+
assert_eq!(fmt(&format, &(ExtendedBigDecimal::MinusZero)), "-0.");
1155+
1156+
let format = Format::<Float, &ExtendedBigDecimal>::parse("%#06.0f").unwrap();
1157+
assert_eq!(fmt(&format, &123.0.into()), "00123.");
1158+
assert_eq!(fmt(&format, &(-123.0).into()), "-0123.");
1159+
assert_eq!(fmt(&format, &123.15e-8.into()), "00000.");
1160+
assert_eq!(fmt(&format, &(-123.15e8).into()), "-12315000000.");
1161+
assert_eq!(fmt(&format, &(ExtendedBigDecimal::Infinity)), " inf");
1162+
assert_eq!(fmt(&format, &(ExtendedBigDecimal::MinusInfinity)), " -inf");
1163+
assert_eq!(fmt(&format, &(ExtendedBigDecimal::Nan)), " nan");
1164+
assert_eq!(fmt(&format, &(ExtendedBigDecimal::MinusNan)), " -nan");
1165+
}
1166+
1167+
#[test]
1168+
fn format_float_others() {
1169+
let f = |fmt_str: &str, n: &ExtendedBigDecimal| {
1170+
let format = Format::<Float, &ExtendedBigDecimal>::parse(fmt_str).unwrap();
1171+
fmt(&format, n)
1172+
};
1173+
1174+
assert_eq!(f("%e", &(-123.0).into()), "-1.230000e+02");
1175+
assert_eq!(f("%#09.e", &(-100.0).into()), "-001.e+02");
1176+
assert_eq!(f("%# 9.E", &100.0.into()), " 1.E+02");
1177+
assert_eq!(f("% 12.2A", &(-100.0).into()), " -0xC.80P+3");
1178+
}
1179+
1180+
#[test]
1181+
#[ignore = "Need issue #7510 to be fixed"]
1182+
fn format_float_others_broken() {
1183+
// TODO: Merge this back into format_float_others.
1184+
let f = |fmt_str: &str, n: &ExtendedBigDecimal| {
1185+
let format = Format::<Float, &ExtendedBigDecimal>::parse(fmt_str).unwrap();
1186+
fmt(&format, n)
1187+
};
1188+
1189+
// #7510
1190+
assert_eq!(f("%012.2a", &(-100.0).into()), "-0x00c.80p+3");
1191+
}
10281192
}

0 commit comments

Comments
 (0)