Skip to content

Commit

Permalink
refactor: Restructure responders, rename respond back to output
Browse files Browse the repository at this point in the history
  • Loading branch information
audunhalland committed Mar 17, 2024
1 parent e1ab6e7 commit 8d45e42
Show file tree
Hide file tree
Showing 21 changed files with 978 additions and 1,032 deletions.
6 changes: 3 additions & 3 deletions src/assemble.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::alloc::{format, vec, BTreeMap, Entry, String, ToString};
use crate::build::dyn_builder::DynCallPatternBuilder;
use crate::call_pattern::CallPattern;
use crate::fn_mocker::{FnMocker, PatternMatchMode};
use crate::respond::ResponderError;
use crate::output::RespondError;
use crate::Clause;
use crate::{clause, MockFnInfo};

Expand Down Expand Up @@ -37,8 +37,8 @@ impl clause::term::Sink for MockAssembler {
fn push(&mut self, info: MockFnInfo, mut builder: DynCallPatternBuilder) -> Result<(), String> {
if let Some(responder_error) = builder.responder_error.take() {
return Err(match responder_error {
ResponderError::OwnershipRequired => "Ownership required".to_string(),
ResponderError::NoMutexApi => {
RespondError::OwnershipRequired => "Ownership required".to_string(),
RespondError::NoMutexApi => {
"No Mutex API available. Enable the `spin-lock` feature in `no_std` mode, or use the `.answers` API instead of `.returns`."
.to_string()
}
Expand Down
61 changes: 31 additions & 30 deletions src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ use crate::alloc::vec;
use crate::alloc::{String, ToString, Vec};
use crate::call_pattern::*;
use crate::fn_mocker::PatternMatchMode;
use crate::output::{IntoReturn, IntoReturnOnce, Kind, Return, ReturnDefault};
use crate::property::*;
use crate::respond::{
Applier, BoxedApplier, IntoReturn, IntoReturnOnce, IntoReturner, Respond, Return, ReturnDefault,
};
use crate::responder::{Applier, BoxedApplier, IntoReturner};
use crate::*;
use dyn_builder::*;

pub(crate) mod dyn_builder {
use crate::alloc::{vec, Vec};
use crate::respond::{ResponderError, Returner};
use crate::output::RespondError;
use crate::responder::Returner;
use crate::MockFn;

use crate::{
Expand All @@ -29,7 +29,7 @@ pub(crate) mod dyn_builder {
pub(crate) responders: Vec<DynCallOrderResponder>,
pub(crate) count_expectation: counter::CallCountExpectation,
pub(crate) current_response_index: usize,
pub(crate) responder_error: Option<ResponderError>,
pub(crate) responder_error: Option<RespondError>,
}

impl DynCallPatternBuilder {
Expand Down Expand Up @@ -91,7 +91,7 @@ pub(crate) mod dyn_builder {

pub fn push_returner_result<F: MockFn>(
&mut self,
result: Result<Returner<F>, ResponderError>,
result: Result<Returner<F>, RespondError>,
) {
match result {
Ok(responder) => self.push_responder(responder.into_dyn_responder()),
Expand Down Expand Up @@ -202,8 +202,8 @@ impl<'p, F: MockFn, O: Ordering> DefineResponse<'p, F, O> {
/// To be able to return this value multiple times, quantify it explicitly.
pub fn returns<T>(self, value: T) -> QuantifyReturnValue<'p, F, T, O>
where
T: IntoReturnOnce<F::Respond>,
<<F as MockFn>::Respond as Respond>::Get: IntoReturner<F>,
T: IntoReturnOnce<F::OutputKind>,
<<F as MockFn>::OutputKind as Kind>::Return: IntoReturner<F>,
{
QuantifyReturnValue {
wrapper: self.wrapper,
Expand All @@ -229,9 +229,9 @@ where
/// Specify the output of the call pattern by providing a value.
/// The output type cannot contain non-static references.
/// It must also be [Send] and [Sync] because unimock needs to store it, and [Clone] because it should be able to be returned multiple times.
pub fn returns<V: IntoReturn<F::Respond>>(mut self, value: V) -> Quantify<'p, F, O>
pub fn returns<V: IntoReturn<F::OutputKind>>(mut self, value: V) -> Quantify<'p, F, O>
where
<<F as MockFn>::Respond as Respond>::Get: IntoReturner<F>,
<<F as MockFn>::OutputKind as Kind>::Return: IntoReturner<F>,
{
self.wrapper
.push_returner_result(value.into_return().map(|r| r.into_returner()));
Expand Down Expand Up @@ -265,14 +265,15 @@ macro_rules! define_response_common_impl {
/// Specify the response of the call pattern by calling `Default::default()`.
pub fn returns_default(mut self) -> Quantify<'p, F, O>
where
F::Respond: Return,
<F::Respond as Return>::Type: ReturnDefault<F::Respond>,
<<F as MockFn>::Respond as Respond>::Get: IntoReturner<F>,
F::OutputKind: Return,
<F::OutputKind as Return>::Type: ReturnDefault<F::OutputKind>,
<<F as MockFn>::OutputKind as Kind>::Return: IntoReturner<F>,
{
self.wrapper.push_returner_result(Ok(
<<F::Respond as Return>::Type as ReturnDefault<F::Respond>>::return_default()
.into_returner(),
));
let default = <<F::OutputKind as Return>::Type as ReturnDefault<
F::OutputKind,
>>::return_default();
self.wrapper
.push_returner_result(Ok(default.into_returner()));
self.quantify()
}

Expand Down Expand Up @@ -336,8 +337,8 @@ define_response_common_impl!(DefineMultipleResponses);
pub struct QuantifyReturnValue<'p, F, T, O>
where
F: MockFn,
T: IntoReturnOnce<F::Respond>,
<<F as MockFn>::Respond as Respond>::Get: IntoReturner<F>,
T: IntoReturnOnce<F::OutputKind>,
<<F as MockFn>::OutputKind as Kind>::Return: IntoReturner<F>,
{
pub(crate) wrapper: DynBuilderWrapper<'p>,
return_value: Option<T>,
Expand All @@ -348,16 +349,16 @@ where
impl<'p, F, T, O> QuantifyReturnValue<'p, F, T, O>
where
F: MockFn,
T: IntoReturnOnce<F::Respond>,
T: IntoReturnOnce<F::OutputKind>,
O: Copy,
<<F as MockFn>::Respond as Respond>::Get: IntoReturner<F>,
<<F as MockFn>::OutputKind as Kind>::Return: IntoReturner<F>,
{
/// Expect this call pattern to be matched exactly once.
///
/// This is the only quantifier that works together with return values that don't implement [Clone].
pub fn once(mut self) -> QuantifiedResponse<'p, F, O, Exact>
where
<<F as MockFn>::Respond as Respond>::Get: IntoReturner<F>,
<<F as MockFn>::OutputKind as Kind>::Return: IntoReturner<F>,
{
self.wrapper.push_returner_result(
self.return_value
Expand All @@ -378,8 +379,8 @@ where
/// Expect this call pattern to be matched exactly the specified number of times.
pub fn n_times(mut self, times: usize) -> QuantifiedResponse<'p, F, O, Exact>
where
T: IntoReturn<F::Respond>,
<<F as MockFn>::Respond as Respond>::Get: IntoReturner<F>,
T: IntoReturn<F::OutputKind>,
<<F as MockFn>::OutputKind as Kind>::Return: IntoReturner<F>,
{
self.wrapper.push_returner_result(
self.return_value
Expand All @@ -403,9 +404,9 @@ where
/// Strictly ordered call patterns must have exact quantification.
pub fn at_least_times(mut self, times: usize) -> QuantifiedResponse<'p, F, O, AtLeast>
where
T: IntoReturn<F::Respond>,
T: IntoReturn<F::OutputKind>,
O: Ordering<Kind = InAnyOrder>,
<<F as MockFn>::Respond as Respond>::Get: IntoReturner<F>,
<<F as MockFn>::OutputKind as Kind>::Return: IntoReturner<F>,
{
self.wrapper.push_returner_result(
self.return_value
Expand All @@ -427,9 +428,9 @@ where
impl<'p, F, T, O> Clause for QuantifyReturnValue<'p, F, T, O>
where
F: MockFn,
T: IntoReturnOnce<F::Respond>,
T: IntoReturnOnce<F::OutputKind>,
O: Copy + Ordering,
<<F as MockFn>::Respond as Respond>::Get: IntoReturner<F>,
<<F as MockFn>::OutputKind as Kind>::Return: IntoReturner<F>,
{
fn deconstruct(self, sink: &mut dyn clause::term::Sink) -> Result<(), String> {
self.once().deconstruct(sink)
Expand All @@ -444,8 +445,8 @@ where
impl<'p, F, T, O> Drop for QuantifyReturnValue<'p, F, T, O>
where
F: MockFn,
T: IntoReturnOnce<F::Respond>,
<<F as MockFn>::Respond as Respond>::Get: IntoReturner<F>,
T: IntoReturnOnce<F::OutputKind>,
<<F as MockFn>::OutputKind as Kind>::Return: IntoReturner<F>,
{
fn drop(&mut self) {
if let Some(return_value) = self.return_value.take() {
Expand Down
2 changes: 1 addition & 1 deletion src/call_pattern.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::alloc::Vec;
use crate::respond::{Applier, BoxedApplier, Returner};
use crate::responder::{Applier, BoxedApplier, Returner};
use core::any::Any;

use crate::private::MismatchReporter;
Expand Down
8 changes: 4 additions & 4 deletions src/cell.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::alloc::Box;
use crate::respond::ResponderError;
use crate::output::RespondError;

/// A cell that can be "taken from"
pub struct DynCell<T: ?Sized>(Box<dyn TryTake<T>>);
Expand All @@ -15,16 +15,16 @@ where
T: Send + Sync + 'static,
{
#[cfg(any(feature = "std", feature = "spin-lock"))]
pub fn once(value: T) -> Result<Self, ResponderError> {
pub fn once(value: T) -> Result<Self, RespondError> {
let mutex = crate::private::MutexIsh::new(Some(value));
Ok(Self(Box::new(Producer::new(move || {
mutex.locked(|option| option.take())
}))))
}

#[cfg(not(any(feature = "std", feature = "spin-lock")))]
pub fn once(value: T) -> Result<Self, ResponderError> {
Err(ResponderError::NoMutexApi)
pub fn once(value: T) -> Result<Self, RespondError> {
Err(RespondError::NoMutexApi)
}

pub fn clonable(value: T) -> Self
Expand Down
77 changes: 23 additions & 54 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,15 +451,10 @@ pub mod alloc {
/// Builder pattern types used for defining mocked behaviour.
pub mod build;

// /// Function outputs.
// pub mod output;

/// Traits and types used for describing the properties of various mock types.
pub mod property;
/// New output modelling
pub mod respond;

pub mod output;
/// Traits and types used for describing the properties of various mock types.
pub mod property;

/// Mock APIs for various crates.
pub mod mock;
Expand Down Expand Up @@ -493,6 +488,7 @@ mod error;
mod eval;
mod fn_mocker;
mod mismatch;
mod responder;
mod state;
mod teardown;

Expand All @@ -513,11 +509,11 @@ use debug::TraitMethodPath;
// use output::{IntoResponse, Respond, StaticRef};
use private::{DefaultImplDelegator, Matching};

use respond::IntoConsume;
use respond::Respond;
use output::IntoRespond;
use output::Kind;

use output::{static_ref::StaticRefResponse, StaticRef};

use output::StaticRefResponse;
use respond::StaticRef;
///
/// Autogenerate mocks for all methods in the annotated traits, and `impl` it for [Unimock].
///
Expand Down Expand Up @@ -1039,12 +1035,12 @@ pub trait MockFn: Sized + 'static {

/// A type that describes how the mocked function responds.
///
/// The Respond trait describes a type used internally to store a response value.
/// The [Kind] trait describes a type used internally to store a response value.
///
/// The response value is Unimock's internal representation of the function's return value between two points it time:
/// 1. The user specifies it upfront as part of a Clause.
/// 2. The conversion of this value into the mocked function's final output value.
type Respond: respond::Respond;
type OutputKind: output::Kind;

/// The function type used for function application on a call pattern.
type ApplyFn: ?Sized + Send + Sync;
Expand Down Expand Up @@ -1215,71 +1211,44 @@ pub trait Clause {
fn deconstruct(self, sink: &mut dyn clause::term::Sink) -> Result<(), alloc::String>;
}

// Hidden responder wrapper used in the Respond/RespondOnce traits hidden methods
#[doc(hidden)]
pub struct Responder(call_pattern::DynResponder);

impl Responder {
// pub(crate) fn cell<F: MockFn>(cell: DynCell<<F::Response as Respond>::Type>) -> Self
// where
// <F::Response as Respond>::Type: Send + Sync + 'static,
// {
// Self(CellResponder::<F> { cell }.into_dyn_responder())
// }
//
// pub(crate) fn borrowing<F: MockFn>(response: <F::Response as Respond>::Type) -> Self
// where
// <F::Response as Respond>::Type: Send + Sync,
// {
// Responder(
// BorrowResponder::<F> {
// borrowable: response,
// }
// .into_dyn_responder(),
// )
// }
}

/// A mocked response
pub struct Response<F: MockFn>(ResponseInner<F>);
pub struct Respond<F: MockFn>(RespondInner<F>);

enum ResponseInner<F: MockFn> {
Response(<F::Respond as Respond>::Consume),
Unimock(&'static dyn Fn(Unimock) -> <F::Respond as Respond>::Consume),
enum RespondInner<F: MockFn> {
Respond(<F::OutputKind as Kind>::Respond),
Unimock(&'static dyn Fn(Unimock) -> <F::OutputKind as Kind>::Respond),
}

/// Turn a value into a mock function response.
pub fn respond<F, T>(input: T) -> Response<F>
pub fn respond<F, T>(input: T) -> Respond<F>
where
F: MockFn,
T: IntoConsume<<F as MockFn>::Respond>,
T: IntoRespond<<F as MockFn>::OutputKind>,
{
Response(ResponseInner::Response(input.into_consume().unwrap()))
Respond(RespondInner::Respond(input.into_respond().unwrap()))
}

/// Make a response that is a static reference to leaked memory.
///
/// This method should only be used when computing a reference based
/// on input parameters is necessary, which should not be a common use case.
pub fn respond_leaked_ref<F, T, R>(input: T) -> Response<F>
pub fn respond_leaked_ref<F, T, R>(input: T) -> Respond<F>
where
F: MockFn<Respond = StaticRef<R>>,
F: MockFn<OutputKind = StaticRef<R>>,
T: core::borrow::Borrow<R> + 'static,
R: Send + Sync + 'static,
{
let response = <T as core::borrow::Borrow<R>>::borrow(Box::leak(Box::new(input)));
Response(ResponseInner::Response(StaticRefResponse {
value: response,
}))
Respond(RespondInner::Respond(StaticRefResponse { value: response }))
}

/// Respond with the unimock instance itself.
pub fn respond_unimock<F>() -> Response<F>
pub fn respond_unimock<F>() -> Respond<F>
where
F: MockFn,
Unimock: IntoConsume<<F as MockFn>::Respond>,
Unimock: IntoRespond<<F as MockFn>::OutputKind>,
{
Response(ResponseInner::Unimock(&|unimock| {
unimock.into_consume().unwrap()
Respond(RespondInner::Unimock(&|unimock| {
unimock.into_respond().unwrap()
}))
}
2 changes: 1 addition & 1 deletion src/mock/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub mod process {
/// Unimock mock API for [std::process::Termination].
#[allow(non_snake_case)]
pub mod TerminationMock {
use crate::{respond::Owned, MockFn, Response};
use crate::{output::Owned, MockFn, Response};
use std::{boxed::Box, string::String};

#[allow(non_camel_case_types)]
Expand Down
Loading

0 comments on commit 8d45e42

Please sign in to comment.