Skip to content

Commit 5b5ca80

Browse files
authored
refactor: share common drt test functions (#2583)
Co-authored-by: Keiven Chang <[email protected]>
1 parent b98188c commit 5b5ca80

File tree

3 files changed

+44
-83
lines changed

3 files changed

+44
-83
lines changed

lib/runtime/src/distributed.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,20 @@ impl DistributedConfig {
355355
config
356356
}
357357
}
358+
359+
#[cfg(test)]
360+
pub mod test_helpers {
361+
//! Common test helper functions for DistributedRuntime tests
362+
// TODO: Use in-memory DistributedRuntime for tests instead of full runtime when available.
363+
364+
/// Helper function to create a DRT instance for tests
365+
/// Uses from_current to leverage existing tokio runtime
366+
/// Note: Settings are read from environment variables inside DistributedRuntime::from_settings_without_discovery
367+
#[cfg(feature = "integration")]
368+
pub async fn create_test_drt_async() -> crate::DistributedRuntime {
369+
let rt = crate::Runtime::from_current().unwrap();
370+
crate::DistributedRuntime::from_settings_without_discovery(rt)
371+
.await
372+
.unwrap()
373+
}
374+
}

lib/runtime/src/metrics.rs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -578,15 +578,6 @@ mod test_helpers {
578578
use super::prometheus_names::{nats_client, nats_service};
579579
use super::*;
580580

581-
/// Helper function to create a DRT instance for testing in async contexts
582-
#[cfg(feature = "integration")]
583-
pub async fn create_test_drt_async() -> crate::DistributedRuntime {
584-
let rt = crate::Runtime::from_current().unwrap();
585-
crate::DistributedRuntime::from_settings_without_discovery(rt)
586-
.await
587-
.unwrap()
588-
}
589-
590581
/// Base function to filter Prometheus output lines based on a predicate.
591582
/// Returns lines that match the predicate, converted to String.
592583
fn filter_prometheus_lines<F>(input: &str, mut predicate: F) -> Vec<String>
@@ -822,7 +813,6 @@ mod test_metricsregistry_units {
822813
println!("✓ Prometheus metric parsing works correctly!");
823814
}
824815

825-
#[cfg(feature = "integration")]
826816
#[test]
827817
fn test_metrics_registry_entry_callbacks() {
828818
use crate::MetricsRegistryEntry;
@@ -923,11 +913,12 @@ mod test_metricsregistry_units {
923913
#[cfg(test)]
924914
mod test_metricsregistry_prefixes {
925915
use super::*;
916+
use crate::distributed::test_helpers::create_test_drt_async;
926917
use prometheus::core::Collector;
927918

928919
#[tokio::test]
929920
async fn test_hierarchical_prefixes_and_parent_hierarchies() {
930-
let drt = super::test_helpers::create_test_drt_async().await;
921+
let drt = create_test_drt_async().await;
931922

932923
const DRT_NAME: &str = "";
933924
const NAMESPACE_NAME: &str = "ns901";
@@ -1002,7 +993,7 @@ mod test_metricsregistry_prefixes {
1002993
#[tokio::test]
1003994
async fn test_recursive_namespace() {
1004995
// Create a distributed runtime for testing
1005-
let drt = super::test_helpers::create_test_drt_async().await;
996+
let drt = create_test_drt_async().await;
1006997

1007998
// Create a deeply chained namespace: ns1.ns2.ns3
1008999
let ns1 = drt.namespace("ns1").unwrap();
@@ -1054,13 +1045,14 @@ mod test_metricsregistry_prometheus_fmt_outputs {
10541045
use super::prometheus_names::{nats_client, nats_service};
10551046
use super::prometheus_names::{COMPONENT_NATS_METRICS, DRT_NATS_METRICS};
10561047
use super::*;
1048+
use crate::distributed::test_helpers::create_test_drt_async;
10571049
use prometheus::Counter;
10581050
use std::sync::Arc;
10591051

10601052
#[tokio::test]
10611053
async fn test_prometheusfactory_using_metrics_registry_trait() {
10621054
// Setup real DRT and registry using the test-friendly constructor
1063-
let drt = super::test_helpers::create_test_drt_async().await;
1055+
let drt = create_test_drt_async().await;
10641056

10651057
// Use a simple constant namespace name
10661058
let namespace_name = "ns345";
@@ -1312,13 +1304,14 @@ mod test_metricsregistry_nats {
13121304
use super::prometheus_names::{nats_client, nats_service};
13131305
use super::prometheus_names::{COMPONENT_NATS_METRICS, DRT_NATS_METRICS};
13141306
use super::*;
1307+
use crate::distributed::test_helpers::create_test_drt_async;
13151308
use crate::pipeline::PushRouter;
13161309
use crate::{DistributedRuntime, Runtime};
13171310
use tokio::time::{sleep, Duration};
13181311
#[tokio::test]
13191312
async fn test_drt_nats_metrics() {
13201313
// Setup real DRT and registry using the test-friendly constructor
1321-
let drt = super::test_helpers::create_test_drt_async().await;
1314+
let drt = create_test_drt_async().await;
13221315

13231316
// Get DRT output which should include NATS client metrics
13241317
let drt_output = drt.prometheus_metrics_fmt().unwrap();
@@ -1382,7 +1375,7 @@ mod test_metricsregistry_nats {
13821375
// the values of the metrics.
13831376

13841377
// Setup real DRT and registry using the test-friendly constructor
1385-
let drt = super::test_helpers::create_test_drt_async().await;
1378+
let drt = create_test_drt_async().await;
13861379

13871380
// Create a namespace and components from the DRT
13881381
let namespace = drt.namespace("ns789").unwrap();

lib/runtime/src/system_status_server.rs

Lines changed: 19 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,14 @@
1515

1616
use crate::config::HealthStatus;
1717
use crate::logging::make_request_span;
18-
use crate::logging::TraceParent;
1918
use crate::metrics::MetricsRegistry;
2019
use crate::traits::DistributedRuntimeProvider;
21-
use axum::{body, http::StatusCode, response::IntoResponse, routing::get, Router};
20+
use axum::{http::StatusCode, response::IntoResponse, routing::get, Router};
2221
use serde_json::json;
23-
use std::collections::HashMap;
24-
use std::sync::Arc;
25-
use std::sync::OnceLock;
22+
use std::sync::{Arc, OnceLock};
2623
use std::time::Instant;
2724
use tokio::{net::TcpListener, task::JoinHandle};
2825
use tokio_util::sync::CancellationToken;
29-
use tower_http::trace::DefaultMakeSpan;
3026
use tower_http::trace::TraceLayer;
3127

3228
/// System status server information containing socket address and handle
@@ -296,61 +292,10 @@ async fn metrics_handler(state: Arc<SystemStatusState>) -> impl IntoResponse {
296292
}
297293

298294
// Regular tests: cargo test system_status_server --lib
299-
// Integration tests: cargo test system_status_server --lib --features integration
300-
301-
#[cfg(test)]
302-
/// Helper function to create a DRT instance for basic unit tests
303-
/// Uses from_current to leverage existing tokio runtime without environment configuration
304-
async fn create_test_drt_async() -> crate::DistributedRuntime {
305-
let rt = crate::Runtime::from_current().unwrap();
306-
crate::DistributedRuntime::from_settings_without_discovery(rt)
307-
.await
308-
.unwrap()
309-
}
310-
311-
#[cfg(test)]
312-
/// Helper function to create a DRT instance for integration tests
313-
/// Uses spawn_blocking to create runtime safely without ownership issues
314-
/// Enables system status server for integration testing
315-
/// Note: This function uses environment variables to configure and create the DistributedRuntime.
316-
async fn create_test_drt_with_settings_async() -> crate::DistributedRuntime {
317-
// Create runtime in blocking context where it can be safely dropped
318-
let handle = tokio::task::spawn_blocking(|| {
319-
// Load configuration from environment/settings
320-
let config = crate::config::RuntimeConfig::from_settings().unwrap();
321-
322-
// Create runtime with the configuration and extract handle
323-
let runtime = config.create_runtime().unwrap();
324-
let handle = runtime.handle().clone();
325-
326-
// Runtime will be automatically dropped when it goes out of scope
327-
handle
328-
})
329-
.await
330-
.unwrap();
331-
332-
// Create Runtime using external handle (no ownership)
333-
let rt = crate::Runtime::from_handle(handle).unwrap();
334-
crate::DistributedRuntime::from_settings_without_discovery(rt)
335-
.await
336-
.unwrap()
337-
}
338-
339295
#[cfg(test)]
340296
mod tests {
341297
use super::*;
342-
use crate::logging::tests::load_log;
343-
use crate::metrics::MetricsRegistry;
344-
use anyhow::{anyhow, Result};
345-
use chrono::{DateTime, Utc};
346-
use jsonschema::{Draft, JSONSchema};
347-
use rstest::rstest;
348-
use serde_json::Value;
349-
use std::fs::File;
350-
use std::io::{BufRead, BufReader};
351-
use std::sync::Arc;
352-
use stdio_override::*;
353-
use tokio::time::{sleep, Duration};
298+
use tokio::time::Duration;
354299

355300
// This is a basic test to verify the HTTP server is working before testing other more complicated tests
356301
#[tokio::test]
@@ -381,8 +326,19 @@ mod tests {
381326
"HTTP server should shut down when cancel token is cancelled"
382327
);
383328
}
329+
}
330+
331+
// Integration tests: cargo test system_status_server --lib --features integration
332+
#[cfg(all(test, feature = "integration"))]
333+
mod integration_tests {
334+
use super::*;
335+
use crate::distributed::test_helpers::create_test_drt_async;
336+
use crate::metrics::MetricsRegistry;
337+
use anyhow::Result;
338+
use rstest::rstest;
339+
use std::sync::Arc;
340+
use tokio::time::Duration;
384341

385-
#[cfg(feature = "integration")]
386342
#[tokio::test]
387343
async fn test_uptime_without_initialization() {
388344
// Test that uptime returns an error if start time is not initialized
@@ -398,7 +354,6 @@ mod tests {
398354
.await;
399355
}
400356

401-
#[cfg(feature = "integration")]
402357
#[tokio::test]
403358
async fn test_runtime_metrics_initialization_and_namespace() {
404359
// Test that metrics have correct namespace
@@ -439,7 +394,6 @@ mod tests {
439394
.await;
440395
}
441396

442-
#[cfg(feature = "integration")]
443397
#[tokio::test]
444398
async fn test_start_time_initialization() {
445399
// Test that start time can only be initialized once
@@ -516,7 +470,7 @@ mod tests {
516470
("DYN_SYSTEM_LIVE_PATH", custom_live_path),
517471
],
518472
(async || {
519-
let drt = Arc::new(create_test_drt_with_settings_async().await);
473+
let drt = Arc::new(create_test_drt_async().await);
520474

521475
// Get system status server info from DRT (instead of manually spawning)
522476
let system_info = drt
@@ -575,7 +529,6 @@ mod tests {
575529
}
576530

577531
#[tokio::test]
578-
#[cfg(feature = "integration")]
579532
async fn test_health_endpoint_tracing() -> Result<()> {
580533
use std::sync::Arc;
581534

@@ -596,7 +549,7 @@ mod tests {
596549

597550
crate::logging::init();
598551

599-
let drt = Arc::new(create_test_drt_with_settings_async().await);
552+
let drt = Arc::new(create_test_drt_async().await);
600553

601554
// Get system status server info from DRT (instead of manually spawning)
602555
let system_info = drt
@@ -631,7 +584,6 @@ mod tests {
631584
Ok(())
632585
}
633586

634-
#[cfg(feature = "integration")]
635587
#[tokio::test]
636588
async fn test_health_endpoint_with_changing_health_status() {
637589
// Test health endpoint starts in not ready status, then becomes ready
@@ -646,7 +598,7 @@ mod tests {
646598
("DYN_SYSTEM_USE_ENDPOINT_HEALTH_STATUS", Some(ENDPOINT_HEALTH_CONFIG)),
647599
],
648600
async {
649-
let drt = Arc::new(create_test_drt_with_settings_async().await);
601+
let drt = Arc::new(create_test_drt_async().await);
650602

651603
// Check if system status server was started
652604
let system_info_opt = drt.system_status_server_info();
@@ -745,7 +697,6 @@ mod tests {
745697
.await;
746698
}
747699

748-
#[cfg(feature = "integration")]
749700
#[tokio::test]
750701
async fn test_spawn_system_status_server_endpoints() {
751702
// use reqwest for HTTP requests
@@ -756,7 +707,7 @@ mod tests {
756707
("DYN_SYSTEM_STARTING_HEALTH_STATUS", Some("ready")),
757708
],
758709
async {
759-
let drt = Arc::new(create_test_drt_with_settings_async().await);
710+
let drt = Arc::new(create_test_drt_async().await);
760711

761712
// Get system status server info from DRT (instead of manually spawning)
762713
let system_info = drt

0 commit comments

Comments
 (0)