/src/wasm-tools/fuzz/src/wit64.rs
Line | Count | Source |
1 | | use arbitrary::{Result, Unstructured}; |
2 | | use std::path::Path; |
3 | | use wit_component as wit_component_new; |
4 | | use wit_parser as wit_parser_new; |
5 | | |
6 | 1.69k | pub fn run(u: &mut Unstructured<'_>) -> Result<()> { |
7 | 1.69k | let wasm = u.arbitrary().and_then(|config| { |
8 | 1.69k | log::debug!("config: {config:#?}"); |
9 | 1.69k | wit_smith::smith(&config, u) |
10 | 1.69k | })?; |
11 | 1.69k | write_file("doc.wasm", &wasm); |
12 | 1.69k | let Ok(r1) = wit_component_old::decode(&wasm) else { |
13 | | // Presumably this is because the old version of `wit-component` doesn't |
14 | | // understand the new `stream`, `future`, or `error-context` types, in |
15 | | // which case there's no point in continuing, so we just return early. |
16 | 426 | return Ok(()); |
17 | | }; |
18 | 1.26k | let r1 = r1.resolve(); |
19 | 1.26k | let r2 = wit_component_new::decode(&wasm).unwrap(); |
20 | 1.26k | let r2 = r2.resolve(); |
21 | | |
22 | 1.26k | let mut sa32 = wit_parser_old::SizeAlign::new(wit_parser_old::AddressSize::Wasm32); |
23 | 1.26k | let mut sa64 = wit_parser_old::SizeAlign::new(wit_parser_old::AddressSize::Wasm64); |
24 | | |
25 | 1.26k | sa32.fill(r1); |
26 | 1.26k | sa64.fill(r1); |
27 | | |
28 | 1.26k | let mut alt = wit_parser_new::SizeAlign::default(); |
29 | 1.26k | alt.fill(r2); |
30 | | |
31 | 7.63k | for ((t1, _), (t2, _)) in r1.types.iter().zip(r2.types.iter()) { |
32 | 7.63k | let t1 = &wit_parser_old::Type::Id(t1); |
33 | 7.63k | let t2 = &wit_parser_new::Type::Id(t2); |
34 | 7.63k | let (s32, a32) = (sa32.size(t1), sa32.align(t1)); |
35 | 7.63k | let (s64, a64) = (sa64.size(t1), sa64.align(t1)); |
36 | 7.63k | let (salt, aalt) = (alt.size(t2), alt.align(t2)); |
37 | | |
38 | 7.63k | assert!(s32 <= s64); |
39 | 7.63k | assert!(a32 <= a64); |
40 | | |
41 | 7.63k | assert_eq!(a32, aalt.align_wasm32()); |
42 | 7.63k | assert_eq!(a64, aalt.align_wasm64()); |
43 | | |
44 | 7.63k | assert_eq!(s32, salt.size_wasm32()); |
45 | 7.63k | assert_eq!(s64, salt.size_wasm64()); |
46 | | |
47 | 7.63k | match (t1, t2) { |
48 | 7.63k | (wit_parser_old::Type::Id(id1), wit_parser_new::Type::Id(id2)) => { |
49 | 7.63k | let tp1 = &r1.types[*id1]; |
50 | 7.63k | let tp2 = &r2.types[*id2]; |
51 | 7.63k | match (&tp1.kind, &tp2.kind) { |
52 | | ( |
53 | 470 | wit_parser_old::TypeDefKind::Record(r1), |
54 | 470 | wit_parser_new::TypeDefKind::Record(r2), |
55 | | ) => { |
56 | 470 | let offsets32 = sa32.field_offsets(r1.fields.iter().map(|f| &f.ty)); |
57 | 470 | let offsets64 = sa64.field_offsets(r1.fields.iter().map(|f| &f.ty)); |
58 | 470 | let offsetsalt = alt.field_offsets(r2.fields.iter().map(|f| &f.ty)); |
59 | 1.21k | for ((fd32, fd64), fdalt) in offsets32 |
60 | 470 | .iter() |
61 | 470 | .zip(offsets64.iter()) |
62 | 470 | .zip(offsetsalt.iter()) |
63 | | { |
64 | 1.21k | assert_eq!(fd32.0, fdalt.0.size_wasm32()); |
65 | 1.21k | assert_eq!(fd64.0, fdalt.0.size_wasm64()); |
66 | | } |
67 | | } |
68 | | ( |
69 | 555 | wit_parser_old::TypeDefKind::Tuple(t1), |
70 | 555 | wit_parser_new::TypeDefKind::Tuple(t2), |
71 | | ) => { |
72 | 555 | let offsets32 = sa32.field_offsets(t1.types.iter()); |
73 | 555 | let offsets64 = sa64.field_offsets(t1.types.iter()); |
74 | 555 | let offsetsalt = alt.field_offsets(t2.types.iter()); |
75 | 2.20k | for ((fd32, fd64), fdalt) in offsets32 |
76 | 555 | .iter() |
77 | 555 | .zip(offsets64.iter()) |
78 | 555 | .zip(offsetsalt.iter()) |
79 | | { |
80 | 2.20k | assert_eq!(fd32.0, fdalt.0.size_wasm32()); |
81 | 2.20k | assert_eq!(fd64.0, fdalt.0.size_wasm64()); |
82 | | } |
83 | | } |
84 | | ( |
85 | 745 | wit_parser_old::TypeDefKind::Variant(v1), |
86 | 745 | wit_parser_new::TypeDefKind::Variant(v2), |
87 | | ) => { |
88 | 745 | let offset32 = |
89 | 2.98k | sa32.payload_offset(v1.tag(), v1.cases.iter().map(|f| f.ty.as_ref())); |
90 | 745 | let offset64 = |
91 | 2.98k | sa64.payload_offset(v1.tag(), v1.cases.iter().map(|f| f.ty.as_ref())); |
92 | 745 | let offsetalt = |
93 | 2.98k | alt.payload_offset(v2.tag(), v2.cases.iter().map(|f| f.ty.as_ref())); |
94 | 745 | assert_eq!(offset32, offsetalt.size_wasm32()); |
95 | 745 | assert_eq!(offset64, offsetalt.size_wasm64()); |
96 | | } |
97 | 5.86k | _ => (), |
98 | | } |
99 | | } |
100 | 0 | _ => (), |
101 | | } |
102 | | } |
103 | | |
104 | 1.26k | Ok(()) |
105 | 1.69k | } |
106 | | |
107 | 1.69k | fn write_file(path: &str, contents: impl AsRef<[u8]>) { |
108 | 1.69k | if !log::log_enabled!(log::Level::Debug) { |
109 | 1.69k | return; |
110 | 0 | } |
111 | 0 | log::debug!("writing file {path}"); |
112 | 0 | let contents = contents.as_ref(); |
113 | 0 | let path = Path::new(path); |
114 | 0 | std::fs::write(path, contents).unwrap(); |
115 | 0 | if path.extension().and_then(|s| s.to_str()) == Some("wasm") { |
116 | 0 | let path = path.with_extension("wat"); |
117 | 0 | log::debug!("writing file {}", path.display()); |
118 | 0 | std::fs::write(path, wasmprinter::print_bytes(&contents).unwrap()).unwrap(); |
119 | 0 | } |
120 | 1.69k | } |
121 | | |
122 | | #[test] |
123 | | fn smoke() { |
124 | | super::test::test_n_times(100, run); |
125 | | } |