use chrono::{Duration, Utc};
use std::sync::Arc;
use tiny_counter::{EventStore, TestClock};
#[test]
fn query_sum_aggregation() {
let store = EventStore::new();
store.record_count("event", 10);
store.record_count("event", 20);
store.record_count("event", 30);
let sum = store.query("event").last_days(1).sum();
assert_eq!(sum, Some(60));
}
#[test]
fn query_sum_with_time_windows() {
let fixed_time = Utc::now();
let clock = TestClock::build_for_testing_at(fixed_time);
let store = EventStore::builder()
.with_clock(Arc::new(clock.clone()))
.track_hours(24)
.build()
.unwrap();
store.record("event");
clock.advance(Duration::hours(2));
store.record("event");
assert_eq!(store.query("event").last_hours(1).sum(), Some(1));
assert_eq!(store.query("event").last_hours(3).sum(), Some(2));
}
#[test]
fn query_many_events_sum() {
let store = EventStore::new();
store.record_count("event1", 10);
store.record_count("event2", 20);
store.record_count("event3", 30);
let total = store
.query_many(&["event1", "event2", "event3"])
.last_days(1)
.sum();
assert_eq!(total, Some(60));
}
#[test]
fn query_many_with_nonexistent_event() {
let store = EventStore::new();
store.record_count("event1", 10);
store.record_count("event2", 20);
let total = store
.query_many(&["event1", "event2", "nonexistent"])
.last_days(1)
.sum();
assert_eq!(total, Some(30));
}
#[test]
fn query_ever_returns_all_data() {
let store = EventStore::new();
store.record_count("event", 100);
let count = store.query("event").ever().sum();
assert_eq!(count, Some(100));
}
#[test]
fn query_all_time_units() {
let store = EventStore::builder()
.track_minutes(60)
.track_hours(72)
.track_days(56)
.track_weeks(52)
.track_months(12)
.track_years(4)
.build()
.unwrap();
for _ in 0..5 {
store.record("test_event");
}
assert_eq!(store.query("test_event").last_minutes(1).sum(), Some(5));
assert_eq!(store.query("test_event").last_hours(1).sum(), Some(5));
assert_eq!(store.query("test_event").last_days(1).sum(), Some(5));
assert_eq!(store.query("test_event").last_weeks(1).sum(), Some(5));
assert_eq!(store.query("test_event").last_months(1).sum(), Some(5));
assert_eq!(store.query("test_event").last_years(1).sum(), Some(5));
}
#[test]
fn query_nonexistent_event_returns_none() {
let store = EventStore::new();
let count = store.query("nonexistent").last_days(1).sum();
assert_eq!(count, None);
}
#[test]
fn query_empty_store() {
let store = EventStore::new();
assert_eq!(store.query("any").last_days(1).sum(), None);
assert_eq!(store.query("any").last_hours(1).sum(), None);
assert_eq!(store.query("any").ever().sum(), None);
}
#[test]
fn query_event_outside_window() {
let fixed_time = Utc::now();
let clock = TestClock::build_for_testing_at(fixed_time);
let store = EventStore::builder()
.with_clock(Arc::new(clock.clone()))
.track_hours(24)
.build()
.unwrap();
store.record("event");
clock.advance(Duration::hours(48));
let count = store.query("event").last_hours(24).sum();
assert_eq!(count, Some(0));
}
#[test]
fn large_count_aggregations() {
let store = EventStore::new();
store.record_count("large", u32::MAX / 2);
let avg = store.query("large").last_days(1).average();
assert!(avg.is_some());
}
#[test]
fn very_old_event_outside_retention() {
let store = EventStore::new();
let long_ago = Utc::now() - Duration::days(3650);
store.record_at("ancient_event", long_ago).unwrap();
let sum = store.query("ancient_event").ever().sum();
assert!(sum == Some(0) || sum.is_none());
}
#[test]
fn events_spanning_years() {
let store = EventStore::builder().track_years(4).build().unwrap();
let now = Utc::now();
for i in 0..3 {
let timestamp = now - Duration::days(365 * i);
store.record_at("yearly_event", timestamp).unwrap();
}
let sum = store.query("yearly_event").ever().sum();
assert_eq!(sum, Some(3));
}
#[test]
fn query_zero_time_range() {
let store = EventStore::new();
store.record("event");
let sum = store.query("event").last_days(0).sum();
assert!(sum.is_some());
}