Skip to content

Commit 5f90f9d

Browse files
committed
Add more test cases.
1 parent 51a029c commit 5f90f9d

56 files changed

Lines changed: 660 additions & 21 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

crates/wac-graph/src/graph.rs

Lines changed: 162 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ pub enum Error {
7474
path: String,
7575
},
7676
/// The specified package version is invalid.
77-
#[error("package version `{version}` is not a valid: {error}")]
77+
#[error("package version `{version}` is not a valid semantic version")]
7878
InvalidPackageVersion {
7979
/// The version that was invalid.
8080
version: String,
@@ -144,7 +144,7 @@ pub enum Error {
144144
node: NodeId,
145145
},
146146
/// The instance does not export an item with the given name.
147-
#[error("instance does not have an export `{export}`")]
147+
#[error("instance does not have an export named `{export}`")]
148148
InstanceMissingExport {
149149
/// The instance node that is missing the export.
150150
node: NodeId,
@@ -195,7 +195,7 @@ pub enum Error {
195195
#[error("the node cannot be unmarked from export as it is a type definition")]
196196
MustExportDefinition,
197197
/// An implicit import on an instantiation conflicts with an explicit import node.
198-
#[error("an instantiation node implicitly imports an item named `{name}`, but it conflicts with an explicit export of the same name")]
198+
#[error("an instantiation node implicitly imports an item named `{name}`, but it conflicts with an explicit import node of the same name")]
199199
ImplicitImportConfig {
200200
/// The existing import node.
201201
import: NodeId,
@@ -205,9 +205,12 @@ pub enum Error {
205205
name: String,
206206
},
207207
/// An error occurred while aggregating a type.
208-
#[error(transparent)]
208+
#[error("failed to aggregate type definition for import `{import}`")]
209209
TypeAggregationError {
210+
/// The name of the import being aggregated.
211+
import: String,
210212
/// The type aggregation error.
213+
#[source]
211214
source: anyhow::Error,
212215
},
213216
}
@@ -1436,7 +1439,10 @@ impl<'a, C> CompositionGraphEncoder<'a, C> {
14361439

14371440
aggregator = aggregator
14381441
.aggregate(name, package.types(), *kind, &mut cache)
1439-
.map_err(|e| Error::TypeAggregationError { source: e })?;
1442+
.map_err(|e| Error::TypeAggregationError {
1443+
import: name.clone(),
1444+
source: e,
1445+
})?;
14401446
arguments.push((node, name));
14411447
}
14421448
}
@@ -1725,3 +1731,154 @@ impl<'a, C> CompositionGraphEncoder<'a, C> {
17251731
}
17261732
}
17271733
}
1734+
1735+
#[cfg(test)]
1736+
mod test {
1737+
use super::*;
1738+
use wac_types::{DefinedType, PrimitiveType, Resource, ValueType};
1739+
1740+
#[test]
1741+
fn it_errors_with_type_not_defined() {
1742+
let mut graph = CompositionGraph::new();
1743+
// Define the type in a different type collection
1744+
let mut types = Types::new();
1745+
let id = types.add_defined_type(DefinedType::Alias(ValueType::Primitive(
1746+
PrimitiveType::Bool,
1747+
)));
1748+
assert!(matches!(
1749+
graph
1750+
.add_type_definition_node(
1751+
"foo",
1752+
Type::Value(ValueType::Defined {
1753+
id,
1754+
contains_borrow: false
1755+
}),
1756+
()
1757+
)
1758+
.unwrap_err(),
1759+
Error::TypeNotDefined { .. }
1760+
));
1761+
}
1762+
1763+
#[test]
1764+
fn it_adds_a_type_definition() {
1765+
let mut graph = CompositionGraph::new();
1766+
let id = graph
1767+
.types_mut()
1768+
.add_defined_type(DefinedType::Alias(ValueType::Primitive(
1769+
PrimitiveType::Bool,
1770+
)));
1771+
assert!(graph
1772+
.add_type_definition_node(
1773+
"foo",
1774+
Type::Value(ValueType::Defined {
1775+
id,
1776+
contains_borrow: false
1777+
}),
1778+
()
1779+
)
1780+
.is_ok());
1781+
}
1782+
1783+
#[test]
1784+
fn it_cannot_define_a_resource() {
1785+
let mut graph = CompositionGraph::new();
1786+
let id = graph.types_mut().add_resource(Resource {
1787+
name: "a".to_string(),
1788+
alias_of: None,
1789+
});
1790+
assert!(matches!(
1791+
graph
1792+
.add_type_definition_node("foo", Type::Resource(id), ())
1793+
.unwrap_err(),
1794+
Error::CannotDefineResource
1795+
));
1796+
}
1797+
1798+
#[test]
1799+
fn it_validates_package_ids() {
1800+
let mut graph = CompositionGraph::new();
1801+
let old = graph
1802+
.register_package(
1803+
Package::from_bytes("foo:bar", None, wat::parse_str("(component)").unwrap())
1804+
.unwrap(),
1805+
)
1806+
.unwrap();
1807+
1808+
assert_eq!(old.index, 0);
1809+
assert_eq!(old.generation, 0);
1810+
1811+
graph.unregister_package(old).unwrap();
1812+
1813+
let new = graph
1814+
.register_package(
1815+
Package::from_bytes("foo:bar", None, wat::parse_str("(component)").unwrap())
1816+
.unwrap(),
1817+
)
1818+
.unwrap();
1819+
1820+
assert_eq!(new.index, 0);
1821+
assert_eq!(new.generation, 1);
1822+
1823+
assert!(matches!(
1824+
graph.add_instantiation_node(old, ()).unwrap_err(),
1825+
Error::InvalidPackageId,
1826+
));
1827+
1828+
graph.add_instantiation_node(new, ()).unwrap();
1829+
}
1830+
1831+
#[test]
1832+
fn it_validates_node_ids() {
1833+
let mut graph = CompositionGraph::new();
1834+
let pkg = graph
1835+
.register_package(
1836+
Package::from_bytes(
1837+
"foo:bar",
1838+
None,
1839+
wat::parse_str(r#"(component (import "foo" (func)) (export "foo" (func 0)))"#)
1840+
.unwrap(),
1841+
)
1842+
.unwrap(),
1843+
)
1844+
.unwrap();
1845+
1846+
let old = graph.add_instantiation_node(pkg, ()).unwrap();
1847+
assert_eq!(old.index, 0);
1848+
assert_eq!(old.generation, 0);
1849+
1850+
assert!(graph.remove_node(old));
1851+
let new = graph.add_instantiation_node(pkg, ()).unwrap();
1852+
assert_eq!(new.index, 0);
1853+
assert_eq!(new.generation, 1);
1854+
1855+
assert!(matches!(
1856+
graph.add_alias_node(old, "foo", ()).unwrap_err(),
1857+
Error::InvalidNodeId,
1858+
));
1859+
1860+
graph.add_alias_node(new, "foo", ()).unwrap();
1861+
}
1862+
1863+
#[test]
1864+
fn it_must_export_a_type_definition() {
1865+
let mut graph = CompositionGraph::new();
1866+
let id = graph
1867+
.types_mut()
1868+
.add_defined_type(DefinedType::Alias(ValueType::Primitive(PrimitiveType::S32)));
1869+
let id = graph
1870+
.add_type_definition_node(
1871+
"foo",
1872+
Type::Value(ValueType::Defined {
1873+
id,
1874+
contains_borrow: false,
1875+
}),
1876+
(),
1877+
)
1878+
.unwrap();
1879+
assert!(matches!(
1880+
graph.unexport_node(id).unwrap_err(),
1881+
Error::MustExportDefinition
1882+
));
1883+
}
1884+
}

crates/wac-graph/tests/encoding.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
use anyhow::{anyhow, bail, Context, Result};
1+
use anyhow::{bail, Context, Result};
22
use pretty_assertions::assert_eq;
33
use semver::Version;
44
use serde::Deserialize;
55
use std::{
66
collections::HashMap,
77
fs::{self, File},
88
path::{Path, PathBuf},
9-
sync::Arc,
109
};
1110
use wac_graph::{CompositionGraph, EncodeOptions, NodeId, PackageId};
1211
use wac_types::Package;
@@ -116,14 +115,13 @@ impl GraphFile {
116115
)
117116
})?;
118117

119-
let package =
120-
Package::from_bytes(&package.name, package.version.as_ref(), Arc::new(bytes))
121-
.with_context(|| {
122-
format!(
123-
"failed to decode package `{path}` for test case `{test_case}`",
124-
path = path.display()
125-
)
126-
})?;
118+
let package = Package::from_bytes(&package.name, package.version.as_ref(), bytes)
119+
.with_context(|| {
120+
format!(
121+
"failed to decode package `{path}` for test case `{test_case}`",
122+
path = path.display()
123+
)
124+
})?;
127125

128126
let id = graph.register_package(package).with_context(|| {
129127
format!(
@@ -199,7 +197,9 @@ impl GraphFile {
199197
format!("invalid target node index {target} referenced in argument {index} for test case `{test_case}`", target = argument.target)
200198
}).copied()?;
201199

202-
graph.add_argument_edge(source, target, &argument.name)?;
200+
graph.add_argument_edge(source, target, &argument.name).with_context(|| {
201+
format!("failed to add argument edge from source node {source} to target node {target} referenced in argument {index} for test case `{test_case}`", source = argument.source, target = argument.target)
202+
})?;
203203
}
204204

205205
Ok(())
@@ -255,13 +255,13 @@ fn encoding() -> Result<()> {
255255
.and_then(|graph| {
256256
graph
257257
.encode(EncodeOptions::default())
258-
.map_err(|e| anyhow!(e))
258+
.context("failed to encode the graph")
259259
});
260260

261261
let (output, baseline_path) = if error_path.is_file() {
262262
match r {
263263
Ok(_) => bail!("expected a test failure for test case `{test_case}`"),
264-
Err(e) => (format!("{e:#}\n").replace('\\', "/"), &error_path),
264+
Err(e) => (format!("{e:?}\n").replace('\\', "/"), &error_path),
265265
}
266266
} else {
267267
let bytes =
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
failed to add argument edge from source node 1 to target node 2 referenced in argument 1 for test case `argument-already-satisfied`
2+
3+
Caused by:
4+
argument `a` has already satisfied
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(component
2+
(import "a" (func))
3+
(type (export "bar") (func))
4+
)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"packages": [
3+
{
4+
"name": "test:foo",
5+
"path": "foo.wat"
6+
}
7+
],
8+
"nodes": [
9+
{
10+
"type": "import",
11+
"name": "foo",
12+
"path": "test:foo/bar"
13+
},
14+
{
15+
"type": "import",
16+
"name": "bar",
17+
"path": "test:foo/bar"
18+
},
19+
{
20+
"type": "instantiation",
21+
"package": 0
22+
}
23+
],
24+
"arguments": [
25+
{
26+
"source": 0,
27+
"target": 2,
28+
"name": "a"
29+
},
30+
{
31+
"source": 1,
32+
"target": 2,
33+
"name": "a"
34+
}
35+
]
36+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
failed to add argument edge from source node 0 to target node 1 referenced in argument 0 for test case `argument-type-mismatch`
2+
3+
Caused by:
4+
0: mismatched instantiation argument `a`
5+
1: expected instance, found function
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
(component
2+
(import "a" (instance))
3+
(type (export "bar") (func))
4+
)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"packages": [
3+
{
4+
"name": "test:foo",
5+
"path": "foo.wat"
6+
}
7+
],
8+
"nodes": [
9+
{
10+
"type": "import",
11+
"name": "foo",
12+
"path": "test:foo/bar"
13+
},
14+
{
15+
"type": "instantiation",
16+
"package": 0
17+
}
18+
],
19+
"arguments": [
20+
{
21+
"source": 0,
22+
"target": 1,
23+
"name": "a"
24+
}
25+
]
26+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
failed to encode the graph
2+
3+
Caused by:
4+
the graph contains a cycle and cannot be encoded
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(component
2+
(import "i" (instance))
3+
)

0 commit comments

Comments
 (0)