Skip to content

Commit d668853

Browse files
iduartgomezclaudesanity
authored
feat: add event log aggregation for multi-node debugging (#2032)
Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Ian Clarke <sanity@users.noreply.github.com>
1 parent 86f5119 commit d668853

File tree

23 files changed

+6900
-4507
lines changed

23 files changed

+6900
-4507
lines changed

Cargo.lock

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

MACRO_TEST_CONVERSION_STATUS.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# Test Conversion Status: `#[freenet_test]` Macro
2+
3+
## Overview
4+
5+
This document tracks which integration tests have been converted to use the `#[freenet_test]` procedural macro and explains why certain tests were not converted.
6+
7+
## Successfully Converted Tests
8+
9+
### error_notification.rs (3/4 tests converted)
10+
11+
**Converted:**
12+
1. `test_get_error_notification` - GET operation error notification
13+
2. `test_put_error_notification` - PUT operation error notification
14+
3. `test_update_error_notification` - UPDATE operation error notification
15+
16+
**Not Converted:**
17+
- `test_connection_drop_error_notification` - Requires custom peer lifecycle management (selective shutdown)
18+
- **Reason:** The macro doesn't support stopping individual nodes mid-test
19+
20+
### isolated_node_regression.rs (4/4 tests converted)
21+
22+
**All Converted:**
23+
1. `test_isolated_node_put_get_workflow` - Complete PUT→GET workflow on isolated node
24+
2. `test_concurrent_get_deduplication_race` - Concurrent GET operations
25+
3. `test_isolated_node_local_subscription` - Subscribe operations on isolated node
26+
4. `test_isolated_node_update_operation` - UPDATE operations on isolated nodes
27+
28+
### test_macro_example.rs (7/7 tests - examples)
29+
30+
**All Using Macro:**
31+
1. `test_single_node` - Single gateway node
32+
2. `test_multi_node` - Multiple nodes (gateway + 2 peers)
33+
3. `test_with_event_aggregation` - Event aggregation on failure
34+
4. `test_always_aggregate` - Event aggregation always
35+
5. `test_custom_tokio_config` - Custom tokio worker threads
36+
6. `test_current_thread_runtime` - Single-threaded tokio runtime
37+
7. `test_multiple_gateways` - Multiple gateway nodes (NEW!)
38+
39+
## Tests Not Yet Converted
40+
41+
### operations.rs (0/11 tests converted)
42+
43+
**Tests in this file:**
44+
- `test_put_contract`
45+
- `test_update_contract`
46+
- `test_put_merge_persists_state`
47+
- `test_multiple_clients_subscription`
48+
- `test_get_with_subscribe_flag`
49+
- `test_put_with_subscribe_flag`
50+
- `test_delegate_request`
51+
- `test_gateway_packet_size_change_after_60s`
52+
- `test_production_decryption_error_scenario`
53+
- `test_subscription_introspection`
54+
- `test_update_no_change_notification`
55+
56+
**Why not converted:**
57+
1. **Complex peer-gateway relationships** - Tests set up specific gateway configurations and peer connections
58+
2. **Custom gateway discovery** - Uses `gw_config()` and `base_node_test_config()` helpers with specific network topologies
59+
3. **Multi-phase testing** - Some tests require stopping/starting nodes at specific points
60+
4. **Contract persistence verification** - Tests verify data persists across specific node restarts
61+
5. **Uses `#[test_log::test]`** - Would need to verify macro compatibility
62+
63+
**Future conversion approach:**
64+
- Macro would need to support:
65+
- Configuring peer gateway lists (which gateways peers should connect to)
66+
- Mid-test node lifecycle control (stop/restart specific nodes)
67+
- Or: Create specialized macros for these patterns (e.g., `#[freenet_network_test]`)
68+
69+
### connectivity.rs (0/3 tests converted)
70+
71+
**Tests in this file:**
72+
- `test_gateway_reconnection`
73+
- `test_basic_gateway_connectivity`
74+
- `test_three_node_network_connectivity`
75+
76+
**Why not converted:**
77+
1. **Network topology testing** - These tests specifically test connection establishment and maintenance
78+
2. **Custom disconnect/reconnect logic** - Tests intentionally disconnect and reconnect nodes
79+
3. **Connection state verification** - Tests verify specific connection counts and states
80+
4. **Requires fine-grained control** - Need to control exactly when nodes connect/disconnect
81+
82+
**Future conversion approach:**
83+
- Similar to operations.rs, would need lifecycle control features
84+
- Or: Keep as-is since these are network layer tests, not contract operation tests
85+
86+
### Other Test Files
87+
88+
- `redb_migration.rs` - Database migration tests (no multi-node setup)
89+
- `token_expiration.rs` - Token config tests (no multi-node setup)
90+
- `ubertest.rs` - Large-scale River app test (too specialized/complex)
91+
92+
## Conversion Statistics
93+
94+
- **Total test files analyzed:** 8
95+
- **Files with converted tests:** 3
96+
- **Total tests converted:** 7
97+
- **Total boilerplate lines eliminated:** ~300+
98+
99+
## Macro Features Used in Converted Tests
100+
101+
### Basic Features
102+
- ✅ Single gateway node
103+
- ✅ Multiple peer nodes
104+
- ✅ Multiple gateway nodes (NEW!)
105+
- ✅ Custom timeouts
106+
- ✅ Custom startup wait times
107+
- ✅ Event aggregation (on_failure, always, never)
108+
- ✅ Custom log levels
109+
- ✅ Tokio flavor configuration
110+
- ✅ Tokio worker thread configuration
111+
112+
### TestContext API Used
113+
-`ctx.node(label)` - Get specific node
114+
-`ctx.gateway()` - Get first gateway
115+
-`ctx.gateways()` - Get all gateways (NEW!)
116+
-`ctx.peers()` - Get all peers (NEW!)
117+
-`ctx.node_labels()` - Get all node labels
118+
-`ctx.event_log_path(label)` - Get node event log path
119+
-`ctx.aggregate_events()` - Aggregate events from all nodes
120+
-`ctx.generate_failure_report(error)` - Generate comprehensive failure report
121+
-`ctx.generate_success_summary()` - Generate success summary
122+
123+
## Future Enhancements
124+
125+
### For Conversion of Remaining Tests
126+
127+
1. **Peer Gateway Configuration**
128+
```rust
129+
#[freenet_test(
130+
nodes = ["gw-1", "gw-2", "peer-1", "peer-2"],
131+
gateways = ["gw-1", "gw-2"],
132+
peer_gateways = {
133+
"peer-1": ["gw-1"],
134+
"peer-2": ["gw-2"]
135+
}
136+
)]
137+
```
138+
139+
2. **Node Lifecycle Control**
140+
```rust
141+
async fn test(ctx: &mut TestContext) -> TestResult {
142+
// Start with nodes running
143+
ctx.stop_node("peer-1").await?;
144+
// Test something
145+
ctx.start_node("peer-1").await?;
146+
// Test something else
147+
Ok(())
148+
}
149+
```
150+
151+
3. **Network State Verification**
152+
```rust
153+
async fn test(ctx: &mut TestContext) -> TestResult {
154+
let conn_count = ctx.connection_count("gateway").await?;
155+
assert_eq!(conn_count, 2);
156+
Ok(())
157+
}
158+
```
159+
160+
### Specialized Macros
161+
162+
For network/connectivity tests, consider creating specialized macros:
163+
164+
```rust
165+
#[freenet_network_test(
166+
topology = "star", // or "mesh", "chain", etc.
167+
gateway_count = 1,
168+
peer_count = 3,
169+
test_disconnections = true
170+
)]
171+
async fn test(ctx: &mut NetworkTestContext) -> TestResult {
172+
// Network-specific test context with connection control
173+
Ok(())
174+
}
175+
```
176+
177+
## Conclusion
178+
179+
The `#[freenet_test]` macro successfully handles:
180+
- ✅ Isolated node tests
181+
- ✅ Simple multi-node tests
182+
- ✅ Tests with multiple gateways
183+
- ✅ Tests with custom tokio configurations
184+
- ✅ Tests with event aggregation
185+
186+
The macro is **not suitable** for:
187+
- ❌ Tests requiring specific peer-gateway connections
188+
- ❌ Tests requiring node lifecycle control (stop/restart)
189+
- ❌ Network topology and connectivity tests
190+
- ❌ Tests with complex custom configurations
191+
192+
For these cases, the existing test infrastructure remains appropriate and should be kept as-is.

crates/core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ serde = { version = "1.0", features = ["derive"] }
8888
arbitrary = { features = ["derive"], version = "1" }
8989
chrono = { features = ["arbitrary"], workspace = true }
9090
freenet-stdlib = { features = ["net", "testing"], workspace = true }
91+
freenet-macros = { path = "../freenet-macros" }
9192
httptest = "0.16"
9293
statrs = "0.18"
9394
tempfile = "3"

0 commit comments

Comments
 (0)