p2panda_auth/test_utils/
mod.rs

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