sentry_options/
testing.rs1use std::cell::RefCell;
20use std::collections::HashMap;
21
22use serde_json::Value;
23
24use crate::{GLOBAL_OPTIONS, Result};
25
26thread_local! {
27 static OVERRIDES: RefCell<HashMap<String, HashMap<String, Value>>> = RefCell::new(HashMap::new());
28}
29
30pub fn set_override(namespace: &str, key: &str, value: Value) {
32 OVERRIDES.with(|o| {
33 o.borrow_mut()
34 .entry(namespace.to_string())
35 .or_default()
36 .insert(key.to_string(), value);
37 });
38}
39
40pub fn get_override(namespace: &str, key: &str) -> Option<Value> {
42 OVERRIDES.with(|o| {
43 o.borrow()
44 .get(namespace)
45 .and_then(|ns| ns.get(key).cloned())
46 })
47}
48
49pub fn clear_override(namespace: &str, key: &str) {
51 OVERRIDES.with(|o| {
52 if let Some(ns_map) = o.borrow_mut().get_mut(namespace) {
53 ns_map.remove(key);
54 }
55 });
56}
57
58pub struct OverrideGuard {
60 previous: Vec<(String, String, Option<Value>)>,
61}
62
63impl Drop for OverrideGuard {
64 fn drop(&mut self) {
65 OVERRIDES.with(|o| {
66 let mut map = o.borrow_mut();
67 for (ns, key, prev_value) in self.previous.drain(..) {
68 match prev_value {
69 Some(v) => {
70 map.entry(ns).or_default().insert(key, v);
71 }
72 None => {
73 if let Some(ns_map) = map.get_mut(&ns) {
74 ns_map.remove(&key);
75 }
76 }
77 }
78 }
79 });
80 }
81}
82
83pub fn override_options(overrides: &[(&str, &str, Value)]) -> Result<OverrideGuard> {
121 let opts = GLOBAL_OPTIONS
123 .get()
124 .expect("options not initialized - call init() first");
125 for (ns, key, value) in overrides {
126 opts.validate_override(ns, key, value)?;
127 }
128
129 let mut previous = Vec::with_capacity(overrides.len());
130
131 OVERRIDES.with(|o| {
132 let mut map = o.borrow_mut();
133 for (ns, key, value) in overrides {
134 let prev = map.get(*ns).and_then(|m| m.get(*key).cloned());
135 previous.push((ns.to_string(), key.to_string(), prev));
136 map.entry(ns.to_string())
137 .or_default()
138 .insert(key.to_string(), value.clone());
139 }
140 });
141
142 Ok(OverrideGuard { previous })
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148 use serde_json::json;
149
150 #[test]
151 fn test_set_get_clear_override() {
152 set_override("ns", "key", json!(true));
153 assert_eq!(get_override("ns", "key"), Some(json!(true)));
154 clear_override("ns", "key");
155 assert_eq!(get_override("ns", "key"), None);
156 }
157
158 #[test]
159 fn test_override_guard_restores() {
160 crate::init().unwrap();
161 set_override("sentry-options-testing", "int-option", json!(1));
162
163 {
164 let _guard =
165 override_options(&[("sentry-options-testing", "int-option", json!(2))]).unwrap();
166 assert_eq!(
167 get_override("sentry-options-testing", "int-option"),
168 Some(json!(2))
169 );
170 }
171
172 assert_eq!(
173 get_override("sentry-options-testing", "int-option"),
174 Some(json!(1))
175 );
176 clear_override("sentry-options-testing", "int-option");
177 }
178
179 #[test]
180 fn test_override_guard_clears_new_key() {
181 crate::init().unwrap();
182 assert_eq!(get_override("sentry-options-testing", "bool-option"), None);
183
184 {
185 let _guard =
186 override_options(&[("sentry-options-testing", "bool-option", json!(true))])
187 .unwrap();
188 assert_eq!(
189 get_override("sentry-options-testing", "bool-option"),
190 Some(json!(true))
191 );
192 }
193
194 assert_eq!(get_override("sentry-options-testing", "bool-option"), None);
195 }
196
197 #[test]
198 fn test_nested_overrides() {
199 crate::init().unwrap();
200 {
201 let _outer =
202 override_options(&[("sentry-options-testing", "int-option", json!(100))]).unwrap();
203 assert_eq!(
204 get_override("sentry-options-testing", "int-option"),
205 Some(json!(100))
206 );
207
208 {
209 let _inner =
210 override_options(&[("sentry-options-testing", "int-option", json!(200))])
211 .unwrap();
212 assert_eq!(
213 get_override("sentry-options-testing", "int-option"),
214 Some(json!(200))
215 );
216 }
217
218 assert_eq!(
219 get_override("sentry-options-testing", "int-option"),
220 Some(json!(100))
221 );
222 }
223
224 assert_eq!(get_override("sentry-options-testing", "int-option"), None);
225 }
226}