reifydb_core/interface/logging/
mock.rs1#[cfg(debug_assertions)]
14use std::cell::RefCell;
15
16#[cfg(debug_assertions)]
17use crossbeam_channel::Sender;
18
19#[cfg(debug_assertions)]
20use super::Record;
21
22#[cfg(debug_assertions)]
23thread_local! {
24 static MOCK_LOGGER: RefCell<Option<Sender<Record>>> = RefCell::new(None);
27}
28
29#[cfg(debug_assertions)]
31pub fn set_mock_logger(sender: Sender<Record>) {
32 MOCK_LOGGER.with(|logger| {
33 *logger.borrow_mut() = Some(sender);
34 });
35}
36
37#[cfg(debug_assertions)]
39pub fn clear_mock_logger() {
40 MOCK_LOGGER.with(|logger| {
41 *logger.borrow_mut() = None;
42 });
43}
44
45#[cfg(debug_assertions)]
47pub fn get_mock_logger() -> Option<Sender<Record>> {
48 MOCK_LOGGER.with(|logger| logger.borrow().clone())
49}
50
51#[cfg(debug_assertions)]
53pub fn is_mock_logger_active() -> bool {
54 MOCK_LOGGER.with(|logger| logger.borrow().is_some())
55}
56
57#[cfg(debug_assertions)]
59pub struct MockLoggerGuard {
60 previous: Option<Sender<Record>>,
62}
63
64#[cfg(debug_assertions)]
65impl MockLoggerGuard {
66 pub fn new(sender: Sender<Record>) -> Self {
68 let previous = get_mock_logger();
69 set_mock_logger(sender);
70 Self {
71 previous,
72 }
73 }
74}
75
76#[cfg(debug_assertions)]
77impl Drop for MockLoggerGuard {
78 fn drop(&mut self) {
79 if let Some(sender) = self.previous.take() {
81 set_mock_logger(sender);
82 } else {
83 clear_mock_logger();
84 }
85 }
86}
87
88#[cfg(debug_assertions)]
90pub fn with_mock_logger<T>(sender: Sender<Record>, f: impl FnOnce() -> T) -> T {
91 let _guard = MockLoggerGuard::new(sender);
92 f()
93}
94
95#[cfg(test)]
96mod tests {
97 use LogLevel::{Debug, Info};
98 use crossbeam_channel::unbounded;
99
100 use super::*;
101 use crate::interface::logging::{LogLevel, Record};
102
103 #[test]
104 fn test_mock_logger_basic() {
105 let (sender, receiver) = unbounded();
106
107 assert!(!is_mock_logger_active());
108
109 set_mock_logger(sender.clone());
110 assert!(is_mock_logger_active());
111
112 let retrieved = get_mock_logger().unwrap();
114 let record = Record::new(Info, "test", "message");
115 retrieved.send(record.clone()).unwrap();
116
117 let received = receiver.try_recv().unwrap();
118 assert_eq!(received.message, "message");
119
120 clear_mock_logger();
121 assert!(!is_mock_logger_active());
122 }
123
124 #[test]
125 fn test_mock_logger_guard() {
126 let (sender1, _) = unbounded();
127 let (sender2, _) = unbounded();
128
129 assert!(!is_mock_logger_active());
130
131 {
132 let _guard = MockLoggerGuard::new(sender1.clone());
133 assert!(is_mock_logger_active());
134
135 {
137 let _guard2 = MockLoggerGuard::new(sender2.clone());
138 assert!(is_mock_logger_active());
139 }
141
142 assert!(is_mock_logger_active());
144 }
145
146 assert!(!is_mock_logger_active());
148 }
149
150 #[test]
151 fn test_with_mock_logger() {
152 let (sender, receiver) = unbounded();
153
154 assert!(!is_mock_logger_active());
155
156 let result = with_mock_logger(sender, || {
157 assert!(is_mock_logger_active());
158
159 let logger = get_mock_logger().unwrap();
160 let record = Record::new(Debug, "test", "test message");
161 logger.send(record).unwrap();
162
163 42
164 });
165
166 assert_eq!(result, 42);
167 assert!(!is_mock_logger_active());
168
169 let received = receiver.try_recv().unwrap();
170 assert_eq!(received.message, "test message");
171 }
172
173 #[test]
174 fn test_thread_isolation() {
175 use std::thread;
176
177 let (sender1, receiver1) = unbounded();
178 let (sender2, receiver2) = unbounded();
179
180 let handle1 = thread::spawn(move || {
181 with_mock_logger(sender1, || {
182 let logger = get_mock_logger().unwrap();
183 let record = Record::new(Info, "thread1", "message1");
184 logger.send(record).unwrap();
185 });
186 });
187
188 let handle2 = thread::spawn(move || {
189 with_mock_logger(sender2, || {
190 let logger = get_mock_logger().unwrap();
191 let record = Record::new(Info, "thread2", "message2");
192 logger.send(record).unwrap();
193 });
194 });
195
196 handle1.join().unwrap();
197 handle2.join().unwrap();
198
199 let received1 = receiver1.try_recv().unwrap();
201 assert_eq!(received1.module, "thread1");
202 assert_eq!(received1.message, "message1");
203
204 let received2 = receiver2.try_recv().unwrap();
205 assert_eq!(received2.module, "thread2");
206 assert_eq!(received2.message, "message2");
207 }
208}