332 lines · 11.5 KB · Rust
RawDownload
use warp_util::standardized_path::StandardizedPath; use super::super::protocol::RequestId;use super::super::server_model::ConnectionId;use super::{DiffModelKey, RemoteDiffStateManager};use crate::code_review::diff_state::{BackendOrigin, DiffMode, LocalDiffStateModel}; /// Uses `try_new` instead of `try_from_local` so that Unix-style paths/// like `/repo` are recognised as absolute on all platforms (including Windows).fn test_key(repo: &str, mode: DiffMode) -> DiffModelKey {    DiffModelKey {        repo_path: StandardizedPath::try_new(repo).unwrap(),        mode,    }} fn new_conn() -> ConnectionId {    uuid::Uuid::new_v4()} // ── Subscription tracking ─────────────────────────────────────────── #[test]fn subscribe_registers_connection() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);    let conn = new_conn();     model.subscribe_connection(key.clone(), conn);     assert_eq!(model.subscribed_connections(&key), vec![conn]);} #[test]fn subscribe_multiple_connections_to_same_key() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);    let conn_a = new_conn();    let conn_b = new_conn();     model.subscribe_connection(key.clone(), conn_a);    model.subscribe_connection(key.clone(), conn_b);     let subs = model.subscribed_connections(&key);    assert_eq!(subs.len(), 2);    assert!(subs.contains(&conn_a));    assert!(subs.contains(&conn_b));} #[test]fn subscribe_same_connection_to_different_keys() {    let mut model = RemoteDiffStateManager::new();    let key_head = test_key("/repo", DiffMode::Head);    let key_main = test_key("/repo", DiffMode::MainBranch);    let conn = new_conn();     model.subscribe_connection(key_head.clone(), conn);    model.subscribe_connection(key_main.clone(), conn);     assert_eq!(model.subscribed_connections(&key_head), vec![conn]);    assert_eq!(model.subscribed_connections(&key_main), vec![conn]);} #[test]fn subscribed_connections_returns_empty_for_unknown_key() {    let model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);     assert!(model.subscribed_connections(&key).is_empty());} // ── Unsubscribe ───────────────────────────────────────────────────── #[test]fn unsubscribe_last_connection_removes_model() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);    let conn = new_conn();     // Simulate model insertion + subscription (what handle_get_diff_state does).    warpui::App::test((), |mut app| async move {        let handle =            app.add_model(|ctx| LocalDiffStateModel::new(None, BackendOrigin::ClientLocal, ctx));        model.insert_model(key.clone(), handle);        model.subscribe_connection(key.clone(), conn);         model.unsubscribe_connection(&key, conn);         assert!(model.get_model(&key).is_none());        assert!(model.subscribed_connections(&key).is_empty());    });} #[test]fn unsubscribe_one_of_two_keeps_model() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);    let conn_a = new_conn();    let conn_b = new_conn();     warpui::App::test((), |mut app| async move {        let handle =            app.add_model(|ctx| LocalDiffStateModel::new(None, BackendOrigin::ClientLocal, ctx));        model.insert_model(key.clone(), handle);        model.subscribe_connection(key.clone(), conn_a);        model.subscribe_connection(key.clone(), conn_b);         model.unsubscribe_connection(&key, conn_a);         assert!(model.get_model(&key).is_some());        assert_eq!(model.subscribed_connections(&key), vec![conn_b]);    });} #[test]fn unsubscribe_clears_pending_responses_for_that_connection() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);    let conn_a = new_conn();    let conn_b = new_conn();     warpui::App::test((), |mut app| async move {        let handle =            app.add_model(|ctx| LocalDiffStateModel::new(None, BackendOrigin::ClientLocal, ctx));        model.insert_model(key.clone(), handle);        model.subscribe_connection(key.clone(), conn_a);        model.subscribe_connection(key.clone(), conn_b);        model.add_pending_response(key.clone(), RequestId::new(), conn_a);        model.add_pending_response(key.clone(), RequestId::new(), conn_b);         model.unsubscribe_connection(&key, conn_a);         // Only conn_b's pending response should remain.        let pending = model.drain_pending_responses(&key);        assert_eq!(pending.len(), 1);        assert_eq!(pending[0].conn_id, conn_b);    });} // ── remove_connection ─────────────────────────────────────────────── #[test]fn remove_connection_unsubscribes_from_all_keys() {    let mut model = RemoteDiffStateManager::new();    let key_head = test_key("/repo", DiffMode::Head);    let key_main = test_key("/repo", DiffMode::MainBranch);    let conn = new_conn();     warpui::App::test((), |mut app| async move {        let h1 =            app.add_model(|ctx| LocalDiffStateModel::new(None, BackendOrigin::ClientLocal, ctx));        let h2 =            app.add_model(|ctx| LocalDiffStateModel::new(None, BackendOrigin::ClientLocal, ctx));        model.insert_model(key_head.clone(), h1);        model.insert_model(key_main.clone(), h2);        model.subscribe_connection(key_head.clone(), conn);        model.subscribe_connection(key_main.clone(), conn);         model.remove_connection(conn);         // Both models dropped because conn was the sole subscriber.        assert!(model.get_model(&key_head).is_none());        assert!(model.get_model(&key_main).is_none());    });} #[test]fn remove_connection_keeps_models_with_other_subscribers() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);    let conn_a = new_conn();    let conn_b = new_conn();     warpui::App::test((), |mut app| async move {        let handle =            app.add_model(|ctx| LocalDiffStateModel::new(None, BackendOrigin::ClientLocal, ctx));        model.insert_model(key.clone(), handle);        model.subscribe_connection(key.clone(), conn_a);        model.subscribe_connection(key.clone(), conn_b);         model.remove_connection(conn_a);         assert!(model.get_model(&key).is_some());        assert_eq!(model.subscribed_connections(&key), vec![conn_b]);    });} #[test]fn remove_connection_clears_pending_responses() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);    let conn = new_conn();     warpui::App::test((), |mut app| async move {        let handle =            app.add_model(|ctx| LocalDiffStateModel::new(None, BackendOrigin::ClientLocal, ctx));        model.insert_model(key.clone(), handle);        model.subscribe_connection(key.clone(), conn);        model.add_pending_response(key.clone(), RequestId::new(), conn);         model.remove_connection(conn);         // Model removed, so pending responses should be gone too.        assert!(!model.has_pending_responses(&key));    });} // ── Pending response tracking ─────────────────────────────────────── #[test]fn has_pending_responses_false_when_empty() {    let model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);     assert!(!model.has_pending_responses(&key));} #[test]fn add_and_drain_pending_responses() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);    let conn = new_conn();    let rid = RequestId::new();     model.add_pending_response(key.clone(), rid, conn);     assert!(model.has_pending_responses(&key));     let drained = model.drain_pending_responses(&key);    assert_eq!(drained.len(), 1);    assert_eq!(drained[0].conn_id, conn);     // After drain, no pending responses remain.    assert!(!model.has_pending_responses(&key));} #[test]fn drain_pending_responses_returns_empty_for_unknown_key() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);     assert!(model.drain_pending_responses(&key).is_empty());} #[test]fn multiple_pending_responses_for_same_key() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);    let conn_a = new_conn();    let conn_b = new_conn();     model.add_pending_response(key.clone(), RequestId::new(), conn_a);    model.add_pending_response(key.clone(), RequestId::new(), conn_b);     let drained = model.drain_pending_responses(&key);    assert_eq!(drained.len(), 2);    assert_eq!(drained[0].conn_id, conn_a);    assert_eq!(drained[1].conn_id, conn_b);} // ── Model CRUD ────────────────────────────────────────────────────── #[test]fn get_model_returns_none_when_empty() {    let model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);     assert!(model.get_model(&key).is_none());} #[test]fn insert_and_get_model() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);     warpui::App::test((), |mut app| async move {        let handle =            app.add_model(|ctx| LocalDiffStateModel::new(None, BackendOrigin::ClientLocal, ctx));        model.insert_model(key.clone(), handle);         assert!(model.get_model(&key).is_some());    });} #[test]fn remove_model_clears_pending_and_subscriptions() {    let mut model = RemoteDiffStateManager::new();    let key = test_key("/repo", DiffMode::Head);    let conn = new_conn();     warpui::App::test((), |mut app| async move {        let handle =            app.add_model(|ctx| LocalDiffStateModel::new(None, BackendOrigin::ClientLocal, ctx));        model.insert_model(key.clone(), handle);        model.subscribe_connection(key.clone(), conn);        model.add_pending_response(key.clone(), RequestId::new(), conn);         model.remove_model(&key);         assert!(model.get_model(&key).is_none());        assert!(!model.has_pending_responses(&key));        assert!(model.subscribed_connections(&key).is_empty());    });} // ── Key equality ──────────────────────────────────────────────────── #[test]fn different_modes_are_different_keys() {    let mut model = RemoteDiffStateManager::new();    let key_head = test_key("/repo", DiffMode::Head);    let key_main = test_key("/repo", DiffMode::MainBranch);    let conn = new_conn();     model.subscribe_connection(key_head.clone(), conn);     assert_eq!(model.subscribed_connections(&key_head).len(), 1);    assert!(model.subscribed_connections(&key_main).is_empty());} #[test]fn different_repos_are_different_keys() {    let mut model = RemoteDiffStateManager::new();    let key_a = test_key("/repo-a", DiffMode::Head);    let key_b = test_key("/repo-b", DiffMode::Head);    let conn = new_conn();     model.subscribe_connection(key_a.clone(), conn);     assert_eq!(model.subscribed_connections(&key_a).len(), 1);    assert!(model.subscribed_connections(&key_b).is_empty());}