Skip to content

Commit 596ea0a

Browse files
drinkcatsylvestre
authored andcommitted
test_seq: Add a few more tests for corner cases
Some of these tests are not completely defined behavior, but in many cases they make sense (or at least one can find some consistent logic to it). However, there are 2 edge cases that are more dubious IMHO. One of them has been reported on list a while back, and I just reported another.
1 parent 59cd6e5 commit 596ea0a

1 file changed

Lines changed: 108 additions & 0 deletions

File tree

tests/by-util/test_seq.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,3 +936,111 @@ fn test_parse_valid_hexadecimal_float_format_issues() {
936936
.succeeds()
937937
.stdout_only("9.92804e-09\n1\n");
938938
}
939+
940+
// GNU `seq` manual states that, when the parameters "all use a fixed point
941+
// decimal representation", the format should be `%.pf`, where the precision
942+
// is inferred from parameters. Else, `%g` is used.
943+
//
944+
// This is understandable, as translating hexadecimal precision to decimal precision
945+
// is not straightforward or intuitive to the user. There are some exceptions though,
946+
// if a mix of hexadecimal _integers_ and decimal floats are provided.
947+
//
948+
// The way precision is inferred is said to be able to "represent the output numbers
949+
// exactly". In practice, this means that trailing zeros in first/increment number are
950+
// considered, but not in the last number. This makes sense if we take that last number
951+
// as a "bound", and not really part of input/output.
952+
#[test]
953+
fn test_precision_corner_cases() {
954+
// Mixed input with integer hex still uses precision in decimal float
955+
new_ucmd!()
956+
.args(&["0x1", "0.90", "3"])
957+
.succeeds()
958+
.stdout_is("1.00\n1.90\n2.80\n");
959+
960+
// Mixed input with hex float reverts to %g
961+
new_ucmd!()
962+
.args(&["0x1.00", "0.90", "3"])
963+
.succeeds()
964+
.stdout_is("1\n1.9\n2.8\n");
965+
966+
// Even if it's the last number.
967+
new_ucmd!()
968+
.args(&["1", "1.20", "0x3.000000"])
969+
.succeeds()
970+
.stdout_is("1\n2.2\n");
971+
972+
// Otherwise, precision in last number is ignored.
973+
new_ucmd!()
974+
.args(&["1", "1.20", "3.000000"])
975+
.succeeds()
976+
.stdout_is("1.00\n2.20\n");
977+
978+
// Infinity is ignored
979+
new_ucmd!()
980+
.args(&["1", "1.2", "inf"])
981+
.run_stdout_starts_with(b"1.0\n2.2\n3.4\n")
982+
.success();
983+
}
984+
985+
// GNU `seq` manual only makes guarantees about `-w` working if the
986+
// provided numbers "all use a fixed point decimal representation",
987+
// and guides the user to use `-f` for other cases.
988+
#[test]
989+
fn test_equalize_widths_corner_cases() {
990+
// Mixed input with hexadecimal does behave as expected
991+
new_ucmd!()
992+
.args(&["-w", "0x1", "5.2", "9"])
993+
.succeeds()
994+
.stdout_is("1.0\n6.2\n");
995+
996+
// Confusingly, the number of integral digits in the last number is
997+
// used to pad the output numbers, while it is ignored for precision
998+
// computation.
999+
//
1000+
// This problem has been reported on list here:
1001+
// "bug#77179: seq incorrectly(?) pads output when last parameter magnitude"
1002+
// https://lists.gnu.org/archive/html/bug-coreutils/2025-03/msg00028.html
1003+
//
1004+
// TODO: This case could be handled correctly, consider fixing this in
1005+
// `uutils` implementation. Output should probably be "1.0\n6.2\n".
1006+
new_ucmd!()
1007+
.args(&["-w", "0x1", "5.2", "10.0000"])
1008+
.succeeds()
1009+
.stdout_is("01.0\n06.2\n");
1010+
1011+
// But if we fixed the case above, we need to make sure we still pad
1012+
// if the last number in the output requires an extra digit.
1013+
new_ucmd!()
1014+
.args(&["-w", "0x1", "5.2", "15.0000"])
1015+
.succeeds()
1016+
.stdout_is("01.0\n06.2\n11.4\n");
1017+
1018+
// GNU `seq` bails out if any hex float is in the output.
1019+
// Unlike the precision corner cases above, it is harder to justify
1020+
// this behavior for hexadecimal float inputs, as it is always be
1021+
// possible to output numbers with a fixed width.
1022+
//
1023+
// This problem has been reported on list here:
1024+
// "bug#76070: Subject: seq, hexadecimal args and equal width"
1025+
// https://lists.gnu.org/archive/html/bug-coreutils/2025-02/msg00007.html
1026+
//
1027+
// TODO: These cases could be handled correctly, consider fixing this in
1028+
// `uutils` implementation.
1029+
// If we ignore hexadecimal precision, the output should be "1.0\n6.2\n".
1030+
new_ucmd!()
1031+
.args(&["-w", "0x1.0000", "5.2", "10"])
1032+
.succeeds()
1033+
.stdout_is("1\n6.2\n");
1034+
// The equivalent `seq -w 1.0625 1.00002 3` correctly pads the first number: "1.06250\n2.06252\n"
1035+
new_ucmd!()
1036+
.args(&["-w", "0x1.1", "1.00002", "3"])
1037+
.succeeds()
1038+
.stdout_is("1.0625\n2.06252\n");
1039+
1040+
// We can't really pad with infinite number of zeros, so `-w` is ignored.
1041+
// (there is another test with infinity as an increment above)
1042+
new_ucmd!()
1043+
.args(&["-w", "1", "1.2", "inf"])
1044+
.run_stdout_starts_with(b"1.0\n2.2\n3.4\n")
1045+
.success();
1046+
}

0 commit comments

Comments
 (0)