Skip to content

Commit 17ba441

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 be41c2f commit 17ba441

File tree

1 file changed

+161
-2
lines changed

1 file changed

+161
-2
lines changed

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

Lines changed: 161 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-
num_format::{Case, ForceDecimal},
666-
ExtendedBigDecimal,
665+
num_format::{Case, Float, ForceDecimal, UnsignedInt},
666+
ExtendedBigDecimal, Format,
667667
};
668668

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

0 commit comments

Comments
 (0)