Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,145 @@
|
||||
use dever_runtime::value::{bytes, decimal::Decimal, parse, text};
|
||||
|
||||
#[test]
|
||||
fn byte_sum_matches_checked_add_at_block_and_integer_boundaries() {
|
||||
for length in [0, 1, 15, 16, 4095, 4096, 4097, 8193] {
|
||||
let values = vec![255; length];
|
||||
let sum = length as i64 * 255;
|
||||
for initial in [
|
||||
i64::MIN,
|
||||
-1,
|
||||
0,
|
||||
i64::MAX - sum,
|
||||
i64::MAX - sum + i64::from(length != 0),
|
||||
i64::MAX,
|
||||
] {
|
||||
let expected = values
|
||||
.iter()
|
||||
.try_fold(initial, |total, value| total.checked_add(i64::from(*value)));
|
||||
assert_eq!(
|
||||
bytes::checked_sum(&values, initial),
|
||||
expected,
|
||||
"{length}/{initial}"
|
||||
);
|
||||
}
|
||||
}
|
||||
assert_eq!(bytes::checked_sum(&[0; 8193], i64::MAX), Some(i64::MAX));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unicode_scalar_conversion_and_positions_keep_boundaries() {
|
||||
assert_eq!(text::codepoint("🙂"), Some(128578));
|
||||
assert_eq!(text::codepoint(""), None);
|
||||
assert_eq!(text::codepoint("e\u{301}"), None);
|
||||
assert_eq!(text::from_codepoint(0), Some("\0".into()));
|
||||
assert_eq!(text::from_codepoint(128578), Some("🙂".into()));
|
||||
for value in [-1, 0xd800, 0x110000] {
|
||||
assert_eq!(text::from_codepoint(value), None);
|
||||
}
|
||||
let value = "a雪🙂e\u{301}";
|
||||
assert_eq!(text::at(value, 2), Some("🙂".into()));
|
||||
assert_eq!(text::slice(value, 1, 3), Some("雪🙂".into()));
|
||||
assert_eq!(text::slice(value, 5, 5), Some("".into()));
|
||||
assert_eq!(text::slice("", 0, 0), Some("".into()));
|
||||
for (start, end) in [(-1, 1), (1, 0), (0, 6), (6, 6), (0, i64::MAX)] {
|
||||
assert_eq!(text::slice(value, start, end), None);
|
||||
}
|
||||
assert_eq!(text::at(value, i64::MAX), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn search_counts_scalars_and_empty_separator_has_no_synthetic_edges() {
|
||||
assert_eq!(text::index_of("a🙂雪", "雪"), Some(2));
|
||||
assert_eq!(text::index_of("雪", ""), Some(0));
|
||||
assert_eq!(text::index_of("雪", "x"), None);
|
||||
assert_eq!(text::split("a🙂", ""), ["a", "🙂"]);
|
||||
assert!(text::split("", "").is_empty());
|
||||
assert_eq!(text::split(",a,,", ","), ["", "a", "", ""]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_parsing_uses_the_existing_numeric_and_special_spellings() {
|
||||
assert_eq!(parse::float("1.25e2"), Some(125.0));
|
||||
assert!(parse::float("NaN").unwrap().is_nan());
|
||||
assert_eq!(parse::float("inf"), Some(f64::INFINITY));
|
||||
assert_eq!(parse::float("-inf"), Some(f64::NEG_INFINITY));
|
||||
assert!(parse::float("-0").unwrap().is_sign_negative());
|
||||
for value in [
|
||||
"nan", "+inf", "Infinity", " 1", "1 ", "1_000", "", "+", "1e",
|
||||
] {
|
||||
assert_eq!(parse::float(value), None);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimal_text_is_finite_exact_and_normalized() {
|
||||
assert_eq!(parse::decimal("1.2300").unwrap().to_string(), "1.23");
|
||||
assert_eq!(parse::decimal("-0").unwrap().to_string(), "0");
|
||||
assert_eq!(parse::decimal("1e2"), Some(Decimal::from_int(100)));
|
||||
for value in [
|
||||
"NaN",
|
||||
"inf",
|
||||
" 1",
|
||||
"1 ",
|
||||
"1_000",
|
||||
"1e9999",
|
||||
"12345678901234567890123456789012345",
|
||||
] {
|
||||
assert_eq!(parse::decimal(value), None, "{value}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimal_rounding_uses_half_even_and_rejects_invalid_quanta() {
|
||||
for (value, places, expected) in [
|
||||
("1.25", 1, "1.2"),
|
||||
("1.35", 1, "1.4"),
|
||||
("-1.25", 1, "-1.2"),
|
||||
("250", -2, "200"),
|
||||
("5e-6176", 6176, "5e-6176"),
|
||||
] {
|
||||
assert_eq!(
|
||||
Decimal::parse(value).unwrap().round(places),
|
||||
Some(Decimal::parse(expected).unwrap()),
|
||||
"{value}"
|
||||
);
|
||||
}
|
||||
let value = Decimal::from_int(1);
|
||||
for places in [i64::MIN, -6112, 6177, i64::MAX] {
|
||||
assert_eq!(value.round(places), None);
|
||||
}
|
||||
assert_eq!(Decimal::parse("1e6144").unwrap().round(0), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decimal_library_parser_preserves_the_strict_text_contract() {
|
||||
// 逐字节插入检查 dec 的词法边界;不能只测普通数值后删除前置扫描。
|
||||
for source in [
|
||||
"", "0", "-1.25", "+.25", "1E-6176", "1e6144", "NaN", "Infinity",
|
||||
] {
|
||||
for position in 0..=source.len() {
|
||||
for byte in 0..=127u8 {
|
||||
let mut text = source.to_owned();
|
||||
text.insert(position, char::from(byte));
|
||||
let library = Decimal::parse(&text).ok();
|
||||
assert_eq!(
|
||||
parse::decimal(&text).map(Decimal::to_be_bytes),
|
||||
library.map(Decimal::to_be_bytes),
|
||||
"{text:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
for text in [
|
||||
"12",
|
||||
"١٢",
|
||||
"1\u{a0}",
|
||||
"\u{2003}1",
|
||||
"-∞",
|
||||
"1.2.3",
|
||||
"1e+",
|
||||
"++1",
|
||||
] {
|
||||
assert_eq!(parse::decimal(text), None, "{text:?}");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user