Skip to content

Commit 80fec81

Browse files
tobzclaude
andcommitted
test(core): expose ComponentContext test-util helpers cross-crate
Promote the seven ComponentContext::test_* constructors from #[cfg(test)] to a non-default 'test-util' Cargo feature so downstream crates can build component contexts in their own tests, mirroring the existing saluki-metrics 'test' feature pattern. Migrate the eight hand-rolled SubsystemIdentifier/ComponentId call sites across saluki-components and agent-data-plane to the shared helpers. Add coverage unlocked by the change: heartbeat source tests (config default, declared output, memory bounds) and double-take panic tests for take_health_handle (all seven context types) and take_shutdown_handle (source and relay). Resolves G1 (KI-1) of the test suite cleanup plan. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 9d0cd3a commit 80fec81

14 files changed

Lines changed: 310 additions & 56 deletions

File tree

bin/agent-data-plane/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,5 @@ chrono = { workspace = true }
8080
datadog-agent-config-testing = { workspace = true }
8181
derive-where = { workspace = true }
8282
saluki-components = { workspace = true }
83+
saluki-core = { workspace = true, features = ["test-util"] }
8384
saluki-metrics = { workspace = true, features = ["test"] }

bin/agent-data-plane/src/components/ottl_filter_processor/mod.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,7 @@ mod tests {
160160
trace::{AttributeValue, Span, Trace},
161161
Event,
162162
},
163-
support::SubsystemIdentifier,
164-
topology::{ComponentId, EventsBuffer},
163+
topology::EventsBuffer,
165164
};
166165
use stringtheory::MetaString;
167166

@@ -200,10 +199,7 @@ mod tests {
200199
}
201200

202201
fn test_component_context() -> ComponentContext {
203-
ComponentContext::transform(
204-
&SubsystemIdentifier::from_segments(["test"]),
205-
ComponentId::try_from("ottl_filter").unwrap(),
206-
)
202+
ComponentContext::test_transform("ottl_filter")
207203
}
208204

209205
/// When `ottl_filter_config` is absent, config defaults to empty conditions and no spans are dropped.

bin/agent-data-plane/src/components/ottl_transform_processor/mod.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,7 @@ mod tests {
163163
trace::{AttributeValue, Span, Trace},
164164
Event,
165165
},
166-
support::SubsystemIdentifier,
167-
topology::{ComponentId, EventsBuffer},
166+
topology::EventsBuffer,
168167
};
169168
use stringtheory::MetaString;
170169

@@ -213,10 +212,7 @@ mod tests {
213212
}
214213

215214
fn test_component_context() -> ComponentContext {
216-
ComponentContext::transform(
217-
&SubsystemIdentifier::from_segments(["test"]),
218-
ComponentId::try_from("ottl_transform").unwrap(),
219-
)
215+
ComponentContext::test_transform("ottl_transform")
220216
}
221217

222218
async fn build_transform(cfg_json: Option<serde_json::Value>) -> Box<dyn SynchronousTransform + Send> {

lib/saluki-components/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ derive-where = { workspace = true }
9595
proptest = { workspace = true }
9696
rcgen = { workspace = true, features = ["crypto", "pem"] }
9797
rustls = { workspace = true }
98+
saluki-core = { workspace = true, features = ["test-util"] }
9899
saluki-metrics = { workspace = true, features = ["test"] }
99100
saluki-tls = { workspace = true }
100101
tempfile = { workspace = true }

lib/saluki-components/src/common/datadog/io.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ mod tests {
989989
};
990990
use saluki_common::buf::FrozenChunkedBytesBuffer;
991991
use saluki_config::ConfigurationLoader;
992-
use saluki_core::{observability::ComponentMetricsExt as _, support::SubsystemIdentifier, topology::ComponentId};
992+
use saluki_core::observability::ComponentMetricsExt as _;
993993
use saluki_io::net::client::http::TlsMinimumVersion;
994994
use saluki_metrics::test::TestRecorder;
995995
use serde_json::json;
@@ -1010,10 +1010,7 @@ mod tests {
10101010
};
10111011

10121012
fn test_component_context() -> ComponentContext {
1013-
ComponentContext::forwarder(
1014-
&SubsystemIdentifier::from_segments(["test"]),
1015-
ComponentId::try_from("test_forwarder").unwrap(),
1016-
)
1013+
ComponentContext::test_forwarder("test_forwarder")
10171014
}
10181015

10191016
fn uri(path: &'static str) -> Uri {

lib/saluki-components/src/common/otlp/mod.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,7 @@ impl<H: OtlpHandler> TraceService for GrpcServiceImpl<H> {
342342
mod tests {
343343
use std::sync::Arc;
344344

345-
use saluki_core::accounting::MemoryLimiter;
346-
use saluki_core::{components::ComponentContext, support::SubsystemIdentifier, topology::ComponentId};
345+
use saluki_core::{accounting::MemoryLimiter, components::ComponentContext};
347346
use saluki_metrics::test::TestRecorder;
348347

349348
use super::*;
@@ -380,10 +379,7 @@ mod tests {
380379
}
381380

382381
fn test_component_context() -> ComponentContext {
383-
ComponentContext::source(
384-
&SubsystemIdentifier::from_segments(["test"]),
385-
ComponentId::try_from("otlp_test").unwrap(),
386-
)
382+
ComponentContext::test_source("otlp_test")
387383
}
388384

389385
#[tokio::test]

lib/saluki-components/src/sources/dogstatsd/metrics.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -362,16 +362,13 @@ fn error_tags(
362362
mod tests {
363363
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
364364

365-
use saluki_core::{components::ComponentContext, support::SubsystemIdentifier, topology::ComponentId};
365+
use saluki_core::components::ComponentContext;
366366
use saluki_metrics::test::TestRecorder;
367367

368368
use super::*;
369369

370370
fn test_context() -> ComponentContext {
371-
ComponentContext::source(
372-
&SubsystemIdentifier::from_segments(["test"]),
373-
ComponentId::try_from("dogstatsd_test").expect("valid component ID"),
374-
)
371+
ComponentContext::test_source("dogstatsd_test")
375372
}
376373

377374
fn udp_listen_addr() -> ListenAddress {

lib/saluki-components/src/sources/dogstatsd/mod.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2054,8 +2054,6 @@ mod tests {
20542054
use saluki_core::{
20552055
components::ComponentContext,
20562056
pooling::{helpers::get_pooled_object_via_builder, ObjectPool as _},
2057-
support::SubsystemIdentifier,
2058-
topology::ComponentId,
20592057
};
20602058
use saluki_env::workload::{CaptureEntityResolver, EntityId};
20612059
use saluki_io::{
@@ -2089,10 +2087,7 @@ mod tests {
20892087
}
20902088

20912089
fn test_component_context() -> ComponentContext {
2092-
ComponentContext::source(
2093-
&SubsystemIdentifier::from_segments(["test"]),
2094-
ComponentId::try_from("dogstatsd_test").unwrap(),
2095-
)
2090+
ComponentContext::test_source("dogstatsd_test")
20962091
}
20972092

20982093
#[derive(Default)]

lib/saluki-components/src/sources/heartbeat/mod.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,49 @@ impl MemoryBounds for HeartbeatConfiguration {
9393
builder.minimum().with_single_value::<Heartbeat>("component struct");
9494
}
9595
}
96+
97+
#[cfg(test)]
98+
mod tests {
99+
use std::mem::size_of;
100+
101+
use saluki_core::accounting::ComponentRegistry;
102+
103+
use super::*;
104+
105+
#[test]
106+
fn default_configuration_uses_ten_second_interval() {
107+
let config = HeartbeatConfiguration::default();
108+
assert_eq!(config.heartbeat_interval_secs, 10);
109+
}
110+
111+
#[test]
112+
fn declares_single_default_output_for_metrics() {
113+
// The source's documented behavior is to emit a heartbeat metric, so it must declare exactly one output --
114+
// the default (unnamed) one -- carrying metric events.
115+
let config = HeartbeatConfiguration::default();
116+
let outputs = config.outputs();
117+
118+
assert_eq!(outputs.len(), 1);
119+
assert_eq!(
120+
outputs[0].output_name(),
121+
None,
122+
"heartbeat emits on the default (unnamed) output"
123+
);
124+
assert_eq!(outputs[0].data_ty(), EventType::Metric);
125+
}
126+
127+
#[test]
128+
fn specify_bounds_accounts_only_for_the_boxed_component_struct() {
129+
// The bounds are documented as a "minimal memory footprint": a single boxed `Heartbeat` value and nothing
130+
// else. The firm limit includes the minimum, so with no additional firm usage both totals equal the struct
131+
// size.
132+
let config = HeartbeatConfiguration::default();
133+
134+
let mut registry = ComponentRegistry::default();
135+
config.specify_bounds(&mut registry.bounds_builder());
136+
let bounds = registry.as_bounds();
137+
138+
assert_eq!(bounds.total_minimum_required_bytes(), size_of::<Heartbeat>());
139+
assert_eq!(bounds.total_firm_limit_bytes(), size_of::<Heartbeat>());
140+
}
141+
}

lib/saluki-components/src/transforms/aggregate/mod.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -908,8 +908,7 @@ mod tests {
908908
use float_cmp::ApproxEqRatio as _;
909909
use saluki_core::{
910910
components::ComponentContext,
911-
support::SubsystemIdentifier,
912-
topology::{interconnect::Dispatcher, ComponentId, OutputName},
911+
topology::{interconnect::Dispatcher, OutputName},
913912
};
914913
use saluki_metrics::test::TestRecorder;
915914
use stringtheory::MetaString;
@@ -961,10 +960,7 @@ mod tests {
961960

962961
/// Constructs a basic `Dispatcher` with a fixed-size event buffer.
963962
fn build_basic_dispatcher() -> (EventsDispatcher, DispatcherReceiver) {
964-
let context = ComponentContext::transform(
965-
&SubsystemIdentifier::from_segments(["test"]),
966-
ComponentId::try_from("test").unwrap(),
967-
);
963+
let context = ComponentContext::test_transform("test");
968964
let mut dispatcher = Dispatcher::new(context);
969965

970966
let (buffer_tx, buffer_rx) = mpsc::channel(1);

0 commit comments

Comments
 (0)