1use std::fmt::Debug;
6
7use serde::{Deserialize, Serialize};
8
9use crate::Access;
10use crate::group::resolver::StrongRemove;
11use crate::group::{GroupAction, GroupCrdt, GroupCrdtError, GroupCrdtState, GroupMember};
12use crate::traits::Operation;
13
14pub type MemberId = char;
15pub type MessageId = u32;
16pub type Conditions = ();
17pub type TestGroupState = GroupCrdtState<MemberId, MessageId, TestOperation, Conditions>;
18pub type TestGroup = GroupCrdt<MemberId, MessageId, TestOperation, Conditions, TestResolver>;
19pub type TestResolver = StrongRemove<MemberId, MessageId, TestOperation, Conditions>;
20pub type TestGroupError =
21 GroupCrdtError<MemberId, MessageId, TestOperation, Conditions, TestResolver>;
22
23#[derive(Clone, Debug, Deserialize, Serialize)]
24pub struct TestOperation {
25 pub id: u32,
26 pub author: char,
27 pub dependencies: Vec<u32>,
28 pub group_id: char,
29 pub action: GroupAction<char, Conditions>,
30}
31
32impl Operation<char, u32, Conditions> for TestOperation {
33 fn id(&self) -> u32 {
34 self.id
35 }
36
37 fn author(&self) -> char {
38 self.author
39 }
40
41 fn dependencies(&self) -> Vec<u32> {
42 self.dependencies.clone()
43 }
44
45 fn group_id(&self) -> char {
46 self.group_id
47 }
48
49 fn action(&self) -> GroupAction<char, Conditions> {
50 self.action.clone()
51 }
52}
53
54fn make_group_op(
55 actor_id: MemberId,
56 operation_id: MessageId,
57 group_id: MemberId,
58 action: GroupAction<MemberId, ()>,
59 dependencies: Vec<MessageId>,
60) -> TestOperation {
61 TestOperation {
62 id: operation_id,
63 author: actor_id,
64 dependencies,
65 group_id,
66 action,
67 }
68}
69
70pub fn create_group(
71 actor_id: MemberId,
72 operation_id: MessageId,
73 group_id: MemberId,
74 initial_members: Vec<(GroupMember<MemberId>, Access<()>)>,
75 dependencies: Vec<MessageId>,
76) -> TestOperation {
77 make_group_op(
78 actor_id,
79 operation_id,
80 group_id,
81 GroupAction::Create { initial_members },
82 dependencies,
83 )
84}
85
86pub fn add_member(
87 actor_id: MemberId,
88 operation_id: MessageId,
89 group_id: MemberId,
90 member: GroupMember<MemberId>,
91 access: Access<()>,
92 dependencies: Vec<MessageId>,
93) -> TestOperation {
94 make_group_op(
95 actor_id,
96 operation_id,
97 group_id,
98 GroupAction::Add { member, access },
99 dependencies,
100 )
101}
102
103pub fn remove_member(
104 actor_id: MemberId,
105 operation_id: MessageId,
106 group_id: MemberId,
107 member: GroupMember<MemberId>,
108 dependencies: Vec<MessageId>,
109) -> TestOperation {
110 make_group_op(
111 actor_id,
112 operation_id,
113 group_id,
114 GroupAction::Remove { member },
115 dependencies,
116 )
117}
118
119pub fn promote_member(
120 actor_id: MemberId,
121 operation_id: MessageId,
122 group_id: MemberId,
123 member: GroupMember<MemberId>,
124 access: Access<()>,
125 dependencies: Vec<MessageId>,
126) -> TestOperation {
127 make_group_op(
128 actor_id,
129 operation_id,
130 group_id,
131 GroupAction::Promote { member, access },
132 dependencies,
133 )
134}
135
136pub fn demote_member(
137 actor_id: MemberId,
138 operation_id: MessageId,
139 group_id: MemberId,
140 member: GroupMember<MemberId>,
141 access: Access<()>,
142 dependencies: Vec<MessageId>,
143) -> TestOperation {
144 make_group_op(
145 actor_id,
146 operation_id,
147 group_id,
148 GroupAction::Demote { member, access },
149 dependencies,
150 )
151}
152
153pub fn sync(
154 y: GroupCrdtState<MemberId, MessageId, TestOperation, Conditions>,
155 ops: &[TestOperation],
156) -> GroupCrdtState<MemberId, MessageId, TestOperation, Conditions> {
157 ops.iter().fold(y, |g, op| {
158 GroupCrdt::<MemberId, MessageId, TestOperation, Conditions, TestResolver>::process(g, op)
159 .unwrap()
160 })
161}
162
163pub fn assert_members(
164 y: &GroupCrdtState<MemberId, MessageId, TestOperation, Conditions>,
165 group_id: MemberId,
166 expected: &[(char, Access<()>)],
167) {
168 let mut actual = y.members(group_id);
169 let mut expected = expected.to_vec();
170 actual.sort();
171 expected.sort();
172 assert_eq!(actual, expected);
173}