use super::*; use crate::core::db::{create_connection, run_migrations}; use std::path::Path; fn setup_test_db() -> Connection { let conn = create_connection(Path::new(":memory:")).unwrap(); run_migrations(&conn).unwrap(); conn } #[test] fn test_sync_run_recorder_start() { let conn = setup_test_db(); let recorder = SyncRunRecorder::start(&conn, "sync", "abc12345").unwrap(); assert!(recorder.row_id > 0); let (status, command, run_id): (String, String, String) = conn .query_row( "SELECT status, command, run_id FROM sync_runs WHERE id = ?1", [recorder.row_id], |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)), ) .unwrap(); assert_eq!(status, "running"); assert_eq!(command, "sync"); assert_eq!(run_id, "abc12345"); } #[test] fn test_sync_run_recorder_succeed() { let conn = setup_test_db(); let recorder = SyncRunRecorder::start(&conn, "sync", "def67890").unwrap(); let row_id = recorder.row_id; let metrics = vec![StageTiming { name: "ingest".to_string(), project: None, elapsed_ms: 1200, items_processed: 50, items_skipped: 0, errors: 2, rate_limit_hits: 0, retries: 0, sub_stages: vec![], }]; recorder.succeed(&conn, &metrics, 50, 2).unwrap(); let (status, finished_at, metrics_json, total_items, total_errors): ( String, Option, Option, i64, i64, ) = conn .query_row( "SELECT status, finished_at, metrics_json, total_items_processed, total_errors FROM sync_runs WHERE id = ?1", [row_id], |row| { Ok(( row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?, )) }, ) .unwrap(); assert_eq!(status, "succeeded"); assert!(finished_at.is_some()); assert!(metrics_json.is_some()); assert_eq!(total_items, 50); assert_eq!(total_errors, 2); let parsed: Vec = serde_json::from_str(&metrics_json.unwrap()).unwrap(); assert_eq!(parsed.len(), 1); assert_eq!(parsed[0].name, "ingest"); } #[test] fn test_sync_run_recorder_fail() { let conn = setup_test_db(); let recorder = SyncRunRecorder::start(&conn, "ingest issues", "fail0001").unwrap(); let row_id = recorder.row_id; recorder.fail(&conn, "GitLab auth failed", None).unwrap(); let (status, finished_at, error, metrics_json): ( String, Option, Option, Option, ) = conn .query_row( "SELECT status, finished_at, error, metrics_json FROM sync_runs WHERE id = ?1", [row_id], |row| Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?)), ) .unwrap(); assert_eq!(status, "failed"); assert!(finished_at.is_some()); assert_eq!(error.as_deref(), Some("GitLab auth failed")); assert!(metrics_json.is_none()); } #[test] fn test_sync_run_recorder_fail_with_partial_metrics() { let conn = setup_test_db(); let recorder = SyncRunRecorder::start(&conn, "sync", "part0001").unwrap(); let row_id = recorder.row_id; let partial_metrics = vec![StageTiming { name: "ingest_issues".to_string(), project: Some("group/repo".to_string()), elapsed_ms: 800, items_processed: 30, items_skipped: 0, errors: 0, rate_limit_hits: 1, retries: 0, sub_stages: vec![], }]; recorder .fail(&conn, "Embedding failed", Some(&partial_metrics)) .unwrap(); let (status, metrics_json): (String, Option) = conn .query_row( "SELECT status, metrics_json FROM sync_runs WHERE id = ?1", [row_id], |row| Ok((row.get(0)?, row.get(1)?)), ) .unwrap(); assert_eq!(status, "failed"); assert!(metrics_json.is_some()); let parsed: Vec = serde_json::from_str(&metrics_json.unwrap()).unwrap(); assert_eq!(parsed.len(), 1); assert_eq!(parsed[0].name, "ingest_issues"); }