2021-12-29 14:20:17 +00:00
|
|
|
|
// spell-checker:ignore lmnop xlmnop
|
2020-05-25 17:05:26 +00:00
|
|
|
|
use crate::common::util::*;
|
2021-09-10 02:02:31 +00:00
|
|
|
|
use std::io::Read;
|
2015-11-16 05:25:01 +00:00
|
|
|
|
|
2022-09-10 16:38:14 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_invalid_arg() {
|
|
|
|
|
new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-02 15:46:09 +00:00
|
|
|
|
#[test]
|
2021-10-03 16:50:49 +00:00
|
|
|
|
fn test_hex_rejects_sign_after_identifier() {
|
2021-10-02 15:46:09 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["0x-123ABC"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
seq: use BigDecimal to represent floats (#2698)
* seq: use BigDecimal to represent floats
Use `BigDecimal` to represent arbitrary precision floats in order to
prevent numerical precision issues when iterating over a sequence of
numbers. This commit makes several changes at once to accomplish this
goal.
First, it creates a new struct, `PreciseNumber`, that is responsible for
storing not only the number itself but also the number of digits (both
integer and decimal) needed to display it. This information is collected
at the time of parsing the number, which lives in the new
`numberparse.rs` module.
Second, it uses the `BigDecimal` struct to store arbitrary precision
floating point numbers instead of the previous `f64` primitive
type. This protects against issues of numerical precision when
repeatedly accumulating a very small increment.
Third, since neither the `BigDecimal` nor `BigInt` types have a
representation of infinity, minus infinity, minus zero, or NaN, we add
the `ExtendedBigDecimal` and `ExtendedBigInt` enumerations which extend
the basic types with these concepts.
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
2021-11-06 14:44:42 +00:00
|
|
|
|
.stderr_contains("invalid floating point argument: '0x-123ABC'")
|
2021-10-02 15:46:09 +00:00
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["0x+123ABC"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
seq: use BigDecimal to represent floats (#2698)
* seq: use BigDecimal to represent floats
Use `BigDecimal` to represent arbitrary precision floats in order to
prevent numerical precision issues when iterating over a sequence of
numbers. This commit makes several changes at once to accomplish this
goal.
First, it creates a new struct, `PreciseNumber`, that is responsible for
storing not only the number itself but also the number of digits (both
integer and decimal) needed to display it. This information is collected
at the time of parsing the number, which lives in the new
`numberparse.rs` module.
Second, it uses the `BigDecimal` struct to store arbitrary precision
floating point numbers instead of the previous `f64` primitive
type. This protects against issues of numerical precision when
repeatedly accumulating a very small increment.
Third, since neither the `BigDecimal` nor `BigInt` types have a
representation of infinity, minus infinity, minus zero, or NaN, we add
the `ExtendedBigDecimal` and `ExtendedBigInt` enumerations which extend
the basic types with these concepts.
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
2021-11-06 14:44:42 +00:00
|
|
|
|
.stderr_contains("invalid floating point argument: '0x+123ABC'")
|
2021-10-02 15:46:09 +00:00
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-0x-123ABC"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
2022-02-06 02:46:31 +00:00
|
|
|
|
.stderr_contains("which wasn't expected, or isn't valid in this context")
|
|
|
|
|
.stderr_contains("For more information try --help");
|
2021-10-02 15:46:09 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-0x+123ABC"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
2022-02-06 02:46:31 +00:00
|
|
|
|
.stderr_contains("which wasn't expected, or isn't valid in this context")
|
|
|
|
|
.stderr_contains("For more information try --help");
|
2021-10-02 15:46:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_hex_lowercase_uppercase() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["0xa", "0xA"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("10\n");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["0Xa", "0XA"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("10\n");
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-03 16:50:49 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_hex_big_number() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&[
|
|
|
|
|
"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
|
|
|
|
"0x100000000000000000000000000000000",
|
|
|
|
|
])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is(
|
|
|
|
|
"340282366920938463463374607431768211455\n340282366920938463463374607431768211456\n",
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 01:41:28 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_hex_identifier_in_wrong_place() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["1234ABCD0x"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
seq: use BigDecimal to represent floats (#2698)
* seq: use BigDecimal to represent floats
Use `BigDecimal` to represent arbitrary precision floats in order to
prevent numerical precision issues when iterating over a sequence of
numbers. This commit makes several changes at once to accomplish this
goal.
First, it creates a new struct, `PreciseNumber`, that is responsible for
storing not only the number itself but also the number of digits (both
integer and decimal) needed to display it. This information is collected
at the time of parsing the number, which lives in the new
`numberparse.rs` module.
Second, it uses the `BigDecimal` struct to store arbitrary precision
floating point numbers instead of the previous `f64` primitive
type. This protects against issues of numerical precision when
repeatedly accumulating a very small increment.
Third, since neither the `BigDecimal` nor `BigInt` types have a
representation of infinity, minus infinity, minus zero, or NaN, we add
the `ExtendedBigDecimal` and `ExtendedBigInt` enumerations which extend
the basic types with these concepts.
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
2021-11-06 14:44:42 +00:00
|
|
|
|
.stderr_contains("invalid floating point argument: '1234ABCD0x'")
|
2021-10-06 01:41:28 +00:00
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-01 16:12:37 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_rejects_nan() {
|
2021-11-09 20:23:41 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.arg("NaN")
|
|
|
|
|
.fails()
|
|
|
|
|
.usage_error("invalid 'not-a-number' argument: 'NaN'");
|
2021-06-01 16:12:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_rejects_non_floats() {
|
2021-11-09 20:23:41 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.arg("foo")
|
|
|
|
|
.fails()
|
|
|
|
|
.usage_error("invalid floating point argument: 'foo'");
|
2021-06-01 16:12:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-03 22:44:43 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_accepts_option_argument_directly() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.arg("-s,")
|
|
|
|
|
.arg("2")
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("1,2\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_option_with_detected_negative_argument() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.arg("-s,")
|
|
|
|
|
.args(&["-1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-1,0,1,2\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_negative_number_as_separator() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.arg("-s")
|
|
|
|
|
.args(&["-1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("1-12\n");
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-11 16:49:12 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_invalid_float() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["1e2.3"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
|
|
|
|
.stderr_contains("invalid floating point argument: '1e2.3'")
|
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["1e2.3", "2"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
|
|
|
|
.stderr_contains("invalid floating point argument: '1e2.3'")
|
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["1", "1e2.3"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
|
|
|
|
.stderr_contains("invalid floating point argument: '1e2.3'")
|
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["1e2.3", "2", "3"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
|
|
|
|
.stderr_contains("invalid floating point argument: '1e2.3'")
|
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["1", "1e2.3", "3"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
|
|
|
|
.stderr_contains("invalid floating point argument: '1e2.3'")
|
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["1", "2", "1e2.3"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
|
|
|
|
.stderr_contains("invalid floating point argument: '1e2.3'")
|
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_invalid_float() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "1e2.3"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
|
|
|
|
.stderr_contains("invalid floating point argument: '1e2.3'")
|
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-31 18:49:02 +00:00
|
|
|
|
// ---- Tests for the big integer based path ----
|
|
|
|
|
|
2015-11-16 05:25:01 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_count_up() {
|
2016-08-23 11:52:43 +00:00
|
|
|
|
new_ucmd!()
|
2020-04-13 18:36:03 +00:00
|
|
|
|
.args(&["10"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n");
|
2015-11-16 05:25:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_count_down() {
|
2016-08-23 11:52:43 +00:00
|
|
|
|
new_ucmd!()
|
2020-04-13 18:36:03 +00:00
|
|
|
|
.args(&["--", "5", "-1", "1"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("5\n4\n3\n2\n1\n");
|
2021-01-02 09:14:18 +00:00
|
|
|
|
new_ucmd!()
|
2020-12-19 10:17:41 +00:00
|
|
|
|
.args(&["5", "-1", "1"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("5\n4\n3\n2\n1\n");
|
2015-11-16 05:25:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_separator_and_terminator() {
|
2016-08-23 11:52:43 +00:00
|
|
|
|
new_ucmd!()
|
2020-04-13 18:36:03 +00:00
|
|
|
|
.args(&["-s", ",", "-t", "!", "2", "6"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("2,3,4,5,6!");
|
2021-05-31 19:19:19 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-s", ",", "2", "6"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("2,3,4,5,6\n");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-s", "\n", "2", "6"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("2\n3\n4\n5\n6\n");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-s", "\\n", "2", "6"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("2\\n3\\n4\\n5\\n6\n");
|
2015-11-16 05:25:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_equalize_widths() {
|
2016-08-23 11:52:43 +00:00
|
|
|
|
new_ucmd!()
|
2020-04-13 18:36:03 +00:00
|
|
|
|
.args(&["-w", "5", "10"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("05\n06\n07\n08\n09\n10\n");
|
2015-11-16 05:25:01 +00:00
|
|
|
|
}
|
2020-10-20 20:35:19 +00:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_seq_wrong_arg() {
|
|
|
|
|
new_ucmd!().args(&["-w", "5", "10", "33", "32"]).fails();
|
|
|
|
|
}
|
2021-02-18 21:10:53 +00:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_zero_step() {
|
|
|
|
|
new_ucmd!().args(&["10", "0", "32"]).fails();
|
|
|
|
|
}
|
2021-05-31 18:49:02 +00:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_big_numbers() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&[
|
|
|
|
|
"1000000000000000000000000000",
|
|
|
|
|
"1000000000000000000000000001",
|
|
|
|
|
])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_only("1000000000000000000000000000\n1000000000000000000000000001\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---- Tests for the floating point based path ----
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_count_up_floats() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["10.0"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_count_down_floats() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["--", "5", "-1.0", "1"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("5.0\n4.0\n3.0\n2.0\n1.0\n");
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["5", "-1", "1.0"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("5\n4\n3\n2\n1\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_separator_and_terminator_floats() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-s", ",", "-t", "!", "2.0", "6"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("2.0,3.0,4.0,5.0,6.0!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_equalize_widths_floats() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "5", "10.0"])
|
|
|
|
|
.run()
|
|
|
|
|
.stdout_is("05\n06\n07\n08\n09\n10\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_seq_wrong_arg_floats() {
|
|
|
|
|
new_ucmd!().args(&["-w", "5", "10.0", "33", "32"]).fails();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_zero_step_floats() {
|
|
|
|
|
new_ucmd!().args(&["10.0", "0", "32"]).fails();
|
|
|
|
|
}
|
2021-08-27 22:55:02 +00:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_preserve_negative_zero_start() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-0", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0\n1\n")
|
|
|
|
|
.no_stderr();
|
2021-09-17 03:02:02 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-0", "1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0\n1\n2\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-0", "1", "2.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0\n1\n2\n")
|
|
|
|
|
.no_stderr();
|
2021-08-27 22:55:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_drop_negative_zero_end() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["1", "-1", "-0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("1\n0\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
2021-08-28 20:28:38 +00:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_scientific_notation() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "999", "1e3"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("0999\n1000\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_negative_zero() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0\n01\n")
|
|
|
|
|
.no_stderr();
|
2021-09-17 03:02:02 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0", "1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0\n01\n02\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0", "1", "2.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0\n01\n02\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_negative_zero_decimal_notation() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.0", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.0\n01.0\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.0", "1.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.0\n01.0\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.0", "1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.0\n01.0\n02.0\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.0", "1", "2.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.0\n01.0\n02.0\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.0", "1.0", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.0\n01.0\n02.0\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.0", "1.0", "2.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.0\n01.0\n02.0\n")
|
|
|
|
|
.no_stderr();
|
2021-08-28 20:28:38 +00:00
|
|
|
|
}
|
2021-09-10 02:02:31 +00:00
|
|
|
|
|
2021-09-11 16:49:12 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_negative_zero_scientific_notation() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0e0", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0\n01\n")
|
|
|
|
|
.no_stderr();
|
2021-09-17 03:02:02 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0e0", "1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0\n01\n02\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0e0", "1", "2.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0\n01\n02\n")
|
|
|
|
|
.no_stderr();
|
2021-09-11 16:49:12 +00:00
|
|
|
|
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0e+1", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-00\n001\n")
|
|
|
|
|
.no_stderr();
|
2021-09-17 03:02:02 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0e+1", "1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-00\n001\n002\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0e+1", "1", "2.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-00\n001\n002\n")
|
|
|
|
|
.no_stderr();
|
2021-09-11 16:49:12 +00:00
|
|
|
|
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e0", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.000\n01.000\n")
|
|
|
|
|
.no_stderr();
|
2021-09-17 03:02:02 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e0", "1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.000\n01.000\n02.000\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e0", "1", "2.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.000\n01.000\n02.000\n")
|
|
|
|
|
.no_stderr();
|
2021-09-11 16:49:12 +00:00
|
|
|
|
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e-2", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.00000\n01.00000\n")
|
|
|
|
|
.no_stderr();
|
2021-09-17 03:02:02 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e-2", "1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.00000\n01.00000\n02.00000\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e-2", "1", "2.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.00000\n01.00000\n02.00000\n")
|
|
|
|
|
.no_stderr();
|
2021-09-11 16:49:12 +00:00
|
|
|
|
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e5", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-000000\n0000001\n")
|
|
|
|
|
.no_stderr();
|
2021-09-17 03:02:02 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e5", "1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-000000\n0000001\n0000002\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e5", "1", "2.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-000000\n0000001\n0000002\n")
|
|
|
|
|
.no_stderr();
|
2021-09-11 16:49:12 +00:00
|
|
|
|
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e5", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-000000\n0000001\n")
|
|
|
|
|
.no_stderr();
|
2021-09-17 03:02:02 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e5", "1", "2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-000000\n0000001\n0000002\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.000e5", "1", "2.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-000000\n0000001\n0000002\n")
|
|
|
|
|
.no_stderr();
|
2021-09-11 16:49:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_decimal_scientific_notation_increment() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", ".1", "1e-2", ".11"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("0.10\n0.11\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", ".0", "1.500e-1", ".2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("0.0000\n0.1500\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Test that trailing zeros in the start argument contribute to precision.
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_decimal_scientific_notation_trailing_zeros_start() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", ".1000", "1e-2", ".11"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("0.1000\n0.1100\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Test that trailing zeros in the increment argument contribute to precision.
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_decimal_scientific_notation_trailing_zeros_increment() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "1e-1", "0.0100", ".11"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("0.1000\n0.1100\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-24 17:44:19 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_negative_decimal_notation() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-.1", ".1", ".11"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.1\n00.0\n00.1\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
seq: use BigDecimal to represent floats (#2698)
* seq: use BigDecimal to represent floats
Use `BigDecimal` to represent arbitrary precision floats in order to
prevent numerical precision issues when iterating over a sequence of
numbers. This commit makes several changes at once to accomplish this
goal.
First, it creates a new struct, `PreciseNumber`, that is responsible for
storing not only the number itself but also the number of digits (both
integer and decimal) needed to display it. This information is collected
at the time of parsing the number, which lives in the new
`numberparse.rs` module.
Second, it uses the `BigDecimal` struct to store arbitrary precision
floating point numbers instead of the previous `f64` primitive
type. This protects against issues of numerical precision when
repeatedly accumulating a very small increment.
Third, since neither the `BigDecimal` nor `BigInt` types have a
representation of infinity, minus infinity, minus zero, or NaN, we add
the `ExtendedBigDecimal` and `ExtendedBigInt` enumerations which extend
the basic types with these concepts.
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
2021-11-06 14:44:42 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_negative_scientific_notation() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-1e-3", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.001\n00.999\n")
|
|
|
|
|
.no_stderr();
|
2021-10-24 17:44:19 +00:00
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-1.e-3", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.001\n00.999\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-1.0e-4", "1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.00010\n00.99990\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-.1e2", "10", "100"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is(
|
|
|
|
|
"-010
|
|
|
|
|
0000
|
|
|
|
|
0010
|
|
|
|
|
0020
|
|
|
|
|
0030
|
|
|
|
|
0040
|
|
|
|
|
0050
|
|
|
|
|
0060
|
|
|
|
|
0070
|
|
|
|
|
0080
|
|
|
|
|
0090
|
|
|
|
|
0100
|
|
|
|
|
",
|
|
|
|
|
)
|
|
|
|
|
.no_stderr();
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.1e2", "10", "100"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is(
|
|
|
|
|
"-010
|
|
|
|
|
0000
|
|
|
|
|
0010
|
|
|
|
|
0020
|
|
|
|
|
0030
|
|
|
|
|
0040
|
|
|
|
|
0050
|
|
|
|
|
0060
|
|
|
|
|
0070
|
|
|
|
|
0080
|
|
|
|
|
0090
|
|
|
|
|
0100
|
|
|
|
|
",
|
|
|
|
|
)
|
|
|
|
|
.no_stderr();
|
seq: use BigDecimal to represent floats (#2698)
* seq: use BigDecimal to represent floats
Use `BigDecimal` to represent arbitrary precision floats in order to
prevent numerical precision issues when iterating over a sequence of
numbers. This commit makes several changes at once to accomplish this
goal.
First, it creates a new struct, `PreciseNumber`, that is responsible for
storing not only the number itself but also the number of digits (both
integer and decimal) needed to display it. This information is collected
at the time of parsing the number, which lives in the new
`numberparse.rs` module.
Second, it uses the `BigDecimal` struct to store arbitrary precision
floating point numbers instead of the previous `f64` primitive
type. This protects against issues of numerical precision when
repeatedly accumulating a very small increment.
Third, since neither the `BigDecimal` nor `BigInt` types have a
representation of infinity, minus infinity, minus zero, or NaN, we add
the `ExtendedBigDecimal` and `ExtendedBigInt` enumerations which extend
the basic types with these concepts.
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
2021-11-06 14:44:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-11 16:49:12 +00:00
|
|
|
|
/// Test that trailing zeros in the end argument do not contribute to width.
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_decimal_scientific_notation_trailing_zeros_end() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "1e-1", "1e-2", ".1100"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("0.10\n0.11\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-14 01:19:49 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_width_floats() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "9.0", "10.0"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("09.0\n10.0\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-10 02:02:31 +00:00
|
|
|
|
// TODO This is duplicated from `test_yes.rs`; refactor them.
|
|
|
|
|
/// Run `seq`, capture some of the output, close the pipe, and verify it.
|
|
|
|
|
fn run(args: &[&str], expected: &[u8]) {
|
|
|
|
|
let mut cmd = new_ucmd!();
|
|
|
|
|
let mut child = cmd.args(args).run_no_wait();
|
|
|
|
|
let mut stdout = child.stdout.take().unwrap();
|
|
|
|
|
let mut buf = vec![0; expected.len()];
|
|
|
|
|
stdout.read_exact(&mut buf).unwrap();
|
|
|
|
|
drop(stdout);
|
|
|
|
|
assert!(child.wait().unwrap().success());
|
|
|
|
|
assert_eq!(buf.as_slice(), expected);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_neg_inf() {
|
|
|
|
|
run(&["--", "-inf", "0"], b"-inf\n-inf\n-inf\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_inf() {
|
|
|
|
|
run(&["inf"], b"1\n2\n3\n");
|
|
|
|
|
}
|
2021-09-12 03:10:13 +00:00
|
|
|
|
|
2021-10-06 00:59:51 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_inf_width() {
|
|
|
|
|
run(
|
|
|
|
|
&["-w", "1.000", "inf", "inf"],
|
|
|
|
|
b"1.000\n inf\n inf\n inf\n",
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_neg_inf_width() {
|
|
|
|
|
run(
|
|
|
|
|
&["-w", "1.000", "-inf", "-inf"],
|
|
|
|
|
b"1.000\n -inf\n -inf\n -inf\n",
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-12 03:10:13 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn test_ignore_leading_whitespace() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.arg(" 1")
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("1\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_trailing_whitespace_error() {
|
|
|
|
|
// In some locales, the GNU error message has curly quotes (‘)
|
|
|
|
|
// instead of straight quotes ('). We just test the straight single
|
|
|
|
|
// quotes.
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.arg("1 ")
|
|
|
|
|
.fails()
|
2021-11-09 20:23:41 +00:00
|
|
|
|
.usage_error("invalid floating point argument: '1 '");
|
2021-09-12 03:10:13 +00:00
|
|
|
|
}
|
seq: use BigDecimal to represent floats (#2698)
* seq: use BigDecimal to represent floats
Use `BigDecimal` to represent arbitrary precision floats in order to
prevent numerical precision issues when iterating over a sequence of
numbers. This commit makes several changes at once to accomplish this
goal.
First, it creates a new struct, `PreciseNumber`, that is responsible for
storing not only the number itself but also the number of digits (both
integer and decimal) needed to display it. This information is collected
at the time of parsing the number, which lives in the new
`numberparse.rs` module.
Second, it uses the `BigDecimal` struct to store arbitrary precision
floating point numbers instead of the previous `f64` primitive
type. This protects against issues of numerical precision when
repeatedly accumulating a very small increment.
Third, since neither the `BigDecimal` nor `BigInt` types have a
representation of infinity, minus infinity, minus zero, or NaN, we add
the `ExtendedBigDecimal` and `ExtendedBigInt` enumerations which extend
the basic types with these concepts.
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
* fixup! seq: use BigDecimal to represent floats
2021-11-06 14:44:42 +00:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_negative_zero_int_start_float_increment() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-0", "0.1", "0.1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.0\n0.1\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_float_precision_increment() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["999", "0.1", "1000.1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is(
|
|
|
|
|
"999.0
|
|
|
|
|
999.1
|
|
|
|
|
999.2
|
|
|
|
|
999.3
|
|
|
|
|
999.4
|
|
|
|
|
999.5
|
|
|
|
|
999.6
|
|
|
|
|
999.7
|
|
|
|
|
999.8
|
|
|
|
|
999.9
|
|
|
|
|
1000.0
|
|
|
|
|
1000.1
|
|
|
|
|
",
|
|
|
|
|
)
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Test for floating point precision issues.
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_negative_increment_decimal() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["0.1", "-0.1", "-0.2"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("0.1\n0.0\n-0.1\n-0.2\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_zero_not_first() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-w", "-0.1", "0.1", "0.1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("-0.1\n00.0\n00.1\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_rounding_end() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["1", "-1", "0.1"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_is("1\n")
|
|
|
|
|
.no_stderr();
|
|
|
|
|
}
|
2021-12-29 14:20:17 +00:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_parse_error_float() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.arg("lmnop")
|
|
|
|
|
.fails()
|
|
|
|
|
.usage_error("invalid floating point argument: 'lmnop'");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_parse_error_hex() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.arg("0xlmnop")
|
|
|
|
|
.fails()
|
|
|
|
|
.usage_error("invalid hexadecimal argument: '0xlmnop'");
|
|
|
|
|
}
|
2022-01-26 01:45:10 +00:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_format_option() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["-f", "%.2f", "0.0", "0.1", "0.5"])
|
|
|
|
|
.succeeds()
|
|
|
|
|
.stdout_only("0.00\n0.10\n0.20\n0.30\n0.40\n0.50\n");
|
|
|
|
|
}
|
2022-01-27 01:44:54 +00:00
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_invalid_zero_increment_value() {
|
|
|
|
|
new_ucmd!()
|
|
|
|
|
.args(&["0", "0", "1"])
|
|
|
|
|
.fails()
|
|
|
|
|
.no_stdout()
|
|
|
|
|
.stderr_contains("invalid Zero increment value: '0'")
|
|
|
|
|
.stderr_contains("for more information.");
|
|
|
|
|
}
|