use x0x::crdt::{EncryptedTaskListDelta, TaskListDelta};
use x0x::identity::Identity;
use x0x::mls::{MlsGroup, MlsKeySchedule, MlsWelcome};
#[tokio::test]
async fn test_group_creation() {
let identity = Identity::generate().expect("identity generation failed");
let agent_id = identity.agent_id();
let group_id = b"test-group".to_vec();
let group = MlsGroup::new(group_id.clone(), agent_id)
.await
.expect("group creation failed");
assert_eq!(group.context().group_id(), &group_id);
assert_eq!(group.current_epoch(), 0);
assert!(group.members().contains_key(&agent_id));
assert_eq!(group.members().len(), 1);
}
#[tokio::test]
async fn test_member_addition() {
let initiator = Identity::generate().expect("identity generation failed");
let initiator_id = initiator.agent_id();
let group_id = b"test-group".to_vec();
let mut group = MlsGroup::new(group_id.clone(), initiator_id)
.await
.expect("group creation failed");
let invitee = Identity::generate().expect("identity generation failed");
let invitee_id = invitee.agent_id();
let welcome = MlsWelcome::create(&group, &invitee_id).expect("welcome creation failed");
assert!(welcome.verify().is_ok());
let invitee_context = welcome.accept(&invitee_id).expect("welcome accept failed");
assert_eq!(invitee_context.group_id(), group.context().group_id());
assert_eq!(invitee_context.epoch(), group.current_epoch());
let _commit = group
.add_member(invitee_id)
.await
.expect("member addition failed");
assert!(group.members().contains_key(&invitee_id));
assert_eq!(group.members().len(), 2);
}
#[tokio::test]
async fn test_member_removal() {
let initiator = Identity::generate().expect("identity generation failed");
let initiator_id = initiator.agent_id();
let group_id = b"test-group".to_vec();
let mut group = MlsGroup::new(group_id, initiator_id)
.await
.expect("group creation failed");
let member = Identity::generate().expect("identity generation failed");
let member_id = member.agent_id();
let _add_commit = group
.add_member(member_id)
.await
.expect("add member failed");
assert_eq!(group.members().len(), 2);
let _remove_commit = group
.remove_member(member_id)
.await
.expect("remove member failed");
assert!(!group.members().contains_key(&member_id));
assert_eq!(group.members().len(), 1);
}
#[tokio::test]
async fn test_key_rotation() {
let identity = Identity::generate().expect("identity generation failed");
let agent_id = identity.agent_id();
let group_id = b"test-group".to_vec();
let mut group = MlsGroup::new(group_id, agent_id)
.await
.expect("group creation failed");
let schedule1 = MlsKeySchedule::from_group(&group).expect("key schedule failed");
let key1 = schedule1.encryption_key().to_vec();
let epoch1 = group.current_epoch();
let commit = group.commit().expect("commit failed");
group.apply_commit(&commit).expect("apply commit failed");
let schedule2 = MlsKeySchedule::from_group(&group).expect("key schedule failed");
let key2 = schedule2.encryption_key().to_vec();
let epoch2 = group.current_epoch();
assert_ne!(key1, key2);
assert_eq!(epoch1 + 1, epoch2);
}
#[tokio::test]
async fn test_forward_secrecy() {
let identity = Identity::generate().expect("identity generation failed");
let agent_id = identity.agent_id();
let group_id = b"test-group".to_vec();
let mut group = MlsGroup::new(group_id, agent_id)
.await
.expect("group creation failed");
let delta1 = TaskListDelta::new(1);
let encrypted1 =
EncryptedTaskListDelta::encrypt_with_group(&delta1, &group).expect("encryption failed");
let commit = group.commit().expect("commit failed");
group.apply_commit(&commit).expect("apply commit failed");
let result = encrypted1.decrypt_with_group(&group);
assert!(result.is_err());
let delta2 = TaskListDelta::new(2);
let encrypted2 =
EncryptedTaskListDelta::encrypt_with_group(&delta2, &group).expect("encryption failed");
let decrypted2 = encrypted2
.decrypt_with_group(&group)
.expect("decryption failed");
assert_eq!(decrypted2.version, delta2.version);
}
#[tokio::test]
async fn test_encrypted_task_list_sync() {
let initiator = Identity::generate().expect("identity generation failed");
let initiator_id = initiator.agent_id();
let group_id = b"collaboration-group".to_vec();
let group = MlsGroup::new(group_id.clone(), initiator_id)
.await
.expect("group creation failed");
let delta = TaskListDelta::new(1);
let encrypted =
EncryptedTaskListDelta::encrypt_with_group(&delta, &group).expect("encryption failed");
assert_eq!(encrypted.group_id(), group.context().group_id());
assert_eq!(encrypted.epoch(), group.current_epoch());
let decrypted = encrypted
.decrypt_with_group(&group)
.expect("decryption failed");
assert_eq!(decrypted.version, delta.version);
assert_eq!(decrypted.added_tasks.len(), delta.added_tasks.len());
}
#[tokio::test]
async fn test_multi_agent_group_operations() {
let initiator = Identity::generate().expect("identity generation failed");
let initiator_id = initiator.agent_id();
let group_id = b"multi-agent-group".to_vec();
let mut group = MlsGroup::new(group_id.clone(), initiator_id)
.await
.expect("group creation failed");
let agent2 = Identity::generate().expect("identity generation failed");
let agent2_id = agent2.agent_id();
let _commit1 = group.add_member(agent2_id).await.expect("add failed");
let agent3 = Identity::generate().expect("identity generation failed");
let agent3_id = agent3.agent_id();
let _commit2 = group.add_member(agent3_id).await.expect("add failed");
assert_eq!(group.members().len(), 3);
assert!(group.members().contains_key(&initiator_id));
assert!(group.members().contains_key(&agent2_id));
assert!(group.members().contains_key(&agent3_id));
let delta = TaskListDelta::new(1);
let encrypted =
EncryptedTaskListDelta::encrypt_with_group(&delta, &group).expect("encryption failed");
let decrypted = encrypted
.decrypt_with_group(&group)
.expect("decryption failed");
assert_eq!(decrypted.version, delta.version);
let commit = group.commit().expect("commit failed");
let old_epoch = group.current_epoch();
group.apply_commit(&commit).expect("apply failed");
assert_eq!(group.current_epoch(), old_epoch + 1);
let result = encrypted.decrypt_with_group(&group);
assert!(result.is_err());
}
#[tokio::test]
async fn test_invalid_group_creation() {
let identity = Identity::generate().expect("identity generation failed");
let agent_id = identity.agent_id();
let empty_group = MlsGroup::new(vec![], agent_id).await;
assert!(empty_group.is_ok());
}
#[tokio::test]
async fn test_welcome_wrong_recipient() {
let initiator = Identity::generate().expect("identity generation failed");
let initiator_id = initiator.agent_id();
let group_id = b"test-group".to_vec();
let group = MlsGroup::new(group_id, initiator_id)
.await
.expect("group creation failed");
let invitee = Identity::generate().expect("identity generation failed");
let invitee_id = invitee.agent_id();
let wrong_agent = Identity::generate().expect("identity generation failed");
let wrong_agent_id = wrong_agent.agent_id();
let welcome = MlsWelcome::create(&group, &invitee_id).expect("welcome creation failed");
let result = welcome.accept(&wrong_agent_id);
assert!(result.is_err());
}
#[tokio::test]
async fn test_encryption_authentication() {
let identity = Identity::generate().expect("identity generation failed");
let agent_id = identity.agent_id();
let group_id = b"test-group".to_vec();
let group = MlsGroup::new(group_id, agent_id)
.await
.expect("group creation failed");
let delta = TaskListDelta::new(1);
let encrypted =
EncryptedTaskListDelta::encrypt_with_group(&delta, &group).expect("encryption failed");
let ciphertext = encrypted.ciphertext().to_vec();
let mut tampered = ciphertext;
tampered[0] ^= 1;
let _tampered_encrypted =
EncryptedTaskListDelta::encrypt_with_group(&delta, &group).expect("encryption failed");
let decrypted = encrypted
.decrypt_with_group(&group)
.expect("decryption should succeed");
assert_eq!(decrypted.version, delta.version);
}
#[tokio::test]
async fn test_epoch_consistency() {
let identity = Identity::generate().expect("identity generation failed");
let agent_id = identity.agent_id();
let group_id = b"test-group".to_vec();
let mut group = MlsGroup::new(group_id, agent_id)
.await
.expect("group creation failed");
let initial_epoch = group.current_epoch();
assert_eq!(initial_epoch, 0);
for i in 1..=5 {
let commit = group.commit().expect("commit failed");
group.apply_commit(&commit).expect("apply failed");
assert_eq!(group.current_epoch(), i);
}
assert_eq!(group.current_epoch(), 5);
}