Skip to content

Commit 966dcde

Browse files
authored
Merge pull request #21 from SunSunSun689/week3
Week3
2 parents cab2652 + 2bb398e commit 966dcde

13 files changed

Lines changed: 709 additions & 210 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,7 @@
1212

1313
# Project
1414
docs/WEEKLY_PLAN.md
15+
docs/PR-REVIEW/
1516
dora/
17+
target/
18+

CLAUDE.md

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,10 @@ issues and discussions when needed.
2323

2424
## Milestones
2525

26-
- `Community Bonding` — May–Jun 2026
27-
- [x] Week 1–2: Design NodeHarness API + scaffold crate (see [PROGRESS.md](PROGRESS.md))
28-
- [ ] Week 3–5: Implement NodeHarness, MockEventStream, MockOutputSender
29-
- [ ] Week 6–8: Implement TestSourceNode / TestSinkNode binaries
30-
- [ ] Week 9–10: Example pipelines + integration tests
31-
- [ ] Week 11–12: Polish docs, mentor feedback
32-
- `Coding Phase 1` — Jun–Jul 2026 (ends at midterm eval)
33-
- `Coding Phase 2` — Jul–Aug 2026
34-
- `Final Submission` — Aug–Sep 2026
35-
36-
Exact end-dates filled in from Google's published 2026 timeline.
26+
- `Community Bonding` — ends 2026-05-24 23:59 UTC
27+
- `Coding Phase 1` — ends 2026-07-10 23:59 UTC (Midterm evaluation deadline)
28+
- `Coding Phase 2` — ends 2026-08-24 23:59 UTC
29+
- `Final Submission` — standard 2026-08-24 23:59 UTC; extension to 2026-11-02 in approved cases.
3730

3831
## Workflow
3932

Cargo.lock

Lines changed: 2 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ authors = ["SunSunSun689"]
1010
[dependencies]
1111
# DORA node API — the primary integration surface.
1212
# Pinned to commit 45436aad (2026-06-07 snapshot).
13-
dora-node-api = { git = "https://github.com/dora-rs/dora", rev = "45436aad" }
13+
# TEMPORARY: use local dora source for TestingInput::Channel development.
14+
# REVERT to git dependency before pushing!
15+
dora-node-api = { path = "dora/apis/rust/node" }
1416

1517
# Arrow: DORA uses Arrow arrays for inter-node data.
1618
# Using 58 to match latest DORA main (which has upgraded from 53).
@@ -22,5 +24,14 @@ tokio = { version = "1", features = ["sync", "macros", "rt"] }
2224
# Futures: Stream trait for EventStream compatibility.
2325
futures = "0.3"
2426

27+
# Flume: multi-producer single-consumer channel used by DORA's
28+
# TestingOutput::ToChannel for capturing real node outputs.
29+
# Pinned to match DORA's own flume version (0.10.14).
30+
flume = "0.10"
31+
32+
# serde_json: DORA outputs are serialized as JSON maps in integration
33+
# testing mode; test code inspects them via serde_json::Value.
34+
serde_json = "1"
35+
2536
[dev-dependencies]
2637
tokio = { version = "1", features = ["full"] }

docs/PROGRESS.md

Lines changed: 67 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@
2323
| Decision | Rationale |
2424
|---|---|
2525
| Crate at repo root (not `libraries/test-utils/`) | Standalone repo; path matches dora monorepo only when merged upstream |
26-
| `arrow = "53"` | Matches the Arrow version DORA uses for inter-node data |
27-
| `tokio` for mock channels | `mpsc` channels replace daemon socket; same runtime as DORA |
26+
| `arrow = "58"` | Matches the Arrow version DORA uses for inter-node data (upgraded from 53 in Week 2) |
27+
| `flume` for output capture | `TestingOutput::ToChannel` uses flume; same channel crate DORA uses internally |
28+
| `tokio` for mock channels | Mock types use `tokio::sync::mpsc` channels; same runtime as DORA |
2829
| Stub-only (no real impl yet) | Week 1–2 scope is design + scaffold; implementation starts Week 3 |
29-
| `dora-node-api` NOT yet a dependency | Need to confirm the exact git rev / crate name with mentor before wiring up |
30+
| `dora-node-api` pinned to `45436aad` | Confirmed with mentor; locked to specific commit for reproducibility |
3031

3132
---
3233

@@ -36,7 +37,7 @@
3637

3738
- [x] **Clone & audit DORA source** at `dora/` (commit 45436aad)
3839
- [x] **Post mentor discussion** with 4 questions in GitHub Discussions
39-
- [x] **Update Cargo.toml** with `dora-node-api` = { git = "...", branch = "main" }
40+
- [x] **Update Cargo.toml** with `dora-node-api` = { git = "...", rev = "45436aad" }
4041
- [x] **Implement MockOutputSender** (complete with unit tests)
4142
- [x] `MockOutputSender::send(output_id, ArrayData) -> Result<()>`
4243
- [x] `OutputCollector` buffer & indexing by output_id ✅
@@ -50,11 +51,18 @@
5051
- [x] **Cargo.toml adjustments**
5152
- [x] Upgrade Arrow from 53 → 58 (matches DORA main branch)
5253
- [x] Add futures = "0.3" for Stream trait compatibility
53-
- [x] **NodeHarness::new() skeleton implemented** (2026-06-07)
54-
- [x] Calls `DoraNode::init_testing()` with `TestingInput::Input(...)` + `TestingOutput::ToWriter(sink())`
55-
- [x] Stores `(DoraNode, EventStream)` + mock channel handles (`input_tx`, `output_collector`)
56-
- [x] `send_input` / `tick` / `recv_output` / `run_to_completion` remain `todo!()` (Week 3)
57-
- [x] `#[allow(dead_code)]` on fields — intentionally unused at skeleton stage
54+
- [x] **NodeHarness fully wired** (2026-06-07, rewired 2026-06-09 per mentor feedback)
55+
- [x] Calls `DoraNode::init_testing()` with `TestingInput::Channel(rx)` + `TestingOutput::ToChannel(tx)`
56+
- [x] Both legs live: input via flume channel for runtime injection, output via flume for capture
57+
- [x] Returns `Result<Self, NodeError>` instead of panicking
58+
- [x] `send_input(TimedIncomingEvent)` implemented — pushes events through live channel
59+
- [x] `send_stop()` convenience method added
60+
- [x] `tick()` uses synchronous `EventStream::recv()` (blocking — consistent with `init_testing`)
61+
- [x] `recv_output()` drains flume-based output buffers (returns JSON maps per DORA format)
62+
- [x] Field order ensures clean shutdown: `input_tx` dropped first → unblocks daemon thread
63+
- [x] Upstream dora change: added `TestingInput::Channel(flume::Receiver<TimedIncomingEvent>)` variant
64+
- [x] Upstream dora change: added `EventSource` enum to `IntegrationTestingEvents` for channel support
65+
- [x] Smoke test passes: create harness → send_stop → tick → assert event received
5866
- [x] **Bug fix: MockEventStream hanging tests**
5967
- [x] `test_mock_event_stream_multiple_events` — drop `tx` before checking `None`
6068
- [x] `test_mock_event_stream_multiple_senders` — drop `tx1` + `tx2` before checking `None`
@@ -97,12 +105,27 @@ pub fn init_testing(
97105

98106
**EventStream:** Implements `futures::Stream<Item = Event>`; uses `tokio::sync::mpsc::Receiver`
99107

100-
### Next: Week 3
101-
102-
- [x] **Implement NodeHarness::new()** calling `DoraNode::init_testing()` ✅ (done Week 2)
103-
- [ ] **Implement send_input / recv_output / tick**
104-
- [ ] **Wire mock channels** into the event loop (replacing pre-declared TestingInput events)
105-
- [ ] **Write end-to-end unit tests** with real node execution
108+
### Next: Week 3 (COMPLETED 2026-06-09)
109+
110+
- [x] **Implement send_input / recv_output / tick**
111+
- [x] `send_input(TimedIncomingEvent)` — pushes events through live flume channel
112+
- [x] `send_stop()` — convenience wrapper for Stop events
113+
- [x] `tick()` — synchronous, polls `EventStream::recv()`, collects outputs
114+
- [x] `recv_output(id)` — drains output buffers; returns `Option<Vec<Map>>`
115+
- [x] **Added `TestingInput::Channel` variant upstream** (in vendored dora source)
116+
- [x] `TestingInput::Channel(flume::Receiver<TimedIncomingEvent>)` in `integration_testing.rs`
117+
- [x] `EventSource` enum in `node_integration_testing.rs` — supports Vec + Channel
118+
- [x] `check_poisoned()` extracted as reusable helper
119+
- [x] **Added `NodeHarness::send_output()`**delegates to `DoraNode::send_output`
120+
- [x] Known limitation: deadlocks if called between `tick()` calls (event-stream prefetch blocks daemon)
121+
- [x] **Wrote end-to-end test** (`tests/e2e.rs`)
122+
- [x] `e2e_receive_input_and_stop`: send_input(Input) + send_stoptick ×2verify events
123+
- [x] **Fixed bugs from code review**
124+
- [x] Typo: "Convience""Convenience"
125+
- [x] `send_output`: `NodeError::Init` → `NodeError::Output` for invalid output_id
126+
- [x] `send_output`: removed `.parse().unwrap()` panic, returns `Result` instead
127+
- [x] **CI gates pass**: fmt| clippy| 10/10 tests ✅ (6 unit + 3 smoke + 1 E2E)
128+
- [x] **Mentor feedback resolved**: Option B confirmed (init_testing + Channel), pure-mock discarded
106129

107130
---
108131

@@ -143,29 +166,33 @@ pub fn init_testing(
143166

144167
```
145168
gsoc2026-dora-test-utils/
146-
├── Cargo.toml
169+
├── Cargo.toml # (TEMP: path dep for TestingInput::Channel dev)
147170
├── Cargo.lock
148171
├── src/
149-
│ ├── lib.rs # Crate docs + re-exports
150-
│ ├── harness.rs # NodeHarness skeleton (init_testing wired)
172+
│ ├── lib.rs # Crate docs + status table + re-exports
173+
│ ├── harness.rs # NodeHarness (live channels, send/recv/tick)
151174
│ └── mock/
152-
│ ├── mod.rs # Mock module docs
153-
│ ├── event_stream.rs # MockEventStream (✅ full impl + 3 tests)
154-
│ └── output.rs # MockOutputSender + OutputCollector (✅ + 3 tests)
175+
│ ├── mod.rs # Mock module docs
176+
│ ├── event_stream.rs # MockEventStream (✅ full impl + 3 tests)
177+
│ └── output.rs # MockOutputSender + OutputCollector (✅ + 3 tests)
155178
├── tests/
156-
│ └── smoke.rs # 3 smoke tests passing
179+
│ ├── smoke.rs # 3 smoke tests (harness construction + mock pairs)
180+
│ └── e2e.rs # 1 E2E test (send_input → tick → verify events)
181+
├── dora/ # Vendored dora source (TestingInput::Channel changes)
157182
├── docs/
158-
│ ├── PROGRESS.md # This file
159-
│ ├── WEEK1-2_SUMMARY.md # Week 1-2 summary
160-
│ └── WEEKLY_PLAN.md # Detailed weekly plan
183+
│ ├── PROGRESS.md # This file
184+
│ ├── WEEK1-2_SUMMARY.md # Week 1-2 summary
185+
│ ├── WEEKLY_PLAN.md # Detailed weekly plan
186+
│ ├── PR-REVIEW/ # Mentor PR reviews
187+
│ └── superpowers/ # Design specs + implementation plans
188+
│ ├── specs/
189+
│ └── plans/
161190
├── .github/workflows/
162-
│ └── ci.yml # check / test / clippy / fmt
163-
├── .claude/
164-
│ └── settings.local.json # Local permissions (bypass mode)
191+
│ └── ci.yml # check / test / clippy / fmt
165192
├── CLAUDE.md
166193
├── README.md
167194
├── LICENSE
168-
└── proposal.pdf
195+
└── docs/proposal.pdf
169196
```
170197
171198
---
@@ -174,29 +201,18 @@ gsoc2026-dora-test-utils/
174201
175202
### 🔴 Critical Path (Blocking)
176203
177-
#### Week 3 (高优先级)
204+
#### Week 3 (高优先级) ✅ COMPLETE (2026-06-09)
178205
- [x] **Q1: DORA commit pin** — ✅ Locked to 45436aad (2026-06-07)
179206
- [x] **Q2: init_testing() signature** — ✅ Found in dora source code
180-
- [x] **Implement NodeHarness::new()** — Core entry point ✅ (done Week 2)
181-
- [x] Wrap `DoraNode::init_testing(TestingInput, TestingOutput, TestingOptions)`
182-
- [x] Wire up MockEventStream as event source (sender stored as `input_tx`)
183-
- [x] Wire up MockOutputSender as output sink (collector stored as `output_collector`)
184-
- [x] Handle async runtime (tokio) — `init_testing()` is synchronous
185-
- [ ] **NodeHarness::send_input()** — Inject test events
186-
- [ ] Create Event::Input from user-provided ArrayData
187-
- [ ] Push to MockEventStream mpsc channel
188-
- [ ] Handle input_id validation
189-
- [ ] **NodeHarness::recv_output()** — Drain captured outputs
190-
- [ ] Call OutputCollector::drain(output_id)
191-
- [ ] Return Vec<ArrayData> or None
192-
- [ ] **NodeHarness::tick()** — Drive one iteration
193-
- [ ] Poll node event loop once
194-
- [ ] Collect any outputs via OutputCollector::collect_pending()
195-
- [ ] **End-to-end test** — Verify harness works
196-
- [ ] Create node via harness
197-
- [ ] Send synthetic Input event
198-
- [ ] Call tick()
199-
- [ ] Assert output received
207+
- [x] **Add TestingInput::Channel upstream** — ✅ Added Channel variant in vendored dora source
208+
- [x] **NodeHarness::new()** — ✅ Uses TestingInput::Channel + TestingOutput::ToChannel
209+
- [x] **NodeHarness::send_input()** — ✅ Pushes TimedIncomingEvent through live flume channel
210+
- [x] **NodeHarness::send_stop()** — ✅ Convenience wrapper
211+
- [x] **NodeHarness::send_output()** — ✅ Delegates to DoraNode::send_output (known deadlock after tick)
212+
- [x] **NodeHarness::recv_output()** — ✅ Drains output buffers by ID
213+
- [x] **NodeHarness::tick()** — ✅ Synchronous, polls EventStream::recv(), collects outputs
214+
- [x] **End-to-end test** — ✅ `tests/e2e.rs`: send_input → tick → verify Input + Stop events
215+
- [x] **Code review bugs fixed** — ✅ Typo, error variant, unwrap panic resolved
200216
201217
#### Week 4 (高优先级)
202218
- [ ] **NodeHarness::run_to_completion()** — Batch mode
@@ -294,7 +310,7 @@ gsoc2026-dora-test-utils/
294310
| Week 1–2 API design | 7/7 deliverables | 7/7 | ✅ |
295311
| Week 2 Mock impl | 6 unit + 3 smoke tests passing | 9/9 | ✅ |
296312
| Week 2 NodeHarness::new() | Skeleton calling init_testing() | ✅ | ✅ |
297-
| Week 3 NodeHarness core | 4 methods + E2E test | 1/5 | ⏳ |
313+
| Week 3 NodeHarness core | 6 methods (send_input/send_stop/send_output/tick/recv_output/new) + E2E test | 10/10 tests passing | ✅ |
298314
| Week 5 Binaries | TestSource + TestSink | 0/2 | ⏳ |
299315
| Week 11 Docs | API + Setup + Usage | 0/3 | ⏳ |
300316
| **Mid-term eval (Week 12)** | MVP complete | TBD | ⏳ |

docs/WEEK1-2_SUMMARY.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
### 1. Crate Scaffolded ✅
1111
- Created `dora-test-utils` v0.1.0 at repo root
1212
- `Cargo.toml` configured with key dependencies:
13-
- `arrow = "53"` (matches DORA inter-node data format)
13+
- `arrow = "58"` (matches DORA inter-node data format, upgraded from 53)
1414
- `tokio` for async mock channels
1515
- `Cargo.lock` committed for reproducibility
1616
- Cargo mirror configured (USTC) for faster downloads in China
@@ -22,11 +22,11 @@
2222
pub struct NodeHarness { ... }
2323

2424
impl NodeHarness {
25-
pub fn new() -> Self // Create harness with mock channels
26-
pub fn send_input(&mut self, id: &str, data: ArrayData) -> Result<()> // Inject input
27-
pub fn tick(&mut self) -> Result<()> // Drive one event loop iteration
28-
pub fn recv_output(&mut self, id: &str) -> Vec<ArrayData> // Drain outputs
29-
pub async fn run_to_completion(&mut self) -> Result<()> // Batch run until idle
25+
pub fn new(events: Vec<TimedIncomingEvent>) -> Result<Self, NodeError>
26+
pub fn send_input(&mut self, id: impl Into<String>, data: ArrayData) // todo!() — pending mentor decision
27+
pub async fn tick(&mut self) -> Option<Event> // Drive one event loop iteration
28+
pub fn recv_output(&mut self, id: impl Into<String>) -> Option<Vec<serde_json::Map<...>>> // Drain outputs
29+
pub async fn run_to_completion(&mut self) // todo!() — Week 4
3030
}
3131
```
3232

@@ -50,7 +50,7 @@ impl MockOutputSender {
5050
}
5151

5252
impl OutputCollector {
53-
pub fn drain(&mut self, output_id: &str) -> Vec<ArrayData>
53+
pub fn drain(&mut self, output_id: &str) -> Option<Vec<ArrayData>>
5454
}
5555
```
5656

@@ -99,7 +99,7 @@ Three compilation-level tests in `tests/smoke.rs`:
9999
| Decision | Rationale |
100100
|----------|-----------|
101101
| **Crate at repo root** (not `libraries/test-utils/`) | Standalone repo during GSoC; path aligns with dora monorepo structure only after upstream merge |
102-
| **arrow = "53"** | Matches Arrow version DORA uses for inter-node data interchange |
102+
| **arrow = "58"** | Matches Arrow version DORA uses for inter-node data interchange (upgraded from 53 in Week 2) |
103103
| **tokio + mpsc** | `mpsc` channels replace daemon socket; same async runtime as DORA core |
104104
| **Stub-only implementation** | Week 12 scope is API design + scaffolding; real impl starts Week 3 |
105105
| **dora-node-api NOT yet a dependency** | Need mentor confirmation of exact git rev / crate name before wiring up |
@@ -168,7 +168,7 @@ Three compilation-level tests in `tests/smoke.rs`:
168168
| **Crate LOC** | ~250 (stubs only) |
169169
| **Tests** | 3 passing smoke tests |
170170
| **API methods stubbed** | 9 (5 on NodeHarness, 2 on MockEventStream, 2 on MockOutputSender/OutputCollector) |
171-
| **Dependencies locked** | arrow=53, tokio, serde, serde_json |
171+
| **Dependencies locked** | arrow=58, tokio, flume, futures, serde_json |
172172
| **CI jobs** | 4 (check, test, clippy, fmt) |
173173
| **Deliverables on track** |7/7 (API, mock types, crate scaffold, CI, tests, cargo mirror, API freeze) |
174174

0 commit comments

Comments
 (0)