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::{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}