qubit_function/testers/tester.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10//! Defines the `Tester` public trait.
11
12use super::{
13 Arc,
14 Rc,
15};
16
17use self::{
18 arc_tester::ArcTester,
19 box_tester::BoxTester,
20 rc_tester::RcTester,
21};
22
23pub mod arc_tester;
24pub mod box_tester;
25pub mod fn_tester_ops;
26pub mod rc_tester;
27
28/// Tests whether a zero-argument condition holds.
29///
30/// `Tester` is a functional abstraction equivalent to `Fn() -> bool`. It
31/// accepts no parameters, uses `&self`, and returns a boolean value indicating
32/// the test result of some state or condition.
33///
34/// # Core Characteristics
35///
36/// - **No input parameters**: Captures context through closures
37/// - **Returns boolean**: Indicates test results
38/// - **Uses `&self`**: Matches `Fn() -> bool` and does not require mutable
39/// access to its own state
40/// - **Repeatable calls**: The same Tester can call `test()` multiple times
41/// - **Stateless closure shape**: For `FnMut() -> bool`, use
42/// [`StatefulTester`](super::stateful_tester::StatefulTester)
43///
44/// # Use Cases
45///
46/// - **State checking**: Check system or service status
47/// - **Condition waiting**: Repeatedly check until conditions are met
48/// - **Health monitoring**: Check system health status
49/// - **Precondition validation**: Verify conditions before operations
50///
51/// # Design Philosophy
52///
53/// Tester's responsibility is "test judgment", not "state management".
54/// State management is the caller's responsibility. Tester only reads state
55/// and returns judgment results.
56///
57/// # Examples
58///
59/// ```rust
60/// use qubit_function::{BoxTester, Tester};
61/// use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
62///
63/// // State managed externally
64/// let ready = Arc::new(AtomicBool::new(false));
65/// let ready_clone = Arc::clone(&ready);
66///
67/// // Tester only responsible for reading state
68/// let tester = BoxTester::new(move || {
69/// ready_clone.load(Ordering::Acquire)
70/// });
71///
72/// // Can be called multiple times
73/// assert!(!tester.test());
74/// ready.store(true, Ordering::Release);
75/// assert!(tester.test());
76/// ```
77pub trait Tester {
78 /// Executes the test and returns the test result
79 ///
80 /// This method can be called multiple times without modifying the Tester's
81 /// own state.
82 ///
83 /// # Return Value
84 ///
85 /// Returns `true` if the condition holds, otherwise returns `false`
86 ///
87 /// # Examples
88 ///
89 /// ```rust
90 /// use qubit_function::{BoxTester, Tester};
91 ///
92 /// let tester = BoxTester::new(|| true);
93 /// assert!(tester.test());
94 /// ```
95 fn test(&self) -> bool;
96
97 /// Converts this tester to `BoxTester`
98 ///
99 /// # Return Value
100 ///
101 /// A `BoxTester` that wraps this tester
102 ///
103 /// # Examples
104 ///
105 /// ```rust
106 /// use qubit_function::{Tester, BoxTester};
107 ///
108 /// let closure = || true;
109 /// let boxed: BoxTester = closure.into_box();
110 /// ```
111 #[inline]
112 fn into_box(self) -> BoxTester
113 where
114 Self: Sized + 'static,
115 {
116 BoxTester {
117 function: Box::new(move || self.test()),
118 }
119 }
120
121 /// Converts this tester to `RcTester`
122 ///
123 /// # Return Value
124 ///
125 /// A `RcTester` that wraps this tester
126 ///
127 /// # Examples
128 ///
129 /// ```rust
130 /// use qubit_function::{Tester, RcTester};
131 ///
132 /// let closure = || true;
133 /// let rc: RcTester = closure.into_rc();
134 /// ```
135 #[inline]
136 fn into_rc(self) -> RcTester
137 where
138 Self: Sized + 'static,
139 {
140 RcTester {
141 function: Rc::new(move || self.test()),
142 }
143 }
144
145 /// Converts this tester to `ArcTester`
146 ///
147 /// # Return Value
148 ///
149 /// An `ArcTester` that wraps this tester
150 ///
151 /// # Examples
152 ///
153 /// ```rust
154 /// use qubit_function::{Tester, ArcTester};
155 ///
156 /// let closure = || true;
157 /// let arc: ArcTester = closure.into_arc();
158 /// ```
159 #[inline]
160 fn into_arc(self) -> ArcTester
161 where
162 Self: Sized + Send + Sync + 'static,
163 {
164 ArcTester {
165 function: Arc::new(move || self.test()),
166 }
167 }
168
169 /// Converts this tester to a boxed function pointer
170 ///
171 /// # Return Value
172 ///
173 /// A `Box<dyn Fn() -> bool>` that wraps this tester
174 ///
175 /// # Examples
176 ///
177 /// ```rust
178 /// use qubit_function::Tester;
179 ///
180 /// let closure = || true;
181 /// let func = closure.into_fn();
182 /// assert!(func());
183 /// ```
184 #[inline]
185 fn into_fn(self) -> impl Fn() -> bool
186 where
187 Self: Sized + 'static,
188 {
189 Box::new(move || self.test())
190 }
191
192 /// Clones and converts this tester to `BoxTester`
193 ///
194 /// # Return Value
195 ///
196 /// A `BoxTester` that wraps a clone of this tester
197 ///
198 /// # Examples
199 ///
200 /// ```rust
201 /// use qubit_function::{Tester, BoxTester, ArcTester};
202 ///
203 /// let arc = ArcTester::new(|| true);
204 /// let boxed: BoxTester = arc.to_box();
205 /// // arc is still available
206 /// ```
207 #[inline]
208 fn to_box(&self) -> BoxTester
209 where
210 Self: Clone + 'static,
211 {
212 self.clone().into_box()
213 }
214
215 /// Clones and converts this tester to `RcTester`
216 ///
217 /// # Return Value
218 ///
219 /// A `RcTester` that wraps a clone of this tester
220 ///
221 /// # Examples
222 ///
223 /// ```rust
224 /// use qubit_function::{Tester, RcTester, ArcTester};
225 ///
226 /// let arc = ArcTester::new(|| true);
227 /// let rc: RcTester = arc.to_rc();
228 /// // arc is still available
229 /// ```
230 #[inline]
231 fn to_rc(&self) -> RcTester
232 where
233 Self: Clone + 'static,
234 {
235 self.clone().into_rc()
236 }
237
238 /// Clones and converts this tester to `ArcTester`
239 ///
240 /// # Return Value
241 ///
242 /// An `ArcTester` that wraps a clone of this tester
243 ///
244 /// # Examples
245 ///
246 /// ```rust
247 /// use qubit_function::{Tester, ArcTester, RcTester};
248 ///
249 /// let rc = RcTester::new(|| true);
250 /// // Note: This will panic for RcTester as it's not Send + Sync
251 /// // let arc: ArcTester = rc.to_arc();
252 /// ```
253 #[inline]
254 fn to_arc(&self) -> ArcTester
255 where
256 Self: Clone + Send + Sync + 'static,
257 {
258 self.clone().into_arc()
259 }
260
261 /// Clones and converts this tester to a boxed function pointer
262 ///
263 /// # Return Value
264 ///
265 /// A `Box<dyn Fn() -> bool>` that wraps a clone of this tester
266 ///
267 /// # Examples
268 ///
269 /// ```rust
270 /// use qubit_function::{Tester, ArcTester};
271 ///
272 /// let arc = ArcTester::new(|| true);
273 /// let func = arc.to_fn();
274 /// // arc is still available
275 /// assert!(func());
276 /// ```
277 #[inline]
278 fn to_fn(&self) -> impl Fn() -> bool
279 where
280 Self: Clone + 'static,
281 {
282 self.clone().into_fn()
283 }
284}