audio_plugin_bsd/
sandbox.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
26pub enum IsolationLevel {
27 None,
30 #[cfg(target_os = "freebsd")]
33 Capsicum,
34 #[cfg(target_os = "freebsd")]
37 CapsicumProcess,
38}
39
40impl IsolationLevel {
41 #[must_use]
44 pub fn is_available(self) -> bool {
45 match self {
46 Self::None => true,
47 #[cfg(target_os = "freebsd")]
48 Self::Capsicum => true,
49 #[cfg(target_os = "freebsd")]
50 Self::CapsicumProcess => true,
51 }
52 }
53
54 #[must_use]
56 pub fn as_str(self) -> &'static str {
57 match self {
58 Self::None => "none",
59 #[cfg(target_os = "freebsd")]
60 Self::Capsicum => "capsicum",
61 #[cfg(target_os = "freebsd")]
62 Self::CapsicumProcess => "capsicum-process",
63 }
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
73pub struct SandboxConfig {
74 isolation_level: IsolationLevel,
76 log_channel_capacity: usize,
81}
82
83impl SandboxConfig {
84 #[must_use]
87 pub fn new() -> Self {
88 Self {
89 isolation_level: IsolationLevel::None,
90 log_channel_capacity: 16,
91 }
92 }
93
94 #[must_use]
96 pub fn with_isolation_level(mut self, level: IsolationLevel) -> Self {
97 self.isolation_level = level;
98 self
99 }
100
101 #[must_use]
106 pub fn with_log_channel_capacity(mut self, capacity: usize) -> Self {
107 self.log_channel_capacity = capacity;
108 self
109 }
110
111 #[must_use]
113 pub fn isolation_level(self) -> IsolationLevel {
114 self.isolation_level
115 }
116
117 #[must_use]
119 pub fn log_channel_capacity(self) -> usize {
120 self.log_channel_capacity
121 }
122
123 #[must_use]
126 pub fn is_platform_supported(self) -> bool {
127 self.isolation_level.is_available()
128 }
129}
130
131impl Default for SandboxConfig {
132 fn default() -> Self {
133 Self::new()
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140
141 #[test]
144 fn none_is_always_available() {
145 assert!(IsolationLevel::None.is_available());
146 }
147
148 #[test]
149 fn none_as_str() {
150 assert_eq!(IsolationLevel::None.as_str(), "none");
151 }
152
153 #[test]
154 fn none_is_copy_clone_eq_debug_hash() {
155 let a = IsolationLevel::None;
156 let b = a;
157 assert_eq!(a, b);
158 assert_eq!(format!("{a:?}"), "None");
159 let mut set = std::collections::HashSet::new();
160 set.insert(a);
161 assert!(set.contains(&b));
162 }
163
164 #[cfg(target_os = "freebsd")]
165 mod freebsd_tests {
166 use super::*;
167
168 #[test]
169 fn capsicum_is_available_on_freebsd() {
170 assert!(IsolationLevel::Capsicum.is_available());
171 }
172
173 #[test]
174 fn capsicum_process_is_available_on_freebsd() {
175 assert!(IsolationLevel::CapsicumProcess.is_available());
176 }
177
178 #[test]
179 fn capsicum_as_str() {
180 assert_eq!(IsolationLevel::Capsicum.as_str(), "capsicum");
181 }
182
183 #[test]
184 fn capsicum_process_as_str() {
185 assert_eq!(IsolationLevel::CapsicumProcess.as_str(), "capsicum-process");
186 }
187 }
188
189 #[test]
192 fn default_has_none_and_capacity_16() {
193 let cfg = SandboxConfig::default();
194 assert_eq!(cfg.isolation_level(), IsolationLevel::None);
195 assert_eq!(cfg.log_channel_capacity(), 16);
196 }
197
198 #[test]
199 fn builder_sets_isolation_level() {
200 let cfg = SandboxConfig::new().with_isolation_level(IsolationLevel::None);
201 assert_eq!(cfg.isolation_level(), IsolationLevel::None);
202 }
203
204 #[test]
205 fn builder_sets_log_channel_capacity() {
206 let cfg = SandboxConfig::new().with_log_channel_capacity(64);
207 assert_eq!(cfg.log_channel_capacity(), 64);
208 }
209
210 #[test]
211 fn builder_chains() {
212 let cfg = SandboxConfig::new()
213 .with_isolation_level(IsolationLevel::None)
214 .with_log_channel_capacity(32);
215 assert_eq!(cfg.isolation_level(), IsolationLevel::None);
216 assert_eq!(cfg.log_channel_capacity(), 32);
217 }
218
219 #[test]
220 fn platform_supported_for_none() {
221 let cfg = SandboxConfig::new().with_isolation_level(IsolationLevel::None);
222 assert!(cfg.is_platform_supported());
223 }
224
225 #[test]
226 fn config_is_copy_clone_eq_debug_hash() {
227 let a = SandboxConfig::new();
228 let b = a;
229 assert_eq!(a, b);
230 assert!(format!("{a:?}").contains("SandboxConfig"));
231 let mut set = std::collections::HashSet::new();
232 set.insert(a);
233 assert!(set.contains(&b));
234 }
235
236 #[test]
237 fn zero_capacity_is_valid() {
238 let cfg = SandboxConfig::new().with_log_channel_capacity(0);
239 assert_eq!(cfg.log_channel_capacity(), 0);
240 }
241
242 #[test]
243 fn large_capacity_is_valid() {
244 let cfg = SandboxConfig::new().with_log_channel_capacity(usize::MAX);
245 assert_eq!(cfg.log_channel_capacity(), usize::MAX);
246 }
247}