Skip to content

Commit 0422c94

Browse files
committed
chore(coverage): remove ignore-filename-regex and add inline tests
Remove the blanket --ignore-filename-regex from cargo-llvm-cov config and add targeted tests for previously excluded code instead. Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
1 parent 035824c commit 0422c94

9 files changed

Lines changed: 197 additions & 0 deletions

File tree

rsworkspace/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rsworkspace/crates/acp-nats-ws/src/connection.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,66 @@ async fn run_send_pump(
180180
}
181181
let _ = ws_sender.close().await;
182182
}
183+
184+
#[cfg(test)]
185+
mod tests {
186+
use super::*;
187+
use axum::extract::State;
188+
use axum::extract::ws::WebSocketUpgrade;
189+
use axum::response::Response;
190+
use std::time::Duration;
191+
use tokio::io::AsyncReadExt;
192+
use tokio::net::TcpListener;
193+
use tokio_tungstenite::connect_async;
194+
use tokio_tungstenite::tungstenite::Message as TungsteniteMessage;
195+
196+
#[derive(Clone)]
197+
struct EchoState;
198+
199+
async fn echo_handler(ws: WebSocketUpgrade, State(_): State<EchoState>) -> Response {
200+
ws.on_upgrade(|socket| async move {
201+
let (ws_sender, ws_receiver) = socket.split();
202+
let (duplex_write, duplex_read) = tokio::io::duplex(DUPLEX_BUFFER_SIZE);
203+
let recv = run_recv_pump(ws_receiver, duplex_write);
204+
let send = run_send_pump(ws_sender, duplex_read);
205+
tokio::join!(recv, send);
206+
})
207+
}
208+
209+
async fn start_echo_server() -> String {
210+
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
211+
let addr = listener.local_addr().unwrap();
212+
let app = axum::Router::new()
213+
.route("/ws", axum::routing::get(echo_handler))
214+
.with_state(EchoState);
215+
tokio::spawn(async move {
216+
axum::serve(listener, app).await.unwrap();
217+
});
218+
format!("ws://{}/ws", addr)
219+
}
220+
221+
#[tokio::test]
222+
async fn multiple_messages_round_trip() {
223+
let url = start_echo_server().await;
224+
let (mut ws, _) = connect_async(&url).await.unwrap();
225+
226+
let messages = vec!["alpha", "beta", "gamma"];
227+
for msg in &messages {
228+
ws.send(TungsteniteMessage::Text((*msg).into()))
229+
.await
230+
.unwrap();
231+
}
232+
233+
for expected in &messages {
234+
let msg = tokio::time::timeout(Duration::from_secs(2), ws.next())
235+
.await
236+
.expect("timeout")
237+
.expect("stream ended")
238+
.unwrap();
239+
match msg {
240+
TungsteniteMessage::Text(t) => assert_eq!(t, *expected),
241+
other => panic!("expected Text('{expected}'), got {other:?}"),
242+
}
243+
}
244+
}
245+
}

rsworkspace/crates/acp-nats-ws/src/upgrade.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,44 @@ pub async fn handle(ws: WebSocketUpgrade, State(state): State<UpgradeState>) ->
3030
}
3131
})
3232
}
33+
34+
#[cfg(test)]
35+
mod tests {
36+
use super::*;
37+
use futures_util::SinkExt;
38+
use std::time::Duration;
39+
use tokio::net::TcpListener;
40+
use tokio_tungstenite::connect_async;
41+
use tokio_tungstenite::tungstenite::Message;
42+
43+
#[tokio::test]
44+
async fn handle_sends_connection_request_through_channel() {
45+
let (shutdown_tx, _shutdown_rx) = watch::channel(false);
46+
let (conn_tx, mut conn_rx) = mpsc::unbounded_channel::<ConnectionRequest>();
47+
48+
let state = UpgradeState {
49+
conn_tx,
50+
shutdown_tx: shutdown_tx.clone(),
51+
};
52+
53+
let app = axum::Router::new()
54+
.route("/ws", axum::routing::get(handle))
55+
.with_state(state);
56+
57+
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
58+
let addr = listener.local_addr().unwrap();
59+
tokio::spawn(async move {
60+
axum::serve(listener, app).await.unwrap();
61+
});
62+
63+
let url = format!("ws://{}/ws", addr);
64+
let (_ws, _) = connect_async(&url).await.unwrap();
65+
66+
let req = tokio::time::timeout(Duration::from_secs(2), conn_rx.recv())
67+
.await
68+
.expect("timeout waiting for ConnectionRequest")
69+
.expect("channel closed");
70+
71+
assert!(!*req.shutdown_rx.borrow());
72+
}
73+
}

rsworkspace/crates/acp-telemetry/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ tracing-subscriber = { version = "0.3.22", features = ["env-filter", "fmt", "jso
1515
trogon-std = { path = "../trogon-std" }
1616

1717
[dev-dependencies]
18+
libc = "0.2"
19+
tokio = { version = "1.49.0", features = ["rt", "macros", "signal"] }
1820
trogon-std = { path = "../trogon-std", features = ["test-support"] }

rsworkspace/crates/acp-telemetry/src/lib.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,21 @@ mod tests {
208208
assert_eq!(ServiceName::AcpNatsStdio.as_str(), "acp-nats-stdio");
209209
assert_eq!(ServiceName::AcpNatsWs.as_str(), "acp-nats-ws");
210210
}
211+
212+
#[test]
213+
fn otel_lifecycle() {
214+
let _ = try_init_otel(ServiceName::AcpNatsStdio, "test");
215+
let m = meter("test-meter");
216+
let _ = m.u64_counter("test_counter").build();
217+
shutdown_otel();
218+
}
219+
220+
#[test]
221+
fn init_logger_without_otel_does_not_panic() {
222+
let env = InMemoryEnv::new();
223+
env.set("ACP_LOG_DIR", "/tmp/test-init-logger");
224+
let fs = MemFs::new();
225+
226+
init_logger(ServiceName::AcpNatsStdio, "test", &env, &fs);
227+
}
211228
}

rsworkspace/crates/acp-telemetry/src/log.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ fn platform_log_dir(service_name: ServiceName) -> Result<PathBuf, Box<dyn std::e
8181
#[cfg(test)]
8282
mod tests {
8383
use super::*;
84+
use opentelemetry::KeyValue;
8485
use trogon_std::env::InMemoryEnv;
8586
use trogon_std::fs::MemFs;
8687

@@ -109,4 +110,17 @@ mod tests {
109110
let dir = platform_log_dir(ServiceName::AcpNatsWs).unwrap();
110111
assert!(dir.ends_with(ServiceName::AcpNatsWs.as_str()));
111112
}
113+
114+
#[test]
115+
fn init_provider_lifecycle() {
116+
let resource = opentelemetry_sdk::Resource::builder()
117+
.with_service_name("test-log")
118+
.with_attributes(vec![KeyValue::new("test", "true")])
119+
.build();
120+
121+
let provider = init_provider(&resource);
122+
assert!(provider.is_ok());
123+
force_flush();
124+
shutdown();
125+
}
112126
}

rsworkspace/crates/acp-telemetry/src/metric.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,23 @@ pub(crate) fn shutdown() {
4242
eprintln!("Failed to shutdown meter provider: {e}");
4343
}
4444
}
45+
46+
#[cfg(test)]
47+
mod tests {
48+
use super::*;
49+
use opentelemetry::KeyValue;
50+
use opentelemetry_sdk::Resource;
51+
52+
#[test]
53+
fn init_provider_returns_valid_provider() {
54+
let resource = Resource::builder()
55+
.with_service_name("test-metric")
56+
.with_attributes(vec![KeyValue::new("test", "true")])
57+
.build();
58+
59+
let provider = init_provider(&resource);
60+
assert!(provider.is_ok());
61+
force_flush();
62+
shutdown();
63+
}
64+
}

rsworkspace/crates/acp-telemetry/src/signal.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,22 @@ pub async fn shutdown_signal() {
3333
_ = terminate => {}
3434
}
3535
}
36+
37+
#[cfg(test)]
38+
mod tests {
39+
use super::*;
40+
41+
#[tokio::test]
42+
async fn shutdown_signal_completes_on_sigterm() {
43+
let handle = tokio::spawn(shutdown_signal());
44+
45+
tokio::task::yield_now().await;
46+
47+
unsafe {
48+
libc::kill(libc::getpid(), libc::SIGTERM);
49+
}
50+
51+
let result = tokio::time::timeout(std::time::Duration::from_secs(2), handle).await;
52+
assert!(result.is_ok());
53+
}
54+
}

rsworkspace/crates/acp-telemetry/src/trace.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,23 @@ pub(crate) fn shutdown() {
3232
eprintln!("Failed to shutdown tracer provider: {e}");
3333
}
3434
}
35+
36+
#[cfg(test)]
37+
mod tests {
38+
use super::*;
39+
use opentelemetry::KeyValue;
40+
use opentelemetry_sdk::Resource;
41+
42+
#[test]
43+
fn init_provider_returns_valid_provider() {
44+
let resource = Resource::builder()
45+
.with_service_name("test-trace")
46+
.with_attributes(vec![KeyValue::new("test", "true")])
47+
.build();
48+
49+
let provider = init_provider(&resource);
50+
assert!(provider.is_ok());
51+
force_flush();
52+
shutdown();
53+
}
54+
}

0 commit comments

Comments
 (0)