4 field
::{self, Field, Value, Visit}
,
8 use std
::{collections::HashMap, fmt}
;
10 #[derive(Default, Debug, Eq, PartialEq)]
12 fields
: HashMap
<String
, MockValue
>,
17 pub struct MockField
{
22 #[derive(Debug, Eq, PartialEq)]
32 pub fn mock
<K
>(name
: K
) -> MockField
38 value
: MockValue
::Any
,
43 /// Expect a field with the given name and value.
44 pub fn with_value(self, value
: &dyn Value
) -> Self {
46 value
: MockValue
::from(value
),
51 pub fn and(self, other
: MockField
) -> Expect
{
53 fields
: HashMap
::new(),
60 pub fn only(self) -> Expect
{
62 fields
: HashMap
::new(),
69 impl From
<MockField
> for Expect
{
70 fn from(field
: MockField
) -> Self {
72 fields
: HashMap
::new(),
80 pub fn and(mut self, field
: MockField
) -> Self {
81 self.fields
.insert(field
.name
, field
.value
);
85 /// Indicates that no fields other than those specified should be expected.
86 pub fn only(self) -> Self {
87 Self { only: true, ..self }
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
!(
96 "\nexpected `{}` to contain:\n\t`{}{}`\nbut got:\n\t`{}{}`",
103 None
if self.only
=> panic
!(
104 "\nexpected `{}` to contain only:\n\t`{}`\nbut got:\n\t`{}{}`",
105 ctx
, self, name
, value
111 pub fn checker(&mut self, ctx
: String
) -> CheckVisitor
<'_
> {
112 CheckVisitor { expect: self, ctx }
115 pub fn is_empty(&self) -> bool
{
116 self.fields
.is_empty()
120 impl fmt
::Display
for MockValue
{
121 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
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
, "_ = _"),
133 pub struct CheckVisitor
<'a
> {
134 expect
: &'a
mut Expect
,
138 impl<'a
> Visit
for CheckVisitor
<'a
> {
139 fn record_i64(&mut self, field
: &Field
, value
: i64) {
141 .compare_or_panic(field
.name(), &value
, &self.ctx
[..])
144 fn record_u64(&mut self, field
: &Field
, value
: u64) {
146 .compare_or_panic(field
.name(), &value
, &self.ctx
[..])
149 fn record_bool(&mut self, field
: &Field
, value
: bool
) {
151 .compare_or_panic(field
.name(), &value
, &self.ctx
[..])
154 fn record_str(&mut self, field
: &Field
, value
: &str) {
156 .compare_or_panic(field
.name(), &value
, &self.ctx
[..])
159 fn record_debug(&mut self, field
: &Field
, value
: &dyn fmt
::Debug
) {
161 .compare_or_panic(field
.name(), &field
::debug(value
), &self.ctx
)
165 impl<'a
> CheckVisitor
<'a
> {
166 pub fn finish(self) {
168 self.expect
.fields
.is_empty(),
176 impl<'a
> From
<&'a
dyn Value
> for MockValue
{
177 fn from(value
: &'a
dyn Value
) -> Self {
178 struct MockValueBuilder
{
179 value
: Option
<MockValue
>,
182 impl Visit
for MockValueBuilder
{
183 fn record_i64(&mut self, _
: &Field
, value
: i64) {
184 self.value
= Some(MockValue
::I64(value
));
187 fn record_u64(&mut self, _
: &Field
, value
: u64) {
188 self.value
= Some(MockValue
::U64(value
));
191 fn record_bool(&mut self, _
: &Field
, value
: bool
) {
192 self.value
= Some(MockValue
::Bool(value
));
195 fn record_str(&mut self, _
: &Field
, value
: &str) {
196 self.value
= Some(MockValue
::Str(value
.to_owned()));
199 fn record_debug(&mut self, _
: &Field
, value
: &dyn fmt
::Debug
) {
200 self.value
= Some(MockValue
::Debug(format
!("{:?}", value
)));
204 let fake_field
= callsite
!(name
: "fake", kind
: Kind
::EVENT
, fields
: fake_field
)
209 let mut builder
= MockValueBuilder { value: None }
;
210 value
.record(&fake_field
, &mut builder
);
213 .expect("finish called before a value was recorded")
217 impl fmt
::Display
for Expect
{
218 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
219 write
!(f
, "fields ")?
;
223 .map(|(k
, v
)| (field
::display(k
), field
::display(v
)));
224 f
.debug_map().entries(entries
).finish()