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#[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 let entry = subscriber.next(None).unwrap().unwrap();
84 assert_eq!(entry, Entry::new_with_timestamp(10, "test_pubsub", vec![10]));
85 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}