Expanded test coverage for core data processing and filtering logic, plus human verification on Linux VM.
Purpose: Fulfills OPS-05 (test coverage for core data processing and display logic) by expanding pipeline_test.rs with aggregator edge cases and filtering tests. Concludes with human verification of CSV logging and man page on the Linux VM.
Output: Expanded pipeline_test.rs with 8+ new tests, human-verified CSV and man page on Linux.
Task 1: Expand pipeline_test.rs with aggregator edge cases and filtering tests
tcptop/tests/pipeline_test.rs
- tcptop/tests/pipeline_test.rs (existing tests to extend)
- tcptop/src/aggregator.rs (ConnectionTable implementation, UDP_IDLE_TIMEOUT = 5s)
- tcptop/src/tui/app.rs (App::filter_records, CliFilters)
- tcptop/src/model.rs (ConnectionRecord, Protocol, TcpState)
- tcptop/src/collector/mod.rs (CollectorEvent variants)
- Test: UDP flow disappears from active list after idle timeout (>5 seconds since last_seen)
- Test: TCP state change with PID=0 inherits PID from earlier data event (PID enrichment)
- Test: Rate calculation is nonzero after two ticks with data between them
- Test: Empty table tick returns empty active and empty closed lists
- Test: Multiple connections can coexist in the same table (TCP + UDP)
- Test: CLI port filter includes connections matching source OR destination port
- Test: CLI pid filter includes only connections with matching PID
- Test: CLI tcp_only filter excludes UDP connections
- Test: Live text filter "/" matches process name substring
Add new tests to the EXISTING tcptop/tests/pipeline_test.rs file. Do NOT replace existing tests. Use the same helper pattern (inline ConnectionKey + CollectorEvent construction) as the existing tests.
**Aggregator tests to add:**
1. `test_udp_idle_timeout` - Create a UDP event, call `table.update()`, then use `std::thread::sleep(Duration::from_secs(6))` to exceed the 5-second idle timeout, then `table.tick()`. Assert `active.len() == 0`. (Note: this test is slow but proves the timeout works.)
2. `test_tcp_state_change_pid_inheritance` - Send TcpSend with pid=1234, then TcpStateChange with pid=0 and new_state=1 (ESTABLISHED). Tick. Assert the record still has pid=1234 (not 0). This tests the PID=0 enrichment logic from softirq context.
3. `test_rate_calculation_across_ticks` - Send TcpSend with bytes=1000. Call `table.tick()` (establishes baseline). Sleep briefly (`std::thread::sleep(Duration::from_millis(100))`). Send another TcpSend with bytes=2000 to same connection. Call `table.tick()` again. Assert `rate_out > 0.0` on the active record (proves rate calculation uses delta bytes / delta time).
4. `test_empty_table_tick` - Create empty ConnectionTable, call tick(). Assert `active.is_empty()` and `closed.is_empty()`.
5. `test_multiple_protocols_coexist` - Create TCP and UDP events with different keys. Tick. Assert `active.len() == 2`. Assert one has `protocol == Protocol::Tcp` and the other `protocol == Protocol::Udp`.
**Filtering tests to add** (using `tcptop::tui::app::{App, CliFilters}`):
Create a helper function `make_test_records() -> Vec<ConnectionRecord>` that returns 3 records:
- TCP connection: pid=100, process="nginx", local_port=80, remote_port=54321
- TCP connection: pid=200, process="curl", local_port=45678, remote_port=443
- UDP connection: pid=300, process="dns", local_port=53, remote_port=12345
6. `test_cli_port_filter` - Create App with CliFilters { port: Some(443), ..defaults }. Call `app.filter_records()` with all 3 records and empty filter_text. Assert result contains only the curl record (remote_port=443).
7. `test_cli_pid_filter` - CliFilters { pid: Some(100), ..defaults }. Assert result contains only nginx.
8. `test_cli_tcp_only_filter` - CliFilters { tcp_only: true, ..defaults }. Assert result contains 2 records (both TCP), no UDP.
9. `test_live_text_filter` - Create App with default CliFilters. Call `app.filter_records()` with filter_text="ngi". Assert result contains only nginx (process name substring match).
For filtering tests, construct ConnectionRecord manually (same as aggregator tests but with specific field values). The `last_seen` field can use `Instant::now()`, `prev_bytes_*` can be 0, `is_partial`/`is_closed` can be false.
cd /Users/zrowitsch/local_src/tcptop && cargo test --package tcptop --test pipeline_test -- --nocapture 2>&1 | tail -30
- tcptop/tests/pipeline_test.rs contains `test_udp_idle_timeout`
- tcptop/tests/pipeline_test.rs contains `test_tcp_state_change_pid_inheritance`
- tcptop/tests/pipeline_test.rs contains `test_rate_calculation_across_ticks`
- tcptop/tests/pipeline_test.rs contains `test_empty_table_tick`
- tcptop/tests/pipeline_test.rs contains `test_multiple_protocols_coexist`
- tcptop/tests/pipeline_test.rs contains `test_cli_port_filter`
- tcptop/tests/pipeline_test.rs contains `test_cli_pid_filter`
- tcptop/tests/pipeline_test.rs contains `test_cli_tcp_only_filter`
- tcptop/tests/pipeline_test.rs contains `test_live_text_filter`
- `cargo test --package tcptop --test pipeline_test` exits 0
- tcptop/tests/pipeline_test.rs is at least 150 lines
9 new tests pass covering aggregator edge cases (UDP timeout, PID inheritance, rate calc, empty table, multi-protocol) and filtering logic (port, pid, tcp-only, live text filter)
Task 2: Human verification of Phase 3 deliverables on Linux VM
n/a
Human syncs code to dev-debian VM and verifies: (1) CSV headless logging produces valid output with header + data rows, (2) --help includes --log flag, (3) man page renders correctly with examples section, (4) all tests pass on Linux.
Human confirms all 5 verification steps below pass on the Linux VM.
Human types "approved" confirming CSV logging, --help, man page, and test suite all work on Linux
Complete Phase 3 deliverables: CSV headless logging (Plan 01), man page and packaging config (Plan 02), expanded test coverage (Plan 03 Task 1). Everything verified automatically on macOS. Now needs functional verification on the Linux VM.
**Pre-step:** Sync code to dev-debian VM per reference_dev_debian.md.
**1. Build on Linux VM:**
```bash
cd ~/tcptop && cargo build --release 2>&1 | tail -5
```
**2. Test CSV logging (OUTP-01, OUTP-02):**
```bash
sudo ./target/release/tcptop --log /tmp/test.csv --interval 2 &
sleep 5
# Generate some traffic
curl -s https://example.com > /dev/null
sleep 3
kill %1
# Inspect CSV
head -5 /tmp/test.csv
# Verify: header row with 16 columns, data rows with timestamps
wc -l /tmp/test.csv
```
**3. Verify --help (OUTP-03):**
```bash
./target/release/tcptop --help
# Verify: --log flag appears in help output
```
**4. Verify man page (OUTP-04):**
```bash
man -l doc/tcptop.1
# Verify: renders correctly, EXAMPLES section visible, all flags documented
```
**5. Run all tests on Linux:**
```bash
cargo test --package tcptop 2>&1 | tail -20
# Verify: all tests pass including csv_test and expanded pipeline_test
```
**Expected outcomes:**
- CSV file has header row + data rows with connection info
- --help shows --log flag
- Man page renders with examples section
- All tests pass on Linux
Type "approved" or describe issues found during Linux VM testing
1. `cargo test --package tcptop --test pipeline_test` -- all 13+ tests pass (4 existing + 9 new)
2. `cargo test --package tcptop --test csv_test` -- all CSV tests pass
3. `cargo test --package tcptop` -- all package tests pass
4. Human verification on Linux VM confirms CSV logging, --help, man page, and test suite
<success_criteria>
9 new tests added to pipeline_test.rs covering aggregator edge cases and filtering
All tests pass on macOS without root
Human confirms CSV logging produces valid output on Linux VM
Human confirms man page renders correctly
Human confirms --help includes --log flag
Human confirms all tests pass on Linux
</success_criteria>
After completion, create `.planning/phases/03-output-distribution/03-03-SUMMARY.md`