Skip to content

Commit 02e4fa7

Browse files
committed
wasi:filesystem@0.3.0-rc-2025-09-16: Add tests for metadata-hash
1 parent 093acaf commit 02e4fa7

2 files changed

Lines changed: 202 additions & 0 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"dirs": ["fs-tests.dir"]
3+
}
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
use std::process;
2+
extern crate wit_bindgen;
3+
4+
wit_bindgen::generate!({
5+
inline: r"
6+
package test:test;
7+
8+
world test {
9+
include wasi:filesystem/imports@0.3.0-rc-2025-09-16;
10+
include wasi:cli/command@0.3.0-rc-2025-09-16;
11+
}
12+
",
13+
additional_derives: [PartialEq, Eq, Hash, Clone],
14+
// Work around https://github.com/bytecodealliance/wasm-tools/issues/2285.
15+
features:["clocks-timezone"],
16+
generate_all
17+
});
18+
19+
use wasi::filesystem::types::Descriptor;
20+
use wasi::filesystem::types::{DescriptorFlags, ErrorCode, OpenFlags, PathFlags};
21+
22+
async fn check_metadata_hash(a: &Descriptor, b: &Descriptor) {
23+
let a_hash = a.metadata_hash().await;
24+
let b_hash = b.metadata_hash().await;
25+
if a_hash.is_ok() && a_hash == b_hash {
26+
assert_eq!(a.stat().await.unwrap(), b.stat().await.unwrap());
27+
}
28+
}
29+
30+
async fn check_metadata_hash_at(
31+
a: &Descriptor,
32+
a_flags: PathFlags,
33+
a_name: &str,
34+
b: &Descriptor,
35+
b_flags: PathFlags,
36+
b_name: &str,
37+
) {
38+
let a_hash = a.metadata_hash_at(a_flags, a_name.to_string()).await;
39+
let b_hash = b.metadata_hash_at(b_flags, b_name.to_string()).await;
40+
if a_hash.is_ok() && a_hash == b_hash {
41+
assert_eq!(
42+
a.stat_at(a_flags, a_name.to_string()).await.unwrap(),
43+
b.stat_at(b_flags, b_name.to_string()).await.unwrap()
44+
);
45+
}
46+
}
47+
48+
async fn test_metadata_hash(dir: &Descriptor) {
49+
let afd = dir
50+
.open_at(
51+
PathFlags::empty(),
52+
"a.txt".to_string(),
53+
OpenFlags::empty(),
54+
DescriptorFlags::READ,
55+
)
56+
.await
57+
.unwrap();
58+
let bfd = dir
59+
.open_at(
60+
PathFlags::empty(),
61+
"b.txt".to_string(),
62+
OpenFlags::empty(),
63+
DescriptorFlags::READ,
64+
)
65+
.await
66+
.unwrap();
67+
68+
dir.create_directory_at("child.cleanup".to_string())
69+
.await
70+
.unwrap();
71+
let child = dir
72+
.open_at(
73+
PathFlags::empty(),
74+
"child.cleanup".to_string(),
75+
OpenFlags::DIRECTORY,
76+
DescriptorFlags::MUTATE_DIRECTORY,
77+
)
78+
.await
79+
.unwrap();
80+
// FIXME: https://github.com/bytecodealliance/wasmtime/issues/12172
81+
// dir.symlink_at(
82+
// "../a.txt".to_string(),
83+
// "child.cleanup/symlink.cleanup".to_string(),
84+
// )
85+
// .await
86+
// .unwrap();
87+
dir.link_at(
88+
PathFlags::empty(),
89+
"a.txt".to_string(),
90+
&child,
91+
"link.cleanup".to_string(),
92+
)
93+
.await
94+
.unwrap();
95+
let a_link = child
96+
.open_at(
97+
PathFlags::empty(),
98+
"link.cleanup".to_string(),
99+
OpenFlags::empty(),
100+
DescriptorFlags::READ,
101+
)
102+
.await
103+
.unwrap();
104+
105+
// metadata-hash: async func() -> result<metadata-hash-value, error-code>;
106+
check_metadata_hash(dir, dir).await;
107+
check_metadata_hash(dir, &afd).await;
108+
check_metadata_hash(&afd, &afd).await;
109+
check_metadata_hash(&afd, &bfd).await;
110+
check_metadata_hash(&afd, &a_link).await;
111+
check_metadata_hash(&bfd, &a_link).await;
112+
113+
// metadata-hash-at: async func(path-flags: path-flags, path: string) -> result<metadata-hash-value, error-code>;
114+
assert_eq!(
115+
dir.metadata_hash_at(PathFlags::empty(), "/".to_string())
116+
.await,
117+
Err(ErrorCode::NotPermitted)
118+
);
119+
assert_eq!(
120+
dir.metadata_hash_at(PathFlags::empty(), "".to_string())
121+
.await,
122+
Err(ErrorCode::NoEntry)
123+
);
124+
assert_eq!(
125+
dir.metadata_hash_at(PathFlags::empty(), "/etc/passwd".to_string())
126+
.await,
127+
Err(ErrorCode::NotPermitted)
128+
);
129+
assert_eq!(
130+
dir.metadata_hash_at(PathFlags::empty(), "/does-not-exist".to_string())
131+
.await,
132+
Err(ErrorCode::NotPermitted)
133+
);
134+
135+
for (adir, aname, bdir, bname) in [
136+
(dir, ".", dir, "a.txt"),
137+
(dir, "a.txt", dir, "a.txt"),
138+
(dir, "a.txt", dir, "b.txt"),
139+
// https://github.com/bytecodealliance/wasmtime/issues/12172
140+
// (dir, "a.txt", &child, "symlink.cleanup"),
141+
(dir, "a.txt", &child, "link.cleanup"),
142+
// (dir, "b.txt", &child, "symlink.cleanup"),
143+
(dir, "a.txt", &child, "link.cleanup"),
144+
] {
145+
check_metadata_hash_at(
146+
adir,
147+
PathFlags::empty(),
148+
aname,
149+
bdir,
150+
PathFlags::empty(),
151+
bname,
152+
)
153+
.await;
154+
check_metadata_hash_at(
155+
adir,
156+
PathFlags::empty(),
157+
aname,
158+
bdir,
159+
PathFlags::SYMLINK_FOLLOW,
160+
bname,
161+
)
162+
.await;
163+
}
164+
165+
// https://github.com/bytecodealliance/wasmtime/issues/12172
166+
// child
167+
// .unlink_file_at("symlink.cleanup".to_string())
168+
// .await
169+
// .unwrap();
170+
child
171+
.unlink_file_at("link.cleanup".to_string())
172+
.await
173+
.unwrap();
174+
drop(child);
175+
dir.remove_directory_at("child.cleanup".to_string())
176+
.await
177+
.unwrap();
178+
}
179+
180+
struct Component;
181+
export!(Component);
182+
impl exports::wasi::cli::run::Guest for Component {
183+
async fn run() -> Result<(), ()> {
184+
match &wasi::filesystem::preopens::get_directories()[..] {
185+
[(dir, dirname)] if dirname == "fs-tests.dir" => {
186+
test_metadata_hash(dir).await;
187+
}
188+
[..] => {
189+
eprintln!("usage: run with one open dir named 'fs-tests.dir'");
190+
process::exit(1)
191+
}
192+
};
193+
Ok(())
194+
}
195+
}
196+
197+
fn main() {
198+
unreachable!("main is a stub");
199+
}

0 commit comments

Comments
 (0)