#[cfg(feature = "serde")]
use tiny_counter::{storage::MemoryStorage, EventStore};
#[test]
#[cfg(feature = "serde")]
fn dirty_tracking_starts_clean() {
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.build()
.unwrap();
assert!(!store.is_dirty());
}
#[test]
#[cfg(feature = "serde")]
fn record_marks_dirty() {
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.build()
.unwrap();
store.record("event");
assert!(store.is_dirty());
}
#[test]
#[cfg(feature = "serde")]
fn persist_clears_dirty() {
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.build()
.unwrap();
store.record("event");
assert!(store.is_dirty());
store.persist().unwrap();
assert!(!store.is_dirty());
}
#[test]
#[cfg(feature = "serde")]
fn multiple_records_single_persist() {
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.build()
.unwrap();
store.record("event1");
store.record("event2");
store.record("event3");
assert!(store.is_dirty());
store.persist().unwrap();
assert!(!store.is_dirty());
assert_eq!(store.query("event1").last_days(1).sum(), Some(1));
assert_eq!(store.query("event2").last_days(1).sum(), Some(1));
assert_eq!(store.query("event3").last_days(1).sum(), Some(1));
}
#[test]
#[cfg(feature = "serde")]
fn reset_dirty_without_persist() {
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.build()
.unwrap();
store.record("event");
assert!(store.is_dirty());
store.reset_dirty();
assert!(!store.is_dirty());
assert_eq!(store.query("event").last_days(1).sum(), Some(1));
}
#[test]
#[cfg(feature = "serde")]
fn persist_when_clean_succeeds() {
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.build()
.unwrap();
assert!(!store.is_dirty());
let result = store.persist();
assert!(result.is_ok());
}
#[test]
#[cfg(feature = "serde")]
fn persist_all_saves_everything() {
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.build()
.unwrap();
store.record("event1");
store.persist().unwrap();
store.record("event2");
store.persist_all().unwrap();
assert!(!store.is_dirty());
assert_eq!(store.query("event1").last_days(1).sum(), Some(1));
assert_eq!(store.query("event2").last_days(1).sum(), Some(1));
}
#[test]
#[cfg(feature = "serde")]
fn multiple_persist_cycles() {
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.build()
.unwrap();
store.record_count("event", 10);
store.persist().unwrap();
assert!(!store.is_dirty());
store.record_count("event", 20);
store.persist().unwrap();
assert!(!store.is_dirty());
store.record_count("event", 30);
store.persist().unwrap();
assert!(!store.is_dirty());
assert_eq!(store.query("event").last_days(1).sum(), Some(60));
}
#[test]
#[cfg(feature = "serde")]
fn memory_storage_persist_and_query() {
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.build()
.unwrap();
store.record_count("event1", 100);
store.record_count("event2", 200);
store.persist().unwrap();
assert_eq!(store.query("event1").last_days(1).sum(), Some(100));
assert_eq!(store.query("event2").last_days(1).sum(), Some(200));
}
#[test]
#[cfg(feature = "storage-fs")]
fn file_per_event_storage_basic() {
use tiny_counter::storage::FilePerEvent;
let test_dir = tempfile::tempdir().unwrap();
let store = EventStore::builder()
.with_storage(FilePerEvent::new(test_dir.path(), ".dat").unwrap())
.build()
.unwrap();
store.record_count("event", 42);
store.persist().unwrap();
assert!(test_dir.path().exists());
}
#[test]
#[cfg(feature = "storage-fs")]
fn file_per_event_reload() {
use tiny_counter::storage::FilePerEvent;
let test_dir = tempfile::tempdir().unwrap();
let path = test_dir.path().to_path_buf();
{
let store = EventStore::builder()
.with_storage(FilePerEvent::new(&path, ".dat").unwrap())
.build()
.unwrap();
store.record_count("event", 999);
store.persist().unwrap();
}
{
let store = EventStore::builder()
.with_storage(FilePerEvent::new(&path, ".dat").unwrap())
.build()
.unwrap();
assert_eq!(store.query("event").last_days(1).sum(), Some(999));
}
}
#[test]
#[cfg(feature = "storage-sqlite")]
fn sqlite_storage_basic() {
use tiny_counter::storage::Sqlite;
let temp_file = tempfile::NamedTempFile::new().unwrap();
let path = temp_file.path();
let store = EventStore::builder()
.with_storage(Sqlite::open(path).unwrap())
.build()
.unwrap();
store.record_count("event", 555);
store.persist().unwrap();
assert_eq!(store.query("event").last_days(1).sum(), Some(555));
}
#[test]
#[cfg(feature = "storage-sqlite")]
fn sqlite_storage_reload() {
use tiny_counter::storage::Sqlite;
let temp_file = tempfile::NamedTempFile::new().unwrap();
let path = temp_file.path().to_path_buf();
{
let store = EventStore::builder()
.with_storage(Sqlite::open(&path).unwrap())
.build()
.unwrap();
store.record_count("event", 777);
store.persist().unwrap();
}
{
let store = EventStore::builder()
.with_storage(Sqlite::open(&path).unwrap())
.build()
.unwrap();
assert_eq!(store.query("event").last_days(1).sum(), Some(777));
}
}
#[test]
#[cfg(all(feature = "serde", feature = "serde-bincode"))]
fn bincode_formatter_basic() {
use tiny_counter::formatter::BincodeFormat;
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.with_format(BincodeFormat)
.build()
.unwrap();
store.record_count("event", 123);
store.persist().unwrap();
assert_eq!(store.query("event").last_days(1).sum(), Some(123));
}
#[test]
#[cfg(all(feature = "storage-fs", feature = "serde-bincode"))]
fn bincode_with_file_storage() {
use tiny_counter::{formatter::BincodeFormat, storage::FilePerEvent};
let test_dir = tempfile::tempdir().unwrap();
let path = test_dir.path().to_path_buf();
{
let store = EventStore::builder()
.with_storage(FilePerEvent::new(&path, ".bin").unwrap())
.with_format(BincodeFormat)
.build()
.unwrap();
store.record_count("event", 456);
store.persist().unwrap();
}
{
let store = EventStore::builder()
.with_storage(FilePerEvent::new(&path, ".bin").unwrap())
.with_format(BincodeFormat)
.build()
.unwrap();
assert_eq!(store.query("event").last_days(1).sum(), Some(456));
}
}
#[test]
#[cfg(all(feature = "serde", feature = "serde-json"))]
fn json_formatter_basic() {
use tiny_counter::formatter::JsonFormat;
let store = EventStore::builder()
.with_storage(MemoryStorage::new())
.with_format(JsonFormat)
.build()
.unwrap();
store.record_count("event", 789);
store.persist().unwrap();
assert_eq!(store.query("event").last_days(1).sum(), Some(789));
}
#[test]
#[cfg(all(feature = "storage-fs", feature = "serde-json"))]
fn json_with_file_storage() {
use tiny_counter::{formatter::JsonFormat, storage::FilePerEvent};
let test_dir = tempfile::tempdir().unwrap();
let path = test_dir.path().to_path_buf();
{
let store = EventStore::builder()
.with_storage(FilePerEvent::new(&path, ".json").unwrap())
.with_format(JsonFormat)
.build()
.unwrap();
store.record_count("event", 321);
store.persist().unwrap();
}
{
let store = EventStore::builder()
.with_storage(FilePerEvent::new(&path, ".json").unwrap())
.with_format(JsonFormat)
.build()
.unwrap();
assert_eq!(store.query("event").last_days(1).sum(), Some(321));
}
}
#[test]
#[cfg(all(feature = "storage-fs", feature = "serde-json"))]
fn json_produces_valid_json() {
use tiny_counter::{formatter::JsonFormat, storage::FilePerEvent};
let test_dir = tempfile::tempdir().unwrap();
let store = EventStore::builder()
.with_storage(FilePerEvent::new(test_dir.path(), ".json").unwrap())
.with_format(JsonFormat)
.build()
.unwrap();
store.record("event");
store.persist().unwrap();
let files: Vec<_> = std::fs::read_dir(test_dir.path())
.unwrap()
.filter_map(|e| e.ok())
.collect();
assert_eq!(files.len(), 1);
let content = std::fs::read_to_string(files[0].path()).unwrap();
let _parsed: serde_json::Value = serde_json::from_str(&content).unwrap();
}
#[test]
#[cfg(all(feature = "serde-bincode", feature = "serde-json", feature = "serde"))]
fn different_formats_are_independent() {
use tiny_counter::formatter::{BincodeFormat, JsonFormat};
let bincode_store = EventStore::builder()
.with_storage(MemoryStorage::new())
.with_format(BincodeFormat)
.build()
.unwrap();
let json_store = EventStore::builder()
.with_storage(MemoryStorage::new())
.with_format(JsonFormat)
.build()
.unwrap();
bincode_store.record("event1");
json_store.record("event2");
bincode_store.persist().unwrap();
json_store.persist().unwrap();
assert_eq!(bincode_store.query("event1").last_days(1).sum(), Some(1));
assert_eq!(json_store.query("event2").last_days(1).sum(), Some(1));
}