Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,120 @@
|
||||
//! PostgreSQL 文档规定的 NUMERIC 分组字节;预期值独立于编码实现。
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn numeric_encoding_matches_protocol_words() {
|
||||
for (text, precision, scale, words) in [
|
||||
("0", 5, 2, vec![0, 0, 0, 2]),
|
||||
("-12.34", 5, 2, vec![2, 0, 0x4000, 2, 12, 3400]),
|
||||
("0.00001", 5, 5, vec![1, -2, 0, 5, 1000]),
|
||||
("10000", 5, 0, vec![1, 1, 0, 0, 1]),
|
||||
("12345678.9012", 12, 4, vec![3, 1, 0, 4, 1234, 5678, 9012]),
|
||||
(
|
||||
"9999999999999999999999999999999999",
|
||||
34,
|
||||
0,
|
||||
vec![
|
||||
9, 8, 0, 0, 99, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999,
|
||||
],
|
||||
),
|
||||
] {
|
||||
let value = Decimal::parse(text).unwrap();
|
||||
let expected = words
|
||||
.into_iter()
|
||||
.flat_map(i16::to_be_bytes)
|
||||
.collect::<Vec<_>>();
|
||||
let mut output = BytesMut::new();
|
||||
encode(value, precision, scale, &mut output).unwrap();
|
||||
assert_eq!(output.as_ref(), expected, "{text}");
|
||||
assert_eq!(decode(&output).unwrap(), value);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn native_numeric_preserves_decimal_extremes_and_zero() {
|
||||
for text in [
|
||||
"0",
|
||||
"-0",
|
||||
"0E-6176",
|
||||
"1E-6176",
|
||||
"1E6111",
|
||||
"-123.456",
|
||||
"1.0000",
|
||||
"9.999999999999999999999999999999999E6144",
|
||||
] {
|
||||
let value = Decimal::parse(text).unwrap();
|
||||
let mut output = BytesMut::new();
|
||||
encode_native(value, &mut output);
|
||||
assert_eq!(decode(&output).unwrap(), value, "{text}");
|
||||
}
|
||||
for (text, precision, scale) in [("1.001", 5, 2), ("1000", 5, 2), ("1", 35, 0), ("1", 2, 3)] {
|
||||
assert!(
|
||||
encode(
|
||||
Decimal::parse(text).unwrap(),
|
||||
precision,
|
||||
scale,
|
||||
&mut BytesMut::new()
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numeric_decode_rejects_malformed_or_inexact_values() {
|
||||
for words in [
|
||||
vec![1, 0, 0, 0],
|
||||
vec![-1, 0, 0, 0],
|
||||
vec![1, 0, 0, 0, 10000],
|
||||
vec![0, 0, 0xc000_u16 as i16, 0],
|
||||
vec![0, 0, 0, -1],
|
||||
vec![1, 1537, 0, 0, 1],
|
||||
vec![1, -1545, 0, 0, 1],
|
||||
vec![
|
||||
9, 8, 0, 0, 999, 9999, 9999, 9999, 9999, 9999, 9999, 9999, 9999,
|
||||
],
|
||||
] {
|
||||
let bytes = words
|
||||
.into_iter()
|
||||
.flat_map(i16::to_be_bytes)
|
||||
.collect::<Vec<_>>();
|
||||
assert!(decode(&bytes).is_err(), "{bytes:?}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "explicit release performance probe"]
|
||||
fn numeric_decode_cost() {
|
||||
use std::{hint::black_box, time::Instant};
|
||||
println!("\ncase,sample,iterations,elapsed_ns,checksum");
|
||||
for (name, text) in [
|
||||
("zero", "0"),
|
||||
("fraction", "-1234567890123456789012345.123456789"),
|
||||
("exponent", "9.999999999999999999999999999999999E6144"),
|
||||
] {
|
||||
let value = Decimal::parse(text).unwrap();
|
||||
let mut encoded = BytesMut::new();
|
||||
encode_native(value, &mut encoded);
|
||||
let expected = decode(&encoded).unwrap();
|
||||
assert_eq!(expected, value);
|
||||
for _ in 0..100 {
|
||||
black_box(decode(&encoded).unwrap());
|
||||
}
|
||||
for sample in 0..15 {
|
||||
let started = Instant::now();
|
||||
let mut decoded = Decimal::ZERO;
|
||||
for _ in 0..100_000 {
|
||||
decoded = black_box(decode(black_box(&encoded)).unwrap());
|
||||
}
|
||||
let elapsed = started.elapsed().as_nanos();
|
||||
assert_eq!(decoded, expected);
|
||||
let checksum: u64 = decoded
|
||||
.to_be_bytes()
|
||||
.iter()
|
||||
.map(|byte| u64::from(*byte))
|
||||
.sum();
|
||||
println!("numeric_decode_{name},{sample},100000,{elapsed},{checksum}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user