]> git.proxmox.com Git - rustc.git/blame - vendor/tracing/tests/support/field.rs
New upstream version 1.54.0+dfsg1
[rustc.git] / vendor / tracing / tests / support / field.rs
CommitLineData
f035d41b
XL
1use tracing::{
2 callsite,
3 callsite::Callsite,
4 field::{self, Field, Value, Visit},
5 metadata::Kind,
6};
7
8use std::{collections::HashMap, fmt};
9
10#[derive(Default, Debug, Eq, PartialEq)]
11pub struct Expect {
12 fields: HashMap<String, MockValue>,
13 only: bool,
14}
15
16#[derive(Debug)]
17pub struct MockField {
18 name: String,
19 value: MockValue,
20}
21
22#[derive(Debug, Eq, PartialEq)]
23pub enum MockValue {
24 I64(i64),
25 U64(u64),
26 Bool(bool),
27 Str(String),
28 Debug(String),
29 Any,
30}
31
32pub fn mock<K>(name: K) -> MockField
33where
34 String: From<K>,
35{
36 MockField {
37 name: name.into(),
38 value: MockValue::Any,
39 }
40}
41
42impl MockField {
43 /// Expect a field with the given name and value.
44 pub fn with_value(self, value: &dyn Value) -> Self {
45 Self {
46 value: MockValue::from(value),
47 ..self
48 }
49 }
50
51 pub fn and(self, other: MockField) -> Expect {
52 Expect {
53 fields: HashMap::new(),
54 only: false,
55 }
56 .and(self)
57 .and(other)
58 }
59
60 pub fn only(self) -> Expect {
61 Expect {
62 fields: HashMap::new(),
63 only: true,
64 }
65 .and(self)
66 }
67}
68
17df50a5
XL
69impl From<MockField> for Expect {
70 fn from(field: MockField) -> Self {
f035d41b
XL
71 Expect {
72 fields: HashMap::new(),
73 only: false,
74 }
17df50a5 75 .and(field)
f035d41b
XL
76 }
77}
78
79impl Expect {
80 pub fn and(mut self, field: MockField) -> Self {
81 self.fields.insert(field.name, field.value);
82 self
83 }
84
85 /// Indicates that no fields other than those specified should be expected.
86 pub fn only(self) -> Self {
87 Self { only: true, ..self }
88 }
89
90 fn compare_or_panic(&mut self, name: &str, value: &dyn Value, ctx: &str) {
91 let value = value.into();
92 match self.fields.remove(name) {
93 Some(MockValue::Any) => {}
94 Some(expected) => assert!(
95 expected == value,
96 "\nexpected `{}` to contain:\n\t`{}{}`\nbut got:\n\t`{}{}`",
97 ctx,
98 name,
99 expected,
100 name,
101 value
102 ),
103 None if self.only => panic!(
104 "\nexpected `{}` to contain only:\n\t`{}`\nbut got:\n\t`{}{}`",
105 ctx, self, name, value
106 ),
107 _ => {}
108 }
109 }
110
111 pub fn checker(&mut self, ctx: String) -> CheckVisitor<'_> {
112 CheckVisitor { expect: self, ctx }
113 }
114
115 pub fn is_empty(&self) -> bool {
116 self.fields.is_empty()
117 }
118}
119
120impl fmt::Display for MockValue {
121 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
122 match self {
123 MockValue::I64(v) => write!(f, "i64 = {:?}", v),
124 MockValue::U64(v) => write!(f, "u64 = {:?}", v),
125 MockValue::Bool(v) => write!(f, "bool = {:?}", v),
126 MockValue::Str(v) => write!(f, "&str = {:?}", v),
127 MockValue::Debug(v) => write!(f, "&fmt::Debug = {:?}", v),
128 MockValue::Any => write!(f, "_ = _"),
129 }
130 }
131}
132
133pub struct CheckVisitor<'a> {
134 expect: &'a mut Expect,
135 ctx: String,
136}
137
138impl<'a> Visit for CheckVisitor<'a> {
139 fn record_i64(&mut self, field: &Field, value: i64) {
140 self.expect
141 .compare_or_panic(field.name(), &value, &self.ctx[..])
142 }
143
144 fn record_u64(&mut self, field: &Field, value: u64) {
145 self.expect
146 .compare_or_panic(field.name(), &value, &self.ctx[..])
147 }
148
149 fn record_bool(&mut self, field: &Field, value: bool) {
150 self.expect
151 .compare_or_panic(field.name(), &value, &self.ctx[..])
152 }
153
154 fn record_str(&mut self, field: &Field, value: &str) {
155 self.expect
156 .compare_or_panic(field.name(), &value, &self.ctx[..])
157 }
158
159 fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) {
160 self.expect
161 .compare_or_panic(field.name(), &field::debug(value), &self.ctx)
162 }
163}
164
165impl<'a> CheckVisitor<'a> {
166 pub fn finish(self) {
167 assert!(
168 self.expect.fields.is_empty(),
169 "{}missing {}",
170 self.expect,
171 self.ctx
172 );
173 }
174}
175
176impl<'a> From<&'a dyn Value> for MockValue {
177 fn from(value: &'a dyn Value) -> Self {
178 struct MockValueBuilder {
179 value: Option<MockValue>,
180 }
181
182 impl Visit for MockValueBuilder {
183 fn record_i64(&mut self, _: &Field, value: i64) {
184 self.value = Some(MockValue::I64(value));
185 }
186
187 fn record_u64(&mut self, _: &Field, value: u64) {
188 self.value = Some(MockValue::U64(value));
189 }
190
191 fn record_bool(&mut self, _: &Field, value: bool) {
192 self.value = Some(MockValue::Bool(value));
193 }
194
195 fn record_str(&mut self, _: &Field, value: &str) {
196 self.value = Some(MockValue::Str(value.to_owned()));
197 }
198
199 fn record_debug(&mut self, _: &Field, value: &dyn fmt::Debug) {
200 self.value = Some(MockValue::Debug(format!("{:?}", value)));
201 }
202 }
203
204 let fake_field = callsite!(name: "fake", kind: Kind::EVENT, fields: fake_field)
205 .metadata()
206 .fields()
207 .field("fake_field")
208 .unwrap();
209 let mut builder = MockValueBuilder { value: None };
210 value.record(&fake_field, &mut builder);
211 builder
212 .value
213 .expect("finish called before a value was recorded")
214 }
215}
216
217impl fmt::Display for Expect {
218 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
219 write!(f, "fields ")?;
220 let entries = self
221 .fields
222 .iter()
223 .map(|(k, v)| (field::display(k), field::display(v)));
224 f.debug_map().entries(entries).finish()
225 }
226}