Skip to content

Commit 3e38098

Browse files
authoredJun 20, 2024
Initialize a test suite for wit-encoder (bytecodealliance#1626)
* change `wit-encoder` indent to 2 * test empty `Result`s in `wit-encoder` * import wit test files for `wit-encoder` * use external wit test file for `functions.rs` test * add `empty` test * add `wit-encoder` overlap tests * fix more existing tests * Add `include` capabilities to `wit-encoder` * tidy up * rebase on main * check in `.gitattributes` to normalize line endings Rebasing brok * remove additional wit files * inline tests
1 parent 8afdf05 commit 3e38098

18 files changed

+314
-134
lines changed
 

‎.gitattributes

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
* text=auto
12
*.waves text eol=lf
23
*.out text eol=lf

‎Cargo.lock

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ bitflags = "2.5.0"
8484
hashbrown = { version = "0.14.3", default-features = false, features = ['ahash'] }
8585
ahash = { version = "0.8.11", default-features = false }
8686
termcolor = "1.2.0"
87+
indoc = "2.0.5"
8788

8889
wasm-compose = { version = "0.211.1", path = "crates/wasm-compose" }
8990
wasm-encoder = { version = "0.211.1", path = "crates/wasm-encoder" }

‎crates/wit-encoder/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ workspace = true
1313
[dependencies]
1414
semver = { workspace = true }
1515
pretty_assertions = { workspace = true }
16+
17+
[dev-dependencies]
18+
indoc = { workspace = true }

‎crates/wit-encoder/src/function.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ where
108108
impl Results {
109109
// For the common case of an empty results list.
110110
pub fn empty() -> Results {
111-
Results::Named(Default::default())
111+
Results::Named(Params::empty())
112112
}
113113

114114
pub fn anon(type_: Type) -> Results {
@@ -166,3 +166,14 @@ impl StandaloneFunc {
166166
self.docs = docs.map(|d| d.into());
167167
}
168168
}
169+
170+
#[cfg(test)]
171+
mod test {
172+
use crate::Results;
173+
174+
#[test]
175+
fn is_empty() {
176+
let res = Results::empty();
177+
assert!(res.is_empty());
178+
}
179+
}

‎crates/wit-encoder/src/include.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::fmt;
2+
3+
use crate::{Ident, Render};
4+
5+
/// Enable the union of a world with another world
6+
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7+
pub struct Include {
8+
use_path: Ident,
9+
include_names_list: Vec<String>,
10+
}
11+
12+
impl Include {
13+
pub fn new(use_path: impl Into<Ident>) -> Self {
14+
Self {
15+
use_path: use_path.into(),
16+
include_names_list: vec![],
17+
}
18+
}
19+
}
20+
21+
impl Render for Include {
22+
fn render(&self, f: &mut fmt::Formatter<'_>, opts: &crate::RenderOpts) -> fmt::Result {
23+
write!(f, "{}include {};\n", opts.spaces(), self.use_path)?;
24+
Ok(())
25+
}
26+
}

‎crates/wit-encoder/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod enum_;
88
mod flags;
99
mod function;
1010
mod ident;
11+
mod include;
1112
mod interface;
1213
mod package;
1314
mod record;
@@ -24,6 +25,7 @@ pub use enum_::*;
2425
pub use flags::*;
2526
pub use function::*;
2627
pub use ident::*;
28+
pub use include::*;
2729
pub use interface::*;
2830
pub use package::*;
2931
pub use record::*;

‎crates/wit-encoder/src/package.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,21 @@ impl Package {
4141
impl Render for Package {
4242
fn render(&self, f: &mut fmt::Formatter<'_>, opts: &RenderOpts) -> fmt::Result {
4343
write!(f, "{}package {};\n", opts.spaces(), self.name)?;
44-
write!(f, "\n")?;
4544
for item in &self.items {
45+
write!(f, "\n")?;
4646
match item {
4747
PackageItem::Interface(interface) => {
4848
if let Some(docs) = &interface.docs {
4949
docs.render(f, opts)?;
5050
}
51-
write!(f, "{}interface {} {{\n", opts.spaces(), interface.name)?;
52-
interface.items.render(f, &opts.indent())?;
53-
write!(f, "{}}}\n", opts.spaces())?;
51+
write!(f, "{}interface {} {{", opts.spaces(), interface.name)?;
52+
if !interface.items.is_empty() {
53+
write!(f, "\n")?;
54+
interface.items.render(f, &opts.indent())?;
55+
write!(f, "{}}}\n", opts.spaces())?;
56+
} else {
57+
write!(f, "}}\n")?;
58+
}
5459
}
5560
PackageItem::World(world) => {
5661
world.render(f, opts)?;

‎crates/wit-encoder/src/render.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub struct RenderOpts {
1111
impl Default for RenderOpts {
1212
fn default() -> Self {
1313
Self {
14-
indent_width: 4,
14+
indent_width: 2,
1515
ident_count: 0,
1616
}
1717
}

‎crates/wit-encoder/src/ty.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,11 @@ impl Render for TypeDef {
317317
if let Some(docs) = &self.docs {
318318
docs.render(f, opts)?;
319319
}
320-
write!(f, "{}record {} {{\n", opts.spaces(), self.name)?;
321-
for field in &record.fields {
320+
write!(f, "{}record {} {{", opts.spaces(), self.name)?;
321+
for (index, field) in record.fields.iter().enumerate() {
322+
if index == 0 {
323+
write!(f, "\n")?;
324+
}
322325
let opts = opts.indent();
323326
if let Some(docs) = &field.docs {
324327
docs.render(f, &opts)?;

‎crates/wit-encoder/src/world.rs

+27-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::fmt;
22

3-
use crate::{ident::Ident, Docs, Interface, Render, RenderOpts, StandaloneFunc};
3+
use crate::{ident::Ident, Docs, Include, Interface, Render, RenderOpts, StandaloneFunc};
44

55
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
66
pub struct World {
@@ -52,6 +52,9 @@ impl World {
5252
pub fn function_export(&mut self, value: StandaloneFunc) {
5353
self.item(WorldItem::function_export(value));
5454
}
55+
pub fn include(&mut self, value: impl Into<Ident>) {
56+
self.item(WorldItem::include(value));
57+
}
5558

5659
/// Set the documentation
5760
pub fn docs(&mut self, docs: Option<impl Into<Docs>>) {
@@ -88,18 +91,28 @@ impl Render for World {
8891
docs.render(f, opts)?;
8992
}
9093
import(f, opts)?;
91-
write!(f, "{}: interface {{\n", interface.name)?;
92-
interface.items.render(f, &opts.indent())?;
93-
write!(f, "{}}}\n", opts.spaces())?;
94+
write!(f, "{}: interface {{", interface.name)?;
95+
if !interface.items.is_empty() {
96+
write!(f, "\n")?;
97+
interface.items.render(f, &opts.indent())?;
98+
write!(f, "{}}}\n", opts.spaces())?;
99+
} else {
100+
write!(f, "}}\n")?;
101+
}
94102
}
95103
WorldItem::InlineInterfaceExport(interface) => {
96104
if let Some(docs) = &interface.docs {
97105
docs.render(f, opts)?;
98106
}
99107
export(f, opts)?;
100-
write!(f, "{}: interface {{\n", interface.name)?;
101-
interface.items.render(f, &opts.indent())?;
102-
write!(f, "{}}}\n", opts.spaces())?;
108+
write!(f, "{}: interface {{", interface.name)?;
109+
if !interface.items.is_empty() {
110+
write!(f, "\n")?;
111+
interface.items.render(f, &opts.indent())?;
112+
write!(f, "{}}}\n", opts.spaces())?;
113+
} else {
114+
write!(f, "}}\n")?;
115+
}
103116
}
104117
WorldItem::NamedInterfaceImport(interface) => {
105118
if let Some(docs) = &interface.docs {
@@ -129,6 +142,7 @@ impl Render for World {
129142
export(f, opts)?;
130143
render_function(f, opts, function)?;
131144
}
145+
WorldItem::Include(include) => include.render(f, opts)?,
132146
}
133147
}
134148
let opts = &opts.outdent();
@@ -156,6 +170,9 @@ pub enum WorldItem {
156170

157171
/// A function is being directly exported from this world.
158172
FunctionExport(StandaloneFunc),
173+
174+
/// Include type
175+
Include(Include),
159176
}
160177

161178
impl WorldItem {
@@ -177,6 +194,9 @@ impl WorldItem {
177194
pub fn function_export(value: StandaloneFunc) -> Self {
178195
Self::FunctionExport(value)
179196
}
197+
pub fn include(value: impl Into<Ident>) -> Self {
198+
Self::Include(Include::new(value))
199+
}
180200
}
181201

182202
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]

‎crates/wit-encoder/tests/empty.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use pretty_assertions::assert_eq;
2+
use wit_encoder::{Package, PackageName};
3+
4+
const PACKAGE: &str = indoc::indoc! {"
5+
package foo:empty;
6+
"};
7+
8+
#[test]
9+
fn concrete_types() {
10+
let package = Package::new(PackageName::new("foo", "empty", None));
11+
assert_eq!(package.to_string(), PACKAGE);
12+
}

‎crates/wit-encoder/tests/functions.rs

+35-35
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,88 @@
11
use pretty_assertions::assert_eq;
2-
use wit_encoder::{Params, Result_, Results, StandaloneFunc, Type};
2+
use wit_encoder::{
3+
Interface, Package, PackageName, Params, Result_, Results, StandaloneFunc, Type,
4+
};
35

4-
const PACKAGE: &str = "package foo:functions;
6+
const PACKAGE: &str = indoc::indoc! {"
7+
package foo:functions;
58
6-
interface functions {
7-
f1: func();
8-
f2: func(a: u32);
9-
f3: func() -> u32;
10-
/// this is a documentation comment
11-
/// for the f4 function
12-
f4: func() -> tuple<u32, u32>;
13-
f5: func(a: f32, b: f32) -> tuple<u32, u32>;
14-
f6: func(a: option<u32>) -> result<u32, f32>;
15-
f7: func() -> (u: u32, f: f32);
16-
f8: func() -> (u: u32);
17-
f9: func() -> result<f32>;
18-
f10: func() -> result<_, f32>;
19-
f11: func() -> result;
20-
}
21-
";
9+
interface functions {
10+
f1: func();
11+
f2: func(a: u32);
12+
f4: func() -> u32;
13+
f6: func() -> tuple<u32, u32>;
14+
f7: func(a: f32, b: f32) -> tuple<u32, u32>;
15+
f8: func(a: option<u32>) -> result<u32, f32>;
16+
f9: func() -> (u: u32, f: f32);
17+
f10: func() -> (u: u32);
18+
f11: func() -> result<f32>;
19+
f12: func() -> result<_, f32>;
20+
f13: func() -> result;
21+
}
22+
"};
2223

2324
#[test]
24-
fn smoke() {
25-
let name = wit_encoder::PackageName::new("foo", "functions", None);
26-
let mut package = wit_encoder::Package::new(name);
25+
fn concrete_types() {
26+
let name = PackageName::new("foo", "functions", None);
27+
let mut package = Package::new(name);
2728

2829
package.interface({
29-
let mut interface = wit_encoder::Interface::new("functions");
30+
let mut interface = Interface::new("functions");
3031
interface.function(StandaloneFunc::new("f1"));
3132
interface.function({
3233
let mut func = StandaloneFunc::new("f2");
3334
func.params(Params::from_iter([("a", Type::U32)]));
3435
func
3536
});
3637
interface.function({
37-
let mut func = StandaloneFunc::new("f3");
38-
func.results(Type::U32);
38+
let mut func = StandaloneFunc::new("f4");
39+
func.results(Results::anon(Type::U32));
3940
func
4041
});
4142
interface.function({
42-
let mut func = StandaloneFunc::new("f4");
43-
func.results(Type::tuple(vec![Type::U32, Type::U32]));
44-
func.docs(Some("this is a documentation comment\nfor the f4 function"));
43+
let mut func = StandaloneFunc::new("f6");
44+
func.results(Results::anon(Type::tuple(vec![Type::U32, Type::U32])));
4545
func
4646
});
4747
interface.function({
48-
let mut func = StandaloneFunc::new("f5");
48+
let mut func = StandaloneFunc::new("f7");
4949
func.params(Params::from_iter([("a", Type::F32), ("b", Type::F32)]));
5050
func.results(Type::tuple(vec![Type::U32, Type::U32]));
5151
func
5252
});
5353
interface.function({
54-
let mut func = StandaloneFunc::new("f6");
54+
let mut func = StandaloneFunc::new("f8");
5555
func.params(Params::from_iter([("a", Type::option(Type::U32))]));
5656
func.results(Type::result(Result_::both(Type::U32, Type::F32)));
5757
func
5858
});
5959
interface.function({
60-
let mut func = StandaloneFunc::new("f7");
60+
let mut func = StandaloneFunc::new("f9");
6161
func.results(Results::named(vec![("u", Type::U32), ("f", Type::F32)]));
6262
func
6363
});
6464
interface.function({
65-
let mut func = StandaloneFunc::new("f8");
65+
let mut func = StandaloneFunc::new("f10");
6666
func.results(Results::named(vec![("u", Type::U32)]));
6767
func
6868
});
6969
interface.function({
70-
let mut func = StandaloneFunc::new("f9");
70+
let mut func = StandaloneFunc::new("f11");
7171
func.results(Type::result(Result_::ok(Type::F32)));
7272
func
7373
});
7474
interface.function({
75-
let mut func = StandaloneFunc::new("f10");
75+
let mut func = StandaloneFunc::new("f12");
7676
func.results(Type::result(Result_::err(Type::F32)));
7777
func
7878
});
7979
interface.function({
80-
let mut func = StandaloneFunc::new("f11");
80+
let mut func = StandaloneFunc::new("f13");
8181
func.results(Type::result(Result_::empty()));
8282
func
8383
});
8484
interface
8585
});
8686

87-
assert_eq!(PACKAGE, package.to_string());
87+
assert_eq!(package.to_string(), PACKAGE);
8888
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use pretty_assertions::assert_eq;
2+
use wit_encoder::{Package, PackageName, StandaloneFunc, World};
3+
4+
const PACKAGE: &str = indoc::indoc! {"
5+
package foo:foo;
6+
7+
world foo {
8+
import a: func();
9+
export a: func();
10+
}
11+
"};
12+
13+
#[test]
14+
fn concrete_types() {
15+
let mut package = Package::new(PackageName::new("foo", "foo", None));
16+
17+
let mut world = World::new("foo");
18+
world.function_import(StandaloneFunc::new("a"));
19+
world.function_export(StandaloneFunc::new("a"));
20+
package.world(world);
21+
22+
assert_eq!(package.to_string(), PACKAGE);
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use pretty_assertions::assert_eq;
2+
use wit_encoder::{Interface, Package, PackageName, StandaloneFunc, World};
3+
4+
const PACKAGE: &str = indoc::indoc! {"
5+
package foo:foo;
6+
7+
world foo {
8+
import a: func();
9+
export a: interface {}
10+
}
11+
"};
12+
13+
#[test]
14+
fn concrete_types() {
15+
let mut package = Package::new(PackageName::new("foo", "foo", None));
16+
17+
let mut world = World::new("foo");
18+
world.function_import(StandaloneFunc::new("a"));
19+
world.inline_interface_export(Interface::new("a"));
20+
package.world(world);
21+
22+
assert_eq!(package.to_string(), PACKAGE);
23+
}
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use pretty_assertions::assert_eq;
2+
use wit_encoder::{Interface, Package, PackageName, World};
3+
4+
const PACKAGE: &str = indoc::indoc! {"
5+
package foo:foo;
6+
7+
interface a {}
8+
9+
interface b {}
10+
11+
world bar {
12+
import a;
13+
export b;
14+
}
15+
16+
world foo {
17+
include bar;
18+
include bar;
19+
include bar;
20+
}
21+
"};
22+
23+
#[test]
24+
fn concrete_types() {
25+
let mut package = Package::new(PackageName::new("foo", "foo", None));
26+
27+
package.interface(Interface::new("a"));
28+
package.interface(Interface::new("b"));
29+
30+
let mut world = World::new("bar");
31+
world.named_interface_import("a");
32+
world.named_interface_export("b");
33+
package.world(world);
34+
35+
let mut world = World::new("foo");
36+
world.include("bar");
37+
world.include("bar");
38+
world.include("bar");
39+
package.world(world);
40+
41+
assert_eq!(package.to_string(), PACKAGE);
42+
}

‎crates/wit-encoder/tests/type_defs.rs

+72-72
Original file line numberDiff line numberDiff line change
@@ -3,109 +3,109 @@ use wit_encoder::{
33
Field, Flag, Params, ResourceFunc, Result_, Results, Type, TypeDef, TypeDefKind, VariantCase,
44
};
55

6-
const PACKAGE: &str = "package wit-encoder:tests;
6+
const PACKAGE: &str = indoc::indoc! {"
7+
package wit-encoder:tests;
78
8-
/// interface documentation
9-
interface type-defs {
10-
type t1 = u8;
11-
type t2 = u16;
12-
type t3 = u32;
13-
type t4 = u64;
14-
type t5 = s8;
15-
type t6 = s16;
16-
type t7 = s32;
17-
type t8 = s64;
18-
type t9a = f32;
19-
type t9b = f32;
20-
type t10a = f64;
21-
type t10b = f64;
22-
type t11 = char;
23-
type t12 = list<char>;
24-
type t13 = string;
25-
type t14 = option<u32>;
26-
type t15 = result<u32, u32>;
27-
type t16 = result<_, u32>;
28-
type t17 = result<u32>;
29-
/// this is a documentation comment
30-
type t18 = result;
31-
record t20 {
32-
}
33-
record t21 {
9+
/// interface documentation
10+
interface type-defs {
11+
type t1 = u8;
12+
type t2 = u16;
13+
type t3 = u32;
14+
type t4 = u64;
15+
type t5 = s8;
16+
type t6 = s16;
17+
type t7 = s32;
18+
type t8 = s64;
19+
type t9a = f32;
20+
type t9b = f32;
21+
type t10a = f64;
22+
type t10b = f64;
23+
type t11 = char;
24+
type t12 = list<char>;
25+
type t13 = string;
26+
type t14 = option<u32>;
27+
type t15 = result<u32, u32>;
28+
type t16 = result<_, u32>;
29+
type t17 = result<u32>;
30+
/// this is a documentation comment
31+
type t18 = result;
32+
record t20 { }
33+
record t21 {
3434
a: u32,
35-
}
36-
record t22 {
35+
}
36+
record t22 {
3737
a: u32,
38-
}
39-
record t23 {
38+
}
39+
record t23 {
4040
a: u32,
4141
b: u64,
42-
}
43-
record t24 {
42+
}
43+
record t24 {
4444
a: u32,
4545
b: u64,
46-
}
47-
record t25 {
46+
}
47+
record t25 {
4848
x: u32,
49-
}
50-
record %record {
49+
}
50+
record %record {
5151
a: u32,
52-
}
53-
type t26 = tuple<>;
54-
type t27 = tuple<u32>;
55-
type t29 = tuple<u32, u64>;
56-
flags t30 {
57-
}
58-
flags t31 {
52+
}
53+
type t26 = tuple<>;
54+
type t27 = tuple<u32>;
55+
type t29 = tuple<u32, u64>;
56+
flags t30 {
57+
}
58+
flags t31 {
5959
/// option a
6060
a,
6161
/// option b
6262
b,
6363
/// option c
6464
c,
65-
}
66-
flags t32 {
65+
}
66+
flags t32 {
6767
a,
6868
b,
6969
c,
70-
}
71-
variant t33 {
70+
}
71+
variant t33 {
7272
a,
73-
}
74-
variant t34 {
73+
}
74+
variant t34 {
7575
a,
7676
b,
77-
}
78-
variant t35 {
77+
}
78+
variant t35 {
7979
a,
8080
b,
81-
}
82-
variant t36 {
81+
}
82+
variant t36 {
8383
a,
8484
b(u32),
85-
}
86-
variant t37 {
85+
}
86+
variant t37 {
8787
a,
8888
b(option<u32>),
89-
}
90-
enum t41 {
89+
}
90+
enum t41 {
9191
a,
9292
b,
9393
c,
94-
}
95-
enum t42 {
94+
}
95+
enum t42 {
9696
a,
9797
b,
9898
c,
99-
}
100-
type t43 = bool;
101-
type t44 = string;
102-
type t45 = list<list<list<t32>>>;
103-
type t46 = t44;
104-
type foo = bar;
105-
type bar = u32;
106-
resource t50 {
107-
}
108-
resource t51 {
99+
}
100+
type t43 = bool;
101+
type t44 = string;
102+
type t45 = list<list<list<t32>>>;
103+
type t46 = t44;
104+
type foo = bar;
105+
type bar = u32;
106+
resource t50 {
107+
}
108+
resource t51 {
109109
/// create a new t51
110110
constructor(a: u32);
111111
/// set a
@@ -114,9 +114,9 @@ interface type-defs {
114114
get-a: func() -> u32;
115115
/// do b
116116
b: static func();
117+
}
117118
}
118-
}
119-
";
119+
"};
120120

121121
#[test]
122122
fn types() {

‎crates/wit-encoder/tests/world.rs

+13-12
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
use pretty_assertions::assert_eq;
22
use wit_encoder::{Interface, StandaloneFunc, Type};
33

4-
const PACKAGE: &str = "package foo:functions;
4+
const PACKAGE: &str = indoc::indoc! {"
5+
package foo:functions;
56
6-
interface error-reporter {
7-
}
8-
world %world {
9-
/// inline interface
10-
export example: interface {
7+
interface error-reporter {}
8+
9+
world %world {
10+
/// inline interface
11+
export example: interface {
1112
/// func docs
1213
do-nothing: func();
14+
}
15+
/// scan stuff
16+
export scan: func() -> list<u8>;
17+
import error-reporter;
18+
import print: func(s: string);
1319
}
14-
/// scan stuff
15-
export scan: func() -> list<u8>;
16-
import error-reporter;
17-
import print: func(s: string);
18-
}
19-
";
20+
"};
2021

2122
#[test]
2223
fn worlds() {

0 commit comments

Comments
 (0)
Please sign in to comment.