Coverage Report

Created: 2025-12-04 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}