tempo_precompiles_macros/
storable_tests.rs1use proc_macro2::TokenStream;
7use quote::quote;
8
9use crate::storable_primitives::{ALLOY_INT_SIZES, RUST_INT_SIZES};
10const FIXED_BYTES_SIZES: &[usize] = &[
11 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
12 27, 28, 29, 30, 31, 32,
13];
14
15pub(crate) fn gen_storable_tests() -> TokenStream {
21 let rust_unsigned_arb = gen_rust_unsigned_arbitrary();
22 let rust_signed_arb = gen_rust_signed_arbitrary();
23 let alloy_unsigned_arb = gen_alloy_unsigned_arbitrary();
24 let alloy_signed_arb = gen_alloy_signed_arbitrary();
25 let fixed_bytes_arb = gen_fixed_bytes_arbitrary();
26
27 let rust_unsigned_tests = gen_rust_unsigned_tests();
28 let rust_signed_tests = gen_rust_signed_tests();
29 let alloy_unsigned_tests = gen_alloy_unsigned_tests();
30 let alloy_signed_tests = gen_alloy_signed_tests();
31 let fixed_bytes_tests = gen_fixed_bytes_tests();
32
33 quote! {
34 #rust_unsigned_arb
37 #rust_signed_arb
38 #alloy_unsigned_arb
39 #alloy_signed_arb
40 #fixed_bytes_arb
41
42 #rust_unsigned_tests
45 #rust_signed_tests
46 #alloy_unsigned_tests
47 #alloy_signed_tests
48 #fixed_bytes_tests
49 }
50}
51
52fn gen_rust_unsigned_arbitrary() -> TokenStream {
54 quote! {}
55}
56
57fn gen_rust_signed_arbitrary() -> TokenStream {
59 quote! {}
60}
61
62fn gen_alloy_unsigned_arbitrary() -> TokenStream {
64 let funcs: Vec<_> = ALLOY_INT_SIZES
65 .iter()
66 .map(|&size| {
67 let type_name = quote::format_ident!("U{size}");
68 let fn_name = quote::format_ident!("arb_u{size}_alloy");
69
70 quote! {
71 fn #fn_name() -> impl Strategy<Value = ::alloy::primitives::#type_name> {
72 Just(()).prop_perturb(|_, _| ::alloy::primitives::#type_name::random())
73 }
74 }
75 })
76 .collect();
77
78 quote! { #(#funcs)* }
79}
80
81fn gen_alloy_signed_arbitrary() -> TokenStream {
83 let funcs: Vec<_> = ALLOY_INT_SIZES
84 .iter()
85 .flat_map(|&size| {
86 let signed_type = quote::format_ident!("I{size}");
87 let unsigned_type = quote::format_ident!("U{size}");
88 let arb_any_fn = quote::format_ident!("arb_i{size}_alloy");
89 let arb_pos_fn = quote::format_ident!("arb_positive_i{size}_alloy");
90 let arb_neg_fn = quote::format_ident!("arb_negative_i{size}_alloy");
91 let arb_unsigned_fn = quote::format_ident!("arb_u{size}_alloy");
92
93 vec![
94 quote! {
96 fn #arb_any_fn() -> impl Strategy<Value = ::alloy::primitives::#signed_type> {
97 #arb_unsigned_fn().prop_map(|u| ::alloy::primitives::#signed_type::from_raw(u))
98 }
99 },
100 quote! {
102 fn #arb_pos_fn() -> impl Strategy<Value = ::alloy::primitives::#signed_type> {
103 #arb_unsigned_fn().prop_map(|u| {
104 ::alloy::primitives::#signed_type::from_raw(
105 u & (::alloy::primitives::#unsigned_type::MAX >> 1)
106 )
107 })
108 }
109 },
110 quote! {
112 fn #arb_neg_fn() -> impl Strategy<Value = ::alloy::primitives::#signed_type> {
113 #arb_pos_fn().prop_map(|i| -i)
114 }
115 },
116 ]
117 })
118 .collect();
119
120 quote! { #(#funcs)* }
121}
122
123fn gen_fixed_bytes_arbitrary() -> TokenStream {
125 let funcs: Vec<_> = FIXED_BYTES_SIZES
126 .iter()
127 .map(|&size| {
128 let fn_name = quote::format_ident!("arb_fixed_bytes_{size}");
129
130 quote! {
131 fn #fn_name() -> impl Strategy<Value = ::alloy::primitives::FixedBytes<#size>> {
132 Just(()).prop_perturb(|_, _| ::alloy::primitives::FixedBytes::<#size>::random())
133 }
134 }
135 })
136 .collect();
137
138 quote! { #(#funcs)* }
139}
140
141fn gen_rust_unsigned_tests() -> TokenStream {
143 let tests: Vec<_> = RUST_INT_SIZES
144 .iter()
145 .map(|&size| {
146 let type_name = quote::format_ident!("u{size}");
147 let test_name = quote::format_ident!("test_u{size}_storage_roundtrip");
148 let label = format!("u{size}");
149
150 quote! {
151 #[test]
152 fn #test_name(value in any::<#type_name>(), base_slot in arb_safe_slot()) {
153 let (mut storage, address) = setup_storage();
154 StorageCtx::enter(&mut storage, || {
155 let mut slot = Slot::<#type_name>::new(base_slot, address);
156
157 slot.write(value).unwrap();
159 let loaded = slot.read().unwrap();
160 assert_eq!(value, loaded, concat!(#label, " roundtrip failed"));
161
162 slot.delete().unwrap();
164 let after_delete = slot.read().unwrap();
165 assert_eq!(after_delete, 0, concat!(#label, " not zero after delete"));
166
167 let word = value.to_word();
169 let recovered = #type_name::from_word(word).unwrap();
170 assert_eq!(value, recovered, concat!(#label, " EVM word roundtrip failed"));
171
172 });
173 }
174 }
175 })
176 .collect();
177
178 quote! {
179 proptest! {
180 #![proptest_config(ProptestConfig::with_cases(500))]
181
182 #(#tests)*
183 }
184 }
185}
186
187fn gen_rust_signed_tests() -> TokenStream {
189 let tests: Vec<_> = RUST_INT_SIZES
190 .iter()
191 .flat_map(|&size| {
192 let type_name = quote::format_ident!("i{size}");
193 let pos_test_name = quote::format_ident!("test_i{size}_positive_storage_roundtrip");
194 let neg_test_name = quote::format_ident!("test_i{size}_negative_storage_roundtrip");
195 let label = format!("i{size}");
196
197 vec![
198 quote! {
200 #[test]
201 fn #pos_test_name(value in 0 as #type_name..=#type_name::MAX, base_slot in arb_safe_slot()) {
202 let (mut storage, address) = setup_storage();
203 StorageCtx::enter(&mut storage, || {
204 let mut slot = Slot::<#type_name>::new(base_slot, address);
205
206 slot.write(value).unwrap();
208 let loaded = slot.read().unwrap();
209 assert_eq!(value, loaded, concat!(#label, " positive roundtrip failed"));
210
211 slot.delete().unwrap();
213 let after_delete = slot.read().unwrap();
214 assert_eq!(after_delete, 0, concat!(#label, " not zero after delete"));
215
216 let word = value.to_word();
218 let recovered = #type_name::from_word(word).unwrap();
219 assert_eq!(value, recovered, concat!(#label, " positive EVM word roundtrip failed"));
220 });
221 }
222 },
223 quote! {
225 #[test]
226 fn #neg_test_name(value in #type_name::MIN..0 as #type_name, base_slot in arb_safe_slot()) {
227 let (mut storage, address) = setup_storage();
228 StorageCtx::enter(&mut storage, || {
229 let mut slot = Slot::<#type_name>::new(base_slot, address);
230
231 slot.write(value).unwrap();
233 let loaded = slot.read().unwrap();
234 assert_eq!(value, loaded, concat!(#label, " negative roundtrip failed"));
235
236 slot.delete().unwrap();
238 let after_delete = slot.read().unwrap();
239 assert_eq!(after_delete, 0, concat!(#label, " not zero after delete"));
240
241 let word = value.to_word();
243 let recovered = #type_name::from_word(word).unwrap();
244 assert_eq!(value, recovered, concat!(#label, " negative EVM word roundtrip failed"));
245 });
246 }
247 },
248 ]
249 })
250 .collect();
251
252 quote! {
253 proptest! {
254 #![proptest_config(ProptestConfig::with_cases(500))]
255
256 #(#tests)*
257 }
258 }
259}
260
261fn gen_alloy_unsigned_tests() -> TokenStream {
263 let tests: Vec<_> = ALLOY_INT_SIZES
264 .iter()
265 .map(|&size| {
266 let type_name = quote::format_ident!("U{size}");
267 let test_name = quote::format_ident!("test_u{size}_alloy_storage_roundtrip");
268 let arb_fn = quote::format_ident!("arb_u{size}_alloy");
269 let label = format!("U{size}");
270
271 quote! {
272 #[test]
273 fn #test_name(value in #arb_fn(), base_slot in arb_safe_slot()) {
274 let (mut storage, address) = setup_storage();
275 StorageCtx::enter(&mut storage, || {
276 let mut slot = Slot::<::alloy::primitives::#type_name>::new(base_slot, address);
277
278 slot.write(value).unwrap();
280 let loaded = slot.read().unwrap();
281 assert_eq!(value, loaded, concat!(#label, " roundtrip failed"));
282
283 slot.delete().unwrap();
285 let after_delete = slot.read().unwrap();
286 assert_eq!(
287 after_delete,
288 ::alloy::primitives::#type_name::ZERO,
289 concat!(#label, " not zero after delete")
290 );
291
292 let word = value.to_word();
294 let recovered = ::alloy::primitives::#type_name::from_word(word).unwrap();
295 assert_eq!(value, recovered, concat!(#label, " EVM word roundtrip failed"));
296
297 });
298 }
299 }
300 })
301 .collect();
302
303 quote! {
304 proptest! {
305 #![proptest_config(ProptestConfig::with_cases(500))]
306
307 #(#tests)*
308 }
309 }
310}
311
312fn gen_alloy_signed_tests() -> TokenStream {
314 let tests: Vec<_> = ALLOY_INT_SIZES
315 .iter()
316 .flat_map(|&size| {
317 let type_name = quote::format_ident!("I{size}");
318 let pos_test_name = quote::format_ident!("test_i{size}_alloy_positive_storage_roundtrip");
319 let neg_test_name = quote::format_ident!("test_i{size}_alloy_negative_storage_roundtrip");
320 let arb_pos_fn = quote::format_ident!("arb_positive_i{size}_alloy");
321 let arb_neg_fn = quote::format_ident!("arb_negative_i{size}_alloy");
322 let label = format!("I{size}");
323
324 vec![
325 quote! {
327 #[test]
328 fn #pos_test_name(value in #arb_pos_fn(), base_slot in arb_safe_slot()) {
329 let (mut storage, address) = setup_storage();
330 StorageCtx::enter(&mut storage, || {
331 let mut slot = Slot::<::alloy::primitives::#type_name>::new(base_slot, address);
332
333 slot.write(value).unwrap();
335 let loaded = slot.read().unwrap();
336 assert_eq!(value, loaded, concat!(#label, " positive roundtrip failed"));
337
338 slot.delete().unwrap();
340 let after_delete = slot.read().unwrap();
341 assert_eq!(
342 after_delete,
343 ::alloy::primitives::#type_name::ZERO,
344 concat!(#label, " not zero after delete")
345 );
346
347 let word = value.to_word();
349 let recovered = ::alloy::primitives::#type_name::from_word(word).unwrap();
350 assert_eq!(value, recovered, concat!(#label, " positive EVM word roundtrip failed"));
351 });
352 }
353 },
354 quote! {
356 #[test]
357 fn #neg_test_name(value in #arb_neg_fn(), base_slot in arb_safe_slot()) {
358 let (mut storage, address) = setup_storage();
359 StorageCtx::enter(&mut storage, || {
360 let mut slot = Slot::<::alloy::primitives::#type_name>::new(base_slot, address);
361
362 slot.write(value).unwrap();
364 let loaded = slot.read().unwrap();
365 assert_eq!(value, loaded, concat!(#label, " negative roundtrip failed"));
366
367 slot.delete().unwrap();
369 let after_delete = slot.read().unwrap();
370 assert_eq!(
371 after_delete,
372 ::alloy::primitives::#type_name::ZERO,
373 concat!(#label, " not zero after delete")
374 );
375
376 let word = value.to_word();
378 let recovered = ::alloy::primitives::#type_name::from_word(word).unwrap();
379 assert_eq!(value, recovered, concat!(#label, " negative EVM word roundtrip failed"));
380 });
381 }
382 },
383 ]
384 })
385 .collect();
386
387 quote! {
388 proptest! {
389 #![proptest_config(ProptestConfig::with_cases(500))]
390
391 #(#tests)*
392 }
393 }
394}
395
396fn gen_fixed_bytes_tests() -> TokenStream {
398 let tests: Vec<_> = FIXED_BYTES_SIZES
399 .iter()
400 .map(|&size| {
401 let test_name = quote::format_ident!("test_fixed_bytes_{size}_storage_roundtrip");
402 let arb_fn = quote::format_ident!("arb_fixed_bytes_{size}");
403
404 quote! {
405 #[test]
406 fn #test_name(value in #arb_fn(), base_slot in arb_safe_slot()) {
407 let (mut storage, address) = setup_storage();
408 StorageCtx::enter(&mut storage, || {
409 let mut slot = Slot::<::alloy::primitives::FixedBytes<#size>>::new(base_slot, address);
410
411 slot.write(value).unwrap();
413 let loaded = slot.read().unwrap();
414 assert_eq!(
415 value, loaded,
416 concat!("FixedBytes<", stringify!(#size), "> roundtrip failed")
417 );
418
419 slot.delete().unwrap();
421 let after_delete = slot.read().unwrap();
422 assert_eq!(
423 after_delete,
424 ::alloy::primitives::FixedBytes::<#size>::ZERO,
425 concat!("FixedBytes<", stringify!(#size), "> not zero after delete")
426 );
427
428 let word = value.to_word();
430 let recovered = ::alloy::primitives::FixedBytes::<#size>::from_word(word).unwrap();
431 assert_eq!(
432 value, recovered,
433 concat!("FixedBytes<", stringify!(#size), "> EVM word roundtrip failed")
434 );
435
436 });
437 }
438 }
439 })
440 .collect();
441
442 quote! {
443 proptest! {
444 #![proptest_config(ProptestConfig::with_cases(500))]
445
446 #(#tests)*
447 }
448 }
449}