/// Convert a trait object reference into a reference to a Boxed trait /// /// # Returns /// /// Returns `true` if it was necessary to box the type. fn dedynify(ty: &mutType) -> bool { ifletType::Reference(refmut tr) = ty { ifletType::TraitObject(ref tto) = tr.elem.as_ref() { iflet Some(lt) = &tr.lifetime { if lt.ident == "static" { // For methods that return 'static references, the user can // usually actually supply one, unlike nonstatic references. // dedynify is unneeded and harmful in such cases. // // But we do need to add parens to prevent parsing errors // when methods like returning add a `+ Send` to the output // type.
*tr.elem = parse2(quote!((#tto))).unwrap(); returnfalse;
}
}
/// Convert a special reference type like "&str" into a reference to its owned /// type like "&String". fn destrify(ty: &mutType) { ifletType::Reference(refmut tr) = ty { iflet Some(lt) = &tr.lifetime { if lt.ident == "static" { // For methods that return 'static references, the user can // usually actually supply one, unlike nonstatic references. // destrify is unneeded and harmful in such cases. return;
}
}
let path_ty: TypePath = parse2(quote!(Path)).unwrap(); let pathbuf_ty: Type = parse2(quote!(::std::path::PathBuf)).unwrap();
let str_ty: TypePath = parse2(quote!(str)).unwrap(); let string_ty: Type = parse2(quote!(::std::string::String)).unwrap();
let cstr_ty: TypePath = parse2(quote!(CStr)).unwrap(); let cstring_ty: Type = parse2(quote!(::std::ffi::CString)).unwrap();
let osstr_ty: TypePath = parse2(quote!(OsStr)).unwrap(); let osstring_ty: Type = parse2(quote!(::std::ffi::OsString)).unwrap();
let (mut declosured_generics, declosured_inputs, call_exprs) = ifself.concretize {
concretize_args(&self.sig.generics, &self.sig.inputs)
} else {
declosurefy(&self.sig.generics, &self.sig.inputs)
}; // TODO: make concretize and declosurefy work for the same function
for fa in declosured_inputs.iter() { iflet FnArg::Typed(pt) = fa { let argname = (*pt.pat).clone();
assert!(!pat_is_self(&argname)); let aty = supersuperfy(&pt.ty, self.levels); ifletType::Reference(ref tr) = aty {
predexprs.push(quote!(#argname));
predty.push((*tr.elem).clone()); let tr2 = Type::Reference(TypeReference {
and_token: tr.and_token,
lifetime: None,
mutability: None,
elem: tr.elem.clone()
});
refpredty.push(tr2);
} else {
predexprs.push(quote!(&#argname));
predty.push(aty.clone()); let tr = TypeReference {
and_token: Token),
lifetime: None,
mutability: None,
elem: Box::new(aty.clone())
};
refpredty.push(Type::Reference(tr));
};
argnames.push(argname);
argty.push(aty.clone());
} else {
is_static = false;
}
} let (output, boxed) = matchself.sig.output {
ReturnType::Default => ( Type::Tuple(TypeTuple {
paren_token: token::Paren::default(),
elems: Punctuated::new(),
}), false,
),
ReturnType::Type(_, ref ty) => { letmut output_ty = supersuperfy(ty, self.levels);
destrify(&mut output_ty); let boxed = dedynify(&mut output_ty);
(output_ty, boxed)
}
};
supersuperfy_generics(&mut declosured_generics, self.levels); let owned_output = ownify(&output); letmut return_ref = false; letmut return_refmut = false; ifletType::Reference(ref tr) = &output { if tr.lifetime.as_ref().map_or(true, |lt| lt.ident != "static")
{ if tr.mutability.is_none() {
return_ref = true;
} else {
return_refmut = true;
}
}
}; if is_static && (return_ref || return_refmut) {
compile_error(self.sig.span(), "Mockall cannot mock static methods that return non-'static references. It's unclear what the return value's lifetime should be.");
} let struct_generics = self.struct_generics.cloned()
.unwrap_or_default(); let (type_generics, salifetimes, srlifetimes) = split_lifetimes(
struct_generics.clone(),
&declosured_inputs,
&ReturnType::Type(<Token![->]>::default(), Box::new(owned_output.clone()))
); let srltg = lifetimes_to_generics(&srlifetimes); let (call_generics, malifetimes, mrlifetimes) = split_lifetimes(
declosured_generics,
&declosured_inputs,
&ReturnType::Type(<Token![->]>::default(), Box::new(owned_output.clone()))
); let mrltg = lifetimes_to_generics(&mrlifetimes); let cgenerics = merge_generics(&type_generics, &call_generics); let egenerics = merge_generics(
&merge_generics(&cgenerics, &srltg),
&mrltg); let alifetimes = salifetimes.into_iter()
.collect::<HashSet<LifetimeParam>>()
.union(&malifetimes.into_iter().collect::<HashSet<_>>())
.cloned()
.collect();
let fn_params = egenerics.type_params()
.map(|tp| tp.ident.clone())
.collect(); let call_levels = self.call_levels.unwrap_or(self.levels);
/// How many levels of modules beneath the original function this one is /// nested. pubfn call_levels(&mutself, levels: usize) -> &mutSelf { self.call_levels = Some(levels); self
}
/// How many levels of modules beneath the original function this one's /// private module is nested. pubfn levels(&mutself, levels: usize) -> &mutSelf { self.levels = levels; self
}
/// # Arguments /// /// * sig: The signature of the mockable function /// * v: The visibility of the mockable function pubfn new(sig: &'a Signature, vis: &'a Visibility) -> Self {
Builder {
attrs: &[],
concretize: false,
levels: 0,
call_levels: None,
parent: None,
sig,
struct_: None,
struct_generics: None,
trait_: None,
vis
}
}
/// Supply the name of the parent module pubfn parent(&mutself, ident: &'a Ident) -> &mut Self { self.parent = Some(ident); self
}
/// Supply the name of the parent struct, if any pubfn struct_(&mutself, ident: &'a Ident) -> &mut Self { self.struct_= Some(ident); self
}
/// Supply the Generics of the parent struct, if any pubfn struct_generics(&mutself, generics: &'a Generics) -> &mut Self { self.struct_generics = Some(generics); self
}
/// Supply the name of the method's trait, if any pubfn trait_(&mutself, ident: &'a Ident) -> &mut Self { self.trait_ = Some(ident); self
}
}
#[derive(Clone)] pub(crate) struct MockFunction { /// Lifetimes of the mocked method that relate to the arguments but not the /// return value
alifetimes: Punctuated<LifetimeParam, token::Comma>, /// Names of the method arguments
argnames: Vec<Pat>, /// Types of the method arguments
argty: Vec<Type>, /// any attributes on the original function, like #[inline] pub attrs: Vec<Attribute>, /// Expressions that should be used for Expectation::call's arguments
call_exprs: Vec<TokenStream>, /// Generics used for the expectation call
call_generics: Generics, /// Visibility of the mock function itself
call_vis: Visibility, /// Are we turning generic arguments into concrete trait objects?
concretize: bool, /// Generics of the Expectation object
egenerics: Generics, /// Generics of the Common object
cgenerics: Generics, /// The mock function's generic types as a list of types
fn_params: Vec<Ident>, /// Is this for a static method or free function?
is_static: bool, /// name of the function's parent module
mod_ident: Ident, /// Output type of the Method, supersuperfied.
output: Type, /// Owned version of the output type of the Method, supersuperfied. /// /// If the real output type is a non-'static reference, then it will differ /// from this field.
owned_output: Type, /// True if the `owned_type` is boxed by `Box<>`.
boxed: bool, /// Expressions that create the predicate arguments from the call arguments
predexprs: Vec<TokenStream>, /// Types used for Predicates. Will be almost the same as args, but every /// type will be a non-reference type.
predty: Vec<Type>, /// Does the function return a non-'static reference?
return_ref: bool, /// Does the function return a mutable reference?
return_refmut: bool, /// References to every type in `predty`.
refpredty: Vec<Type>, /// The signature of the mockable function
sig: Signature, /// Name of the parent structure, if any
struct_: Option<Ident>, /// Generics of the parent structure
struct_generics: Generics, /// Name of this method's trait, if the method comes from a trait
trait_: Option<Ident>, /// Type generics of the mock structure
type_generics: Generics, /// Visibility of the expectation and its methods
privmod_vis: Visibility
}
impl MockFunction { /// Return the mock function itself /// /// # Arguments /// /// * `modname`: Name of the parent struct's private module // Supplying modname is an unfortunately hack. Ideally MockFunction // wouldn't need to know that. pubfn call(&self, modname: Option<&Ident>) -> impl ToTokens { let attrs = AttrFormatter::new(&self.attrs).format(); let call_exprs = &self.call_exprs; let (_, tg, _) = ifself.is_method_generic() || self.is_static() {
&self.egenerics
} else {
&self.call_generics
}.split_for_impl(); let tbf = tg.as_turbofish(); let name = self.name(); let desc = self.desc(); let no_match_msg = quote!(std::format!( "{}: No matching expectation found", #desc)); let sig = &self.sig; let (vis, dead_code) = ifself.trait_.is_some() {
(&Visibility::Inherited, quote!())
} else { let dead_code = iflet Visibility::Inherited = self.call_vis { // This private method may be a helper only used by the struct's // other methods, which we are mocking. If so, the mock method // will be dead code. But we can't simply eliminate it, because // it might also be used by other code in the same module.
quote!(#[allow(dead_code)])
} else {
quote!()
};
(&self.call_vis, dead_code)
}; // Add #[no_mangle] attribute to preserve the function name // as-is, without mangling, for compatibility with C functions. let no_mangle = iflet Some(ref abi) = self.sig.abi { iflet Some(ref name) = abi.name { if name.value().ne("Rust") {
quote!(#[no_mangle])
} else {
quote!()
}
} else { // This is the same as extern "C"
quote!(#[no_mangle])
}
} else {
quote!()
}; let substruct_obj: TokenStream = iflet Some(trait_) = &self.trait_ { let ident = format_ident!("{}_expectations", trait_);
quote!(#ident.)
} else {
quote!()
}; let call = ifself.return_refmut {
Ident::new("call_mut", Span::call_site())
} else {
Ident::new("call", Span::call_site())
}; letmut deref = quote!(); ifself.boxed { ifself.return_ref {
deref = quote!(&**);
} elseifself.return_refmut {
deref = quote!(&mut **);
}
} ifself.is_static { let outer_mod_path = self.outer_mod_path(modname);
quote!( // Don't add a doc string. The original is included in #attrs #(#attrs)* #dead_code #no_mangle #vis#sig { use ::mockall::{ViaDebug, ViaNothing}; let no_match_msg = #no_match_msg; #deref { let __mockall_guard = #outer_mod_path::EXPECTATIONS
.lock().unwrap(); /* *TODO:catchpanics,thengracefullyreleasethemutex *soitwon'tbepoisoned.Thisrequiresboundingany *genericparameterswithUnwindSafe
*/ /* std::panic::catch_unwind(|| */
__mockall_guard.#call#tbf(#(#call_exprs,)*) /*)*/
}.expect(&no_match_msg)
}
)
} else {
quote!( // Don't add a doc string. The original is included in #attrs #(#attrs)* #dead_code #no_mangle #vis#sig { use ::mockall::{ViaDebug, ViaNothing}; let no_match_msg = #no_match_msg; #derefself.#substruct_obj#name.#call#tbf(#(#call_exprs,)*)
.expect(&no_match_msg)
}
)
}
}
/// Return this method's contribution to its parent's checkpoint method pubfn checkpoint(&self) -> impl ToTokens { let attrs = AttrFormatter::new(&self.attrs)
.doc(false)
.format(); let inner_mod_ident = self.inner_mod_ident(); ifself.is_static {
quote!( #(#attrs)*
{ let __mockall_timeses = #inner_mod_ident::EXPECTATIONS.lock()
.unwrap()
.checkpoint()
.collect::<Vec<_>>();
}
)
} else { let name = &self.name();
quote!(#(#attrs)* { self.#name.checkpoint(); })
}
}
/// Return a function that creates a Context object for this function /// /// # Arguments /// /// * `modname`: Name of the parent struct's private module // Supplying modname is an unfortunately hack. Ideally MockFunction // wouldn't need to know that. pubfn context_fn(&self, modname: Option<&Ident>) -> impl ToTokens { let attrs = AttrFormatter::new(&self.attrs)
.doc(false)
.format(); let context_docstr = format!("Create a [`Context`]({}{}/struct.Context.html) for mocking the `{}` method",
modname.map(|m| format!("{m}/")).unwrap_or_default(), self.inner_mod_ident(), self.name()); let context_ident = format_ident!("{}_context", self.name()); let (_, tg, _) = self.type_generics.split_for_impl(); let outer_mod_path = self.outer_mod_path(modname); let v = &self.call_vis;
quote!( #(#attrs)* #[doc = #context_docstr] #vfn#context_ident() -> #outer_mod_path::Context #tg
{ #outer_mod_path::Context::default()
}
)
}
/// Generate a code fragment that will print a description of the invocation fn desc(&self) -> impl ToTokens { let argnames = &self.argnames; let name = iflet Some(s) = &self.struct_ {
format!("{}::{}", s, self.sig.ident)
} else {
format!("{}::{}", self.mod_ident, self.sig.ident)
}; let fields = vec!["{:?}"; argnames.len()].join(", "); let fstr = format!("{name}({fields})");
quote!(std::format!(#fstr, #((&&::mockall::ArgPrinter(&#argnames)).debug_string()),*))
}
/// Generate code for the expect_ method /// /// # Arguments /// /// * `modname`: Name of the parent struct's private module /// * `self_args`: If supplied, these are the /// AngleBracketedGenericArguments of the self type of the /// trait impl. e.g. The `T` in `impl Foo for Bar<T>`. // Supplying modname is an unfortunately hack. Ideally MockFunction // wouldn't need to know that. pubfn expect(&self, modname: &Ident, self_args: Option<&PathArguments>)
-> impl ToTokens
{ let attrs = AttrFormatter::new(&self.attrs)
.doc(false)
.format(); let name = self.name(); let expect_ident = format_ident!("expect_{}", name); let expectation_obj = self.expectation_obj(self_args); let funcname = &self.sig.ident; let (_, tg, _) = ifself.is_method_generic() {
&self.egenerics
} else {
&self.call_generics
}.split_for_impl(); let (ig, _, wc) = self.call_generics.split_for_impl(); letmut wc = wc.cloned(); ifself.is_method_generic() && (self.return_ref || self.return_refmut) { // Add Senc + Sync, required for downcast, since Expectation // stores an Option<#owned_output>
send_syncify(&mut wc, self.owned_output.clone());
} let tbf = tg.as_turbofish(); let vis = &self.call_vis;
#[cfg(not(feature = "nightly_derive"))] let must_use = quote!(#[must_use = "Must set return value when not using the \"nightly\" feature"
]); #[cfg(feature = "nightly_derive")] let must_use = quote!();
let substruct_obj = iflet Some(trait_) = &self.trait_ { let ident = format_ident!("{trait_}_expectations");
quote!(#ident.)
} else {
quote!()
}; let docstr = format!("Create an [`Expectation`]({}/{}/struct.Expectation.html) for mocking the `{}` method",
modname, self.inner_mod_ident(), funcname);
quote!( #must_use #[doc = #docstr] #(#attrs)* #visfn#expect_ident#ig(&mutself)
-> &mut#modname::#expectation_obj #wc
{ self.#substruct_obj#name.expect #tbf()
}
)
}
/// Return the name of this function's expecation object fn expectation_obj(&self, self_args: Option<&PathArguments>)
-> impl ToTokens
{ let inner_mod_ident = self.inner_mod_ident(); iflet Some(PathArguments::AngleBracketed(abga)) = self_args { // staticize any lifetimes that might be present in the Expectation // object but not in the self args. These come from the method's // return type. letmut abga2 = abga.clone(); for _ inself.egenerics.lifetimes() { let lt = Lifetime::new("'static", Span::call_site()); let la = GenericArgument::Lifetime(lt);
abga2.args.insert(0, la);
}
assert!(!self.is_method_generic(), "specific impls with generic methods are TODO");
quote!(#inner_mod_ident::Expectation #abga2)
} else { // staticize any lifetimes. This is necessary for methods that // return non-static types, because the Expectation itself must be // 'static. let segenerics = staticize(&self.egenerics); let (_, tg, _) = segenerics.split_for_impl();
quote!(#inner_mod_ident::Expectation #tg)
}
}
/// Return the name of this function's expecations object pubfn expectations_obj(&self) -> impl ToTokens { let inner_mod_ident = self.inner_mod_ident(); ifself.is_method_generic() {
quote!(#inner_mod_ident::GenericExpectations)
} else {
quote!(#inner_mod_ident::Expectations)
}
}
pubfn field_definition(&self, modname: Option<&Ident>) -> TokenStream { let name = self.name(); let attrs = AttrFormatter::new(&self.attrs)
.doc(false)
.format(); let expectations_obj = &self.expectations_obj(); ifself.is_method_generic() {
quote!(#(#attrs)* #name: #modname::#expectations_obj)
} else { // staticize any lifetimes. This is necessary for methods that // return non-static types, because the Expectation itself must be // 'static. let segenerics = staticize(&self.egenerics); let (_, tg, _) = segenerics.split_for_impl();
quote!(#(#attrs)* #name: #modname::#expectations_obj#tg)
}
}
/// Human-readable name of the mock function fn funcname(&self) -> String { iflet Some(si) = &self.struct_ {
format!("{}::{}", si, self.name())
} else {
format!("{}", self.name())
}
}
/// Holds parts of the expectation that are common for all output types struct Common<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for Common<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let argnames = &self.f.argnames; let predty = &self.f.predty; let hrtb = self.f.hrtb(); let funcname = self.f.funcname(); let (ig, tg, wc) = self.f.cgenerics.split_for_impl(); let lg = lifetimes_to_generics(&self.f.alifetimes); let refpredty = &self.f.refpredty; let with_generics_idents = (0..self.f.predty.len())
.map(|i| format_ident!("MockallMatcher{i}"))
.collect::<Vec<_>>(); let with_generics = with_generics_idents.iter()
.zip(self.f.predty.iter())
.map(|(id, mt)|
quote!(#id: #hrtb ::mockall::Predicate<#mt> + Send + 'static, )
).collect::<TokenStream>(); let with_args = self.f.argnames.iter()
.zip(with_generics_idents.iter())
.map(|(argname, id)| quote!(#argname: #id, ))
.collect::<TokenStream>(); let boxed_withargs = argnames.iter()
.map(|aa| quote!(Box::new(#aa), ))
.collect::<TokenStream>(); let with_method = ifself.f.concretize {
quote!( // No `with` method when concretizing generics
)
} else {
quote!( fn with<#with_generics>(&mutself, #with_args)
{ letmut __mockall_guard = self.matcher.lock().unwrap();
*__mockall_guard.deref_mut() =
Matcher::Pred(Box::new((#boxed_withargs)));
}
)
};
quote!( /// Holds the stuff that is independent of the output type struct Common #ig#wc {
matcher: Mutex<Matcher #tg>,
seq_handle: Option<::mockall::SeqHandle>,
times: ::mockall::Times
}
impl#ig std::default::Default for Common #tg#wc
{ fn default() -> Self {
Common {
matcher: Mutex::new(Matcher::default()),
seq_handle: None,
times: ::mockall::Times::default()
}
}
}
/// Expect this expectation to be called any number of times /// contained with the given range. fn times<MockallR>(&mutself, __mockall_r: MockallR) where MockallR: Into<::mockall::TimesRange>
{ self.times.times(__mockall_r)
}
impl#ig Drop for Common #tg#wc { fn drop(&mutself) { if !::std::thread::panicking() { let desc = std::format!( "{}", self.matcher.lock().unwrap()); matchself.times.is_satisfied() {
::mockall::ExpectedCalls::TooFew => {
panic!("{}: Expectation({}) called {} time(s) which is fewer than expected {}", #funcname,
desc, self.times.count(), self.times.minimum());
},
::mockall::ExpectedCalls::TooMany => {
panic!("{}: Expectation({}) called {} time(s) which is more than expected {}", #funcname,
desc, self.times.count(), self.times.maximum());
},
_ => ()
}
}
}
}
).to_tokens(tokens);
}
}
/// Generates methods that are common for all Expectation types struct CommonExpectationMethods<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for CommonExpectationMethods<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let argnames = &self.f.argnames; let hrtb = self.f.hrtb(); let lg = lifetimes_to_generics(&self.f.alifetimes); let predty = &self.f.predty; let with_generics_idents = (0..self.f.predty.len())
.map(|i| format_ident!("MockallMatcher{i}"))
.collect::<Vec<_>>(); let with_generics = with_generics_idents.iter()
.zip(self.f.predty.iter())
.map(|(id, mt)|
quote!(#id: #hrtb ::mockall::Predicate<#mt> + Send + 'static, )
).collect::<TokenStream>(); let with_args = self.f.argnames.iter()
.zip(with_generics_idents.iter())
.map(|(argname, id)| quote!(#argname: #id, ))
.collect::<TokenStream>(); let v = &self.f.privmod_vis; let with_method = ifself.f.concretize {
quote!( // No `with` method when concretizing generics
)
} else {
quote!( /// Set matching criteria for this Expectation. /// /// The matching predicate can be anything implemening the /// [`Predicate`](../../../mockall/trait.Predicate.html) trait. Only /// one matcher can be set per `Expectation` at a time. #vfn with<#with_generics>(&mutself, #with_args) -> &mutSelf
{ self.common.with(#(#argnames, )*); self
}
)
};
quote!( /// Add this expectation to a /// [`Sequence`](../../../mockall/struct.Sequence.html). #vfn in_sequence(&mutself, __mockall_seq: &mut ::mockall::Sequence)
-> &mutSelf
{ self.common.in_sequence(__mockall_seq); self
}
/// Expect this expectation to be called exactly once. Shortcut for /// [`times(1)`](#method.times). #vfn once(&mutself) -> &mutSelf { self.times(1)
}
/// Restrict the number of times that that this method may be called. /// /// The argument may be: /// * A fixed number: `.times(4)` /// * Various types of range: /// - `.times(5..10)` /// - `.times(..10)` /// - `.times(5..)` /// - `.times(5..=10)` /// - `.times(..=10)` /// * The wildcard: `.times(..)` #vfn times<MockallR>(&mutself, __mockall_r: MockallR) -> &e='color:red'>mutSelf where MockallR: Into<::mockall::TimesRange>
{ self.common.times(__mockall_r); self
}
#with_method
/// Set a matching function for this Expectation. /// /// This is equivalent to calling [`with`](#method.with) with a /// function argument, like `with(predicate::function(f))`. #vfn withf<MockallF>(&mutself, __mockall_f: MockallF) -> &e='color:red'>mutSelf where MockallF: #hrtbFn(#(&#predty, )*)
-> bool + Send + 'static
{ self.common.withf(__mockall_f); self
}
/// Single-threaded version of [`withf`](#method.withf). /// Can be used when the argument type isn't `Send`. #vfn withf_st<MockallF>(&mutself, __mockall_f: MockallF) -> &tyle='color:red'>mutSelf where MockallF: #hrtbFn(#(&#predty, )*)
-> bool + 'static
{ self.common.withf_st(__mockall_f); self
}
).to_tokens(tokens);
}
}
/// Holds the moethods of the Expectations object that are common for all /// Expectation types struct CommonExpectationsMethods<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for CommonExpectationsMethods<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let (ig, tg, wc) = self.f.egenerics.split_for_impl(); let v = &self.f.privmod_vis;
quote!( /// A collection of [`Expectation`](struct.Expectations.html) /// objects. Users will rarely if ever use this struct directly. #[doc(hidden)] #vstruct Expectations #ig ( Vec<Expectation #tg>) #wc;
impl#ig Expectations #tg#wc { /// Verify that all current expectations are satisfied and clear /// them. #vfn checkpoint(&mutself) -> std::vec::Drain<Expectation #tg>
{ self.0.drain(..)
}
/// Create a new expectation for this method. #vfn expect(&mutself) -> &mut Expectation #tg
{ self.0.push(Expectation::default()); let __mockall_l = self.0.len();
&mutself.0[__mockall_l - 1]
}
/// The ExpectationGuard structure for static methods with no generic types struct ExpectationGuardCommonMethods<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for ExpectationGuardCommonMethods<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if !self.f.is_static { return;
}
let argnames = &self.f.argnames; let argty = &self.f.argty; let (_, tg, _) = self.f.egenerics.split_for_impl(); let keyid = gen_keyid(&self.f.egenerics); let expectations = ifself.f.is_expectation_generic() {
quote!(self.guard
.store
.get_mut(&::mockall::Key::new::#keyid())
.unwrap()
.downcast_mut::<Expectations #tg>()
.unwrap())
} else {
quote!(self.guard)
}; let hrtb = self.f.hrtb(); let output = &self.f.output; let predty = &self.f.predty; let with_generics_idents = (0..self.f.predty.len())
.map(|i| format_ident!("MockallMatcher{i}"))
.collect::<Vec<_>>(); let with_generics = with_generics_idents.iter()
.zip(self.f.predty.iter())
.map(|(id, mt)|
quote!(#id: #hrtb ::mockall::Predicate<#mt> + Send + 'static, )
).collect::<TokenStream>(); let with_args = self.f.argnames.iter()
.zip(with_generics_idents.iter())
.map(|(argname, id)| quote!(#argname: #id, ))
.collect::<TokenStream>(); let v = &self.f.privmod_vis; let with_method = ifself.f.concretize {
quote!()
} else {
quote!( /// Just like /// [`Expectation::with`](struct.Expectation.html#method.with) #vfn with<#with_generics> (&mutself, #with_args)
-> &mut Expectation #tg
{ #expectations.0[self.i].with(#(#argnames, )*)
}
)
};
quote!( /// Just like /// [`Expectation::in_sequence`](struct.Expectation.html#method.in_sequence) #vfn in_sequence(&mutself,
__mockall_seq: &mut ::mockall::Sequence)
-> &mut Expectation #tg
{ #expectations.0[self.i].in_sequence(__mockall_seq)
}
/// Just like /// [`Expectation::never`](struct.Expectation.html#method.never) #vfn never(&mutself) -> &mut Expectation #tg { #expectations.0[self.i].never()
}
/// Just like /// [`Expectation::once`](struct.Expectation.html#method.once) #vfn once(&mutself) -> &mut Expectation #tg { #expectations.0[self.i].once()
}
/// Just like /// [`Expectation::return_const`](struct.Expectation.html#method.return_const) #vfn return_const<MockallOutput>
(&mutself, __mockall_c: MockallOutput)
-> &mut Expectation #tg where MockallOutput: Clone + Into<#output> + Send + 'static
{ #expectations.0[self.i].return_const(__mockall_c)
}
/// Just like /// [`Expectation::return_const_st`](struct.Expectation.html#method.return_const_st) #vfn return_const_st<MockallOutput>
(&mutself, __mockall_c: MockallOutput)
-> &mut Expectation #tg where MockallOutput: Clone + Into<#output> + 'static
{ #expectations.0[self.i].return_const_st(__mockall_c)
}
/// Just like /// [`Expectation::returning`](struct.Expectation.html#method.returning) #vfn returning<MockallF>(&mutself, __mockall_f: MockallF)
-> &mut Expectation #tg where MockallF: #hrtb FnMut(#(#argty, )*)
-> #output + Send + 'static
{ #expectations.0[self.i].returning(__mockall_f)
}
/// Just like /// [`Expectation::return_once`](struct.Expectation.html#method.return_once) #vfn return_once<MockallF>(&mutself, __mockall_f: MockallF)
-> &mut Expectation #tg where MockallF: #hrtb FnOnce(#(#argty, )*)
-> #output + Send + 'static
{ #expectations.0[self.i].return_once(__mockall_f)
}
/// Just like /// [`Expectation::return_once_st`](struct.Expectation.html#method.return_once_st) #vfn return_once_st<MockallF>(&mutself, __mockall_f: MockallF)
-> &mut Expectation #tg where MockallF: #hrtb FnOnce(#(#argty, )*)
-> #output + 'static
{ #expectations.0[self.i].return_once_st(__mockall_f)
}
/// Just like /// [`Expectation::returning_st`](struct.Expectation.html#method.returning_st) #vfn returning_st<MockallF>(&mutself, __mockall_f: MockallF)
-> &mut Expectation #tg where MockallF: #hrtb FnMut(#(#argty, )*)
-> #output + 'static
{ #expectations.0[self.i].returning_st(__mockall_f)
}
/// Just like /// [`Expectation::times`](struct.Expectation.html#method.times) #vfn times<MockallR>(&mutself, __mockall_r: MockallR)
-> &mut Expectation #tg where MockallR: Into<::mockall::TimesRange>
{ #expectations.0[self.i].times(__mockall_r)
}
#with_method
/// Just like /// [`Expectation::withf`](struct.Expectation.html#method.withf) #vfn withf<MockallF>(&mutself, __mockall_f: MockallF)
-> &mut Expectation #tg where MockallF: #hrtbFn(#(&#predty, )*)
-> bool + Send + 'static
{ #expectations.0[self.i].withf(__mockall_f)
}
/// Just like /// [`Expectation::withf_st`](struct.Expectation.html#method.withf_st) #vfn withf_st<MockallF>(&mutself, __mockall_f: MockallF)
-> &mut Expectation #tg where MockallF: #hrtbFn(#(&#predty, )*)
-> bool + 'static
{ #expectations.0[self.i].withf_st(__mockall_f)
}
).to_tokens(tokens);
}
}
/// The ExpectationGuard structure for static methods with no generic types struct ConcreteExpectationGuard<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for ConcreteExpectationGuard<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if !self.f.is_static { return;
}
let common_methods = ExpectationGuardCommonMethods{f: self.f}; let (_, tg, _) = self.f.egenerics.split_for_impl(); let ltdef = LifetimeParam::new(
Lifetime::new("'__mockall_lt", Span::call_site())
); letmut e_generics = self.f.egenerics.clone();
e_generics.lt_token.get_or_insert(<Token![<]>::default());
e_generics.params.push(GenericParam::Lifetime(ltdef));
e_generics.gt_token.get_or_insert(<Token![>]>::default()); let (e_ig, e_tg, e_wc) = e_generics.split_for_impl(); let (ei_ig, _, _) = e_generics.split_for_impl(); let v = &self.f.privmod_vis;
quote!(
::mockall::lazy_static! { #[doc(hidden)] #vstaticref EXPECTATIONS:
::std::sync::Mutex<Expectations #tg> =
::std::sync::Mutex::new(Expectations::new());
} /// Like an [`&Expectation`](struct.Expectation.html) but /// protected by a Mutex guard. Useful for mocking static /// methods. Forwards accesses to an `Expectation` object. // We must return the MutexGuard to the caller so he can // configure the expectation. But we can't bundle both the // guard and the &Expectation into the same structure; the // borrow checker won't let us. Instead we'll record the // expectation's position within the Expectations vector so we // can proxy its methods. // // ExpectationGuard is only defined for expectations that return // 'static return types. #vstruct ExpectationGuard #e_ig#e_wc {
guard: MutexGuard<'__mockall_lt, Expectations #tg>,
i: usize
}
#[allow(clippy::unused_unit)] impl#ei_ig ExpectationGuard #e_tg#e_wc
{ // Should only be called from the mockall_derive generated // code #[doc(hidden)] #vfn new(mut __mockall_guard: MutexGuard<'__mockall_lt, Expectations #tg>)
-> Self
{
__mockall_guard.expect(); // Drop the &Expectation let __mockall_i = __mockall_guard.0.len() - 1;
ExpectationGuard{guard: __mockall_guard, i: __mockall_i}
}
#common_methods
}
).to_tokens(tokens);
}
}
/// The ExpectationGuard structure for static methods with generic types struct GenericExpectationGuard<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for GenericExpectationGuard<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if !self.f.is_static { return;
}
let common_methods = ExpectationGuardCommonMethods{f: self.f}; let (_, tg, _) = self.f.egenerics.split_for_impl(); let keyid = gen_keyid(&self.f.egenerics); let ltdef = LifetimeParam::new(
Lifetime::new("'__mockall_lt", Span::call_site())
); letmut egenerics = self.f.egenerics.clone();
egenerics.lt_token.get_or_insert(<Token![<]>::default());
egenerics.params.push(GenericParam::Lifetime(ltdef));
egenerics.gt_token.get_or_insert(<Token![>]>::default()); let (e_ig, e_tg, e_wc) = egenerics.split_for_impl(); let fn_params = &self.f.fn_params; let tbf = tg.as_turbofish(); let v = &self.f.privmod_vis;
quote!(
::mockall::lazy_static! { #vstaticref EXPECTATIONS:
::std::sync::Mutex<GenericExpectations> =
::std::sync::Mutex::new(GenericExpectations::new());
} /// Like an [`&Expectation`](struct.Expectation.html) but /// protected by a Mutex guard. Useful for mocking static /// methods. Forwards accesses to an `Expectation` object. #vstruct ExpectationGuard #e_ig#e_wc{
guard: MutexGuard<'__mockall_lt, GenericExpectations>,
i: usize,
_phantom: ::std::marker::PhantomData<(#(#fn_params,)*)>,
}
#[allow(clippy::unused_unit)] impl#e_ig ExpectationGuard #e_tg#e_wc
{ // Should only be called from the mockall_derive generated // code #[doc(hidden)] #vfn new(mut __mockall_guard: MutexGuard<'__mockall_lt, GenericExpectations>)
-> Self
{ let __mockall_ee: &mut Expectations #tg =
__mockall_guard.store.entry(
::mockall::Key::new::#keyid()
).or_insert_with(|| Box::new(Expectations #tbf ::new()))
.downcast_mut()
.unwrap();
__mockall_ee.expect(); // Drop the &Expectation let __mockall_i = __mockall_ee.0.len() - 1;
ExpectationGuard{guard: __mockall_guard, i: __mockall_i,
_phantom: ::std::marker::PhantomData}
}
#common_methods
}
).to_tokens(tokens);
}
}
/// Generates Context, which manages the context for expectations of static /// methods. struct Context<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for Context<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if !self.f.is_static { return;
}
let ltdef = LifetimeParam::new(
Lifetime::new("'__mockall_lt", Span::call_site())
); letmut egenerics = self.f.egenerics.clone();
egenerics.lt_token.get_or_insert(<Token![<]>::default());
egenerics.params.push(GenericParam::Lifetime(ltdef));
egenerics.gt_token.get_or_insert(<Token![>]>::default()); let (_, e_tg, _) = egenerics.split_for_impl(); let (ty_ig, ty_tg, ty_wc) = self.f.type_generics.split_for_impl(); letmut meth_generics = self.f.call_generics.clone(); let ltdef = LifetimeParam::new(
Lifetime::new("'__mockall_lt", Span::call_site())
);
meth_generics.params.push(GenericParam::Lifetime(ltdef)); let (meth_ig, _meth_tg, meth_wc) = meth_generics.split_for_impl(); let ctx_fn_params = self.f.struct_generics.type_params()
.map(|tp| tp.ident.clone())
.collect::<Punctuated::<Ident, Token![,]>>(); let v = &self.f.privmod_vis;
#[cfg(not(feature = "nightly_derive"))] let must_use = quote!(#[must_use = "Must set return value when not using the \"nightly\" feature"
]); #[cfg(feature = "nightly_derive")] let must_use = quote!();
quote!( /// Manages the context for expectations of static methods. /// /// Expectations on this method will be validated and cleared when /// the `Context` object drops. The `Context` object does *not* /// provide any form of synchronization, so multiple tests that set /// expectations on the same static method must provide their own. #[must_use = "Context only serves to create expectations" ] #vstruct Context #ty_ig#ty_wc { // Prevent "unused type parameter" errors // Surprisingly, PhantomData<Fn(generics)> is Send even if // generics are not, unlike PhantomData<generics>
_phantom: ::std::marker::PhantomData< Box<dynFn(#ctx_fn_params) + Send>
>
} impl#ty_ig Context #ty_tg#ty_wc { /// Verify that all current expectations for this method are /// satisfied and clear them. #vfn checkpoint(&self) { Self::do_checkpoint()
} #[doc(hidden)] #vfn do_checkpoint() { let __mockall_timeses = EXPECTATIONS
.lock()
.unwrap()
.checkpoint()
.collect::<Vec<_>>();
}
/// Create a new expectation for this method. #must_use #vfn expect #meth_ig ( &self,) -> ExpectationGuard #e_tg #meth_wc
{
ExpectationGuard::new(EXPECTATIONS.lock().unwrap())
}
} impl#ty_ig Default for Context #ty_tg#ty_wc { fn default() -> Self {
Context {_phantom: std::marker::PhantomData}
}
} impl#ty_ig Drop for Context #ty_tg#ty_wc { fn drop(&mutself) { if ::std::thread::panicking() { // Drain all expectations so other tests can run with a // blank slate. But ignore errors so we don't // double-panic. let _ = EXPECTATIONS
.lock()
.map(|mut g| g.checkpoint().collect::<Vec<_>>());
} else { // Verify expectations are satisfied Self::do_checkpoint();
}
}
}
).to_tokens(tokens);
}
}
struct Matcher<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for Matcher<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let (ig, tg, wc) = self.f.cgenerics.split_for_impl(); let argnames = &self.f.argnames; let braces = argnames.iter()
.fold(String::new(), |mut acc, _argname| { if acc.is_empty() {
acc.push_str("{}");
} else {
acc.push_str(", {}");
}
acc
}); let fn_params = &self.f.fn_params; let hrtb = self.f.hrtb(); let indices = (0..argnames.len())
.map(|i| {
syn::Index::from(i)
}).collect::<Vec<_>>(); let lg = lifetimes_to_generics(&self.f.alifetimes); let pred_matches = argnames.iter().enumerate()
.map(|(i, argname)| { let idx = syn::Index::from(i);
quote!(__mockall_pred.#idx.eval(#argname),)
}).collect::<TokenStream>(); let preds = ifself.f.concretize {
quote!(())
} else { self.f.predty.iter()
.map(|t| quote!(Box<dyn#hrtb ::mockall::Predicate<#t> + Send>,))
.collect::<TokenStream>()
}; let predty = &self.f.predty; let refpredty = &self.f.refpredty; let predmatches_body = ifself.f.concretize {
quote!()
} else {
quote!(Matcher::Pred(__mockall_pred) => [#pred_matches].iter().all(|__mockall_x| *__mockall_x),)
}; let preddbg_body = ifself.f.concretize {
quote!()
} else {
quote!(
Matcher::Pred(__mockall_p) => {
write!(__mockall_fmt, #braces, #(__mockall_p.#indices,)*)
}
)
};
quote!( enum Matcher #ig#wc {
Always,
Func(Box<dyn#hrtbFn(#(#refpredty, )*) -> bool + Send>), // Version of Matcher::Func for closures that aren't Send
FuncSt(::mockall::Fragile<Box<dyn#hrtbFn(#(#refpredty, )*) -> bool>>),
Pred(Box<(#preds)>), // Prevent "unused type parameter" errors // Surprisingly, PhantomData<Fn(generics)> is Send even if // generics are not, unlike PhantomData<generics>
_Phantom(Box<dynFn(#(#fn_params,)*) + Send>)
} impl#ig Matcher #tg#wc { #[allow(clippy::ptr_arg)] fn matches #lg (&self, #(#argnames: &#predty, )*) -> bool { matchself {
Matcher::Always => true,
Matcher::Func(__mockall_f) =>
__mockall_f(#(#argnames, )*),
Matcher::FuncSt(__mockall_f) =>
(__mockall_f.get())(#(#argnames, )*), #predmatches_body
_ => unreachable!()
}
}
}
impl<'a> ToTokens for RefRfunc<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let fn_params = &self.f.fn_params; let (ig, tg, wc) = self.f.egenerics.split_for_impl(); let lg = lifetimes_to_generics(&self.f.alifetimes); let owned_output = &self.f.owned_output;
#[cfg(not(feature = "nightly_derive"))] let default_err_msg = "Returning default values requires the \"nightly\" feature"; #[cfg(feature = "nightly_derive")] let default_err_msg = "Can only return default values for types that impl std::Default";
quote!( enum Rfunc #ig#wc {
Default(Option<#owned_output>), Const(#owned_output), // Prevent "unused type parameter" errors Surprisingly, // PhantomData<Fn(generics)> is Send even if generics are not, // unlike PhantomData<generics>
_Phantom(Mutex<Box<dynFn(#(#fn_params,)*) + Send>>)
}
impl#ig std::default::Default for Rfunc #tg#wc
{ fn default() -> Self { use ::mockall::ReturnDefault;
Rfunc::Default(::mockall::DefaultReturner::<#owned_output>
::maybe_return_default())
}
}
).to_tokens(tokens);
}
}
struct RefMutRfunc<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for RefMutRfunc<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let argnames = &self.f.argnames; let argty = &self.f.argty; let fn_params = &self.f.fn_params; let (ig, tg, wc) = self.f.egenerics.split_for_impl(); let lg = lifetimes_to_generics(&self.f.alifetimes); let owned_output = &self.f.owned_output; let output = &self.f.output;
#[cfg(not(feature = "nightly_derive"))] let default_err_msg = "Returning default values requires the \"nightly\" feature"; #[cfg(feature = "nightly_derive")] let default_err_msg = "Can only return default values for types that impl std::Default";
quote!( #[allow(clippy::unused_unit)] enum Rfunc #ig#wc {
Default(Option<#owned_output>), Mut((Box<dyn FnMut(#(#argty, )*) -> #owned_output + Send + Sync>),
Option<#owned_output>), // Version of Rfunc::Mut for closures that aren't Send
MutSt((::mockall::Fragile< Box<dyn FnMut(#(#argty, )*) -> #owned_output >>
), Option<#owned_output>
),
Var(#owned_output), // Prevent "unused type parameter" errors Surprisingly, // PhantomData<Fn(generics)> is Send even if generics are not, // unlike PhantomData<generics>
_Phantom(Mutex<Box<dynFn(#(#fn_params,)*) + Send>>)
}
impl#ig std::default::Default for Rfunc #tg#wc
{ fn default() -> Self { use ::mockall::ReturnDefault;
Rfunc::Default(::mockall::DefaultReturner::<#owned_output>
::maybe_return_default())
}
}
).to_tokens(tokens);
}
}
struct StaticRfunc<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for StaticRfunc<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let argnames = &self.f.argnames; let argty = &self.f.argty; let fn_params = &self.f.fn_params; let (ig, tg, wc) = self.f.egenerics.split_for_impl(); let hrtb = self.f.hrtb(); let lg = lifetimes_to_generics(&self.f.alifetimes); let output = &self.f.output;
quote!( #[allow(clippy::unused_unit)] enum Rfunc #ig#wc {
Default, // Indicates that a `return_once` expectation has already // returned
Expired, Mut(Box<dyn#hrtb FnMut(#(#argty, )*) -> #output + Send>), // Version of Rfunc::Mut for closures that aren't Send
MutSt(::mockall::Fragile< Box<dyn#hrtb FnMut(#(#argty, )*) -> #output >>
),
Once(Box<dyn#hrtb FnOnce(#(#argty, )*) -> #output + Send>), // Version of Rfunc::Once for closure that aren't Send
OnceSt(::mockall::Fragile< Box<dyn#hrtb FnOnce(#(#argty, )*) -> #output>>
), // Prevent "unused type parameter" errors Surprisingly, // PhantomData<Fn(generics)> is Send even if generics are not, // unlike PhantomData<generics>
_Phantom(Box<dynFn(#(#fn_params,)*) + Send>)
}
/// An expectation type for functions that take a &self and return a reference struct RefExpectation<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for RefExpectation<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let argnames = &self.f.argnames; let argty = &self.f.argty; let common_methods = CommonExpectationMethods{f: self.f}; let desc = self.f.desc(); let funcname = self.f.funcname(); let (ig, tg, wc) = self.f.egenerics.split_for_impl();
let (_, common_tg, _) = self.f.cgenerics.split_for_impl(); let lg = lifetimes_to_generics(&self.f.alifetimes); let output = &self.f.output; let owned_output = &self.f.owned_output; let v = &self.f.privmod_vis;
quote!( /// Expectation type for methods taking a `&self` argument and /// returning immutable references. This is the type returned by /// the `expect_*` methods. #vstruct Expectation #ig#wc {
common: Common #common_tg,
rfunc: Rfunc #tg,
}
#[allow(clippy::unused_unit)] impl#ig Expectation #tg#wc { /// Call this [`Expectation`] as if it were the real method. #vfn call #lg (&self, #(#argnames: #argty, )*) -> #output
{ use ::mockall::{ViaDebug, ViaNothing}; self.common.call(&#desc); self.rfunc.call().unwrap_or_else(|m| { let desc = std::format!( "{}", self.common.matcher.lock().unwrap());
panic!("{}: Expectation({}) {}", #funcname, desc,
m);
})
}
/// Return a reference to a constant value from the `Expectation` #vfn return_const(&mutself, __mockall_o: #owned_output)
-> &mutSelf
{ self.rfunc = Rfunc::Const(__mockall_o); self
}
/// For methods that take &mut self and return a reference struct RefMutExpectation<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for RefMutExpectation<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let common_methods = CommonExpectationMethods{f: self.f}; let argnames = &self.f.argnames; let argty = &self.f.argty; let desc = self.f.desc(); let funcname = self.f.funcname(); let (ig, tg, wc) = self.f.egenerics.split_for_impl(); let (_, common_tg, _) = self.f.cgenerics.split_for_impl(); let lg = lifetimes_to_generics(&self.f.alifetimes); let owned_output = &self.f.owned_output; let v = &self.f.privmod_vis;
quote!( /// Expectation type for methods taking a `&mut self` argument and /// returning references. This is the type returned by the /// `expect_*` methods. #vstruct Expectation #ig#wc {
common: Common #common_tg,
rfunc: Rfunc #tg
}
#[allow(clippy::unused_unit)] impl#ig Expectation #tg#wc { /// Simulating calling the real method for this expectation #vfn call_mut #lg (&mutself, #(#argnames: #argty, )*)
-> &mut#owned_output
{ use ::mockall::{ViaDebug, ViaNothing}; self.common.call(&#desc); let desc = std::format!( "{}", self.common.matcher.lock().unwrap()); self.rfunc.call_mut(#(#argnames, )*).unwrap_or_else(|m| {
panic!("{}: Expectation({}) {}", #funcname, desc,
m);
})
}
/// Convenience method that can be used to supply a return value /// for a `Expectation`. The value will be returned by mutable /// reference. #vfn return_var(&mutself, __mockall_o: #owned_output) -> &yle='color:red'>mutSelf
{ self.rfunc = Rfunc::Var(__mockall_o); self
}
/// Supply a closure that the `Expectation` will use to create its /// return value. The return value will be returned by mutable /// reference. #vfn returning<MockallF>(&mutself, __mockall_f: MockallF)
-> &mutSelf where MockallF: FnMut(#(#argty, )*) -> #owned_output + Send + Sync + 'static
{ self.rfunc = Rfunc::Mut(Box::new(__mockall_f), None); self
}
/// Single-threaded version of [`returning`](#method.returning). /// Can be used when the argument or return type isn't `Send`. #vfn returning_st<MockallF>(&mutself, __mockall_f: MockallF)
-> &mutSelf where MockallF: FnMut(#(#argty, )*) -> #owned_output + 'static
{ self.rfunc = Rfunc::MutSt(
::mockall::Fragile::new(Box::new(__mockall_f)), None); self
}
/// An expectation type for functions return a `'static` value struct StaticExpectation<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for StaticExpectation<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let common_methods = CommonExpectationMethods{f: self.f}; let argnames = &self.f.argnames; let argty = &self.f.argty; let desc = self.f.desc(); let hrtb = self.f.hrtb(); let funcname = self.f.funcname(); let (ig, tg, wc) = self.f.egenerics.split_for_impl(); let (_, common_tg, _) = self.f.cgenerics.split_for_impl(); let lg = lifetimes_to_generics(&self.f.alifetimes); let output = &self.f.output; let v = &self.f.privmod_vis;
quote!( /// Expectation type for methods that return a `'static` type. /// This is the type returned by the `expect_*` methods. #vstruct Expectation #ig#wc {
common: Common #common_tg,
rfunc: Mutex<Rfunc #tg>,
}
#[allow(clippy::unused_unit)] impl#ig Expectation #tg#wc { /// Call this [`Expectation`] as if it were the real method. #[doc(hidden)] #vfn call #lg (&self, #(#argnames: #argty, )* ) -> #output
{ use ::mockall::{ViaDebug, ViaNothing}; self.common.call(&#desc); self.rfunc.lock().unwrap().call_mut(#(#argnames, )*)
.unwrap_or_else(|message| { let desc = std::format!( "{}", self.common.matcher.lock().unwrap());
panic!("{}: Expectation({}) {}", #funcname, desc,
message);
})
}
/// Return a constant value from the `Expectation` /// /// The output type must be `Clone`. The compiler can't always /// infer the proper type to use with this method; you will /// usually need to specify it explicitly. i.e. /// `return_const(42i32)` instead of `return_const(42)`. // We must use Into<#output> instead of #output because where // clauses don't accept equality constraints. // https://github.com/rust-lang/rust/issues/20041 #[allow(unused_variables)] #vfn return_const<MockallOutput>(&mutself,
__mockall_c: MockallOutput)
-> &mutSelf where MockallOutput: Clone + Into<#output> + Send + 'static
{ self.returning(move |#(#argnames, )*| __mockall_c.clone().into())
}
/// Single-threaded version of /// [`return_const`](#method.return_const). This is useful for /// return types that are not `Send`. /// /// The output type must be `Clone`. The compiler can't always /// infer the proper type to use with this method; you will /// usually need to specify it explicitly. i.e. /// `return_const(42i32)` instead of `return_const(42)`. /// /// It is a runtime error to call the mock method from a /// different thread than the one that originally called this /// method. // We must use Into<#output> instead of #output because where // clauses don't accept equality constraints. // https://github.com/rust-lang/rust/issues/20041 #[allow(unused_variables)] #vfn return_const_st<MockallOutput>(&mutself,
__mockall_c: MockallOutput)
-> &mutSelf where MockallOutput: Clone + Into<#output> + 'static
{ self.returning_st(move |#(#argnames, )*| __mockall_c.clone().into())
}
/// Supply an `FnOnce` closure that will provide the return /// value for this Expectation. This is useful for return types /// that aren't `Clone`. It will be an error to call this /// method multiple times. #vfn return_once<MockallF>(&mutself, __mockall_f: MockallF)
-> &mutSelf where MockallF: #hrtb FnOnce(#(#argty, )*)
-> #output + Send + 'static
{
{ letmut __mockall_guard = self.rfunc.lock().unwrap();
*__mockall_guard.deref_mut() =
Rfunc::Once(Box::new(__mockall_f));
} self
}
/// Single-threaded version of /// [`return_once`](#method.return_once). This is useful for /// return types that are neither `Send` nor `Clone`. /// /// It is a runtime error to call the mock method from a /// different thread than the one that originally called this /// method. It is also a runtime error to call the method more /// than once. #vfn return_once_st<MockallF>(&mutself, __mockall_f:
MockallF) -> &mutSelf where MockallF: #hrtb FnOnce(#(#argty, )*)
-> #output + 'static
{
{ letmut __mockall_guard = self.rfunc.lock().unwrap();
*__mockall_guard.deref_mut() = Rfunc::OnceSt(
::mockall::Fragile::new(Box::new(__mockall_f)));
} self
}
/// Supply a closure that will provide the return value for this /// `Expectation`. The method's arguments are passed to the /// closure by value. #vfn returning<MockallF>(&mutself, __mockall_f: MockallF)
-> &mutSelf where MockallF: #hrtb FnMut(#(#argty, )*)
-> #output + Send + 'static
{
{ letmut __mockall_guard = self.rfunc.lock().unwrap();
*__mockall_guard.deref_mut() =
Rfunc::Mut(Box::new(__mockall_f));
} self
}
/// Single-threaded version of [`returning`](#method.returning). /// Can be used when the argument or return type isn't `Send`. /// /// It is a runtime error to call the mock method from a /// different thread than the one that originally called this /// method. #vfn returning_st<MockallF>(&mutself, __mockall_f: MockallF)
-> &mutSelf where MockallF: #hrtb FnMut(#(#argty, )*)
-> #output + 'static
{
{ letmut __mockall_guard = self.rfunc.lock().unwrap();
*__mockall_guard.deref_mut() = Rfunc::MutSt(
::mockall::Fragile::new(Box::new(__mockall_f)));
} self
}
/// An collection of RefExpectation's struct RefExpectations<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for RefExpectations<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let common_methods = CommonExpectationsMethods{f: self.f}; let argnames = &self.f.argnames; let argty = &self.f.argty; let (ig, tg, wc) = self.f.egenerics.split_for_impl(); let lg = lifetimes_to_generics(&self.f.alifetimes); let output = &self.f.output; let predexprs = &self.f.predexprs; let v = &self.f.privmod_vis;
quote!( #common_methods impl#ig Expectations #tg#wc { /// Simulate calling the real method. Every current expectation /// will be checked in FIFO order and the first one with /// matching arguments will be used. #vfn call #lg (&self, #(#argnames: #argty, )* )
-> Option<#output>
{ self.0.iter()
.find(|__mockall_e|
__mockall_e.matches(#(#predexprs, )*) &&
(!__mockall_e.is_done() || self.0.len() == 1))
.map(move |__mockall_e|
__mockall_e.call(#(#argnames),*)
)
}
}
).to_tokens(tokens);
}
}
/// An collection of RefMutExpectation's struct RefMutExpectations<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for RefMutExpectations<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let common_methods = CommonExpectationsMethods{f: self.f}; let argnames = &self.f.argnames; let argty = &self.f.argty; let (ig, tg, wc) = self.f.egenerics.split_for_impl(); let lg = lifetimes_to_generics(&self.f.alifetimes); let output = &self.f.output; let predexprs = &self.f.predexprs; let v = &self.f.privmod_vis;
quote!( #common_methods impl#ig Expectations #tg#wc { /// Simulate calling the real method. Every current expectation /// will be checked in FIFO order and the first one with /// matching arguments will be used. #vfn call_mut #lg (&mutself, #(#argnames: #argty, )* )
-> Option<#output>
{ let __mockall_n = self.0.len(); self.0.iter_mut()
.find(|__mockall_e|
__mockall_e.matches(#(#predexprs, )*) &&
(!__mockall_e.is_done() || __mockall_n == 1))
.map(move |__mockall_e|
__mockall_e.call_mut(#(#argnames, )*)
)
}
}
).to_tokens(tokens);
}
}
/// An collection of Expectation's for methods returning static values struct StaticExpectations<'a> {
f: &'a MockFunction
}
impl<'a> ToTokens for StaticExpectations<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { let common_methods = CommonExpectationsMethods{f: self.f}; let argnames = &self.f.argnames; let argty = &self.f.argty; let (ig, tg, wc) = self.f.egenerics.split_for_impl(); let lg = lifetimes_to_generics(&self.f.alifetimes); let output = &self.f.output; let predexprs = &self.f.predexprs; let v = &self.f.privmod_vis;
quote!( #common_methods impl#ig Expectations #tg#wc { /// Simulate calling the real method. Every current expectation /// will be checked in FIFO order and the first one with /// matching arguments will be used. #vfn call #lg (&self, #(#argnames: #argty, )* )
-> Option<#output>
{ self.0.iter()
.find(|__mockall_e|
__mockall_e.matches(#(#predexprs, )*) &&
(!__mockall_e.is_done() || self.0.len() == 1))
.map(move |__mockall_e|
__mockall_e.call(#(#argnames, )*)
)
}
impl<'a> ToTokens for GenericExpectations<'a> { fn to_tokens(&self, tokens: &mut TokenStream) { if ! self.f.is_expectation_generic() { return;
} if ! self.f.is_static() && ! self.f.is_method_generic() { return;
}
let ge = StaticGenericExpectations{f: self.f}; let v = &self.f.privmod_vis;
quote!( /// A collection of [`Expectation`](struct.Expectations.html) /// objects for a generic method. Users will rarely if ever use /// this struct directly. #[doc(hidden)] #[derive(Default)] #vstruct GenericExpectations{
store: std::collections::hash_map::HashMap<::mockall::Key, Box<dyn ::mockall::AnyExpectations>>
} impl GenericExpectations { /// Verify that all current expectations are satisfied and clear /// them. This applies to all sets of generic parameters! #vfn checkpoint(&mutself) ->
std::collections::hash_map::Drain<::mockall::Key, Box<dyn ::mockall::AnyExpectations>>
{ self.store.drain()
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.