Skip to main content

p2panda_auth/test_utils/
mod.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! Test utilities.
4
5use 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}