faucet_transform_wasm/
config.rs1use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
8pub struct WasmTransformConfig {
9 pub module: String,
12 #[serde(default = "default_function")]
14 pub function: String,
15 #[serde(default = "default_memory_limit_mb")]
19 pub memory_limit_mb: u32,
20 #[serde(default = "default_fuel_limit")]
25 pub fuel_limit: u64,
26 #[serde(default)]
29 pub on_error: WasmOnError,
30 #[serde(default)]
34 pub reload_on_change: bool,
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize, JsonSchema)]
39#[serde(rename_all = "snake_case")]
40pub enum WasmOnError {
41 #[default]
44 Fail,
45 Skip,
47 Passthrough,
49}
50
51fn default_function() -> String {
52 "transform".to_owned()
53}
54
55fn default_memory_limit_mb() -> u32 {
56 16
57}
58
59fn default_fuel_limit() -> u64 {
60 10_000_000
61}
62
63impl WasmTransformConfig {
64 pub(crate) fn module_label(&self) -> String {
66 std::path::Path::new(&self.module)
67 .file_name()
68 .map(|s| s.to_string_lossy().into_owned())
69 .unwrap_or_else(|| self.module.clone())
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use serde_json::json;
77
78 #[test]
79 fn decodes_minimal_config_with_defaults() {
80 let cfg: WasmTransformConfig =
81 serde_json::from_value(json!({"module": "./t.wasm"})).unwrap();
82 assert_eq!(cfg.module, "./t.wasm");
83 assert_eq!(cfg.function, "transform");
84 assert_eq!(cfg.memory_limit_mb, 16);
85 assert_eq!(cfg.fuel_limit, 10_000_000);
86 assert_eq!(cfg.on_error, WasmOnError::Fail);
87 assert!(!cfg.reload_on_change);
88 }
89
90 #[test]
91 fn decodes_full_config() {
92 let cfg: WasmTransformConfig = serde_json::from_value(json!({
93 "module": "/abs/redact.wasm",
94 "function": "run",
95 "memory_limit_mb": 32,
96 "fuel_limit": 5000,
97 "on_error": "skip",
98 "reload_on_change": true
99 }))
100 .unwrap();
101 assert_eq!(cfg.function, "run");
102 assert_eq!(cfg.memory_limit_mb, 32);
103 assert_eq!(cfg.fuel_limit, 5000);
104 assert_eq!(cfg.on_error, WasmOnError::Skip);
105 assert!(cfg.reload_on_change);
106 }
107
108 #[test]
109 fn rejects_missing_module() {
110 let err = serde_json::from_value::<WasmTransformConfig>(json!({})).unwrap_err();
111 assert!(err.to_string().contains("module"), "{err}");
112 }
113
114 #[test]
115 fn rejects_unknown_on_error() {
116 let err = serde_json::from_value::<WasmTransformConfig>(
117 json!({"module": "t.wasm", "on_error": "explode"}),
118 )
119 .unwrap_err();
120 assert!(
121 err.to_string().to_lowercase().contains("on_error")
122 || err.to_string().contains("explode"),
123 "{err}"
124 );
125 }
126
127 #[test]
128 fn module_label_is_basename() {
129 let cfg: WasmTransformConfig =
130 serde_json::from_value(json!({"module": "/a/b/redact_email.wasm"})).unwrap();
131 assert_eq!(cfg.module_label(), "redact_email.wasm");
132 let bare: WasmTransformConfig =
133 serde_json::from_value(json!({"module": "x.wasm"})).unwrap();
134 assert_eq!(bare.module_label(), "x.wasm");
135 }
136
137 #[test]
138 fn schema_builds_with_module_property() {
139 let schema = schemars::schema_for!(WasmTransformConfig);
140 let json = serde_json::to_value(&schema).unwrap();
141 assert!(
142 json.get("properties")
143 .and_then(|p| p.get("module"))
144 .is_some()
145 );
146 }
147}