Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit bce82b3

Browse files
committedDec 18, 2024
test: [#1069] example of capturing tracing output
1 parent df101fb commit bce82b3

File tree

2 files changed

+101
-3
lines changed

2 files changed

+101
-3
lines changed
 

‎tests/common/logging.rs

+92-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
//! ´´´
1111
//!
1212
13-
use std::sync::Once;
13+
use std::io;
14+
use std::sync::{Arc, Mutex, Once};
1415

1516
use tracing::level_filters::LevelFilter;
17+
use tracing_subscriber::fmt::MakeWriter;
1618

1719
#[allow(dead_code)]
1820
pub static INIT: Once = Once::new();
@@ -28,3 +30,92 @@ pub fn tracing_stderr_init(filter: LevelFilter) {
2830

2931
tracing::info!("Logging initialized");
3032
}
33+
34+
#[allow(dead_code)]
35+
pub fn tracing_init_with_capturer(filter: LevelFilter, log_capturer: Arc<Mutex<LogCapturer>>) {
36+
let writer = LogCapturerWrapper::new(log_capturer);
37+
38+
let builder = tracing_subscriber::fmt()
39+
.with_max_level(filter)
40+
.with_ansi(true)
41+
.with_writer(writer);
42+
43+
builder.pretty().with_file(true).init();
44+
45+
tracing::info!("Logging initialized");
46+
}
47+
48+
pub struct LogCapturerWrapper {
49+
inner: Arc<Mutex<LogCapturer>>,
50+
}
51+
52+
impl LogCapturerWrapper {
53+
pub fn new(inner: Arc<Mutex<LogCapturer>>) -> Self {
54+
Self { inner }
55+
}
56+
}
57+
58+
impl<'a> tracing_subscriber::fmt::MakeWriter<'a> for LogCapturerWrapper {
59+
type Writer = LogCapturerGuard;
60+
61+
fn make_writer(&'a self) -> Self::Writer {
62+
LogCapturerGuard {
63+
inner: self.inner.clone(),
64+
}
65+
}
66+
}
67+
68+
pub struct LogCapturerGuard {
69+
inner: Arc<Mutex<LogCapturer>>,
70+
}
71+
72+
impl io::Write for LogCapturerGuard {
73+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
74+
let mut capturer = self.inner.lock().unwrap();
75+
capturer.write(buf)
76+
}
77+
78+
fn flush(&mut self) -> io::Result<()> {
79+
let mut capturer = self.inner.lock().unwrap();
80+
capturer.flush()
81+
}
82+
}
83+
84+
#[derive(Debug, Default)]
85+
pub struct LogCapturer {
86+
output: String,
87+
}
88+
89+
impl LogCapturer {
90+
pub fn new() -> Self {
91+
Self::default()
92+
}
93+
94+
pub fn contains(&self, message: &str) -> bool {
95+
self.output.contains(message)
96+
}
97+
}
98+
99+
impl io::Write for LogCapturer {
100+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
101+
let out_str = String::from_utf8_lossy(buf);
102+
103+
print!("{out_str}");
104+
105+
self.output.push_str(&out_str);
106+
107+
Ok(buf.len())
108+
}
109+
110+
fn flush(&mut self) -> io::Result<()> {
111+
Ok(())
112+
}
113+
}
114+
115+
impl<'a> MakeWriter<'a> for LogCapturer {
116+
type Writer = Self;
117+
118+
fn make_writer(&'a self) -> Self::Writer {
119+
Self::default()
120+
}
121+
}

‎tests/servers/api/v1/contract/context/auth_key.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
use std::sync::{Arc, Mutex};
12
use std::time::Duration;
23

34
use serde::Serialize;
45
use torrust_tracker::core::auth::Key;
56
use torrust_tracker_test_helpers::configuration;
67
use tracing::level_filters::LevelFilter;
78

8-
use crate::common::logging::{tracing_stderr_init, INIT};
9+
use crate::common::logging::{tracing_init_with_capturer, tracing_stderr_init, LogCapturer, INIT};
910
use crate::servers::api::connection_info::{connection_with_invalid_token, connection_with_no_token};
1011
use crate::servers::api::v1::asserts::{
1112
assert_auth_key_utf8, assert_failed_to_delete_key, assert_failed_to_generate_key, assert_failed_to_reload_keys,
@@ -250,8 +251,10 @@ async fn should_fail_deleting_an_auth_key_when_the_key_id_is_invalid() {
250251

251252
#[tokio::test]
252253
async fn should_fail_when_the_auth_key_cannot_be_deleted() {
254+
let log_capturer = Arc::new(Mutex::new(LogCapturer::new()));
255+
253256
INIT.call_once(|| {
254-
tracing_stderr_init(LevelFilter::ERROR);
257+
tracing_init_with_capturer(LevelFilter::ERROR, log_capturer.clone());
255258
});
256259

257260
let env = Started::new(&configuration::ephemeral().into()).await;
@@ -271,6 +274,10 @@ async fn should_fail_when_the_auth_key_cannot_be_deleted() {
271274

272275
assert_failed_to_delete_key(response).await;
273276

277+
// We expect to see a 500 error, it's the current API behavior
278+
assert!(log_capturer.lock().unwrap().contains("ERROR tower_http"));
279+
assert!(log_capturer.lock().unwrap().contains("500 Internal Server Error"));
280+
274281
env.stop().await;
275282
}
276283

0 commit comments

Comments
 (0)
Please sign in to comment.