value_bag/
test.rs

1//! Test support for inspecting values.
2
3use crate::{
4    internal,
5    std::{fmt, str, string::String},
6    Error, ValueBag,
7};
8
9#[cfg(test)]
10use crate::visit::Visit;
11
12#[cfg(test)]
13pub(crate) trait IntoValueBag<'v> {
14    fn into_value_bag(self) -> ValueBag<'v>;
15}
16
17#[cfg(test)]
18impl<'v, T> IntoValueBag<'v> for T
19where
20    T: Into<ValueBag<'v>>,
21{
22    fn into_value_bag(self) -> ValueBag<'v> {
23        self.into()
24    }
25}
26
27/**
28A tokenized representation of the captured value for testing.
29*/
30#[derive(Debug, PartialEq)]
31#[non_exhaustive]
32pub enum TestToken {
33    U64(u64),
34    I64(i64),
35    F64(f64),
36    U128(u128),
37    I128(i128),
38    Char(char),
39    Bool(bool),
40    Str(String),
41    None,
42
43    #[cfg(feature = "error")]
44    Error,
45
46    #[cfg(feature = "sval2")]
47    Sval {
48        version: u32,
49    },
50
51    #[cfg(feature = "serde1")]
52    Serde {
53        version: u32,
54    },
55
56    #[cfg(feature = "seq")]
57    Seq,
58
59    Poisoned(String),
60}
61
62impl<'v> ValueBag<'v> {
63    /**
64    Convert the value bag into a token for testing.
65
66    This _isn't_ a general-purpose API for working with values outside of testing.
67    */
68    pub fn to_test_token(&self) -> TestToken {
69        struct TestVisitor(Option<TestToken>);
70
71        impl<'v> internal::InternalVisitor<'v> for TestVisitor {
72            fn fill(&mut self, v: &dyn crate::fill::Fill) -> Result<(), Error> {
73                v.fill(crate::fill::Slot::new(self))
74            }
75
76            fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error> {
77                self.0 = Some(TestToken::Str(format!("{:?}", v)));
78                Ok(())
79            }
80
81            fn display(&mut self, v: &dyn fmt::Display) -> Result<(), Error> {
82                self.0 = Some(TestToken::Str(format!("{}", v)));
83                Ok(())
84            }
85
86            fn u64(&mut self, v: u64) -> Result<(), Error> {
87                self.0 = Some(TestToken::U64(v));
88                Ok(())
89            }
90
91            fn i64(&mut self, v: i64) -> Result<(), Error> {
92                self.0 = Some(TestToken::I64(v));
93                Ok(())
94            }
95
96            fn u128(&mut self, v: &u128) -> Result<(), Error> {
97                self.0 = Some(TestToken::U128(*v));
98                Ok(())
99            }
100
101            fn i128(&mut self, v: &i128) -> Result<(), Error> {
102                self.0 = Some(TestToken::I128(*v));
103                Ok(())
104            }
105
106            fn f64(&mut self, v: f64) -> Result<(), Error> {
107                self.0 = Some(TestToken::F64(v));
108                Ok(())
109            }
110
111            fn bool(&mut self, v: bool) -> Result<(), Error> {
112                self.0 = Some(TestToken::Bool(v));
113                Ok(())
114            }
115
116            fn char(&mut self, v: char) -> Result<(), Error> {
117                self.0 = Some(TestToken::Char(v));
118                Ok(())
119            }
120
121            fn str(&mut self, v: &str) -> Result<(), Error> {
122                self.0 = Some(TestToken::Str(v.into()));
123                Ok(())
124            }
125
126            fn none(&mut self) -> Result<(), Error> {
127                self.0 = Some(TestToken::None);
128                Ok(())
129            }
130
131            #[cfg(feature = "error")]
132            fn error(&mut self, _: &dyn internal::error::Error) -> Result<(), Error> {
133                self.0 = Some(TestToken::Error);
134                Ok(())
135            }
136
137            #[cfg(feature = "sval2")]
138            fn sval2(&mut self, _: &dyn internal::sval::v2::Value) -> Result<(), Error> {
139                self.0 = Some(TestToken::Sval { version: 2 });
140                Ok(())
141            }
142
143            #[cfg(feature = "serde1")]
144            fn serde1(&mut self, _: &dyn internal::serde::v1::Serialize) -> Result<(), Error> {
145                self.0 = Some(TestToken::Serde { version: 1 });
146                Ok(())
147            }
148
149            #[cfg(feature = "seq")]
150            fn seq(&mut self, _: &dyn internal::seq::Seq) -> Result<(), Error> {
151                self.0 = Some(TestToken::Seq);
152                Ok(())
153            }
154
155            fn poisoned(&mut self, msg: &'static str) -> Result<(), Error> {
156                self.0 = Some(TestToken::Poisoned(msg.into()));
157                Ok(())
158            }
159        }
160
161        let mut visitor = TestVisitor(None);
162        self.internal_visit(&mut visitor).unwrap();
163
164        visitor.0.unwrap()
165    }
166}
167
168#[cfg(test)]
169pub(crate) struct TestVisit {
170    pub i64: i64,
171    pub u64: u64,
172    pub i128: i128,
173    pub u128: u128,
174    pub f64: f64,
175    pub bool: bool,
176    pub str: &'static str,
177    pub borrowed_str: &'static str,
178    pub char: char,
179}
180
181#[cfg(test)]
182impl Default for TestVisit {
183    fn default() -> Self {
184        TestVisit {
185            i64: -42,
186            u64: 42,
187            i128: -42,
188            u128: 42,
189            f64: 11.0,
190            bool: true,
191            str: "some string",
192            borrowed_str: "some borrowed string",
193            char: 'n',
194        }
195    }
196}
197
198#[cfg(test)]
199impl<'v> Visit<'v> for TestVisit {
200    fn visit_any(&mut self, v: ValueBag) -> Result<(), Error> {
201        panic!("unexpected value: {}", v)
202    }
203
204    fn visit_i64(&mut self, v: i64) -> Result<(), Error> {
205        assert_eq!(self.i64, v);
206        Ok(())
207    }
208
209    fn visit_u64(&mut self, v: u64) -> Result<(), Error> {
210        assert_eq!(self.u64, v);
211        Ok(())
212    }
213
214    fn visit_i128(&mut self, v: i128) -> Result<(), Error> {
215        assert_eq!(self.i128, v);
216        Ok(())
217    }
218
219    fn visit_u128(&mut self, v: u128) -> Result<(), Error> {
220        assert_eq!(self.u128, v);
221        Ok(())
222    }
223
224    fn visit_f64(&mut self, v: f64) -> Result<(), Error> {
225        assert_eq!(self.f64, v);
226        Ok(())
227    }
228
229    fn visit_bool(&mut self, v: bool) -> Result<(), Error> {
230        assert_eq!(self.bool, v);
231        Ok(())
232    }
233
234    fn visit_str(&mut self, v: &str) -> Result<(), Error> {
235        assert_eq!(self.str, v);
236        Ok(())
237    }
238
239    fn visit_borrowed_str(&mut self, v: &'v str) -> Result<(), Error> {
240        assert_eq!(self.borrowed_str, v);
241        Ok(())
242    }
243
244    fn visit_char(&mut self, v: char) -> Result<(), Error> {
245        assert_eq!(self.char, v);
246        Ok(())
247    }
248
249    #[cfg(feature = "error")]
250    fn visit_error(&mut self, err: &(dyn crate::std::error::Error + 'static)) -> Result<(), Error> {
251        assert!(err.downcast_ref::<crate::std::io::Error>().is_some());
252        Ok(())
253    }
254
255    #[cfg(feature = "error")]
256    fn visit_borrowed_error(
257        &mut self,
258        err: &'v (dyn crate::std::error::Error + 'static),
259    ) -> Result<(), Error> {
260        assert!(err.downcast_ref::<crate::std::io::Error>().is_some());
261        Ok(())
262    }
263}