#[cfg(test)] mod tests { use super::*; use crate::models::{ApiTokenInfo, ConnectionType, Device, HaReading, Reading}; #[test] fn history_compaction_keeps_one_sample_per_old_bucket() { let dir = tempfile::tempdir().unwrap(); let db = Db::open(&dir.path().join("compact.db")).unwrap(); let device = Device::simulated_default(); db.save_device(&device).unwrap(); let seconds = (Utc::now().timestamp() - 2 * 86_400) / 600 * 600; let base = DateTime::::from_timestamp(seconds, 0).unwrap(); for offset in [10_i64, 20_i64] { db.add_reading(&Reading { id: 0, device_id: device.id.clone(), timestamp: base + Duration::seconds(offset), indoor_temperature: Some(22.0), outdoor_temperature: None, target_temperature: 23.0, power: true, source: "gree".into(), }) .unwrap(); } assert_eq!(db.history_counts().unwrap().0, 2); assert_eq!(db.compact_history(30).unwrap(), 1); assert_eq!(db.history_counts().unwrap().0, 1); } #[test] fn sqlite_round_trip() { let dir = tempfile::tempdir().unwrap(); let db = Db::open(&dir.path().join("test.db")).unwrap(); let device = Device::simulated_default(); db.save_device(&device).unwrap(); let loaded = db.get_device(&device.id).unwrap().unwrap(); assert_eq!(loaded.mac, device.mac); assert_eq!(db.list_devices().unwrap().len(), 1); let event_id = db .log_event("info", "test", "ok", &serde_json::json!({"a":1})) .unwrap(); assert_eq!(db.list_events(10).unwrap().len(), 1); db.update_event_metadata( event_id, &serde_json::json!({"a":1,"notification":{"status":"silent"}}), ) .unwrap(); assert_eq!( db.list_events(10).unwrap()[0].metadata["notification"]["status"], "silent" ); { let conn = db.lock().unwrap(); conn.execute( queries::INSERT_EVENT, rusqlite::params![ (Utc::now() - Duration::days(40)).to_rfc3339(), "info", "old", "old", "{}" ], ) .unwrap(); } assert_eq!(db.prune_events(30).unwrap(), 1); assert_eq!(db.list_events(10).unwrap().len(), 1); let access_token = ApiTokenInfo { id: "token-1".into(), name: "Home Assistant".into(), token_prefix: "gree_controller_test...".into(), created_at: Utc::now(), }; db.save_api_token(&access_token, "test-hash").unwrap(); assert!(db.api_token_exists("test-hash").unwrap()); assert_eq!(db.list_api_tokens().unwrap().len(), 1); assert!(db.delete_api_token(&access_token.id).unwrap()); assert!(!db.api_token_exists("test-hash").unwrap()); let chart_share = serde_json::json!({ "title": "Room temperatures", "series": ["device|dev-1|indoor"], "hours": 24, "lang": "en" }); db.save_public_chart_share("chart-hash", &chart_share).unwrap(); assert_eq!( db.get_public_chart_share("chart-hash").unwrap(), Some(chart_share) ); assert!(db.get_public_chart_share("missing-chart").unwrap().is_none()); let now = Utc::now(); db.add_reading(&Reading { id: 0, device_id: device.id.clone(), timestamp: now.clone(), indoor_temperature: Some(22.5), outdoor_temperature: Some(31.0), target_temperature: 23.0, power: true, source: "gree".into(), }) .unwrap(); assert_eq!( db.list_device_history( Some(&device.id), now.clone() - Duration::minutes(1), 30, 100 ) .unwrap() .len(), 1 ); db.add_ha_reading_if_due( &HaReading { id: 0, entity_id: "sensor.room".into(), zone_id: Some("zone-room".into()), kind: "room".into(), timestamp: now.clone(), temperature: 22.1, }, 15, ) .unwrap(); assert_eq!( db.list_ha_history( Some("sensor.room"), now.clone() - Duration::minutes(1), 30, 100 ) .unwrap() .len(), 1 ); assert_eq!(db.history_counts().unwrap(), (1, 0, 1)); } #[test] fn local_and_cloud_entries_with_same_physical_mac_can_coexist() { let dir = tempfile::tempdir().unwrap(); let db = Db::open(&dir.path().join("duplicate-transport.db")).unwrap(); let mut local = Device::simulated_default(); local.id = "local-device".into(); local.mac = "AABBCCDDEEFF".into(); local.connection_type = ConnectionType::Local; let mut cloud = local.clone(); cloud.id = "cloud-device".into(); cloud.connection_type = ConnectionType::GreeCloud; cloud.cloud_device_id = Some(local.mac.clone()); cloud.ip.clear(); cloud.port = 0; cloud.key = Some("0123456789abcdef".into()); db.save_device(&local).unwrap(); db.save_device(&cloud).unwrap(); let devices = db.list_devices().unwrap(); assert_eq!(devices.len(), 2); assert!(devices.iter().any(|item| item.connection_type == ConnectionType::Local)); assert!(devices.iter().any(|item| item.connection_type == ConnectionType::GreeCloud)); } }