tiny-counter 0.1.0

Track event counts across time windows with fixed memory and fast queries
Documentation
//! Tests for EventStore builder and configuration

use chrono::Utc;
use std::sync::Arc;
use tiny_counter::{EventStore, TestClock};

#[test]
fn create_store_with_defaults() {
    let store = EventStore::new();

    // Default store should work immediately
    store.record("test_event");
    assert_eq!(store.query("test_event").last_days(1).sum(), Some(1));
}

#[test]
fn create_store_with_builder() {
    let store = EventStore::builder()
        .track_hours(24)
        .track_days(7)
        .build()
        .unwrap();

    store.record("test");
    assert_eq!(store.query("test").last_hours(1).sum(), Some(1));
    assert_eq!(store.query("test").last_days(1).sum(), Some(1));
}

#[test]
fn builder_preset_for_rate_limiting() {
    let store = EventStore::builder().for_rate_limiting().build().unwrap();

    // Should have minutes and hours tracking
    store.record("event");
    assert_eq!(store.query("event").last_minutes(1).sum(), Some(1));
    assert_eq!(store.query("event").last_hours(1).sum(), Some(1));
}

#[test]
fn builder_preset_for_analytics() {
    let store = EventStore::builder().for_analytics().build().unwrap();

    // Should have days, weeks, months tracking
    store.record("event");
    assert_eq!(store.query("event").last_days(1).sum(), Some(1));
    assert_eq!(store.query("event").last_weeks(1).sum(), Some(1));
    assert_eq!(store.query("event").last_months(1).sum(), Some(1));
}

#[test]
fn builder_custom_configuration() {
    let store = EventStore::builder()
        .track_seconds(60)
        .track_minutes(60)
        .track_hours(24)
        .track_days(7)
        .track_weeks(4)
        .track_months(12)
        .track_years(2)
        .build()
        .unwrap();

    store.record("event");

    // All time units should work
    assert_eq!(store.query("event").last_seconds(1).sum(), Some(1));
    assert_eq!(store.query("event").last_minutes(1).sum(), Some(1));
    assert_eq!(store.query("event").last_hours(1).sum(), Some(1));
    assert_eq!(store.query("event").last_days(1).sum(), Some(1));
    assert_eq!(store.query("event").last_weeks(1).sum(), Some(1));
    assert_eq!(store.query("event").last_months(1).sum(), Some(1));
    assert_eq!(store.query("event").last_years(1).sum(), Some(1));
}

#[test]
fn builder_with_custom_clock() {
    let fixed_time = Utc::now();
    let clock = TestClock::build_for_testing_at(fixed_time);

    let store = EventStore::builder()
        .with_clock(Arc::new(clock.clone()))
        .build()
        .unwrap();

    store.record("event");

    // Verify clock is working
    assert_eq!(store.clock_now(), fixed_time);
    assert_eq!(store.query("event").last_days(1).sum(), Some(1));
}

#[test]
fn builder_rejects_zero_bucket_count() {
    let result = EventStore::builder().track_days(0).build();

    assert!(result.is_err());
}

#[test]
fn builder_rejects_all_zero_buckets() {
    let result = EventStore::builder().track_days(0).track_hours(0).build();

    assert!(result.is_err());
}

#[test]
fn memory_usage_is_reasonable() {
    let store = EventStore::new();

    store.record("event1");
    store.record("event2");

    let usage = store.memory_usage();

    // Each event should use ~2KB (with default 256 buckets)
    // Allow some overhead for data structures
    assert!(usage > 0);
    assert!(usage < 10_000); // Less than 10KB for 2 events
}

#[test]
fn tracked_intervals_returns_configuration() {
    let store = EventStore::builder()
        .track_hours(24)
        .track_days(7)
        .build()
        .unwrap();

    let intervals = store.tracked_intervals();

    assert_eq!(intervals.len(), 2);
    // intervals contain (TimeUnit, bucket_count) pairs
}

#[test]
fn query_with_seconds() {
    let store = EventStore::builder().track_seconds(60).build().unwrap();

    store.record("event");

    assert_eq!(store.query("event").last_seconds(60).sum(), Some(1));
}

#[test]
fn mix_of_valid_and_zero_buckets_rejected() {
    let result = EventStore::builder().track_hours(24).track_days(0).build();

    assert!(result.is_err());
}