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