mry 0.7.1

A simple but powerful mocking library that supports struct, trait, and function.
Documentation
use std::{ops::Deref, sync::Arc};

use parking_lot::Mutex;

use crate::{times::Times, Matcher};

pub struct Logs<I>(Vec<Arc<Mutex<I>>>);

impl<I: 'static> Logs<I> {
    pub(crate) fn push(&mut self, item: Arc<Mutex<I>>) {
        self.0.push(item);
    }

    pub fn filter_matches(&self, matcher: &Matcher<I>) -> Self {
        Self(
            self.0
                .iter()
                .filter(|log| matcher.matches(&log.lock()))
                .cloned()
                .collect(),
        )
    }

    pub(crate) fn assert_called(&self, name: &str, matcher: &Matcher<I>, times: Times) -> Self {
        let logs = self.filter_matches(matcher);
        let actual = logs.0.len();
        if !times.contains(&actual) {
            panic!(
                "Expected {} to be called {} times, but it was called {} times",
                name, times, actual,
            );
        }
        logs
    }

    pub fn iter(&self) -> impl Iterator<Item = impl Deref<Target = I> + '_> {
        self.0.iter().map(|log| log.lock())
    }
}

impl<I> Default for Logs<I> {
    fn default() -> Self {
        Self(Default::default())
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn filter_matches() {
        let mut logs = Logs::default();
        logs.push(Arc::new(Mutex::new(1)));
        logs.push(Arc::new(Mutex::new(2)));
        logs.push(Arc::new(Mutex::new(3)));
        logs.push(Arc::new(Mutex::new(2)));

        let matcher = Matcher::new_eq(2);

        let filtered = logs.filter_matches(&matcher);
        assert_eq!(filtered.0.len(), 2);
    }
}