Skip to content

Commit bd9ab04

Browse files
iduartgomezclaudesanity
authored
fix(tests): prevent span accumulation across async tasks (#2007)
Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Ian Clarke <sanity@users.noreply.github.com>
1 parent 073f4a0 commit bd9ab04

File tree

3 files changed

+29
-77
lines changed

3 files changed

+29
-77
lines changed

crates/core/src/test_utils.rs

Lines changed: 13 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -42,59 +42,6 @@ pub fn set_peer_id(peer_id: impl Into<String>) {
4242
tracing::Span::current().record("test_node", peer_id);
4343
}
4444

45-
/// Create a span with a peer identifier that will be included in all logs
46-
/// within the span.
47-
///
48-
/// # Example
49-
/// ```ignore
50-
/// async fn start_gateway() {
51-
/// let _span = with_peer_id("gateway");
52-
/// tracing::info!("Starting gateway"); // Will include test_node="gateway"
53-
/// // ... gateway initialization
54-
/// }
55-
///
56-
/// async fn start_peer(id: usize) {
57-
/// let _span = with_peer_id(format!("peer-{}", id));
58-
/// tracing::info!("Starting peer"); // Will include test_node="peer-N"
59-
/// // ... peer initialization
60-
/// }
61-
/// ```
62-
///
63-
/// # Note
64-
/// The field name `test_node` is used to avoid conflicts with the production
65-
/// `peer` field which contains the actual cryptographic PeerId.
66-
///
67-
/// # Important
68-
/// The returned guard must be held for the entire duration you want the peer ID
69-
/// to be active. When the guard is dropped, the span exits.
70-
#[must_use = "Span guard must be held for the duration of the operation"]
71-
pub fn with_peer_id(peer_id: impl Into<String>) -> impl Drop {
72-
let peer_id = peer_id.into();
73-
tracing::info_span!("test_peer", test_node = %peer_id).entered()
74-
}
75-
76-
/// Execute a function with tracing enabled.
77-
///
78-
/// This function is now deprecated in favor of using the `#[test_log::test]` macro
79-
/// which provides better integration with test frameworks and only shows logs for
80-
/// failing tests.
81-
///
82-
/// # Deprecated
83-
/// Use `#[test_log::test]` or `#[test_log::test(tokio::test)]` instead.
84-
#[deprecated(
85-
since = "0.1.0",
86-
note = "Use #[test_log::test] or #[test_log::test(tokio::test)] instead"
87-
)]
88-
pub fn with_tracing<T>(f: impl FnOnce() -> T) -> T {
89-
let subscriber = tracing_subscriber::fmt()
90-
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
91-
.with_line_number(true)
92-
.with_file(true)
93-
.with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE)
94-
.finish();
95-
tracing::subscriber::with_default(subscriber, f)
96-
}
97-
9845
/// Format for test logger output
9946
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10047
pub enum LogFormat {
@@ -113,28 +60,32 @@ pub enum LogFormat {
11360
///
11461
/// # Peer Identification
11562
///
116-
/// For multi-peer tests, use the `with_peer_id()` function in each async block:
63+
/// For multi-peer tests, use `.instrument()` to attach isolated spans:
11764
/// ```ignore
65+
/// use tracing::Instrument;
66+
///
11867
/// let gateway = async {
119-
/// let _span = with_peer_id("gateway");
12068
/// tracing::info!("Gateway starting");
121-
/// };
69+
/// }
70+
/// .instrument(tracing::info_span!("test_peer", test_node = "gateway"));
12271
/// ```
12372
///
12473
/// # Example
12574
/// ```ignore
75+
/// use tracing::Instrument;
76+
///
12677
/// #[tokio::test]
12778
/// async fn my_test() -> anyhow::Result<()> {
12879
/// let _logger = TestLogger::new()
12980
/// .with_json()
13081
/// .with_level("debug")
13182
/// .init();
13283
///
133-
/// // For multi-peer tests, use with_peer_id() in each async block
84+
/// // For multi-peer tests, use .instrument() to isolate spans
13485
/// let gateway = async {
135-
/// let _span = with_peer_id("gateway");
13686
/// tracing::info!("Gateway starting");
137-
/// };
87+
/// }
88+
/// .instrument(tracing::info_span!("test_peer", test_node = "gateway"));
13889
///
13990
/// Ok(())
14091
/// }
@@ -778,7 +729,7 @@ mod test {
778729
fn test_logger_with_peer_id() {
779730
let _logger = TestLogger::new().with_level("info").init();
780731

781-
let _span = with_peer_id("test-peer");
732+
let _span = tracing::info_span!("test_peer", test_node = "test-peer").entered();
782733

783734
tracing::info!("Message with peer ID");
784735
}
@@ -820,7 +771,7 @@ mod test {
820771
async fn test_logger_async() {
821772
let _logger = TestLogger::new().with_json().with_level("debug").init();
822773

823-
let _span = with_peer_id("async-peer");
774+
let _span = tracing::info_span!("test_peer", test_node = "async-peer").entered();
824775

825776
tracing::info!("Async test message");
826777
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
@@ -836,7 +787,7 @@ mod test {
836787
.init();
837788

838789
// Create a span with test_node field
839-
let _span = with_peer_id("test-gateway");
790+
let _span = tracing::info_span!("test_peer", test_node = "test-gateway").entered();
840791

841792
tracing::info!("Message from gateway");
842793

crates/core/tests/connectivity.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use freenet::{
44
dev_tool::TransportKeypair,
55
local_node::NodeConfig,
66
server::serve_gateway,
7-
test_utils::{self, make_get, make_put, with_peer_id},
7+
test_utils::{self, make_get, make_put},
88
};
99
use freenet_stdlib::{
1010
client_api::{ClientRequest, ContractResponse, HostResponse, WebApi},
@@ -20,6 +20,7 @@ use std::{
2020
use testresult::TestResult;
2121
use tokio::select;
2222
use tokio_tungstenite::connect_async;
23+
use tracing::Instrument;
2324

2425
static RNG: LazyLock<Mutex<rand::rngs::StdRng>> = LazyLock::new(|| {
2526
Mutex::new(rand::rngs::StdRng::from_seed(
@@ -144,7 +145,6 @@ async fn test_gateway_reconnection() -> TestResult {
144145

145146
// Start gateway node with peer identification
146147
let gateway = async {
147-
let _span = with_peer_id("gateway");
148148
tracing::info!("Starting gateway node");
149149
let config = gateway_config.build().await?;
150150
let node = NodeConfig::new(config.clone())
@@ -154,11 +154,11 @@ async fn test_gateway_reconnection() -> TestResult {
154154
tracing::info!("Gateway node running");
155155
node.run().await
156156
}
157+
.instrument(tracing::info_span!("test_peer", test_node = "gateway"))
157158
.boxed_local();
158159

159160
// Start peer node with peer identification
160161
let peer = async move {
161-
let _span = with_peer_id("peer-1");
162162
tracing::info!("Starting peer node");
163163
let config = peer_config.build().await?;
164164
let node = NodeConfig::new(config.clone())
@@ -168,6 +168,7 @@ async fn test_gateway_reconnection() -> TestResult {
168168
tracing::info!("Peer node running");
169169
node.run().await
170170
}
171+
.instrument(tracing::info_span!("test_peer", test_node = "peer-1"))
171172
.boxed_local();
172173

173174
// Main test logic
@@ -374,7 +375,6 @@ async fn test_basic_gateway_connectivity() -> TestResult {
374375

375376
// Start the gateway node with peer identification
376377
let gateway = async {
377-
let _span = with_peer_id("gateway");
378378
tracing::info!("Starting gateway node");
379379
let config = config.build().await?;
380380
let node = NodeConfig::new(config.clone())
@@ -384,6 +384,7 @@ async fn test_basic_gateway_connectivity() -> TestResult {
384384
tracing::info!("Gateway node running");
385385
node.run().await
386386
}
387+
.instrument(tracing::info_span!("test_peer", test_node = "gateway"))
387388
.boxed_local();
388389

389390
// Test logic
@@ -646,7 +647,6 @@ async fn test_three_node_network_connectivity() -> TestResult {
646647

647648
// Start gateway node with peer identification
648649
let gateway = async {
649-
let _span = with_peer_id("gateway");
650650
tracing::info!("Starting gateway node");
651651
let config = gateway_config.build().await?;
652652
let node = NodeConfig::new(config.clone())
@@ -656,11 +656,11 @@ async fn test_three_node_network_connectivity() -> TestResult {
656656
tracing::info!("Gateway node running");
657657
node.run().await
658658
}
659+
.instrument(tracing::info_span!("test_peer", test_node = "gateway"))
659660
.boxed_local();
660661

661662
// Start first peer node with peer identification
662663
let peer1 = async move {
663-
let _span = with_peer_id("peer-1");
664664
tokio::time::sleep(Duration::from_secs(5)).await;
665665
tracing::info!("Starting peer 1 node");
666666
let config = peer1_config.build().await?;
@@ -671,11 +671,11 @@ async fn test_three_node_network_connectivity() -> TestResult {
671671
tracing::info!("Peer 1 node running");
672672
node.run().await
673673
}
674+
.instrument(tracing::info_span!("test_peer", test_node = "peer-1"))
674675
.boxed_local();
675676

676677
// Start second peer node with peer identification
677678
let peer2 = async move {
678-
let _span = with_peer_id("peer-2");
679679
tokio::time::sleep(Duration::from_secs(10)).await;
680680
tracing::info!("Starting peer 2 node");
681681
let config = peer2_config.build().await?;
@@ -686,6 +686,7 @@ async fn test_three_node_network_connectivity() -> TestResult {
686686
tracing::info!("Peer 2 node running");
687687
node.run().await
688688
}
689+
.instrument(tracing::info_span!("test_peer", test_node = "peer-2"))
689690
.boxed_local();
690691

691692
// Main test logic

crates/core/tests/operations.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use freenet::{
66
server::serve_gateway,
77
test_utils::{
88
self, load_delegate, make_get, make_put, make_subscribe, make_update,
9-
verify_contract_exists, with_peer_id, TestLogger,
9+
verify_contract_exists, TestLogger,
1010
},
1111
};
1212
use freenet_stdlib::{
@@ -170,7 +170,6 @@ async fn test_put_contract() -> TestResult {
170170

171171
std::mem::drop(ws_api_port_socket_a); // Free the port so it does not fail on initialization
172172
let node_a = async move {
173-
let _span = with_peer_id("peer-a");
174173
tracing::info!("Starting peer A node");
175174
let config = config_a.build().await?;
176175
let node = NodeConfig::new(config.clone())
@@ -180,12 +179,12 @@ async fn test_put_contract() -> TestResult {
180179
tracing::info!("Peer A node running");
181180
node.run().await
182181
}
182+
.instrument(tracing::info_span!("test_peer", test_node = "peer-a"))
183183
.boxed_local();
184184

185185
std::mem::drop(network_socket_b); // Free the port so it does not fail on initialization
186186
std::mem::drop(ws_api_port_socket_b);
187187
let node_b = async {
188-
let _span = with_peer_id("gateway");
189188
tracing::info!("Starting gateway node");
190189
let config = config_b.build().await?;
191190
let node = NodeConfig::new(config.clone())
@@ -195,6 +194,7 @@ async fn test_put_contract() -> TestResult {
195194
tracing::info!("Gateway node running");
196195
node.run().await
197196
}
197+
.instrument(tracing::info_span!("test_peer", test_node = "gateway"))
198198
.boxed_local();
199199

200200
let test = tokio::time::timeout(Duration::from_secs(180), async {
@@ -586,7 +586,6 @@ async fn test_put_merge_persists_state() -> TestResult {
586586
// Start node A (peer)
587587
std::mem::drop(ws_api_port_socket_a);
588588
let node_a = async move {
589-
let _span = with_peer_id("peer-a");
590589
tracing::info!("Starting peer A node");
591590
let config = config_a.build().await?;
592591
let node = NodeConfig::new(config.clone())
@@ -596,13 +595,13 @@ async fn test_put_merge_persists_state() -> TestResult {
596595
tracing::info!("Peer A node running");
597596
node.run().await
598597
}
598+
.instrument(tracing::info_span!("test_peer", test_node = "peer-a"))
599599
.boxed_local();
600600

601601
// Start node B (gateway)
602602
std::mem::drop(network_socket_b);
603603
std::mem::drop(ws_api_port_socket_b);
604604
let node_b = async {
605-
let _span = with_peer_id("gateway");
606605
tracing::info!("Starting gateway node");
607606
let config = config_b.build().await?;
608607
let node = NodeConfig::new(config.clone())
@@ -612,6 +611,7 @@ async fn test_put_merge_persists_state() -> TestResult {
612611
tracing::info!("Gateway node running");
613612
node.run().await
614613
}
614+
.instrument(tracing::info_span!("test_peer", test_node = "gateway"))
615615
.boxed_local();
616616

617617
let test = tokio::time::timeout(Duration::from_secs(180), async {
@@ -868,7 +868,6 @@ async fn test_multiple_clients_subscription() -> TestResult {
868868

869869
// Start node A (first client)
870870
let node_a = async move {
871-
let _span = with_peer_id("node-a");
872871
tracing::info!("Starting node A");
873872
let config = config_a.build().await?;
874873
let node = NodeConfig::new(config.clone())
@@ -878,11 +877,11 @@ async fn test_multiple_clients_subscription() -> TestResult {
878877
tracing::info!("Node A running");
879878
node.run().await
880879
}
880+
.instrument(tracing::info_span!("test_peer", test_node = "node-a"))
881881
.boxed_local();
882882

883883
// Start GW node
884884
let node_gw = async {
885-
let _span = with_peer_id("gateway");
886885
tracing::info!("Starting gateway node");
887886
let config = config_gw.build().await?;
888887
let node = NodeConfig::new(config.clone())
@@ -892,11 +891,11 @@ async fn test_multiple_clients_subscription() -> TestResult {
892891
tracing::info!("Gateway node running");
893892
node.run().await
894893
}
894+
.instrument(tracing::info_span!("test_peer", test_node = "gateway"))
895895
.boxed_local();
896896

897897
// Start node B (second client)
898898
let node_b = async {
899-
let _span = with_peer_id("node-b");
900899
tracing::info!("Starting node B");
901900
let config = config_b.build().await?;
902901
let node = NodeConfig::new(config.clone())
@@ -906,6 +905,7 @@ async fn test_multiple_clients_subscription() -> TestResult {
906905
tracing::info!("Node B running");
907906
node.run().await
908907
}
908+
.instrument(tracing::info_span!("test_peer", test_node = "node-b"))
909909
.boxed_local();
910910

911911
let test = tokio::time::timeout(Duration::from_secs(600), async {

0 commit comments

Comments
 (0)