camel_config/
wasm_limits.rs1use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize, Serialize)]
28#[serde(rename_all = "kebab-case", deny_unknown_fields)]
29pub struct WasmLimitsConfig {
30 #[serde(default, skip_serializing_if = "Option::is_none")]
33 pub timeout_secs: Option<u64>,
34
35 #[serde(default, skip_serializing_if = "Option::is_none")]
41 pub max_memory: Option<u64>,
42
43 #[serde(default, skip_serializing_if = "Option::is_none")]
48 pub max_concurrent_calls: Option<usize>,
49
50 #[serde(default, skip_serializing_if = "Option::is_none")]
52 pub max_wasm_size: Option<u64>,
53
54 #[serde(default, skip_serializing_if = "Option::is_none")]
58 pub allow_call_schemes: Option<String>,
59
60 #[serde(default, skip_serializing_if = "Option::is_none")]
63 pub max_stream_bytes: Option<u64>,
64
65 #[serde(default, skip_serializing_if = "Option::is_none")]
69 pub max_instances: Option<usize>,
70
71 #[serde(default, skip_serializing_if = "Option::is_none")]
75 pub max_tables: Option<usize>,
76
77 #[serde(default, skip_serializing_if = "Option::is_none")]
80 pub max_table_elements: Option<usize>,
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn defaults_to_all_none() {
89 let cfg = WasmLimitsConfig::default();
90 assert_eq!(cfg.timeout_secs, None);
91 assert_eq!(cfg.max_memory, None);
92 assert_eq!(cfg.max_concurrent_calls, None);
93 assert_eq!(cfg.max_wasm_size, None);
94 assert_eq!(cfg.allow_call_schemes, None);
95 assert_eq!(cfg.max_stream_bytes, None);
96 assert_eq!(cfg.max_instances, None);
97 assert_eq!(cfg.max_tables, None);
98 assert_eq!(cfg.max_table_elements, None);
99 }
100
101 #[test]
102 fn deserialises_full_block() {
103 let toml = toml::toml! {
104 timeout-secs = 600
105 max-memory = 4294967296i64
106 max-concurrent-calls = 2
107 max-wasm-size = 20971520i64
108 allow-call-schemes = "log,direct"
109 max-stream-bytes = 52428800i64
110 max-instances = 100
111 max-tables = 50
112 max-table-elements = 200
113 };
114 let cfg: WasmLimitsConfig = toml.try_into().expect("deserialize");
115 assert_eq!(cfg.timeout_secs, Some(600));
116 assert_eq!(cfg.max_memory, Some(4_294_967_296));
117 assert_eq!(cfg.max_concurrent_calls, Some(2));
118 assert_eq!(cfg.max_wasm_size, Some(20_971_520));
119 assert_eq!(cfg.allow_call_schemes.as_deref(), Some("log,direct"));
120 assert_eq!(cfg.max_stream_bytes, Some(52_428_800));
121 assert_eq!(cfg.max_instances, Some(100));
122 assert_eq!(cfg.max_tables, Some(50));
123 assert_eq!(cfg.max_table_elements, Some(200));
124 }
125
126 #[test]
127 fn deserialises_partial_block() {
128 let toml = toml::toml! {
129 timeout-secs = 120
130 };
131 let cfg: WasmLimitsConfig = toml.try_into().expect("deserialize");
132 assert_eq!(cfg.timeout_secs, Some(120));
133 assert_eq!(cfg.max_memory, None);
134 assert_eq!(cfg.max_concurrent_calls, None);
135 assert_eq!(cfg.max_wasm_size, None);
136 assert_eq!(cfg.allow_call_schemes, None);
137 assert_eq!(cfg.max_stream_bytes, None);
138 assert_eq!(cfg.max_instances, None);
139 assert_eq!(cfg.max_tables, None);
140 assert_eq!(cfg.max_table_elements, None);
141 }
142
143 #[test]
144 fn deserialises_allow_call_schemes() {
145 let toml = toml::toml! {
146 timeout-secs = 10
147 allow-call-schemes = "log,direct"
148 };
149 let cfg: WasmLimitsConfig = toml.try_into().expect("deserialize");
150 assert_eq!(cfg.allow_call_schemes.as_deref(), Some("log,direct"));
151 }
152
153 #[test]
154 fn rejects_unknown_field() {
155 let toml = toml::toml! {
156 timeout-secs = 10
157 fuel = 1000
158 };
159 let result: Result<WasmLimitsConfig, _> = toml.try_into();
160 assert!(result.is_err(), "deny_unknown_fields must reject `fuel`");
161 }
162
163 #[test]
164 fn serde_round_trip_preserves_set_fields() {
165 let original = WasmLimitsConfig {
166 timeout_secs: Some(45),
167 max_memory: Some(64 * 1024 * 1024),
168 max_concurrent_calls: None,
169 ..WasmLimitsConfig::default()
170 };
171 let serialized = toml::to_string(&original).expect("serialize");
172 let back: WasmLimitsConfig = toml::from_str(&serialized).expect("deserialize");
173 assert_eq!(original, back);
174 }
175
176 #[test]
177 fn skip_serializing_none_fields() {
178 let cfg = WasmLimitsConfig {
179 timeout_secs: Some(30),
180 max_memory: None,
181 max_concurrent_calls: None,
182 ..WasmLimitsConfig::default()
183 };
184 let s = toml::to_string(&cfg).expect("serialize");
185 assert!(s.contains("timeout-secs"));
186 assert!(!s.contains("max-memory"));
187 assert!(!s.contains("max-concurrent-calls"));
188 assert!(!s.contains("max-wasm-size"));
189 assert!(!s.contains("allow-call-schemes"));
190 assert!(!s.contains("max-stream-bytes"));
191 assert!(!s.contains("max-instances"));
192 assert!(!s.contains("max-tables"));
193 assert!(!s.contains("max-table-elements"));
194 }
195
196 #[test]
197 fn max_stream_bytes_round_trip() {
198 let cfg = WasmLimitsConfig {
199 max_stream_bytes: Some(52_428_800),
200 ..WasmLimitsConfig::default()
201 };
202 let serialized = toml::to_string(&cfg).expect("serialize");
203 assert!(serialized.contains("max-stream-bytes"));
204 let back: WasmLimitsConfig = toml::from_str(&serialized).expect("deserialize");
205 assert_eq!(back.max_stream_bytes, Some(52_428_800));
206 }
207
208 #[test]
209 fn instances_tables_table_elements_round_trip() {
210 let cfg = WasmLimitsConfig {
211 max_instances: Some(100),
212 max_tables: Some(50),
213 max_table_elements: Some(200),
214 ..WasmLimitsConfig::default()
215 };
216 let serialized = toml::to_string(&cfg).expect("serialize");
217 assert!(serialized.contains("max-instances"));
218 assert!(serialized.contains("max-tables"));
219 assert!(serialized.contains("max-table-elements"));
220 let back: WasmLimitsConfig = toml::from_str(&serialized).expect("deserialize");
221 assert_eq!(back.max_instances, Some(100));
222 assert_eq!(back.max_tables, Some(50));
223 assert_eq!(back.max_table_elements, Some(200));
224 }
225}