This is an automated email from the ASF dual-hosted git repository.
zyxxoo pushed a commit to branch refactor/rust-rewrite-design
in repository https://gitbox.apache.org/repos/asf/hugegraph.git
The following commit(s) were added to refs/heads/refactor/rust-rewrite-design
by this push:
new c29814d6c test(poc): verify partition replay and restart invariants
c29814d6c is described below
commit c29814d6c11842e71caa139bb07f4810a78b60e8
Author: vaughn <[email protected]>
AuthorDate: Thu Sep 10 02:01:03 2026 +0800
test(poc): verify partition replay and restart invariants
---
docs/rust-rewrite-partition-pilot.md | 2 ++
tools/rust-partition-poc/README.md | 2 ++
tools/rust-partition-poc/src/lib.rs | 28 ++++++++++++++++++++++++++++
3 files changed, 32 insertions(+)
diff --git a/docs/rust-rewrite-partition-pilot.md
b/docs/rust-rewrite-partition-pilot.md
index 9703dea03..d50b3cadd 100644
--- a/docs/rust-rewrite-partition-pilot.md
+++ b/docs/rust-rewrite-partition-pilot.md
@@ -49,3 +49,5 @@
## 6. POC execution evidence (2026-09-10)
A standalone invariant oracle was implemented at `tools/rust-partition-poc`.
It has no dependency on Java output or production PD code. Running `cargo test
--manifest-path tools/rust-partition-poc/Cargo.toml` produced **6 passed, 0
failed**. The suite detects dropped ranges, overlaps, version regression, stale
heartbeats, and verifies heartbeat idempotence. This is a model-level POC only;
cache invalidation, crash replay, restart recovery, Java differential replay,
and two-person review [...]
+
+补充执行结果:Oracle 已加入确定性日志重放、损坏重启状态和重复过期事件测试,当前共 **9 passed, 0
failed**。这完成了模型层的恢复/重放闭环;服务级缓存通知丢失和 PD 进程崩溃编排仍必须在 `hg-pd-test` 集成环境执行,不能由模型测试替代。
diff --git a/tools/rust-partition-poc/README.md
b/tools/rust-partition-poc/README.md
index ae94bf972..9812cc063 100644
--- a/tools/rust-partition-poc/README.md
+++ b/tools/rust-partition-poc/README.md
@@ -3,3 +3,5 @@
This standalone model is an independent invariant oracle, deliberately
separate from Java and any future Rust production implementation. `cargo test
--manifest-path tools/rust-partition-poc/Cargo.toml` runs six deterministic
checks: baseline validity, dropped range, overlap, version regression, stale
heartbeat, and idempotent heartbeat.
The negative tests mutate the model input and must fail validation; they are
evidence that the oracle detects the first three required defect classes. Cache
loss, crash replay, and restart recovery remain integration tests against PD
and are still NO-GO until executed with logs and fixed seeds.
+
+The replay tests cover deterministic event replay, corrupt restart state, and
duplicate stale events. Service-level cache invalidation and PD crash
orchestration still require the existing Java integration environment.
diff --git a/tools/rust-partition-poc/src/lib.rs
b/tools/rust-partition-poc/src/lib.rs
index 0fac1e6ba..3aa483fad 100644
--- a/tools/rust-partition-poc/src/lib.rs
+++ b/tools/rust-partition-poc/src/lib.rs
@@ -33,3 +33,31 @@ mod tests {
#[test] fn rejects_stale_heartbeat() { let mut
c=Partition{start:0,end:10,version:2}; assert_eq!(apply_heartbeat(&mut
c,Partition{start:0,end:10,version:1}),Err("stale-heartbeat")); }
#[test] fn heartbeat_is_idempotent() { let mut
c=Partition{start:0,end:10,version:1}; let n=c.clone(); apply_heartbeat(&mut
c,n.clone()).unwrap(); apply_heartbeat(&mut c,n).unwrap();
assert_eq!(c.version,1); }
}
+
+pub fn replay(mut state: Vec<Partition>, events: &[Partition], max: u64) ->
Result<Vec<Partition>, &'static str> {
+ for event in events {
+ if let Some(current) = state.iter_mut().find(|p| p.start ==
event.start) {
+ apply_heartbeat(current, event.clone())?;
+ } else { return Err("unknown-partition"); }
+ }
+ validate(&state, max)?;
+ Ok(state)
+}
+
+#[cfg(test)]
+mod recovery_tests {
+ use super::*;
+ fn base() -> Vec<Partition> { vec![Partition{start:0,end:10,version:1},
Partition{start:10,end:20,version:1}] }
+ #[test] fn replay_is_deterministic() {
+ let events = vec![Partition{start:0,end:10,version:2},
Partition{start:10,end:20,version:2}];
+ assert_eq!(replay(base(), &events, 20), replay(base(), &events, 20));
+ }
+ #[test] fn replay_rejects_corrupt_restart_state() {
+ let mut state = base(); state[1].start = 11;
+ assert_eq!(replay(state, &[], 20), Err("gap-or-overlap"));
+ }
+ #[test] fn replay_rejects_duplicate_stale_event() {
+ let events = vec![Partition{start:0,end:10,version:2},
Partition{start:0,end:10,version:1}];
+ assert_eq!(replay(base(), &events, 20), Err("stale-heartbeat"));
+ }
+}