use {super::*, crate::session::SessionToken};
fn test_registry() -> Arc<SessionRegistry> {
let registry = Arc::new(SessionRegistry::new());
let session = Arc::new(Session::new(SessionId::new("test")));
registry.insert(&session);
registry
}
fn test_tokens() -> Arc<TokenRegistry> {
Arc::new(TokenRegistry::new())
}
fn authed_request<T>(body: T, client_id: ClientId) -> Request<T> {
let mut request = Request::new(body);
request.extensions_mut().insert(client_id);
request
}
#[tokio::test]
async fn test_join_no_session() {
let registry = Arc::new(SessionRegistry::new());
let service = PresenceServiceImpl::new(registry, SessionId::new("nonexistent"), test_tokens());
let request = Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
});
let response = service.join(request).await;
assert!(response.is_err());
let err = response.err().unwrap();
assert_eq!(err.code(), tonic::Code::NotFound);
}
#[tokio::test]
async fn test_join_success() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let request = Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
});
let response = service.join(request).await;
assert!(response.is_ok());
let resp = response.unwrap().into_inner();
assert!(resp.client_id > 0);
assert!(resp.peers.is_empty()); assert!(!resp.session_token.is_empty());
assert_eq!(resp.session_token.len(), 32); }
#[tokio::test]
async fn test_join_returns_peers() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let request1 = Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
});
let _ = service.join(request1).await.unwrap();
let request2 = Request::new(JoinRequest {
client_type: "android".to_string(),
display_name: "phone".to_string(),
});
let response = service.join(request2).await;
assert!(response.is_ok());
let resp = response.unwrap().into_inner();
assert_eq!(resp.peers.len(), 1);
assert_eq!(resp.peers[0].display_name, "laptop");
}
#[tokio::test]
async fn test_leave_success() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let join_req = Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
});
let join_resp = service.join(join_req).await.unwrap().into_inner();
let cid = ClientId::new(join_resp.client_id as usize);
let leave_req = authed_request(LeaveRequest {}, cid);
let response = service.leave(leave_req).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_leave_unknown_client() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let request = authed_request(LeaveRequest {}, ClientId::new(999));
let response = service.leave(request).await;
assert!(response.is_ok());
assert!(!response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_update_presence_success() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let join_req = Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
});
let join_resp = service.join(join_req).await.unwrap().into_inner();
let cid = ClientId::new(join_resp.client_id as usize);
let update_req = authed_request(
UpdatePresenceRequest {
buffer_id: Some(42),
visible_lines: Some(LineRange { start: 5, end: 30 }),
mode: Some("INSERT".to_string()),
},
cid,
);
let response = service.update_presence(update_req).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_update_presence_unknown_client() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let request = authed_request(
UpdatePresenceRequest {
buffer_id: Some(42),
visible_lines: None,
mode: None,
},
ClientId::new(999),
);
let response = service.update_presence(request).await;
assert!(response.is_err());
assert_eq!(response.err().unwrap().code(), tonic::Code::NotFound);
}
#[tokio::test]
async fn test_set_sync_mode_independent() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let join_resp = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(join_resp.client_id as usize);
let request = authed_request(
SetSyncModeRequest {
mode: ProtoSyncMode::Independent as i32,
follow_target: None,
},
cid,
);
let response = service.set_sync_mode(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_set_sync_mode_present() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let join_resp = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(join_resp.client_id as usize);
let request = authed_request(
SetSyncModeRequest {
mode: ProtoSyncMode::Present as i32,
follow_target: None,
},
cid,
);
let response = service.set_sync_mode(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_set_sync_mode_follow_success() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let resp1 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "presenter".to_string(),
}))
.await
.unwrap()
.into_inner();
let presenter_id = resp1.client_id;
let resp2 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "follower".to_string(),
}))
.await
.unwrap()
.into_inner();
let follower_cid = ClientId::new(resp2.client_id as usize);
let request = authed_request(
SetSyncModeRequest {
mode: ProtoSyncMode::Follow as i32,
follow_target: Some(presenter_id),
},
follower_cid,
);
let response = service.set_sync_mode(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_set_sync_mode_follow_missing_target() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let join_resp = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(join_resp.client_id as usize);
let request = authed_request(
SetSyncModeRequest {
mode: ProtoSyncMode::Follow as i32,
follow_target: None,
},
cid,
);
let response = service.set_sync_mode(request).await;
assert!(response.is_err());
assert_eq!(response.err().unwrap().code(), tonic::Code::InvalidArgument);
}
#[tokio::test]
async fn test_set_sync_mode_follow_invalid_target() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let join_resp = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(join_resp.client_id as usize);
let request = authed_request(
SetSyncModeRequest {
mode: ProtoSyncMode::Follow as i32,
follow_target: Some(9999),
},
cid,
);
let response = service.set_sync_mode(request).await;
assert!(response.is_err());
assert_eq!(response.err().unwrap().code(), tonic::Code::InvalidArgument);
}
#[tokio::test]
async fn test_list_clients() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let request = Request::new(ListClientsRequest {});
let response = service.list_clients(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().clients.is_empty());
let _ = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
}))
.await
.unwrap();
let _ = service
.join(Request::new(JoinRequest {
client_type: "android".to_string(),
display_name: "phone".to_string(),
}))
.await
.unwrap();
let request = Request::new(ListClientsRequest {});
let response = service.list_clients(request).await;
assert!(response.is_ok());
let clients = response.unwrap().into_inner().clients;
assert_eq!(clients.len(), 2);
}
#[tokio::test]
async fn test_stream_presence_returns_stream() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let request = Request::new(StreamPresenceRequest {});
let response = service.stream_presence(request).await;
assert!(response.is_ok());
}
#[tokio::test]
async fn test_join_returns_session_token() {
let tokens = test_tokens();
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), Arc::clone(&tokens));
let resp = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "test".to_string(),
}))
.await
.unwrap()
.into_inner();
assert_eq!(resp.session_token.len(), 32);
let token = SessionToken::from(resp.session_token.as_str());
assert_eq!(tokens.resolve(&token), Some(ClientId::new(resp.client_id as usize)));
}
#[tokio::test]
async fn test_leave_revokes_token() {
let tokens = test_tokens();
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), Arc::clone(&tokens));
let join_resp = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "test".to_string(),
}))
.await
.unwrap()
.into_inner();
let token = SessionToken::from(join_resp.session_token.as_str());
assert!(tokens.resolve(&token).is_some());
let cid = ClientId::new(join_resp.client_id as usize);
service
.leave(authed_request(LeaveRequest {}, cid))
.await
.unwrap();
assert!(tokens.resolve(&token).is_none());
assert!(tokens.is_empty());
}
#[test]
fn test_to_proto_client_info_independent() {
use {
crate::session::ClientMetadata,
reovim_kernel::api::v1::{ModeId, ModeStack, ModuleId},
};
let mode = ModeId::new(ModuleId::new("test"), "normal");
let mode_stack = ModeStack::new(mode);
let metadata = ClientMetadata::default();
let client = Client::with_mode_stack(ClientId::new(42), metadata, mode_stack);
let info = to_proto_client_info(&client);
assert_eq!(info.id, 42);
assert!(info.relation.is_none()); assert!(info.view.is_some());
assert_eq!(info.view.as_ref().unwrap().mode, "normal");
assert!(info.metadata.is_some());
}
#[test]
fn test_to_proto_client_info_following() {
use {
crate::session::{ClientMetadata, ClientRelation},
reovim_driver_session::Window,
reovim_kernel::api::v1::{ModeId, ModeStack, ModuleId},
};
let mode = ModeId::new(ModuleId::new("test"), "normal");
let mode_stack = ModeStack::new(mode);
let buffer_id = reovim_kernel::api::v1::BufferId::from_raw(10);
let window = Window::with_buffer(buffer_id);
let metadata = ClientMetadata::default();
let mut client =
Client::with_mode_stack_and_window(ClientId::new(5), metadata, mode_stack, window);
client.set_relation_unchecked(Some(ClientRelation::Following {
target: ClientId::new(1),
}));
let info = to_proto_client_info(&client);
assert_eq!(info.id, 5);
let rel = info.relation.unwrap();
assert_eq!(rel.r#type, ProtoRelationType::RelationTypeFollowing as i32);
assert_eq!(rel.target_id, 1);
assert!(info.view.as_ref().unwrap().buffer_id.is_some());
}
#[test]
fn test_to_proto_client_info_sharing() {
use {
crate::session::{ClientMetadata, ClientRelation},
reovim_kernel::api::v1::{ModeId, ModeStack, ModuleId},
};
let mode = ModeId::new(ModuleId::new("test"), "normal");
let mode_stack = ModeStack::new(mode);
let metadata = ClientMetadata::default();
let mut client = Client::with_mode_stack(ClientId::new(3), metadata, mode_stack);
client.set_relation_unchecked(Some(ClientRelation::Sharing {
with: ClientId::new(2),
}));
let info = to_proto_client_info(&client);
let rel = info.relation.unwrap();
assert_eq!(rel.r#type, ProtoRelationType::RelationTypeSharing as i32);
assert_eq!(rel.target_id, 2);
}
#[test]
fn test_to_proto_presence_independent() {
let presence = ClientPresence::new(ClientId::new(1), "tui", "laptop");
let proto = to_proto_presence(&presence);
assert_eq!(proto.client_id, 1);
assert_eq!(proto.client_type, "tui");
assert_eq!(proto.display_name, "laptop");
assert_eq!(proto.sync_mode, ProtoSyncMode::Independent as i32);
assert!(proto.follow_target.is_none());
}
#[test]
fn test_to_proto_presence_follow() {
let mut presence = ClientPresence::new(ClientId::new(2), "cli", "terminal");
presence.sync_mode = SyncMode::Follow {
target: ClientId::new(1),
};
let proto = to_proto_presence(&presence);
assert_eq!(proto.sync_mode, ProtoSyncMode::Follow as i32);
assert_eq!(proto.follow_target, Some(1));
}
#[test]
fn test_to_proto_presence_present() {
let mut presence = ClientPresence::new(ClientId::new(3), "web", "browser");
presence.sync_mode = SyncMode::Present;
let proto = to_proto_presence(&presence);
assert_eq!(proto.sync_mode, ProtoSyncMode::Present as i32);
assert!(proto.follow_target.is_none());
}
#[test]
fn test_notification_to_presence_update_joined() {
let presence = ClientPresence::new(ClientId::new(1), "tui", "laptop");
let notification = build_presence_joined_notification(&presence);
let update = notification_to_presence_update(¬ification);
assert!(update.is_some());
let u = update.unwrap();
assert!(matches!(u.update, Some(Update::Joined(_))));
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[test]
fn test_notification_to_presence_update_left() {
let notification = build_presence_left_notification(ClientId::new(5), "laptop");
let update = notification_to_presence_update(¬ification);
assert!(update.is_some());
let u = update.unwrap();
if let Some(Update::Left(id)) = u.update {
assert_eq!(id, 5);
} else {
panic!("Expected Left update");
}
}
#[test]
fn test_notification_to_presence_update_updated() {
let presence = ClientPresence::new(ClientId::new(3), "cli", "term");
let notification = build_presence_updated_notification(&presence);
let update = notification_to_presence_update(¬ification);
assert!(update.is_some());
assert!(matches!(update.unwrap().update, Some(Update::Updated(_))));
}
#[test]
fn test_notification_to_presence_update_non_presence() {
let notification = Notification {
event_type: "mode_changed".to_string(),
timestamp_ms: 0,
payload: None,
};
let update = notification_to_presence_update(¬ification);
assert!(update.is_none());
}
#[tokio::test]
async fn test_set_role_owner() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let join_resp = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "laptop".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(join_resp.client_id as usize);
let request = authed_request(
SetRoleRequest {
role: ProtoRole::Owner as i32,
target_id: None,
},
cid,
);
let response = service.set_role(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_set_role_follow() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let r1 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "owner".to_string(),
}))
.await
.unwrap()
.into_inner();
let r2 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "follower".to_string(),
}))
.await
.unwrap()
.into_inner();
let follower_cid = ClientId::new(r2.client_id as usize);
let request = authed_request(
SetRoleRequest {
role: ProtoRole::Follow as i32,
target_id: Some(r1.client_id),
},
follower_cid,
);
let response = service.set_role(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_set_role_share() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let r1 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "owner".to_string(),
}))
.await
.unwrap()
.into_inner();
let r2 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "sharer".to_string(),
}))
.await
.unwrap()
.into_inner();
let sharer_cid = ClientId::new(r2.client_id as usize);
let request = authed_request(
SetRoleRequest {
role: ProtoRole::Share as i32,
target_id: Some(r1.client_id),
},
sharer_cid,
);
let response = service.set_role(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_set_role_follow_missing_target_id() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let join_resp = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "test".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(join_resp.client_id as usize);
let request = authed_request(
SetRoleRequest {
role: ProtoRole::Follow as i32,
target_id: None, },
cid,
);
let response = service.set_role(request).await;
assert!(response.is_err());
assert_eq!(response.unwrap_err().code(), tonic::Code::InvalidArgument);
}
#[tokio::test]
async fn test_set_role_client_not_found() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let request = authed_request(
SetRoleRequest {
role: ProtoRole::Owner as i32,
target_id: None,
},
ClientId::new(999),
);
let response = service.set_role(request).await;
assert!(response.is_ok());
let resp = response.unwrap().into_inner();
assert!(!resp.ok);
assert!(resp.error.is_some());
}
#[tokio::test]
async fn test_set_role_follow_target_not_found() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let join_resp = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "test".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(join_resp.client_id as usize);
let request = authed_request(
SetRoleRequest {
role: ProtoRole::Follow as i32,
target_id: Some(9999), },
cid,
);
let response = service.set_role(request).await;
assert!(response.is_err());
assert_eq!(response.unwrap_err().code(), tonic::Code::FailedPrecondition);
}
#[tokio::test]
async fn test_set_relation_following() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let r1 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "target".to_string(),
}))
.await
.unwrap()
.into_inner();
let r2 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "follower".to_string(),
}))
.await
.unwrap()
.into_inner();
let follower_cid = ClientId::new(r2.client_id as usize);
let request = authed_request(
SetRelationRequest {
relation: Some(ProtoClientRelation {
r#type: ProtoRelationType::RelationTypeFollowing as i32,
target_id: r1.client_id,
}),
},
follower_cid,
);
let response = service.set_relation(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_set_relation_sharing() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let r1 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "owner".to_string(),
}))
.await
.unwrap()
.into_inner();
let r2 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "sharer".to_string(),
}))
.await
.unwrap()
.into_inner();
let sharer_cid = ClientId::new(r2.client_id as usize);
let request = authed_request(
SetRelationRequest {
relation: Some(ProtoClientRelation {
r#type: ProtoRelationType::RelationTypeSharing as i32,
target_id: r1.client_id,
}),
},
sharer_cid,
);
let response = service.set_relation(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_set_relation_independent() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let r1 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "test".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(r1.client_id as usize);
let request = authed_request(SetRelationRequest { relation: None }, cid);
let response = service.set_relation(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_set_relation_target_not_found() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let r1 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "test".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(r1.client_id as usize);
let request = authed_request(
SetRelationRequest {
relation: Some(ProtoClientRelation {
r#type: ProtoRelationType::RelationTypeFollowing as i32,
target_id: 99999,
}),
},
cid,
);
let response = service.set_relation(request).await;
assert!(response.is_ok());
let resp = response.unwrap().into_inner();
assert!(!resp.ok);
assert!(resp.error.is_some());
}
#[tokio::test]
async fn test_set_relation_self_target() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let r1 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "test".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(r1.client_id as usize);
let request = authed_request(
SetRelationRequest {
relation: Some(ProtoClientRelation {
r#type: ProtoRelationType::RelationTypeFollowing as i32,
target_id: r1.client_id,
}),
},
cid,
);
let response = service.set_relation(request).await;
assert!(response.is_ok());
let resp = response.unwrap().into_inner();
assert!(!resp.ok);
assert!(resp.error.is_some());
}
#[tokio::test]
async fn test_set_sync_mode_client_not_in_presence_map() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let request = authed_request(
SetSyncModeRequest {
mode: ProtoSyncMode::Independent as i32,
follow_target: None,
},
ClientId::new(42),
);
let response = service.set_sync_mode(request).await;
assert!(response.is_err());
assert_eq!(response.unwrap_err().code(), tonic::Code::NotFound);
}
#[tokio::test]
async fn test_set_role_share_missing_target_id() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let join_resp = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "test".to_string(),
}))
.await
.unwrap()
.into_inner();
let cid = ClientId::new(join_resp.client_id as usize);
let request = authed_request(
SetRoleRequest {
role: ProtoRole::Share as i32,
target_id: None, },
cid,
);
let response = service.set_role(request).await;
assert!(response.is_err());
assert_eq!(response.unwrap_err().code(), tonic::Code::InvalidArgument);
}
#[tokio::test]
async fn test_set_relation_invalid_type_defaults_to_following() {
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), test_tokens());
let r1 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "target".to_string(),
}))
.await
.unwrap()
.into_inner();
let r2 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "follower".to_string(),
}))
.await
.unwrap()
.into_inner();
let follower_cid = ClientId::new(r2.client_id as usize);
let request = authed_request(
SetRelationRequest {
relation: Some(ProtoClientRelation {
r#type: 999,
target_id: r1.client_id,
}),
},
follower_cid,
);
let response = service.set_relation(request).await;
assert!(response.is_ok());
assert!(response.unwrap().into_inner().ok);
}
#[tokio::test]
async fn test_each_client_gets_unique_token() {
let tokens = test_tokens();
let registry = test_registry();
let service = PresenceServiceImpl::new(registry, SessionId::new("test"), Arc::clone(&tokens));
let r1 = service
.join(Request::new(JoinRequest {
client_type: "tui".to_string(),
display_name: "a".to_string(),
}))
.await
.unwrap()
.into_inner();
let r2 = service
.join(Request::new(JoinRequest {
client_type: "cli".to_string(),
display_name: "b".to_string(),
}))
.await
.unwrap()
.into_inner();
assert_ne!(r1.session_token, r2.session_token);
assert_eq!(tokens.len(), 2);
}