Skip to content

Commit 6f5e664

Browse files
authored
Merge pull request #40 from SunSunSun689/week10
Week10
2 parents f0c7408 + 8ae9811 commit 6f5e664

11 files changed

Lines changed: 1143 additions & 150 deletions

File tree

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,7 @@ path = "src/bin/test-sink.rs"
6565
[[bin]]
6666
name = "test-source"
6767
path = "src/bin/test_source.rs"
68+
69+
[[example]]
70+
name = "demo_replay"
71+
path = "examples/demo_replay.rs"

README.md

Lines changed: 92 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
[DORA](https://dora-rs.ai/) 数据流框架提供单元测试和集成测试支持的 Rust 工具库。
44

5-
65
## 三层测试支持
76

87
```
@@ -13,7 +12,7 @@
1312
│ Layer 2: TestSource / TestSink — 集成测试 │
1413
│ 扔进真实 YAML dataflow,端到端验证 │
1514
├──────────────────────────────────────────────────┤
16-
│ Layer 3: Record / Replay — 回归测试 (开发中)
15+
│ Layer 3: Record / Replay — 回归测试
1716
│ 录制一次真实运行 → 之后每次重放比对 │
1817
└──────────────────────────────────────────────────┘
1918
```
@@ -27,16 +26,16 @@ use dora_test_utils::NodeHarness;
2726

2827
#[test]
2928
fn test_my_node() {
30-
let mut harness = NodeHarness::new().expect("创建 harness 失败");
29+
let mut harness = NodeHarness::new().expect("failed to create harness");
3130

32-
// 往节点注入数据
31+
// Buffer input data (deferred init — node created on first tick)
3332
harness.send_data("image", serde_json::json!([1, 2, 3]));
3433

35-
// 跑到结束,收集所有事件
34+
// Run to completion, collect all events
3635
let events = harness.run_to_completion();
3736
assert!(!events.is_empty());
3837

39-
// 节点产生的输出也能拿到
38+
// Collect node outputs
4039
let outputs = harness.recv_output("result");
4140
assert!(outputs.is_some());
4241
}
@@ -53,51 +52,74 @@ fn test_my_node() {
5352
| `echo-node` | 透传:收到啥发啥,用于验证链路通不通 |
5453
| `classifier-node` | 按阈值分流:Int64 数值 > 阈值发到 high,否则发到 low |
5554

56-
**用法示例** — 写一个 YAML dataflow:
57-
5855
```yaml
5956
nodes:
6057
- id: test-source
6158
path: ./target/debug/test-source
6259
args: "--output data:source.json"
6360
outputs: [data]
64-
6561
- id: my-node
6662
path: ./target/debug/my-node
6763
inputs:
6864
data: test-source/data
6965
outputs: [result]
70-
7166
- id: test-sink
7267
path: ./target/debug/test-sink
7368
inputs:
7469
result: my-node/result
7570
args: "--expected-file expected.json --output-file result.json"
7671
```
7772
78-
然后一行命令跑起来:
79-
8073
```bash
8174
dora run my-dataflow.yml --stop-after 10s
8275
cat result.json # {"match": true} 或 {"match": false, "differences": [...]}
8376
```
8477

85-
**多输出模式**(Week 8 新增):
78+
### Layer 3: RecordSession / ReplaySession(回归测试)
8679

87-
```bash
88-
test-source --output data_a:a.json --output data_b:b.json
80+
录制一次真实 dataflow 运行的输出,之后每次重放自动比对,检测回归:
81+
82+
```rust
83+
use dora_test_utils::record::RecordSession;
84+
use std::time::Duration;
85+
86+
// ── 录制基线 ──
87+
let recording = RecordSession::attach("dataflow.yml")?
88+
.record_sink("test-sink", "sink_output.json")
89+
.with_timeout(Duration::from_secs(10))
90+
.run()?;
91+
recording.save("baseline.json")?;
92+
93+
// ── 重放比对 ──
94+
let result = ReplaySession::load("baseline.json")?
95+
.replay_sink("test-sink", "sink_output.json")
96+
.with_timeout(Duration::from_secs(10))
97+
.run()?;
98+
99+
if result.is_clean() {
100+
println!("No regressions detected");
101+
} else {
102+
println!("{}", result.diff()); // structured diff report
103+
result.assert_no_regression(); // panics with formatted diff
104+
}
89105
```
90106

91-
一条命令往两个输出通道发不同的数据。
107+
**二层比对**
108+
- Layer 1: 快速 JSON 结构 diff
109+
- Layer 2: Arrow 语义比对(容忍 Int32→Int64 等类型差异)
110+
111+
**DiffReport** 支持 `Display` + `Serialize`,区分四种状态:
112+
- `Match` — 完全一致
113+
- `Mismatch` — 数据差异(含字段级路径和值)
114+
- `Missing` — 基线中有但重放中没有的 sink
115+
- `Extra` — 重放中有但基线中没有的 sink
92116

93117
## 快速上手
94118

95119
### 前置条件
96120

97121
- Rust 工具链
98-
- 本仓库 clone 到本地
99-
- dora CLI(可通过 `cargo install dora-cli --git https://github.com/dora-rs/dora.git` 安装,或从 PATH 获取)
100-
- 集成测试和 record/replay 测试需要 `dora run` 命令
122+
- dora CLI(从 PATH 获取,或 `cargo install dora-cli --git https://github.com/dora-rs/dora.git`
101123

102124
### 编译所有二进制
103125

@@ -108,35 +130,45 @@ cargo build --bin test-source --bin test-sink --bin echo-node --bin classifier-n
108130
### 跑测试
109131

110132
```bash
111-
# 库单元测试(42 个)
133+
# 库单元测试(52 个)
112134
cargo test --lib
113135

114136
# 端到端测试(5 个)
115137
cargo test --test e2e
116138

139+
# Record e2e 测试(4 个,需要 dora CLI)
140+
cargo test --test e2e_record -- --test-threads=1
141+
142+
# Replay e2e 测试(11 个,需要 dora CLI)
143+
cargo test --test e2e_replay -- --test-threads=1
144+
117145
# 集成测试(6 个,需要 dora CLI)
118146
cargo test --test integration -- --test-threads=1
119147

148+
# 冒烟测试(3 个)
149+
cargo test --test smoke
150+
120151
# 全部
121152
cargo test
122153
```
123154

124-
### 跑演示脚本
155+
### 演示脚本
125156

126157
```bash
127-
bash scripts/demo-week8.sh
158+
bash scripts/demo-week12.sh
128159
```
129160

130-
一键跑通 3 个流水线(echo、multi-echo、classifier)+ 全部测试
161+
一键展示:RecordSession 录制基线 → ReplaySession 验证无回归 → 制造变更 → 检测到回归
131162

132163
## 项目结构
133164

134165
```
135166
src/
136-
├── lib.rs # crate 入口,模块声明
137-
├── harness.rs # NodeHarness — 单元测试驱动
138-
├── source.rs # TestSource — 数据注入库
139-
├── sink.rs # TestSink — 数据比对库
167+
├── lib.rs # crate 入口,模块声明 + API 稳定性表格
168+
├── harness.rs # NodeHarness — 单元测试驱动(deferred-init 模型)
169+
├── source.rs # TestSource — 数据注入库(JSON → Arrow 转换)
170+
├── sink.rs # TestSink — 数据比对库(语义比对 + 严格比对)
171+
├── record.rs # RecordSession + ReplaySession + DiffReport
140172
├── traits.rs # IntoInputData trait
141173
├── mock/ # MockEventStream、MockOutputSender
142174
└── bin/
@@ -146,34 +178,48 @@ src/
146178
tests/
147179
├── fixtures/ # YAML dataflow、测试数据文件
148180
├── echo-node.rs # echo-node 二进制(透传)
149-
├── e2e.rs # 端到端测试 (5)
181+
├── e2e.rs # NodeHarness 端到端测试 (5)
182+
├── e2e_record.rs # RecordSession e2e 测试 (4)
183+
├── e2e_replay.rs # ReplaySession e2e 测试 (11)
150184
├── integration.rs # 集成测试 (6)
151185
└── smoke.rs # 冒烟测试 (3)
152186
docs/ # 设计文档、进度记录、upstream PR 计划
187+
scripts/ # Demo 脚本
153188
```
154189

190+
## API 稳定性
191+
192+
| API | 状态 | 说明 |
193+
|-----|------|------|
194+
| `NodeHarness` | **Stable** | 单元测试驱动,deferred-init 模型 |
195+
| `TestSource` / `TestSink` | **Stable** | JSON/Arrow 数据注入和比对 |
196+
| `MockEventStream` / `MockOutputSender` | **Stable** | 无 daemon mock 测试 |
197+
| `IntoInputData` trait | **Stable** | 数据注入 trait |
198+
| `RecordSession` / `Recording` | **Experimental** | 录制 dataflow 输出为基线 |
199+
| `ReplaySession` / `ReplayResult` | **Experimental** | 重放比对,检测回归 |
200+
| `DiffReport` / `SinkDiff` / `FieldDiff` | **Experimental** | 结构化差异报告 |
201+
155202
## 测试统计(Week 10)
156203

157-
| 类别 | 数量 |
158-
|------|------|
159-
| 库单元测试 | 45 |
160-
| 端到端测试 (e2e) | 5 |
161-
| Record/Replay 测试 (e2e_record) | 4 |
162-
| 集成测试 | 6 |
163-
| 冒烟测试 | 3 |
164-
| Mock 测试 | 6 |
165-
| **总计** | **62** |
166-
| CI jobs | 5(check / test / clippy / fmt / integration) |
204+
| 类别 | 数量 | 位置 |
205+
|------|------|------|
206+
| 库单元测试 | 52 | `src/*.rs` |
207+
| 端到端测试 (e2e) | 5 | `tests/e2e.rs` |
208+
| Record e2e (e2e_record) | 4 | `tests/e2e_record.rs` |
209+
| Replay e2e (e2e_replay) | 11 | `tests/e2e_replay.rs` |
210+
| 集成测试 | 6 | `tests/integration.rs` |
211+
| 冒烟测试 | 3 | `tests/smoke.rs` |
212+
| **总计** | **81** | |
167213

168214
## CI
169215

170-
5 个 CI jobs,全绿:
216+
6 个 CI jobs,全绿:
171217

172218
- **check**`cargo check`
173-
- **test**`cargo test --lib`
219+
- **test**`cargo test --lib` + `cargo test --test e2e` + `cargo test --test smoke`
174220
- **clippy**`cargo clippy -- -D warnings`
175221
- **fmt**`cargo fmt --check`
176-
- **integration-test** — 编译 dora CLI + 跑集成测试
222+
- **integration-test** — 编译 dora CLI + test 二进制 + 集成测试 + e2e_record + e2e_replay
177223

178224
GitHub Actions 配置在 `.github/workflows/ci.yml`
179225

@@ -187,8 +233,11 @@ GitHub Actions 配置在 `.github/workflows/ci.yml`。
187233
| 6 | Echo 流水线 + 集成测试 ||
188234
| 7 | 边界测试 + CI 集成 ||
189235
| 8 | 多输出 + classifier + 3 条流水线 ||
190-
| 9 | flume→tokio mpsc + Record/Replay 设计 ||
191-
| 10+ | Record/Replay 实现 ||
236+
| 9 | flume→tokio mpsc + RecordSession ||
237+
| 10 | ReplaySession + code review 修复 ||
238+
| 11 | Upstream PR (a) 代码准备 ||
239+
| 12 | Demo + 边界测试 + docs polish | 🚧 |
240+
| 13 | Final submission ||
192241

193242
详见 [`docs/PROGRESS.md`](docs/PROGRESS.md)
194243

docs/PROGRESS.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ Code review of the Week 10 ReplaySession implementation found 15 issues.
148148

149149
`replay_sink_not_in_baseline``replay_sink_not_in_baseline_reported_as_extra` (behavior changed: no longer a hard error, reported as Extra in DiffReport)
150150

151+
### Commits
152+
153+
| Commit | Description |
154+
|--------|-------------|
155+
| `dfa071a` | fix: 13 code-review findings — comparison correctness, CI coverage, type fidelity |
156+
151157
### Verification
152158

153159
- `cargo check`
@@ -159,6 +165,30 @@ Code review of the Week 10 ReplaySession implementation found 15 issues.
159165
- `cargo test --test e2e_replay -- --test-threads=1` ✅ (11/11 pass)
160166
- `cargo test --test smoke -- --test-threads=1` ✅ (3/3 pass)
161167

168+
## Week 12 (2026-08-02): Demo script, README, edge-case tests
169+
170+
### Changes
171+
172+
- **`examples/demo_replay.rs`**: Record→Replay→regression detection showcase
173+
- **`scripts/demo-week12.sh`**: full demo script (build + demo + test suite)
174+
- **`README.md`**: Updated API docs, Record/Replay examples, test counts (52→80), API stability table
175+
- **Edge-case tests**: +28 unit tests (80 total) covering compare_recordings, json_diff, compare_data_semantic, DiffReport, NodeHarness, TestSink, TestSource
176+
177+
### Commits
178+
179+
| Commit | Description |
180+
|--------|-------------|
181+
| `98d1f24` | docs: Week 12 — demo script, README update, edge-case tests |
182+
| `5abca01` | docs: annotate upstream flume->tokio-mpsc migration plan |
183+
184+
### Verification
185+
186+
- `cargo check`
187+
- `cargo fmt --check`
188+
- `cargo clippy --lib`
189+
- `cargo test --lib` ✅ (80/80 pass)
190+
- `cargo test --test e2e` ✅ (5/5 pass)
191+
162192
## Remaining Plan (Adjusted 2026-07-27)
163193

164194
| Week | Dates (China, Mon–Sun) | Deliverable |

0 commit comments

Comments
 (0)