use std::fmt::Debug;
use serde::{Deserialize, Serialize};
use crate::Access;
use crate::group::resolver::StrongRemove;
use crate::group::{GroupAction, GroupCrdt, GroupCrdtError, GroupCrdtState, GroupMember};
use crate::traits::{IdentityHandle, Operation, OperationId};
impl IdentityHandle for char {}
impl OperationId for u32 {}
pub type MemberId = char;
pub type MessageId = u32;
pub type Conditions = ();
pub type TestGroupState = GroupCrdtState<MemberId, MessageId, TestOperation, Conditions>;
pub type TestGroup = GroupCrdt<MemberId, MessageId, TestOperation, Conditions, TestResolver>;
pub type TestResolver = StrongRemove<MemberId, MessageId, TestOperation, Conditions>;
pub type TestGroupError =
GroupCrdtError<MemberId, MessageId, TestOperation, Conditions, TestResolver>;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TestOperation {
pub id: u32,
pub author: char,
pub dependencies: Vec<u32>,
pub group_id: char,
pub action: GroupAction<char, Conditions>,
}
impl Operation<char, u32, Conditions> for TestOperation {
fn id(&self) -> u32 {
self.id
}
fn author(&self) -> char {
self.author
}
fn dependencies(&self) -> Vec<u32> {
self.dependencies.clone()
}
fn group_id(&self) -> char {
self.group_id
}
fn action(&self) -> GroupAction<char, Conditions> {
self.action.clone()
}
}
fn make_group_op(
actor_id: MemberId,
operation_id: MessageId,
group_id: MemberId,
action: GroupAction<MemberId, ()>,
dependencies: Vec<MessageId>,
) -> TestOperation {
TestOperation {
id: operation_id,
author: actor_id,
dependencies,
group_id,
action,
}
}
pub fn create_group(
actor_id: MemberId,
operation_id: MessageId,
group_id: MemberId,
initial_members: Vec<(GroupMember<MemberId>, Access<()>)>,
dependencies: Vec<MessageId>,
) -> TestOperation {
make_group_op(
actor_id,
operation_id,
group_id,
GroupAction::Create { initial_members },
dependencies,
)
}
pub fn add_member(
actor_id: MemberId,
operation_id: MessageId,
group_id: MemberId,
member: GroupMember<MemberId>,
access: Access<()>,
dependencies: Vec<MessageId>,
) -> TestOperation {
make_group_op(
actor_id,
operation_id,
group_id,
GroupAction::Add { member, access },
dependencies,
)
}
pub fn remove_member(
actor_id: MemberId,
operation_id: MessageId,
group_id: MemberId,
member: GroupMember<MemberId>,
dependencies: Vec<MessageId>,
) -> TestOperation {
make_group_op(
actor_id,
operation_id,
group_id,
GroupAction::Remove { member },
dependencies,
)
}
pub fn promote_member(
actor_id: MemberId,
operation_id: MessageId,
group_id: MemberId,
member: GroupMember<MemberId>,
access: Access<()>,
dependencies: Vec<MessageId>,
) -> TestOperation {
make_group_op(
actor_id,
operation_id,
group_id,
GroupAction::Promote { member, access },
dependencies,
)
}
pub fn demote_member(
actor_id: MemberId,
operation_id: MessageId,
group_id: MemberId,
member: GroupMember<MemberId>,
access: Access<()>,
dependencies: Vec<MessageId>,
) -> TestOperation {
make_group_op(
actor_id,
operation_id,
group_id,
GroupAction::Demote { member, access },
dependencies,
)
}
pub fn sync(
y: GroupCrdtState<MemberId, MessageId, TestOperation, Conditions>,
ops: &[TestOperation],
) -> GroupCrdtState<MemberId, MessageId, TestOperation, Conditions> {
ops.iter().fold(y, |g, op| {
GroupCrdt::<MemberId, MessageId, TestOperation, Conditions, TestResolver>::process(g, op)
.unwrap()
})
}
pub fn assert_members(
y: &GroupCrdtState<MemberId, MessageId, TestOperation, Conditions>,
group_id: MemberId,
expected: &[(char, Access<()>)],
) {
let mut actual = y.members(group_id);
let mut expected = expected.to_vec();
actual.sort();
expected.sort();
assert_eq!(actual, expected);
}