Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,171 @@
|
||||
//! 出站帧保留 JSON 原文,并在写出长度前验证合并后的预算。
|
||||
use super::*;
|
||||
use crate::wire::json::Json;
|
||||
use std::{hint::black_box, process::Stdio, time::Instant};
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct Call<'input> {
|
||||
kind: &'static str,
|
||||
id: u64,
|
||||
operation: &'input str,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn outgoing_payload_preserves_spelling_and_combined_limits() {
|
||||
let header = Call {
|
||||
kind: "call",
|
||||
id: 1,
|
||||
operation: "雪\"\\",
|
||||
};
|
||||
for source in ["null", " \n{\"雪\":[1e9999,-0,\"\\u96ea\"]}\t "] {
|
||||
let value = Json::parse(source).unwrap();
|
||||
let head = payload_header(
|
||||
serde_json::to_string(&header).unwrap(),
|
||||
4,
|
||||
",\"payload\":",
|
||||
value.shape().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let frame = format!("{head}{}}}", source.trim_ascii());
|
||||
#[derive(serde::Serialize)]
|
||||
struct Reference<'input> {
|
||||
#[serde(flatten)]
|
||||
header: &'input Call<'input>,
|
||||
payload: &'input RawValue,
|
||||
}
|
||||
assert_eq!(
|
||||
frame,
|
||||
serde_json::to_string(&Reference {
|
||||
header: &header,
|
||||
payload: serde_json::from_str(source).unwrap(),
|
||||
})
|
||||
.unwrap()
|
||||
);
|
||||
crate::wire::raw::validate(&frame).unwrap();
|
||||
}
|
||||
for count in [document::MAX_VALUES - 5, document::MAX_VALUES - 4] {
|
||||
let value = Json::encode(&vec![0; count]).unwrap();
|
||||
let encoded = payload_header(
|
||||
serde_json::to_string(&header).unwrap(),
|
||||
4,
|
||||
",\"payload\":",
|
||||
value.shape().unwrap(),
|
||||
);
|
||||
assert_eq!(encoded.is_ok(), count == document::MAX_VALUES - 5);
|
||||
}
|
||||
for depth in [document::MAX_DEPTH - 1, document::MAX_DEPTH] {
|
||||
let value = Json::parse(&("[".repeat(depth) + &"]".repeat(depth))).unwrap();
|
||||
assert_eq!(
|
||||
payload_header(
|
||||
serde_json::to_string(&header).unwrap(),
|
||||
4,
|
||||
",\"payload\":",
|
||||
value.shape().unwrap()
|
||||
)
|
||||
.is_ok(),
|
||||
depth < document::MAX_DEPTH
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn oversized_frame_does_not_write_a_partial_prefix() {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
runtime.block_on(async {
|
||||
let mut child = tokio::process::Command::new("cat")
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
let mut channel = Channel::new(child.stdin.take().unwrap(), child.stdout.take().unwrap());
|
||||
let payload = Json::string(&"a".repeat(LIMIT - 2)).unwrap();
|
||||
let header = Call {
|
||||
kind: "call",
|
||||
id: 1,
|
||||
operation: "measure",
|
||||
};
|
||||
assert!(
|
||||
channel
|
||||
.send_payload(
|
||||
serde_json::to_string(&header).unwrap(),
|
||||
4,
|
||||
",\"payload\":",
|
||||
payload.as_str(),
|
||||
payload.shape().unwrap()
|
||||
)
|
||||
.await
|
||||
.is_err()
|
||||
);
|
||||
let control = serde_json::json!({"kind":"health","id":0});
|
||||
channel.send(&control).await.unwrap();
|
||||
assert_eq!(channel.read().await.unwrap().as_str(), control.to_string());
|
||||
drop(channel);
|
||||
assert!(child.wait().await.unwrap().success());
|
||||
});
|
||||
}
|
||||
|
||||
fn reference_header(header: &Call<'_>, values: usize, depth: usize) -> Result<String, String> {
|
||||
if values + 4 > document::MAX_VALUES || depth + 1 > document::MAX_DEPTH {
|
||||
return Err("JSON budget".into());
|
||||
}
|
||||
let mut text = serde_json::to_string(header).map_err(|error| error.to_string())?;
|
||||
// 与正式通道一样,整帧字节预算在写出长度前检查,不属于帧头编码计时。
|
||||
text.pop();
|
||||
text.push_str(",\"payload\":");
|
||||
Ok(text)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "explicit release performance probe; header only, not complete IPC"]
|
||||
fn outgoing_header_cost() {
|
||||
let header = Call {
|
||||
kind: "call",
|
||||
id: 42,
|
||||
operation: "measure",
|
||||
};
|
||||
let shape = document::Shape::new(2, 1);
|
||||
let expected = reference_header(&header, 2, 1).unwrap();
|
||||
assert_eq!(
|
||||
payload_header(
|
||||
serde_json::to_string(&header).unwrap(),
|
||||
4,
|
||||
",\"payload\":",
|
||||
shape
|
||||
)
|
||||
.unwrap(),
|
||||
expected
|
||||
);
|
||||
for sample in 0..15 {
|
||||
for native in if sample % 2 == 0 {
|
||||
[false, true]
|
||||
} else {
|
||||
[true, false]
|
||||
} {
|
||||
let started = Instant::now();
|
||||
let mut checksum = 0;
|
||||
for _ in 0..100_000 {
|
||||
let text = if native {
|
||||
reference_header(black_box(&header), black_box(2), black_box(1))
|
||||
} else {
|
||||
payload_header(
|
||||
serde_json::to_string(black_box(&header)).unwrap(),
|
||||
4,
|
||||
",\"payload\":",
|
||||
black_box(shape),
|
||||
)
|
||||
}
|
||||
.unwrap();
|
||||
checksum += black_box(text).len();
|
||||
}
|
||||
assert_eq!(checksum, 100_000 * expected.len());
|
||||
println!(
|
||||
"worker_header,{sample},{},{},{checksum}",
|
||||
if native { "rust" } else { "dever" },
|
||||
started.elapsed().as_nanos()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user