atelier_data 0.0.15

Data Artifacts and I/O for the atelier-rs engine
#[cfg(test)]
mod tests {
    use atelier_data::workers::*;
    use std::time::Duration;

    #[test]
    fn first_event_never_detects_gap() {
        let mut det = GapDetector::with_defaults("test.topic");
        assert!(det.record_event().is_none());
        assert_eq!(det.gap_count(), 0);
    }

    #[test]
    fn rapid_events_no_gap() {
        let mut det = GapDetector::new("test.topic", Duration::from_secs(1));
        det.record_event();
        // Immediate second call — well within threshold
        assert!(det.record_event().is_none());
        assert_eq!(det.gap_count(), 0);
        assert_eq!(det.total_gap_ms(), 0);
    }

    #[tokio::test]
    async fn detects_gap_after_silence() {
        let threshold = Duration::from_millis(50);
        let mut det = GapDetector::new("test.topic", threshold);

        det.record_event();
        tokio::time::sleep(Duration::from_millis(80)).await;

        let gap = det.record_event();
        assert!(gap.is_some());
        let gap_ms = gap.unwrap();
        // Should be roughly 80ms (allow jitter)
        assert!(gap_ms >= 50, "gap_ms={} should be >= 50", gap_ms);
        assert!(gap_ms < 200, "gap_ms={} should be < 200", gap_ms);
        assert_eq!(det.gap_count(), 1);
    }

    #[test]
    fn gap_detector_set_routes_by_topic() {
        let topics = &["topic.a", "topic.b"];
        let mut set = GapDetectorSet::new(topics, Duration::from_secs(1));

        assert!(set.record_event("topic.a").is_none());
        assert!(set.record_event("topic.b").is_none());
        // Unknown topic
        assert!(set.record_event("topic.c").is_none());

        let stats = set.stats();
        assert_eq!(stats.len(), 2);
    }
}