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