Skip to content

Commit 9d79e58

Browse files
authored
Add a new style of test suite for the witx tooling similar to *.wast (#392)
* Add a wast-like testsuite for the witx tool As the functionality of `witx` grows this will hopefully make adding tests for new functionality as well as new kinds of tests easier. The goal is to make it very easy to drop a test file with various directives to exercise the functionality of `witx` and its internals. For now the testsuite is quite simple, simply asserting whether documents are either valid or invalid. My hope, though, is that this can be expanded over time with more styles of assertions directives. * Migrate union test to `union.witxt` * Add documentation/roundtrip testing to all documents * Translate multi-module test suite to `*.witxt` * Move wasi tests into `witxt` test suites * Convert representation tests to `*.witxt` * Rebased onto origin/main
1 parent 09bb902 commit 9d79e58

22 files changed

+726
-431
lines changed

phases/ephemeral/docs.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -871,12 +871,12 @@ Alignment: 8
871871
- align: 8
872872
- tag_size: 1
873873
### Variant cases
874+
- <a href="#event_u.clock" name="event_u.clock"></a> `clock`
875+
874876
- <a href="#event_u.fd_read" name="event_u.fd_read"></a> `fd_read`: [`event_fd_readwrite`](#event_fd_readwrite)
875877

876878
- <a href="#event_u.fd_write" name="event_u.fd_write"></a> `fd_write`: [`event_fd_readwrite`](#event_fd_readwrite)
877879

878-
- <a href="#event_u.clock" name="event_u.clock"></a> `clock`
879-
880880
## <a href="#event" name="event"></a> `event`: Record
881881
An event that occurred.
882882

tools/witx/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,8 @@ wast = { version = "22.0.0", default-features = false }
2323
diff = "0.1.11"
2424
pretty_env_logger = "0.4"
2525
structopt = "0.3"
26+
rayon = "1.0"
27+
28+
[[test]]
29+
name = "witxt"
30+
harness = false

tools/witx/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod io;
99
/// Calculate memory layout of types
1010
mod layout;
1111
/// Witx syntax parsing from SExprs
12-
mod parser;
12+
pub mod parser;
1313
/// Paths to witx documents for various proposal phases
1414
pub mod phases;
1515
/// Calculate required polyfill between interfaces
@@ -28,10 +28,9 @@ pub use coretypes::{AtomType, CoreFuncType, CoreParamSignifies, CoreParamType, T
2828
pub use docs::Documentation;
2929
pub use io::{Filesystem, MockFs, WitxIo};
3030
pub use layout::{Layout, RecordMemberLayout, SizeAlign};
31-
pub use parser::DeclSyntax;
3231
pub use render::SExpr;
3332
pub use representation::{RepEquality, Representable};
34-
pub use validate::ValidationError;
33+
pub use validate::{DocValidation, ValidationError};
3534

3635
use std::path::{Path, PathBuf};
3736
use thiserror::Error;

tools/witx/src/parser.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,6 @@ impl<'a> Parse<'a> for UnionSyntax<'a> {
477477
None
478478
};
479479
let mut fields = Vec::new();
480-
fields.push(parser.parse()?);
481480
while !parser.is_empty() {
482481
fields.push(parser.parse()?);
483482
}
@@ -505,7 +504,9 @@ impl<'a> Parse<'a> for VariantSyntax<'a> {
505504
};
506505
let mut cases = Vec::new();
507506
while !parser.is_empty() {
508-
cases.push(parser.parens(|p| p.parse())?);
507+
let comments = parser.parse()?;
508+
let item = parser.parens(|p| p.parse())?;
509+
cases.push(Documented { comments, item });
509510
}
510511
Ok(VariantSyntax { tag, cases })
511512
}

tools/witx/src/representation.rs

Lines changed: 5 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,14 @@ impl Representable for Variant {
8181
let other_by_name = by
8282
.cases
8383
.iter()
84-
.map(|c| (&c.name, c))
84+
.enumerate()
85+
.map(|(i, c)| (&c.name, (c, i)))
8586
.collect::<HashMap<_, _>>();
8687
// For each variant in self, must have variant of same name in by:
87-
for v in self.cases.iter() {
88+
for (i, v) in self.cases.iter().enumerate() {
8889
let other_ty = match other_by_name.get(&v.name) {
89-
Some(other) => &other.tref,
90+
Some((_, j)) if i != *j => return RepEquality::NotEq,
91+
Some((other, _)) => &other.tref,
9092
None => return RepEquality::NotEq,
9193
};
9294
match (&v.tref, other_ty) {
@@ -157,76 +159,3 @@ impl Representable for Type {
157159
}
158160
}
159161
}
160-
161-
#[cfg(test)]
162-
mod test {
163-
use super::*;
164-
use crate::io::MockFs;
165-
use crate::toplevel::parse_witx_with;
166-
use crate::Id;
167-
use std::rc::Rc;
168-
169-
fn def_type(typename: &str, syntax: &str) -> Rc<NamedType> {
170-
use std::path::Path;
171-
let doc = parse_witx_with(&[Path::new("-")], &MockFs::new(&[("-", syntax)]))
172-
.expect("parse witx doc");
173-
let t = doc.typename(&Id::new(typename)).expect("defined type");
174-
// Identity should always be true:
175-
assert_eq!(t.representable(&t), RepEquality::Eq, "identity");
176-
t
177-
}
178-
179-
#[test]
180-
fn different_typenames() {
181-
let a = def_type("a", "(typename $a (flags (@witx bitflags u32) $b $c))");
182-
let d = def_type("d", "(typename $d (flags (@witx bitflags u32) $b $c))");
183-
184-
assert_eq!(a.representable(&d), RepEquality::Eq);
185-
assert_eq!(d.representable(&a), RepEquality::Eq);
186-
}
187-
188-
#[test]
189-
fn enum_() {
190-
let base = def_type("a", "(typename $a (enum $b $c))");
191-
let extra_variant = def_type("a", "(typename $a (enum $b $c $d))");
192-
193-
assert_eq!(base.representable(&extra_variant), RepEquality::Superset);
194-
assert_eq!(extra_variant.representable(&base), RepEquality::NotEq);
195-
196-
let smaller_size = def_type("a", "(typename $a (enum (@witx tag u16) $b $c))");
197-
assert_eq!(smaller_size.representable(&base), RepEquality::Superset);
198-
assert_eq!(
199-
smaller_size.representable(&extra_variant),
200-
RepEquality::Superset
201-
);
202-
}
203-
204-
#[test]
205-
fn union() {
206-
let base = def_type(
207-
"a",
208-
"(typename $tag (enum (@witx tag u8) $b $c))
209-
(typename $a (union (@witx tag $tag) u32 f32))",
210-
);
211-
let extra_variant = def_type(
212-
"a",
213-
"(typename $tag (enum (@witx tag u8) $b $c $d))
214-
(typename $a (union (@witx tag $tag) u32 f32 f64))",
215-
);
216-
217-
assert_eq!(base.representable(&extra_variant), RepEquality::Superset);
218-
assert_eq!(extra_variant.representable(&base), RepEquality::NotEq);
219-
220-
let other_ordering = def_type(
221-
"a",
222-
"(typename $tag (enum (@witx tag u8) $b $c))
223-
(typename $a (variant (@witx tag $tag) (case $c f32) (case $b u32)))",
224-
);
225-
assert_eq!(base.representable(&other_ordering), RepEquality::Eq);
226-
assert_eq!(other_ordering.representable(&base), RepEquality::Eq);
227-
assert_eq!(
228-
other_ordering.representable(&extra_variant),
229-
RepEquality::Superset
230-
);
231-
}
232-
}

tools/witx/src/toplevel.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ fn _parse_witx_with(paths: &[&Path], io: &dyn WitxIo) -> Result<Document, WitxEr
3232
&mut parsed,
3333
)?;
3434
}
35-
Ok(Document::new(definitions, validator.entries))
35+
Ok(validator.into_document(definitions))
3636
}
3737

3838
fn parse_file(

tools/witx/src/validate.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ use crate::{
55
ImportTypeSyntax, ModuleDeclSyntax, RecordSyntax, TypedefSyntax, UnionSyntax,
66
VariantSyntax,
77
},
8-
BuiltinType, Case, Constant, Definition, Entry, HandleDatatype, Id, IntRepr, InterfaceFunc,
9-
InterfaceFuncParam, InterfaceFuncParamPosition, Location, Module, ModuleDefinition,
10-
ModuleEntry, ModuleImport, ModuleImportVariant, NamedType, RecordDatatype, RecordMember, Type,
11-
TypePassedBy, TypeRef, Variant,
8+
BuiltinType, Case, Constant, Definition, Document, Entry, HandleDatatype, Id, IntRepr,
9+
InterfaceFunc, InterfaceFuncParam, InterfaceFuncParamPosition, Location, Module,
10+
ModuleDefinition, ModuleEntry, ModuleImport, ModuleImportVariant, NamedType, RecordDatatype,
11+
RecordMember, Type, TypePassedBy, TypeRef, Variant,
1212
};
1313
use std::collections::{HashMap, HashSet};
1414
use std::path::Path;
@@ -129,7 +129,7 @@ impl IdentValidation {
129129

130130
pub struct DocValidation {
131131
scope: IdentValidation,
132-
pub entries: HashMap<Id, Entry>,
132+
entries: HashMap<Id, Entry>,
133133
constant_scopes: HashMap<Id, IdentValidation>,
134134
}
135135

@@ -155,6 +155,10 @@ impl DocValidation {
155155
path,
156156
}
157157
}
158+
159+
pub fn into_document(self, defs: Vec<Definition>) -> Document {
160+
Document::new(defs, self.entries)
161+
}
158162
}
159163

160164
impl DocValidationScope<'_> {
@@ -439,14 +443,16 @@ impl DocValidationScope<'_> {
439443
}
440444
}
441445

442-
let mut names = names.map(|names| names.into_iter().collect::<HashSet<_>>());
446+
let mut name_set = names
447+
.as_ref()
448+
.map(|names| names.iter().collect::<HashSet<_>>());
443449

444-
let cases = syntax
450+
let mut cases = syntax
445451
.cases
446452
.iter()
447453
.map(|case| {
448454
let name = Id::new(case.item.name.name());
449-
if let Some(names) = &mut names {
455+
if let Some(names) = &mut name_set {
450456
if !names.remove(&name) {
451457
return Err(ValidationError::InvalidUnionField {
452458
name: name.as_str().to_string(),
@@ -467,6 +473,18 @@ impl DocValidationScope<'_> {
467473
})
468474
})
469475
.collect::<Result<Vec<_>, _>>()?;
476+
477+
// If we have an explicit tag with an enum then that's instructing us to
478+
// reorder cases based on the order of the enum itself, so do that here.
479+
if let Some(names) = names {
480+
let name_pos = names
481+
.iter()
482+
.enumerate()
483+
.map(|(i, name)| (name, i))
484+
.collect::<HashMap<_, _>>();
485+
cases.sort_by_key(|c| name_pos[&&c.name]);
486+
}
487+
470488
Ok(Variant { tag_repr, cases })
471489
}
472490

tools/witx/tests/anonymous.rs

Lines changed: 0 additions & 43 deletions
This file was deleted.

tools/witx/tests/multimodule.rs

Lines changed: 0 additions & 58 deletions
This file was deleted.

0 commit comments

Comments
 (0)