p2panda_core/
test_utils.rs1use std::cell::RefCell;
4use std::rc::Rc;
5
6use tracing_subscriber;
7
8use crate::timestamp::Timestamp;
9use crate::{Body, Extensions, Hash, Header, Operation, SigningKey, Topic, VerifyingKey};
10
11pub fn setup_logging() {
12 if std::env::var("RUST_LOG").is_ok() {
13 let _ = tracing_subscriber::fmt()
14 .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
15 .try_init();
16 }
17}
18
19#[derive(Clone, Default)]
20pub struct TestLog {
21 signing_key: SigningKey,
22 backlink: Rc<RefCell<Option<Hash>>>,
23 seq_num: Rc<RefCell<u64>>,
24 log_id: Topic,
25}
26
27impl TestLog {
28 pub fn new() -> Self {
29 Self {
30 signing_key: SigningKey::generate(),
31 backlink: Rc::default(),
32 seq_num: Rc::default(),
33 log_id: Topic::random(),
34 }
35 }
36
37 pub fn from_signing_key(signing_key: SigningKey) -> Self {
38 let mut log = TestLog::new();
39 log.signing_key = signing_key;
40 log
41 }
42
43 pub fn id(&self) -> Topic {
44 self.log_id
45 }
46
47 pub fn author(&self) -> VerifyingKey {
48 self.signing_key.verifying_key()
49 }
50
51 pub fn operation<E: Extensions>(&self, body: &[u8], extensions: E) -> Operation<E> {
52 let body = Body::from(body);
53
54 let mut seq_num = self.seq_num.borrow_mut();
55 let mut backlink = self.backlink.borrow_mut();
56
57 let mut header = Header::<E> {
58 verifying_key: self.signing_key.verifying_key(),
59 version: 1,
60 signature: None,
61 payload_size: body.size(),
62 payload_hash: if body.size() == 0 {
63 None
64 } else {
65 Some(body.hash())
66 },
67 timestamp: Timestamp::now(),
68 seq_num: *seq_num,
69 backlink: *backlink,
70 extensions,
71 };
72 header.sign(&self.signing_key);
73
74 *backlink = Some(header.hash());
75 *seq_num += 1;
76
77 Operation {
78 hash: header.hash(),
79 header,
80 body: if body.size() == 0 { None } else { Some(body) },
81 }
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use crate::Header;
88 use crate::cbor::{decode_cbor, encode_cbor};
89
90 use super::TestLog;
91
92 #[test]
93 fn zero_byte_body() {
94 let log = TestLog::new();
95 let operation = log.operation(&[], ());
96 let bytes = encode_cbor(operation.header()).unwrap();
97 assert!(decode_cbor::<Header, _>(&bytes[..]).is_ok());
98 }
99}