Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(fn_traits, unboxed_closures)]
#![feature(fn_traits, tuple_trait, unboxed_closures)]

//! Mocking framework for Rust (currently only nightly)
//!
Expand Down
14 changes: 7 additions & 7 deletions src/mock_store.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::mocking::MockResult;
use std::any::TypeId;
use std::{any::TypeId, marker::Tuple};
use std::cell::RefCell;
use std::collections::HashMap;
use std::mem::transmute;
Expand Down Expand Up @@ -32,7 +32,7 @@ impl MockStore {
self.layers.borrow_mut().pop();
}

pub unsafe fn add_to_thread_layer<I, O>(
pub unsafe fn add_to_thread_layer<I: Tuple, O>(
&self,
id: TypeId,
mock: Box<dyn FnMut<I, Output = MockResult<I, O>> + 'static>,
Expand All @@ -44,7 +44,7 @@ impl MockStore {
.add(id, mock);
}

pub unsafe fn call<I, O>(&self, id: TypeId, mut input: I) -> MockResult<I, O> {
pub unsafe fn call<I: Tuple, O>(&self, id: TypeId, mut input: I) -> MockResult<I, O> {
// Do not hold RefCell borrow while calling mock, it can try to modify mocks
let layer_count = self.layers.borrow().len();
for layer_idx in (0..layer_count).rev() {
Expand Down Expand Up @@ -93,7 +93,7 @@ impl MockLayer {
self.mocks.remove(&id);
}

pub unsafe fn add<I, O>(
pub unsafe fn add<I: Tuple, O>(
&mut self,
id: TypeId,
mock: Box<dyn FnMut<I, Output = MockResult<I, O>> + 'static>,
Expand All @@ -118,19 +118,19 @@ struct ErasedStoredMock {
}

impl ErasedStoredMock {
unsafe fn call<I, O>(self, input: I) -> MockLayerResult<I, O> {
unsafe fn call<I: Tuple, O>(self, input: I) -> MockLayerResult<I, O> {
let unerased: StoredMock<I, O> = transmute(self.mock);
unerased.call(input)
}
}

/// Guarantees that while mock is running it's not overwritten, destroyed, or called again
#[derive(Clone)]
struct StoredMock<I, O> {
struct StoredMock<I: Tuple, O> {
mock: Rc<RefCell<Box<dyn FnMut<I, Output = MockResult<I, O>>>>>,
}

impl<I, O> StoredMock<I, O> {
impl<I: Tuple, O> StoredMock<I, O> {
fn new(mock: Box<dyn FnMut<I, Output = MockResult<I, O>> + 'static>) -> Self {
StoredMock {
mock: Rc::new(RefCell::new(mock)),
Expand Down
10 changes: 5 additions & 5 deletions src/mocking.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::mock_store::{MockLayer, MockStore};
use std::any::{Any, TypeId};
use std::{any::{Any, TypeId}, marker::Tuple};
use std::marker::PhantomData;
use std::mem::transmute;

Expand All @@ -8,7 +8,7 @@ use std::mem::transmute;
/// The trait is implemented for all functions, so its methods can be called on any function.
///
/// Note: methods have any effect only if called on functions [annotated as mockable](https://docs.rs/mocktopus_macros).
pub trait Mockable<T, O> {
pub trait Mockable<T: Tuple, O> {
/// Core function for setting up mocks
///
/// Always consider using [mock_safe](#tymethod.mock_safe) or [MockContext](struct.MockContext.html).
Expand Down Expand Up @@ -97,7 +97,7 @@ pub fn clear_mocks() {
MOCK_STORE.with(|mock_store| mock_store.clear())
}

impl<T, O, F: FnOnce<T, Output = O>> Mockable<T, O> for F {
impl<T: Tuple, O, F: FnOnce<T, Output = O>> Mockable<T, O> for F {
unsafe fn mock_raw<M: FnMut<T, Output = MockResult<T, O>>>(&self, mock: M) {
let id = self.get_mock_id();
let boxed = Box::new(mock) as Box<dyn FnMut<_, Output = _>>;
Expand Down Expand Up @@ -186,7 +186,7 @@ impl<'a> MockContext<'a> {
///
/// This function doesn't actually mock the function. It registers it as a
/// function that will be mocked when [`run`](#method.run) is called.
pub fn mock_safe<I, O, F, M>(self, mockable: F, mock: M) -> Self
pub fn mock_safe<I: Tuple, O, F, M>(self, mockable: F, mock: M) -> Self
where
F: Mockable<I, O>,
M: FnMut<I, Output = MockResult<I, O>> + 'a,
Expand All @@ -198,7 +198,7 @@ impl<'a> MockContext<'a> {
///
/// This is an unsafe version of [`mock_safe`](#method.mock_safe),
/// without lifetime constraint on mock
pub unsafe fn mock_raw<I, O, F, M>(mut self, mockable: F, mock: M) -> Self
pub unsafe fn mock_raw<I: Tuple, O, F, M>(mut self, mockable: F, mock: M) -> Self
where
F: Mockable<I, O>,
M: FnMut<I, Output = MockResult<I, O>>,
Expand Down
2 changes: 1 addition & 1 deletion tests/injecting.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(const_fn, proc_macro_hygiene)]
#![feature(proc_macro_hygiene)]

// Test if injecting works even if mocktopus is aliased
extern crate mocktopus as mocktopus_aliased;
Expand Down