objects/store/
store_compliance.rs1use crate::{
9 object::{Attribution, Blob, ContentHash, Principal, State, Tree},
10 store::ObjectStore,
11};
12
13fn attribution() -> Attribution {
14 Attribution::human(Principal::new("Compliance Test", "test@example.com"))
15}
16
17pub fn run_compliance_tests<S: ObjectStore>(store: &S) {
22 blob_round_trip(store);
23 blob_missing_returns_none(store);
24 blob_has(store);
25 blob_list(store);
26 tree_round_trip(store);
27 tree_missing_returns_none(store);
28 state_round_trip(store);
29 state_has(store);
30 state_list(store);
31}
32
33fn blob_round_trip<S: ObjectStore>(store: &S) {
36 let blob = Blob::from("compliance: blob round-trip");
37 let hash = store.put_blob(&blob).expect("put_blob failed");
38 let got = store
39 .get_blob(&hash)
40 .expect("get_blob failed")
41 .expect("blob missing after put");
42 assert_eq!(
43 got.content(),
44 blob.content(),
45 "blob content changed after round-trip"
46 );
47}
48
49fn blob_missing_returns_none<S: ObjectStore>(store: &S) {
50 let hash = ContentHash::compute(b"compliance-nonexistent-blob");
51 let result = store
52 .get_blob(&hash)
53 .expect("get_blob error on missing key");
54 assert!(
55 result.is_none(),
56 "get_blob should return None for unknown hash"
57 );
58}
59
60fn blob_has<S: ObjectStore>(store: &S) {
61 let blob = Blob::from("compliance: has_blob");
62 let hash = store.put_blob(&blob).expect("put_blob failed");
63 assert!(
64 store.has_blob(&hash).expect("has_blob failed"),
65 "has_blob returned false immediately after put"
66 );
67}
68
69fn blob_list<S: ObjectStore>(store: &S) {
70 let blob = Blob::from("compliance: list_blobs");
71 let hash = store.put_blob(&blob).expect("put_blob failed");
72 let list = store.list_blobs().expect("list_blobs failed");
73 assert!(
74 list.contains(&hash),
75 "list_blobs does not contain hash after put"
76 );
77}
78
79fn tree_round_trip<S: ObjectStore>(store: &S) {
82 let tree = Tree::new();
83 let hash = store.put_tree(&tree).expect("put_tree failed");
84 let got = store
85 .get_tree(&hash)
86 .expect("get_tree failed")
87 .expect("tree missing after put");
88 assert_eq!(got.hash(), hash, "tree hash changed after round-trip");
89}
90
91fn tree_missing_returns_none<S: ObjectStore>(store: &S) {
92 let hash = ContentHash::compute(b"compliance-nonexistent-tree");
93 let result = store
94 .get_tree(&hash)
95 .expect("get_tree error on missing key");
96 assert!(
97 result.is_none(),
98 "get_tree should return None for unknown hash"
99 );
100}
101
102fn state_round_trip<S: ObjectStore>(store: &S) {
105 let tree = Tree::new();
106 let tree_hash = store
107 .put_tree(&tree)
108 .expect("put_tree in state test failed");
109 let state = State::new(tree_hash, vec![], attribution());
110 let id = state.change_id;
111
112 store.put_state(&state).expect("put_state failed");
113
114 let got = store
115 .get_state(&id)
116 .expect("get_state failed")
117 .expect("state missing after put");
118
119 assert_eq!(got.change_id, id, "change_id changed after round-trip");
120 assert_eq!(got.tree, tree_hash, "tree hash changed after round-trip");
121}
122
123fn state_has<S: ObjectStore>(store: &S) {
124 let tree = Tree::new();
125 let tree_hash = store
126 .put_tree(&tree)
127 .expect("put_tree in state test failed");
128 let state = State::new(tree_hash, vec![], attribution());
129 let id = state.change_id;
130 store.put_state(&state).expect("put_state failed");
131 assert!(
132 store.has_state(&id).expect("has_state failed"),
133 "has_state returned false immediately after put"
134 );
135}
136
137fn state_list<S: ObjectStore>(store: &S) {
138 let tree = Tree::new();
139 let tree_hash = store
140 .put_tree(&tree)
141 .expect("put_tree in state test failed");
142 let state = State::new(tree_hash, vec![], attribution());
143 let id = state.change_id;
144 store.put_state(&state).expect("put_state failed");
145 let ids = store.list_states().expect("list_states failed");
146 assert!(
147 ids.contains(&id),
148 "list_states does not contain id after put"
149 );
150}