Skip to content

Commit f1dd212

Browse files
committed
test(tofu): add unit tests for TofuStore trait
- Implement for testing purposes - Add comprehensive tests covering first-use storage, certificate matching/replacement, and large payloads NOTE: Unit tests and supporting mock implementation were created with AI assistance.
1 parent 3ddfa45 commit f1dd212

1 file changed

Lines changed: 124 additions & 0 deletions

File tree

src/tofu/mod.rs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,127 @@ pub trait TofuStore: Send + Sync + Debug {
1919
) -> Result<(), Box<dyn Send + Sync + Error>>;
2020
}
2121

22+
#[cfg(test)]
23+
mod tests {
24+
use super::*;
25+
use std::collections::HashMap;
26+
use std::sync::Mutex;
27+
28+
#[derive(Debug)]
29+
struct InMemoryTofuStore {
30+
store: Mutex<HashMap<String, Vec<u8>>>,
31+
}
32+
33+
impl InMemoryTofuStore {
34+
fn new() -> Self {
35+
Self {
36+
store: Mutex::new(HashMap::new()),
37+
}
38+
}
39+
}
40+
41+
impl TofuStore for InMemoryTofuStore {
42+
fn get_certificate(
43+
&self,
44+
host: &str,
45+
) -> Result<Option<Vec<u8>>, Box<dyn Send + Sync + Error>> {
46+
let store = self.store.lock().unwrap();
47+
Ok(store.get(host).cloned())
48+
}
49+
50+
fn set_certificate(
51+
&self,
52+
host: &str,
53+
cert: Vec<u8>,
54+
) -> Result<(), Box<dyn Send + Sync + Error>> {
55+
let mut store = self.store.lock().unwrap();
56+
store.insert(host.to_string(), cert);
57+
Ok(())
58+
}
59+
}
60+
61+
#[test]
62+
fn test_tofu_first_use() {
63+
let store = InMemoryTofuStore::new();
64+
65+
let host = "example.com";
66+
let cert = b"test certificate data".to_vec();
67+
68+
// First use: certificate should not exist
69+
let result = store.get_certificate(host).unwrap();
70+
assert!(
71+
result.is_none(),
72+
"Certificate should not exist on first use"
73+
);
74+
75+
store.set_certificate(host, cert.clone()).unwrap();
76+
77+
let stored = store.get_certificate(host).unwrap();
78+
assert_eq!(stored, Some(cert), "Certificate should be stored");
79+
}
80+
81+
#[test]
82+
fn test_tofu_certificate_match() {
83+
let store = InMemoryTofuStore::new();
84+
85+
let host = "example.com";
86+
let cert = b"test certificate data".to_vec();
87+
88+
// Store certificate
89+
store.set_certificate(host, cert.clone()).unwrap();
90+
91+
// Retrieve and verify it matches
92+
let stored = store.get_certificate(host).unwrap();
93+
assert_eq!(stored, Some(cert), "Stored certificate should match");
94+
}
95+
96+
#[test]
97+
fn test_tofu_certificate_change() {
98+
let store = InMemoryTofuStore::new();
99+
100+
let host = "example.com";
101+
let cert1 = b"first certificate".to_vec();
102+
let cert2 = b"second certificate".to_vec();
103+
104+
// Store first certificate
105+
store.set_certificate(host, cert1.clone()).unwrap();
106+
let stored1 = store.get_certificate(host).unwrap();
107+
assert_eq!(
108+
stored1,
109+
Some(cert1.clone()),
110+
"First certificate should be stored"
111+
);
112+
113+
// Update with different certificate
114+
store.set_certificate(host, cert2.clone()).unwrap();
115+
let stored2 = store.get_certificate(host).unwrap();
116+
assert_eq!(
117+
stored2,
118+
Some(cert2.clone()),
119+
"Second certificate should replace first"
120+
);
121+
assert_ne!(
122+
stored2,
123+
Some(cert1),
124+
"Stored certificate should not match first"
125+
);
126+
}
127+
128+
#[test]
129+
fn test_tofu_large_certificate() {
130+
let store = InMemoryTofuStore::new();
131+
132+
let host = "example.com";
133+
// Create a large certificate (10KB)
134+
let cert = vec![0x42; 10 * 1024];
135+
136+
// Store large certificate
137+
store.set_certificate(host, cert.clone()).unwrap();
138+
let stored = store.get_certificate(host).unwrap();
139+
assert_eq!(
140+
stored,
141+
Some(cert),
142+
"Large certificate should be stored correctly"
143+
);
144+
}
145+
}

0 commit comments

Comments
 (0)