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