binlog/
tests.rs

1use std::borrow::Cow;
2use std::collections::VecDeque;
3use std::time::Duration;
4
5use crate::{Entry, Error, Range, RangeableStore, Store, SubscribeableStore, Subscription};
6
7use string_cache::DefaultAtom as Atom;
8
9/// Defines a unit test function.
10#[doc(hidden)]
11#[macro_export]
12macro_rules! define_test {
13    ($name:ident, $store_constructor:expr) => {
14        #[test]
15        fn $name() {
16            let store = $store_constructor;
17            $crate::tests::$name(&store);
18        }
19    };
20}
21
22#[doc(hidden)]
23#[macro_export]
24macro_rules! test_store_impl {
25    ($code:expr) => {
26        define_test!(latest, $code);
27    };
28}
29
30#[macro_export]
31macro_rules! test_rangeable_store_impl {
32    ($code:expr) => {
33        define_test!(remove, $code);
34        define_test!(iter, $code);
35    };
36}
37
38#[doc(hidden)]
39#[macro_export]
40macro_rules! test_subscribeable_store_impl {
41    ($code:expr) => {
42        define_test!(pubsub, $code);
43    };
44}
45
46fn insert_sample_data<S: Store>(store: &S, name: &str) -> Result<(), Error> {
47    for i in 1..11 {
48        let entry = Entry::new_with_timestamp(i.into(), name, vec![i]);
49        store.push(Cow::Owned(entry))?;
50    }
51    Ok(())
52}
53
54fn check_sample_data(mut results: VecDeque<Result<Entry, Error>>, name: &str) -> Result<(), Error> {
55    assert_eq!(results.len(), 10);
56    for i in 1..11u8 {
57        let result = results.pop_front().unwrap()?;
58        assert_eq!(result, Entry::new_with_timestamp(i.into(), name, vec![i]));
59    }
60    Ok(())
61}
62
63pub fn remove<S: RangeableStore>(store: &S) {
64    insert_sample_data(store, "test_remove").unwrap();
65    assert_eq!(store.range(.., Option::<Atom>::None).unwrap().count().unwrap(), 10);
66    store.range(2.., Option::<Atom>::None).unwrap().remove().unwrap();
67    assert_eq!(store.range(.., Option::<Atom>::None).unwrap().count().unwrap(), 1);
68    store.range(.., Some("test_remove")).unwrap().remove().unwrap();
69    assert_eq!(store.range(.., Option::<Atom>::None).unwrap().count().unwrap(), 0);
70}
71
72pub fn iter<S: RangeableStore>(store: &S) {
73    insert_sample_data(store, "test_iter").unwrap();
74    let results: VecDeque<Result<Entry, Error>> =
75        store.range(.., Option::<Atom>::None).unwrap().iter().unwrap().collect();
76    check_sample_data(results, "test_iter").unwrap();
77}
78
79pub fn pubsub<S: SubscribeableStore + Clone>(store: &S) {
80    let mut subscriber = store.subscribe("test_pubsub").unwrap();
81    insert_sample_data(store, "test_pubsub").unwrap();
82    // should get just the last entry
83    let entry = subscriber.next(None).unwrap().unwrap();
84    assert_eq!(entry, Entry::new_with_timestamp(10, "test_pubsub", vec![10]));
85    // should timeout
86    let entry = subscriber.next(Some(Duration::from_millis(10))).unwrap();
87    assert!(entry.is_none());
88}
89
90pub fn latest<S: Store + Clone>(store: &S) {
91    assert_eq!(store.latest("test_latest").unwrap(), None);
92    insert_sample_data(store, "test_latest").unwrap();
93    assert_eq!(
94        store.latest("test_latest").unwrap(),
95        Some(Entry::new_with_timestamp(10, "test_latest", vec![10]))
96    );
97}