Merge wasi-misc-tests repo as a subdir (#174)
* Initial checkin.
* Update to rust-lang libc.
* Add a .gitignore file.
* Factor out functions for cleaning up files and directories.
* Fix a typo in a comment.
* Print a "Success!" message if all tests passed.
* Factor out code for creating directories.
* Add wrappers around WASI functions.
These wrappers handle converting from &str to pointer+length and handle
unsafe.
* More refactoring.
* Refactor a fd_close helper.
* Move utility functions into a separate file.
* cargo update
* Add a basic test for random_get.
* Test that directories aren't resizable.
* Test clearing __WASI_RIGHT_PATH_FILESTAT_SET_SIZE.
Ensure that clearing __WASI_RIGHT_PATH_FILESTAT_SET_SIZE succeeds before
testing file truncation.
* cargo update
* Modularise tests for easier use with wasi-common crate
* Add a Code of Conduct and CONTRIBUTING.md.
* Fix typo
* Add testcase for fd_allocate
* Add positive test for fd_renumber
* Assert bufused in readlink_no_buffer testcase
* Add positive readlink testcase
* Add testcase for fd_seek and fd_tell
* Add fd_p{read, write} test
* Add README
* Add cases with trailing slashes to interesting_paths
* Split nofollow_errors testcase into two
* nofollow_errors now operators on symlinks to existing resources
* dangling_symlink covers danling symlinks tests
* Factor out a `create_file` helper function.
* Switch from the error crate to `std::io::Error::last_os_error()`.
* Use `create_file` in the readlink test too.
* Add a test for fd_filestat_set_*
* Minor refactoring
Add missing cleanup_file calls to file_pread_pwrite and
file_seek_tell.
* Add testcase for unbuffered fd_write; fixes #11
* Add testcase for path_rename
* Use the wasi crate.
Switch from depending on libc to depending on the new wasi crate to provide
the low-level WASI interfaces.
See also https://github.com/rust-lang/libc/pull/1461.
* Add a test for path_filestat_*
* Add a test for fd_readdir
* Use expect instead of unwrap
* Add a check for ino.
* Fix the build
* Don't assume a specific order of dirents
* Better test
* Test cookie value
* Fix file types
* Fix the test
* Fix the test
* Fix the test
* Cleanup
* Minor formatting tidying in README.md.
* Fix miscellaneous clippy warnings.
* Rename the crate to wasi-misc-tests.
* Update to wasi 0.7.0.
This switches from using the libc wasi bindings to using the wasi
crate's bindings. This eliminates a git dependency on libc, updates
to the new-style bindings which use Result where possible, and treats
functions that operate on raw file descriptors as unsafe.
* Add various tests for trailing-slash behavior.
* Sync new testcases with latest upstream
* Fix path_filestat testcase
* Add smoke test for fd_advise
This test is a true smoke test as it only tests whether issuing
an advise call to the host's kernel doesn't yield an error. The
consequence of issuing such a syscall is not tested.
* Check if CLOCK_MONOTONIC is actually monotonic
* Refactor the inequality assertions for more debuggable errors.
* Bump libc from 0.2.62 to 0.2.65
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.62 to 0.2.65.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.62...0.2.65)
Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
* Fix compilation error
* Enable Actions and add rust.yml (#35)
* Enable Actions and add rust.yml
This commit enables Github Actions and adds corresponding configuration in rust.yml file.
* Update rust.yml
* Fix formatting
* Add empty .rustfmt.toml config file
* Add badge to README
* Update README
* Clean up Github Actions and README
* Add test case for `poll_oneoff` syscall (#38)
* Add test case for `poll_oneoff` syscall
This commit adds a test case for `poll_oneoff` syscall. In particular,
it builds on the excellent test use case provided by @dunnock in their
repo [poll_oneoff_tests] (thanks!), and tests:
* simple timeout
* stdin read with timeout
* fd read and fd write polls
[poll_oneoff_tests]: https://github.com/dunnock/poll_oneoff_tests
* Apply suggestions and negative test for bad fd
Co-authored-by: Maxim Vorobjov <maxim.vorobjov@gmail.com>
* Add smoke test for STDOUT/ERR readwrite poll
* Add comment on stdin/out/err
* Add a test for `*at`-style functions returning `ENOTDIR` when `dirfd` is not a dir.
* Remove misc_testsuite submodule
* Add "publish=false" to Cargo.toml; remove LICENSE
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,6 +1,3 @@
|
||||
[submodule "misc_testsuite"]
|
||||
path = misc_testsuite
|
||||
url = https://github.com/cranestation/wasi-misc-tests
|
||||
[submodule "WASI"]
|
||||
path = WASI
|
||||
url = https://github.com/WebAssembly/WASI
|
||||
|
||||
23
Cargo.toml
23
Cargo.toml
@@ -1,11 +1,7 @@
|
||||
[package]
|
||||
name = "wasi-common"
|
||||
version = "0.5.0"
|
||||
authors = [
|
||||
"Adam C. Foltzer <acfoltzer@fastly.com>",
|
||||
"Frank Denis <github@pureftpd.org>",
|
||||
"Jakub Konka <kubkon@jakubkonka.com>",
|
||||
"Dan Gohman <sunfish@mozilla.com>"]
|
||||
authors = ["The Wasmtime Project Developers"]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0 WITH LLVM-exception"
|
||||
description = "WASI implementation in Rust"
|
||||
@@ -41,18 +37,15 @@ cpu-time = "1.0"
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
wasmtime-runtime = { git = "https://github.com/acfoltzer/wasmtime", rev = "d99e2fb" }
|
||||
wasmtime-environ = { git = "https://github.com/acfoltzer/wasmtime", rev = "d99e2fb" }
|
||||
wasmtime-jit = { git = "https://github.com/acfoltzer/wasmtime", rev = "d99e2fb" }
|
||||
wasmtime-wasi = { git = "https://github.com/acfoltzer/wasmtime", rev = "d99e2fb" }
|
||||
wasmtime-api = { git = "https://github.com/acfoltzer/wasmtime", rev = "d99e2fb" }
|
||||
cranelift-codegen = "0.47.0"
|
||||
wasmtime-runtime = { git = "https://github.com/CraneStation/wasmtime", rev = "ab3cd94" }
|
||||
wasmtime-environ = { git = "https://github.com/CraneStation/wasmtime", rev = "ab3cd94" }
|
||||
wasmtime-jit = { git = "https://github.com/CraneStation/wasmtime", rev = "ab3cd94" }
|
||||
wasmtime-wasi = { git = "https://github.com/CraneStation/wasmtime", rev = "ab3cd94" }
|
||||
wasmtime-api = { git = "https://github.com/CraneStation/wasmtime", rev = "ab3cd94" }
|
||||
cranelift-codegen = "0.49"
|
||||
target-lexicon = "0.8.1"
|
||||
pretty_env_logger = "0.3.0"
|
||||
tempfile = "3.1.0"
|
||||
# this is just a temp fix to make the tests build and run; I hope this to be
|
||||
# completely removed when we merge `wasi-common` into `wasmtime`
|
||||
faerie = "=0.11.0"
|
||||
|
||||
[patch."https://github.com/CraneStation/wasi-common"]
|
||||
wasi-common = { path = "." }
|
||||
@@ -66,4 +59,4 @@ crate-type = ["rlib", "staticlib", "cdylib"]
|
||||
|
||||
[workspace]
|
||||
members = ["wasi-common-cbindgen"]
|
||||
exclude = ["winx", "misc_testsuite"]
|
||||
exclude = ["wasi-misc-tests", "wig", "winx", "WASI/tools/witx"]
|
||||
|
||||
20
build.rs
20
build.rs
@@ -21,8 +21,8 @@ mod wasm_tests {
|
||||
|
||||
pub(crate) fn build_and_generate_tests() {
|
||||
// Validate if any of test sources are present and if they changed
|
||||
let bin_tests = std::fs::read_dir("misc_testsuite/src/bin")
|
||||
.expect("wasm_tests feature requires initialized misc_testsuite: `git submodule update --init`?");
|
||||
// This should always work since there is no submodule to init anymore
|
||||
let bin_tests = std::fs::read_dir("wasi-misc-tests/src/bin").unwrap();
|
||||
for test in bin_tests {
|
||||
if let Ok(test_file) = test {
|
||||
let test_file_path = test_file
|
||||
@@ -33,23 +33,17 @@ mod wasm_tests {
|
||||
println!("cargo:rerun-if-changed={}", test_file_path);
|
||||
}
|
||||
}
|
||||
|
||||
// Build tests to OUT_DIR (target/*/build/wasi-common-*/out/wasm32-wasi/release/*.wasm)
|
||||
let out_dir = PathBuf::from(
|
||||
env::var("OUT_DIR").expect("The OUT_DIR environment variable must be set"),
|
||||
);
|
||||
let mut out = File::create(out_dir.join("misc_testsuite_tests.rs"))
|
||||
let mut out = File::create(out_dir.join("wasi_misc_tests.rs"))
|
||||
.expect("error generating test source file");
|
||||
build_tests("misc_testsuite", &out_dir).expect("building tests");
|
||||
test_directory(&mut out, "misc_testsuite", &out_dir).expect("generating tests");
|
||||
build_tests("wasi-misc-tests", &out_dir).expect("building tests");
|
||||
test_directory(&mut out, "wasi-misc-tests", &out_dir).expect("generating tests");
|
||||
}
|
||||
|
||||
fn build_tests(testsuite: &str, out_dir: &Path) -> io::Result<()> {
|
||||
// if the submodule has not been checked out, the build will stall
|
||||
if !Path::new(&format!("{}/Cargo.toml", testsuite)).exists() {
|
||||
panic!("Testsuite {} not checked out", testsuite);
|
||||
}
|
||||
|
||||
let mut cmd = Command::new("cargo");
|
||||
cmd.args(&[
|
||||
"build",
|
||||
@@ -191,7 +185,7 @@ mod wasm_tests {
|
||||
} else {
|
||||
/// Ignore tests that aren't supported yet.
|
||||
fn ignore(testsuite: &str, name: &str) -> bool {
|
||||
if testsuite == "misc_testsuite" {
|
||||
if testsuite == "wasi-misc-tests" {
|
||||
match name {
|
||||
"readlink_no_buffer" => true,
|
||||
"dangling_symlink" => true,
|
||||
@@ -211,7 +205,7 @@ mod wasm_tests {
|
||||
|
||||
/// Mark tests which do not require preopens
|
||||
fn no_preopens(testsuite: &str, name: &str) -> bool {
|
||||
if testsuite == "misc_testsuite" {
|
||||
if testsuite == "wasi-misc-tests" {
|
||||
match name {
|
||||
"big_random_buf" => true,
|
||||
"clock_time_get" => true,
|
||||
|
||||
Submodule misc_testsuite deleted from f677228706
@@ -13,4 +13,4 @@ fn setup_log() {
|
||||
})
|
||||
}
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/misc_testsuite_tests.rs"));
|
||||
include!(concat!(env!("OUT_DIR"), "/wasi_misc_tests.rs"));
|
||||
|
||||
11
wasi-misc-tests/Cargo.toml
Normal file
11
wasi-misc-tests/Cargo.toml
Normal file
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "wasi-misc-tests"
|
||||
version = "0.1.0"
|
||||
authors = ["The Wasmtime Project Developers"]
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2.65"
|
||||
wasi = "0.7.0"
|
||||
more-asserts = "0.2.1"
|
||||
4
wasi-misc-tests/README.md
Normal file
4
wasi-misc-tests/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
This is the `wasi-misc-test` crate, which contains source code for the system-level WASI tests.
|
||||
|
||||
Building these tests requires `wasm32-wasi` target installed
|
||||
|
||||
18
wasi-misc-tests/src/bin/big_random_buf.rs
Normal file
18
wasi-misc-tests/src/bin/big_random_buf.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
use wasi::wasi_unstable;
|
||||
|
||||
fn test_big_random_buf() {
|
||||
let mut buf = Vec::new();
|
||||
buf.resize(1024, 0);
|
||||
assert!(
|
||||
wasi_unstable::random_get(&mut buf).is_ok(),
|
||||
"calling get_random on a large buffer"
|
||||
);
|
||||
// Chances are pretty good that at least *one* byte will be non-zero in
|
||||
// any meaningful random function producing 1024 u8 values.
|
||||
assert!(buf.iter().any(|x| *x != 0), "random_get returned all zeros");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Run the tests.
|
||||
test_big_random_buf()
|
||||
}
|
||||
37
wasi-misc-tests/src/bin/clock_time_get.rs
Normal file
37
wasi-misc-tests/src/bin/clock_time_get.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use more_asserts::assert_le;
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::wasi_wrappers::wasi_clock_time_get;
|
||||
|
||||
unsafe fn test_clock_time_get() {
|
||||
// Test that clock_time_get succeeds. Even in environments where it's not
|
||||
// desirable to expose high-precision timers, it should still succeed.
|
||||
// clock_res_get is where information about precision can be provided.
|
||||
let mut time: wasi_unstable::Timestamp = 0;
|
||||
let status = wasi_clock_time_get(wasi_unstable::CLOCK_MONOTONIC, 1, &mut time);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"clock_time_get with a precision of 1"
|
||||
);
|
||||
|
||||
let status = wasi_clock_time_get(wasi_unstable::CLOCK_MONOTONIC, 0, &mut time);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"clock_time_get with a precision of 0"
|
||||
);
|
||||
let first_time = time;
|
||||
|
||||
let status = wasi_clock_time_get(wasi_unstable::CLOCK_MONOTONIC, 0, &mut time);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"clock_time_get with a precision of 0"
|
||||
);
|
||||
assert_le!(first_time, time, "CLOCK_MONOTONIC should be monotonic");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Run the tests.
|
||||
unsafe { test_clock_time_get() }
|
||||
}
|
||||
83
wasi-misc-tests/src/bin/close_preopen.rs
Normal file
83
wasi-misc-tests/src/bin/close_preopen.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, mem, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::wasi_wrappers::wasi_fd_fdstat_get;
|
||||
|
||||
unsafe fn test_close_preopen(dir_fd: wasi_unstable::Fd) {
|
||||
let pre_fd: wasi_unstable::Fd = (libc::STDERR_FILENO + 1) as wasi_unstable::Fd;
|
||||
|
||||
assert_gt!(dir_fd, pre_fd, "dir_fd number");
|
||||
|
||||
// Try to close a preopened directory handle.
|
||||
assert_eq!(
|
||||
wasi_unstable::fd_close(pre_fd),
|
||||
Err(wasi_unstable::ENOTSUP),
|
||||
"closing a preopened file descriptor",
|
||||
);
|
||||
|
||||
// Try to renumber over a preopened directory handle.
|
||||
assert_eq!(
|
||||
wasi_unstable::fd_renumber(dir_fd, pre_fd),
|
||||
Err(wasi_unstable::ENOTSUP),
|
||||
"renumbering over a preopened file descriptor",
|
||||
);
|
||||
|
||||
// Ensure that dir_fd is still open.
|
||||
let mut dir_fdstat: wasi_unstable::FdStat = mem::zeroed();
|
||||
let mut status = wasi_fd_fdstat_get(dir_fd, &mut dir_fdstat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"calling fd_fdstat on the scratch directory"
|
||||
);
|
||||
assert_eq!(
|
||||
dir_fdstat.fs_filetype,
|
||||
wasi_unstable::FILETYPE_DIRECTORY,
|
||||
"expected the scratch directory to be a directory",
|
||||
);
|
||||
|
||||
// Try to renumber a preopened directory handle.
|
||||
assert_eq!(
|
||||
wasi_unstable::fd_renumber(pre_fd, dir_fd),
|
||||
Err(wasi_unstable::ENOTSUP),
|
||||
"renumbering over a preopened file descriptor",
|
||||
);
|
||||
|
||||
// Ensure that dir_fd is still open.
|
||||
status = wasi_fd_fdstat_get(dir_fd, &mut dir_fdstat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"calling fd_fdstat on the scratch directory"
|
||||
);
|
||||
assert_eq!(
|
||||
dir_fdstat.fs_filetype,
|
||||
wasi_unstable::FILETYPE_DIRECTORY,
|
||||
"expected the scratch directory to be a directory",
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_close_preopen(dir_fd) }
|
||||
}
|
||||
62
wasi-misc-tests/src/bin/dangling_symlink.rs
Normal file
62
wasi-misc-tests/src/bin/dangling_symlink.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::cleanup_file;
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_path_open, wasi_path_symlink};
|
||||
|
||||
unsafe fn test_dangling_symlink(dir_fd: wasi_unstable::Fd) {
|
||||
// First create a dangling symlink.
|
||||
assert!(
|
||||
wasi_path_symlink("target", dir_fd, "symlink").is_ok(),
|
||||
"creating a symlink"
|
||||
);
|
||||
|
||||
// Try to open it as a directory with O_NOFOLLOW.
|
||||
let mut file_fd: wasi_unstable::Fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"symlink",
|
||||
wasi_unstable::O_DIRECTORY,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ELOOP,
|
||||
"opening a dangling symlink as a directory",
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Clean up.
|
||||
cleanup_file(dir_fd, "symlink");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_dangling_symlink(dir_fd) }
|
||||
}
|
||||
90
wasi-misc-tests/src/bin/directory_seek.rs
Normal file
90
wasi-misc-tests/src/bin/directory_seek.rs
Normal file
@@ -0,0 +1,90 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, mem, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_dir, close_fd, create_dir};
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_fd_fdstat_get, wasi_fd_seek, wasi_path_open};
|
||||
|
||||
unsafe fn test_directory_seek(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a directory in the scratch directory.
|
||||
create_dir(dir_fd, "dir");
|
||||
|
||||
// Open the directory and attempt to request rights for seeking.
|
||||
let mut fd: wasi_unstable::Fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let mut status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"dir",
|
||||
0,
|
||||
wasi_unstable::RIGHT_FD_SEEK,
|
||||
0,
|
||||
0,
|
||||
&mut fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
// Attempt to seek.
|
||||
let mut newoffset = 1;
|
||||
status = wasi_fd_seek(fd, 0, wasi_unstable::WHENCE_CUR, &mut newoffset);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOTCAPABLE,
|
||||
"seek on a directory"
|
||||
);
|
||||
|
||||
// Check if we obtained the right to seek.
|
||||
let mut fdstat: wasi_unstable::FdStat = mem::zeroed();
|
||||
status = wasi_fd_fdstat_get(fd, &mut fdstat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"calling fd_fdstat on a directory"
|
||||
);
|
||||
assert_eq!(
|
||||
fdstat.fs_filetype,
|
||||
wasi_unstable::FILETYPE_DIRECTORY,
|
||||
"expected the scratch directory to be a directory",
|
||||
);
|
||||
assert_eq!(
|
||||
(fdstat.fs_rights_base & wasi_unstable::RIGHT_FD_SEEK),
|
||||
0,
|
||||
"directory has the seek right",
|
||||
);
|
||||
|
||||
// Clean up.
|
||||
close_fd(fd);
|
||||
cleanup_dir(dir_fd, "dir");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_directory_seek(dir_fd) }
|
||||
}
|
||||
98
wasi-misc-tests/src/bin/fd_advise.rs
Normal file
98
wasi-misc-tests/src/bin/fd_advise.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, close_fd};
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_fd_advise, wasi_fd_filestat_get, wasi_path_open};
|
||||
|
||||
unsafe fn test_fd_advise(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a file in the scratch directory.
|
||||
let mut file_fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_CREAT,
|
||||
wasi_unstable::RIGHT_FD_READ | wasi_unstable::RIGHT_FD_WRITE,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
// Check file size
|
||||
let mut stat = wasi_unstable::FileStat {
|
||||
st_dev: 0,
|
||||
st_ino: 0,
|
||||
st_filetype: 0,
|
||||
st_nlink: 0,
|
||||
st_size: 0,
|
||||
st_atim: 0,
|
||||
st_mtim: 0,
|
||||
st_ctim: 0,
|
||||
};
|
||||
let status = wasi_fd_filestat_get(file_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats"
|
||||
);
|
||||
assert_eq!(stat.st_size, 0, "file size should be 0");
|
||||
|
||||
// Allocate some size
|
||||
assert!(
|
||||
wasi_unstable::fd_allocate(file_fd, 0, 100).is_ok(),
|
||||
"allocating size"
|
||||
);
|
||||
|
||||
let status = wasi_fd_filestat_get(file_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats after initial allocation"
|
||||
);
|
||||
assert_eq!(stat.st_size, 100, "file size should be 100");
|
||||
|
||||
// Advise the kernel
|
||||
let status = wasi_fd_advise(file_fd, 10, 50, wasi_unstable::ADVICE_NORMAL);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"advising the kernel"
|
||||
);
|
||||
|
||||
close_fd(file_fd);
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_fd_advise(dir_fd) }
|
||||
}
|
||||
120
wasi-misc-tests/src/bin/fd_filestat_set.rs
Normal file
120
wasi-misc-tests/src/bin/fd_filestat_set.rs
Normal file
@@ -0,0 +1,120 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, close_fd};
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_fd_filestat_get, wasi_path_open};
|
||||
|
||||
unsafe fn test_fd_filestat_set(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a file in the scratch directory.
|
||||
let mut file_fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_CREAT,
|
||||
wasi_unstable::RIGHT_FD_READ | wasi_unstable::RIGHT_FD_WRITE,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
// Check file size
|
||||
let mut stat = wasi_unstable::FileStat {
|
||||
st_dev: 0,
|
||||
st_ino: 0,
|
||||
st_filetype: 0,
|
||||
st_nlink: 0,
|
||||
st_size: 0,
|
||||
st_atim: 0,
|
||||
st_mtim: 0,
|
||||
st_ctim: 0,
|
||||
};
|
||||
let status = wasi_fd_filestat_get(file_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats"
|
||||
);
|
||||
assert_eq!(stat.st_size, 0, "file size should be 0");
|
||||
|
||||
// Check fd_filestat_set_size
|
||||
assert!(
|
||||
wasi_unstable::fd_filestat_set_size(file_fd, 100).is_ok(),
|
||||
"fd_filestat_set_size"
|
||||
);
|
||||
|
||||
let status = wasi_fd_filestat_get(file_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats after fd_filestat_set_size"
|
||||
);
|
||||
assert_eq!(stat.st_size, 100, "file size should be 100");
|
||||
|
||||
// Check fd_filestat_set_times
|
||||
let old_atim = stat.st_atim;
|
||||
let new_mtim = stat.st_mtim - 100;
|
||||
assert!(
|
||||
wasi_unstable::fd_filestat_set_times(
|
||||
file_fd,
|
||||
new_mtim,
|
||||
new_mtim,
|
||||
wasi_unstable::FILESTAT_SET_MTIM,
|
||||
)
|
||||
.is_ok(),
|
||||
"fd_filestat_set_times"
|
||||
);
|
||||
|
||||
let status = wasi_fd_filestat_get(file_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats after fd_filestat_set_times"
|
||||
);
|
||||
assert_eq!(
|
||||
stat.st_size, 100,
|
||||
"file size should remain unchanged at 100"
|
||||
);
|
||||
assert_eq!(stat.st_mtim, new_mtim, "mtim should change");
|
||||
assert_eq!(stat.st_atim, old_atim, "atim should not change");
|
||||
|
||||
// let status = wasi_fd_filestat_set_times(file_fd, new_mtim, new_mtim, wasi_unstable::FILESTAT_SET_MTIM | wasi_unstable::FILESTAT_SET_MTIM_NOW);
|
||||
// assert_eq!(status, wasi_unstable::EINVAL, "ATIM & ATIM_NOW can't both be set");
|
||||
|
||||
close_fd(file_fd);
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_fd_filestat_set(dir_fd) }
|
||||
}
|
||||
189
wasi-misc-tests/src/bin/fd_readdir.rs
Normal file
189
wasi-misc-tests/src/bin/fd_readdir.rs
Normal file
@@ -0,0 +1,189 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{cmp::min, env, mem, process, slice, str};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_fd_filestat_get, wasi_fd_readdir, wasi_path_open};
|
||||
|
||||
const BUF_LEN: usize = 256;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DirEntry {
|
||||
dirent: wasi_unstable::Dirent,
|
||||
name: String,
|
||||
}
|
||||
|
||||
// Manually reading the output from fd_readdir is tedious and repetitive,
|
||||
// so encapsulate it into an iterator
|
||||
struct ReadDir<'a> {
|
||||
buf: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> ReadDir<'a> {
|
||||
fn from_slice(buf: &'a [u8]) -> Self {
|
||||
Self { buf }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for ReadDir<'a> {
|
||||
type Item = DirEntry;
|
||||
|
||||
fn next(&mut self) -> Option<DirEntry> {
|
||||
unsafe {
|
||||
if self.buf.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Read the data
|
||||
let dirent_ptr = self.buf.as_ptr() as *const wasi_unstable::Dirent;
|
||||
let dirent = *dirent_ptr;
|
||||
let name_ptr = dirent_ptr.offset(1) as *const u8;
|
||||
// NOTE Linux syscall returns a NULL-terminated name, but WASI doesn't
|
||||
let namelen = dirent.d_namlen as usize;
|
||||
let slice = slice::from_raw_parts(name_ptr, namelen);
|
||||
let name = str::from_utf8(slice).expect("invalid utf8").to_owned();
|
||||
|
||||
// Update the internal state
|
||||
let delta = mem::size_of_val(&dirent) + namelen;
|
||||
self.buf = &self.buf[delta..];
|
||||
|
||||
DirEntry { dirent, name }.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn exec_fd_readdir(
|
||||
fd: wasi_unstable::Fd,
|
||||
cookie: wasi_unstable::DirCookie,
|
||||
) -> Vec<DirEntry> {
|
||||
let mut buf: [u8; BUF_LEN] = [0; BUF_LEN];
|
||||
let mut bufused = 0;
|
||||
let status = wasi_fd_readdir(fd, &mut buf, BUF_LEN, cookie, &mut bufused);
|
||||
assert_eq!(status, wasi_unstable::raw::__WASI_ESUCCESS, "fd_readdir");
|
||||
|
||||
let sl = slice::from_raw_parts(buf.as_ptr(), min(BUF_LEN, bufused));
|
||||
let dirs: Vec<_> = ReadDir::from_slice(sl).collect();
|
||||
dirs
|
||||
}
|
||||
|
||||
unsafe fn test_fd_readdir(dir_fd: wasi_unstable::Fd) {
|
||||
let mut stat: wasi_unstable::FileStat = mem::zeroed();
|
||||
let status = wasi_fd_filestat_get(dir_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading scratch directory stats"
|
||||
);
|
||||
|
||||
// Check the behavior in an empty directory
|
||||
let mut dirs = exec_fd_readdir(dir_fd, wasi_unstable::DIRCOOKIE_START);
|
||||
dirs.sort_by_key(|d| d.name.clone());
|
||||
assert_eq!(dirs.len(), 2, "expected two entries in an empty directory");
|
||||
let mut dirs = dirs.into_iter();
|
||||
|
||||
// the first entry should be `.`
|
||||
let dir = dirs.next().expect("first entry is None");
|
||||
assert_eq!(dir.name, ".", "first name");
|
||||
assert_eq!(
|
||||
dir.dirent.d_type,
|
||||
wasi_unstable::FILETYPE_DIRECTORY,
|
||||
"first type"
|
||||
);
|
||||
assert_eq!(dir.dirent.d_ino, stat.st_ino);
|
||||
assert_eq!(dir.dirent.d_namlen, 1);
|
||||
|
||||
// the second entry should be `..`
|
||||
let dir = dirs.next().expect("second entry is None");
|
||||
assert_eq!(dir.name, "..", "second name");
|
||||
assert_eq!(
|
||||
dir.dirent.d_type,
|
||||
wasi_unstable::FILETYPE_DIRECTORY,
|
||||
"second type"
|
||||
);
|
||||
|
||||
assert!(
|
||||
dirs.next().is_none(),
|
||||
"the directory should be seen as empty"
|
||||
);
|
||||
|
||||
// Add a file and check the behavior
|
||||
let mut file_fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_CREAT,
|
||||
wasi_unstable::RIGHT_FD_READ | wasi_unstable::RIGHT_FD_WRITE,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
let status = wasi_fd_filestat_get(file_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats"
|
||||
);
|
||||
|
||||
// Execute another readdir
|
||||
let mut dirs = exec_fd_readdir(dir_fd, wasi_unstable::DIRCOOKIE_START);
|
||||
assert_eq!(dirs.len(), 3, "expected three entries");
|
||||
// Save the data about the last entry. We need to do it before sorting.
|
||||
let lastfile_cookie = dirs[1].dirent.d_next;
|
||||
let lastfile_name = dirs[2].name.clone();
|
||||
dirs.sort_by_key(|d| d.name.clone());
|
||||
let mut dirs = dirs.into_iter();
|
||||
|
||||
let dir = dirs.next().expect("first entry is None");
|
||||
assert_eq!(dir.name, ".", "first name");
|
||||
let dir = dirs.next().expect("second entry is None");
|
||||
assert_eq!(dir.name, "..", "second name");
|
||||
let dir = dirs.next().expect("third entry is None");
|
||||
// check the file info
|
||||
assert_eq!(dir.name, "file", "file name doesn't match");
|
||||
assert_eq!(
|
||||
dir.dirent.d_type,
|
||||
wasi_unstable::FILETYPE_REGULAR_FILE,
|
||||
"type for the real file"
|
||||
);
|
||||
assert_eq!(dir.dirent.d_ino, stat.st_ino);
|
||||
|
||||
// check if cookie works as expected
|
||||
let dirs = exec_fd_readdir(dir_fd, lastfile_cookie);
|
||||
assert_eq!(dirs.len(), 1, "expected one entry");
|
||||
assert_eq!(dirs[0].name, lastfile_name, "name of the only entry");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_fd_readdir(dir_fd) }
|
||||
}
|
||||
125
wasi-misc-tests/src/bin/file_allocate.rs
Normal file
125
wasi-misc-tests/src/bin/file_allocate.rs
Normal file
@@ -0,0 +1,125 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, close_fd};
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_fd_filestat_get, wasi_path_open};
|
||||
|
||||
unsafe fn test_file_allocate(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a file in the scratch directory.
|
||||
let mut file_fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_CREAT,
|
||||
wasi_unstable::RIGHT_FD_READ | wasi_unstable::RIGHT_FD_WRITE,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
// Check file size
|
||||
let mut stat = wasi_unstable::FileStat {
|
||||
st_dev: 0,
|
||||
st_ino: 0,
|
||||
st_filetype: 0,
|
||||
st_nlink: 0,
|
||||
st_size: 0,
|
||||
st_atim: 0,
|
||||
st_mtim: 0,
|
||||
st_ctim: 0,
|
||||
};
|
||||
let status = wasi_fd_filestat_get(file_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats"
|
||||
);
|
||||
assert_eq!(stat.st_size, 0, "file size should be 0");
|
||||
|
||||
// Allocate some size
|
||||
assert!(
|
||||
wasi_unstable::fd_allocate(file_fd, 0, 100).is_ok(),
|
||||
"allocating size"
|
||||
);
|
||||
|
||||
let status = wasi_fd_filestat_get(file_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats after initial allocation"
|
||||
);
|
||||
assert_eq!(stat.st_size, 100, "file size should be 100");
|
||||
|
||||
// Allocate should not modify if less than current size
|
||||
assert!(
|
||||
wasi_unstable::fd_allocate(file_fd, 10, 10).is_ok(),
|
||||
"allocating size less than current size"
|
||||
);
|
||||
|
||||
let status = wasi_fd_filestat_get(file_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats after additional allocation was not required"
|
||||
);
|
||||
assert_eq!(
|
||||
stat.st_size, 100,
|
||||
"file size should remain unchanged at 100"
|
||||
);
|
||||
|
||||
// Allocate should modify if offset+len > current_len
|
||||
assert!(
|
||||
wasi_unstable::fd_allocate(file_fd, 90, 20).is_ok(),
|
||||
"allocating size larger than current size"
|
||||
);
|
||||
|
||||
let status = wasi_fd_filestat_get(file_fd, &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats after additional allocation was required"
|
||||
);
|
||||
assert_eq!(
|
||||
stat.st_size, 110,
|
||||
"file size should increase from 100 to 110"
|
||||
);
|
||||
|
||||
close_fd(file_fd);
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_file_allocate(dir_fd) }
|
||||
}
|
||||
131
wasi-misc-tests/src/bin/file_pread_pwrite.rs
Normal file
131
wasi-misc-tests/src/bin/file_pread_pwrite.rs
Normal file
@@ -0,0 +1,131 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, close_fd};
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_fd_pread, wasi_fd_pwrite, wasi_path_open};
|
||||
|
||||
unsafe fn test_file_pread_pwrite(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a file in the scratch directory.
|
||||
let mut file_fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let mut status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_CREAT,
|
||||
wasi_unstable::RIGHT_FD_READ | wasi_unstable::RIGHT_FD_WRITE,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
let contents = &[0u8, 1, 2, 3];
|
||||
let ciovec = wasi_unstable::CIoVec {
|
||||
buf: contents.as_ptr() as *const libc::c_void,
|
||||
buf_len: contents.len(),
|
||||
};
|
||||
let mut nwritten = 0;
|
||||
status = wasi_fd_pwrite(file_fd, &mut [ciovec], 0, &mut nwritten);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"writing bytes at offset 0"
|
||||
);
|
||||
assert_eq!(nwritten, 4, "nwritten bytes check");
|
||||
|
||||
let contents = &mut [0u8; 4];
|
||||
let iovec = wasi_unstable::IoVec {
|
||||
buf: contents.as_mut_ptr() as *mut libc::c_void,
|
||||
buf_len: contents.len(),
|
||||
};
|
||||
let mut nread = 0;
|
||||
status = wasi_fd_pread(file_fd, &[iovec], 0, &mut nread);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading bytes at offset 0"
|
||||
);
|
||||
assert_eq!(nread, 4, "nread bytes check");
|
||||
assert_eq!(contents, &[0u8, 1, 2, 3], "written bytes equal read bytes");
|
||||
|
||||
let contents = &mut [0u8; 4];
|
||||
let iovec = wasi_unstable::IoVec {
|
||||
buf: contents.as_mut_ptr() as *mut libc::c_void,
|
||||
buf_len: contents.len(),
|
||||
};
|
||||
let mut nread = 0;
|
||||
status = wasi_fd_pread(file_fd, &[iovec], 2, &mut nread);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading bytes at offset 2"
|
||||
);
|
||||
assert_eq!(nread, 2, "nread bytes check");
|
||||
assert_eq!(contents, &[2u8, 3, 0, 0], "file cursor was overwritten");
|
||||
|
||||
let contents = &[1u8, 0];
|
||||
let ciovec = wasi_unstable::CIoVec {
|
||||
buf: contents.as_ptr() as *const libc::c_void,
|
||||
buf_len: contents.len(),
|
||||
};
|
||||
let mut nwritten = 0;
|
||||
status = wasi_fd_pwrite(file_fd, &mut [ciovec], 2, &mut nwritten);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"writing bytes at offset 2"
|
||||
);
|
||||
assert_eq!(nwritten, 2, "nwritten bytes check");
|
||||
|
||||
let contents = &mut [0u8; 4];
|
||||
let iovec = wasi_unstable::IoVec {
|
||||
buf: contents.as_mut_ptr() as *mut libc::c_void,
|
||||
buf_len: contents.len(),
|
||||
};
|
||||
let mut nread = 0;
|
||||
status = wasi_fd_pread(file_fd, &[iovec], 0, &mut nread);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading bytes at offset 0"
|
||||
);
|
||||
assert_eq!(nread, 4, "nread bytes check");
|
||||
assert_eq!(contents, &[0u8, 1, 1, 0], "file cursor was overwritten");
|
||||
|
||||
close_fd(file_fd);
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_file_pread_pwrite(dir_fd) }
|
||||
}
|
||||
133
wasi-misc-tests/src/bin/file_seek_tell.rs
Normal file
133
wasi-misc-tests/src/bin/file_seek_tell.rs
Normal file
@@ -0,0 +1,133 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, close_fd};
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_fd_seek, wasi_fd_tell, wasi_fd_write, wasi_path_open};
|
||||
|
||||
unsafe fn test_file_seek_tell(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a file in the scratch directory.
|
||||
let mut file_fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let mut status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_CREAT,
|
||||
wasi_unstable::RIGHT_FD_READ | wasi_unstable::RIGHT_FD_WRITE,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
// Check current offset
|
||||
let mut offset: wasi_unstable::FileSize = 0;
|
||||
status = wasi_fd_tell(file_fd, &mut offset);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"getting initial file offset"
|
||||
);
|
||||
assert_eq!(offset, 0, "current offset should be 0");
|
||||
|
||||
// Write to file
|
||||
let buf = &[0u8; 100];
|
||||
let iov = wasi_unstable::CIoVec {
|
||||
buf: buf.as_ptr() as *const _,
|
||||
buf_len: buf.len(),
|
||||
};
|
||||
let iovs = &[iov];
|
||||
let mut nwritten = 0;
|
||||
status = wasi_fd_write(file_fd, iovs, &mut nwritten);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"writing to a file"
|
||||
);
|
||||
assert_eq!(nwritten, 100, "should write 100 bytes to file");
|
||||
|
||||
// Check current offset
|
||||
status = wasi_fd_tell(file_fd, &mut offset);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"getting file offset after writing"
|
||||
);
|
||||
assert_eq!(offset, 100, "offset after writing should be 100");
|
||||
|
||||
// Seek to middle of the file
|
||||
let mut newoffset = 1;
|
||||
status = wasi_fd_seek(file_fd, -50, wasi_unstable::WHENCE_CUR, &mut newoffset);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"seeking to the middle of a file"
|
||||
);
|
||||
assert_eq!(
|
||||
newoffset, 50,
|
||||
"offset after seeking to the middle should be at 50"
|
||||
);
|
||||
|
||||
// Seek to the beginning of the file
|
||||
status = wasi_fd_seek(file_fd, 0, wasi_unstable::WHENCE_SET, &mut newoffset);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"seeking to the beginning of the file"
|
||||
);
|
||||
assert_eq!(
|
||||
newoffset, 0,
|
||||
"offset after seeking to the beginning of the file should be at 0"
|
||||
);
|
||||
|
||||
// Seek beyond the file should be possible
|
||||
status = wasi_fd_seek(file_fd, 1000, wasi_unstable::WHENCE_CUR, &mut newoffset);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"seeking beyond the end of the file"
|
||||
);
|
||||
|
||||
// Seek before byte 0 is an error though
|
||||
status = wasi_fd_seek(file_fd, -2000, wasi_unstable::WHENCE_CUR, &mut newoffset);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_EINVAL,
|
||||
"seeking before byte 0 is an error"
|
||||
);
|
||||
|
||||
close_fd(file_fd);
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_file_seek_tell(dir_fd) }
|
||||
}
|
||||
116
wasi-misc-tests/src/bin/file_unbuffered_write.rs
Normal file
116
wasi-misc-tests/src/bin/file_unbuffered_write.rs
Normal file
@@ -0,0 +1,116 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, close_fd, create_file};
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_fd_read, wasi_fd_write, wasi_path_open};
|
||||
|
||||
unsafe fn test_file_unbuffered_write(dir_fd: wasi_unstable::Fd) {
|
||||
// Create file
|
||||
create_file(dir_fd, "file");
|
||||
|
||||
// Open file for reading
|
||||
let mut fd_read = wasi_unstable::Fd::max_value() - 1;
|
||||
let mut status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
0,
|
||||
wasi_unstable::RIGHT_FD_READ,
|
||||
0,
|
||||
0,
|
||||
&mut fd_read,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
fd_read,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
// Open the same file but for writing
|
||||
let mut fd_write = wasi_unstable::Fd::max_value() - 1;
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
0,
|
||||
wasi_unstable::RIGHT_FD_WRITE,
|
||||
0,
|
||||
0,
|
||||
&mut fd_write,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
fd_write,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
// Write to file
|
||||
let contents = &[1u8];
|
||||
let ciovec = wasi_unstable::CIoVec {
|
||||
buf: contents.as_ptr() as *const libc::c_void,
|
||||
buf_len: contents.len(),
|
||||
};
|
||||
let mut nwritten = 0;
|
||||
status = wasi_fd_write(fd_write, &[ciovec], &mut nwritten);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"writing byte to file"
|
||||
);
|
||||
assert_eq!(nwritten, 1, "nwritten bytes check");
|
||||
|
||||
// Read from file
|
||||
let contents = &mut [0u8; 1];
|
||||
let iovec = wasi_unstable::IoVec {
|
||||
buf: contents.as_mut_ptr() as *mut libc::c_void,
|
||||
buf_len: contents.len(),
|
||||
};
|
||||
let mut nread = 0;
|
||||
status = wasi_fd_read(fd_read, &[iovec], &mut nread);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading bytes from file"
|
||||
);
|
||||
assert_eq!(nread, 1, "nread bytes check");
|
||||
assert_eq!(contents, &[1u8], "written bytes equal read bytes");
|
||||
|
||||
// Clean up
|
||||
close_fd(fd_write);
|
||||
close_fd(fd_read);
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_file_unbuffered_write(dir_fd) }
|
||||
}
|
||||
173
wasi-misc-tests/src/bin/interesting_paths.rs
Normal file
173
wasi-misc-tests/src/bin/interesting_paths.rs
Normal file
@@ -0,0 +1,173 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{close_fd, create_dir, create_file};
|
||||
use wasi_misc_tests::wasi_wrappers::{
|
||||
wasi_path_open, wasi_path_remove_directory, wasi_path_unlink_file,
|
||||
};
|
||||
|
||||
unsafe fn test_interesting_paths(dir_fd: wasi_unstable::Fd, arg: &str) {
|
||||
// Create a directory in the scratch directory.
|
||||
create_dir(dir_fd, "dir");
|
||||
|
||||
// Create a directory in the directory we just created.
|
||||
create_dir(dir_fd, "dir/nested");
|
||||
|
||||
// Create a file in the nested directory.
|
||||
create_file(dir_fd, "dir/nested/file");
|
||||
|
||||
// Now open it with an absolute path.
|
||||
let mut file_fd: wasi_unstable::Fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let mut status = wasi_path_open(dir_fd, 0, "/dir/nested/file", 0, 0, 0, 0, &mut file_fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOTCAPABLE,
|
||||
"opening a file with an absolute path"
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Now open it with a path containing "..".
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"dir/.//nested/../../dir/nested/../nested///./file",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file with \"..\" in the path"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
close_fd(file_fd);
|
||||
|
||||
// Now open it with a trailing NUL.
|
||||
status = wasi_path_open(dir_fd, 0, "dir/nested/file\0", 0, 0, 0, 0, &mut file_fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_EILSEQ,
|
||||
"opening a file with a trailing NUL"
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Now open it with a trailing slash.
|
||||
status = wasi_path_open(dir_fd, 0, "dir/nested/file/", 0, 0, 0, 0, &mut file_fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOTDIR,
|
||||
"opening a file with a trailing slash"
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Now open it with trailing slashes.
|
||||
status = wasi_path_open(dir_fd, 0, "dir/nested/file///", 0, 0, 0, 0, &mut file_fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOTDIR,
|
||||
"opening a file with trailing slashes"
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Now open the directory with a trailing slash.
|
||||
status = wasi_path_open(dir_fd, 0, "dir/nested/", 0, 0, 0, 0, &mut file_fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a directory with a trailing slash"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
close_fd(file_fd);
|
||||
|
||||
// Now open the directory with trailing slashes.
|
||||
status = wasi_path_open(dir_fd, 0, "dir/nested///", 0, 0, 0, 0, &mut file_fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a directory with trailing slashes"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
close_fd(file_fd);
|
||||
|
||||
// Now open it with a path containing too many ".."s.
|
||||
let bad_path = format!("dir/nested/../../../{}/dir/nested/file", arg);
|
||||
status = wasi_path_open(dir_fd, 0, &bad_path, 0, 0, 0, 0, &mut file_fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOTCAPABLE,
|
||||
"opening a file with too many \"..\"s in the path"
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
assert!(
|
||||
wasi_path_unlink_file(dir_fd, "dir/nested/file").is_ok(),
|
||||
"unlink_file on a symlink should succeed"
|
||||
);
|
||||
assert!(
|
||||
wasi_path_remove_directory(dir_fd, "dir/nested").is_ok(),
|
||||
"remove_directory on a directory should succeed"
|
||||
);
|
||||
assert!(
|
||||
wasi_path_remove_directory(dir_fd, "dir").is_ok(),
|
||||
"remove_directory on a directory should succeed"
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_interesting_paths(dir_fd, &arg) }
|
||||
}
|
||||
63
wasi-misc-tests/src/bin/isatty.rs
Normal file
63
wasi-misc-tests/src/bin/isatty.rs
Normal file
@@ -0,0 +1,63 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, close_fd};
|
||||
use wasi_misc_tests::wasi_wrappers::wasi_path_open;
|
||||
|
||||
unsafe fn test_isatty(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a file in the scratch directory and test if it's a tty.
|
||||
let mut file_fd: wasi_unstable::Fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_CREAT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
assert_eq!(
|
||||
libc::isatty(file_fd as std::os::raw::c_int),
|
||||
0,
|
||||
"file is a tty"
|
||||
);
|
||||
close_fd(file_fd);
|
||||
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_isatty(dir_fd) }
|
||||
}
|
||||
177
wasi-misc-tests/src/bin/nofollow_errors.rs
Normal file
177
wasi-misc-tests/src/bin/nofollow_errors.rs
Normal file
@@ -0,0 +1,177 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, close_fd, create_dir, create_file};
|
||||
use wasi_misc_tests::wasi_wrappers::{
|
||||
wasi_path_open, wasi_path_remove_directory, wasi_path_symlink,
|
||||
};
|
||||
|
||||
unsafe fn test_nofollow_errors(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a directory for the symlink to point to.
|
||||
create_dir(dir_fd, "target");
|
||||
|
||||
// Create a symlink.
|
||||
assert!(
|
||||
wasi_path_symlink("target", dir_fd, "symlink").is_ok(),
|
||||
"creating a symlink"
|
||||
);
|
||||
|
||||
// Try to open it as a directory with O_NOFOLLOW again.
|
||||
let mut file_fd: wasi_unstable::Fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let mut status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"symlink",
|
||||
wasi_unstable::O_DIRECTORY,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ELOOP,
|
||||
"opening a directory symlink as a directory",
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Try to open it with just O_NOFOLLOW.
|
||||
status = wasi_path_open(dir_fd, 0, "symlink", 0, 0, 0, 0, &mut file_fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ELOOP,
|
||||
"opening a symlink with O_NOFOLLOW should return ELOOP",
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Try to open it as a directory without O_NOFOLLOW.
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
wasi_unstable::LOOKUP_SYMLINK_FOLLOW,
|
||||
"symlink",
|
||||
wasi_unstable::O_DIRECTORY,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a symlink as a directory"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
close_fd(file_fd);
|
||||
|
||||
// Replace the target directory with a file.
|
||||
cleanup_file(dir_fd, "symlink");
|
||||
|
||||
assert!(
|
||||
wasi_path_remove_directory(dir_fd, "target").is_ok(),
|
||||
"remove_directory on a directory should succeed"
|
||||
);
|
||||
create_file(dir_fd, "target");
|
||||
|
||||
assert!(
|
||||
wasi_path_symlink("target", dir_fd, "symlink").is_ok(),
|
||||
"creating a symlink"
|
||||
);
|
||||
|
||||
// Try to open it as a directory with O_NOFOLLOW again.
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"symlink",
|
||||
wasi_unstable::O_DIRECTORY,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ELOOP,
|
||||
"opening a directory symlink as a directory",
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Try to open it with just O_NOFOLLOW.
|
||||
status = wasi_path_open(dir_fd, 0, "symlink", 0, 0, 0, 0, &mut file_fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ELOOP,
|
||||
"opening a symlink with O_NOFOLLOW should return ELOOP",
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Try to open it as a directory without O_NOFOLLOW.
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
wasi_unstable::LOOKUP_SYMLINK_FOLLOW,
|
||||
"symlink",
|
||||
wasi_unstable::O_DIRECTORY,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOTDIR,
|
||||
"opening a symlink to a file as a directory",
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Clean up.
|
||||
cleanup_file(dir_fd, "target");
|
||||
cleanup_file(dir_fd, "symlink");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_nofollow_errors(dir_fd) }
|
||||
}
|
||||
184
wasi-misc-tests/src/bin/path_filestat.rs
Normal file
184
wasi-misc-tests/src/bin/path_filestat.rs
Normal file
@@ -0,0 +1,184 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, close_fd};
|
||||
use wasi_misc_tests::wasi_wrappers::{
|
||||
wasi_fd_fdstat_get, wasi_path_filestat_get, wasi_path_filestat_set_times, wasi_path_open,
|
||||
};
|
||||
|
||||
unsafe fn test_path_filestat(dir_fd: wasi_unstable::Fd) {
|
||||
let mut fdstat: wasi_unstable::FdStat = std::mem::zeroed();
|
||||
let status = wasi_fd_fdstat_get(dir_fd, &mut fdstat);
|
||||
assert_eq!(status, wasi_unstable::raw::__WASI_ESUCCESS, "fd_fdstat_get");
|
||||
|
||||
assert_ne!(
|
||||
fdstat.fs_rights_base & wasi_unstable::RIGHT_PATH_FILESTAT_GET,
|
||||
0,
|
||||
"the scratch directory should have RIGHT_PATH_FILESTAT_GET as base right",
|
||||
);
|
||||
assert_ne!(
|
||||
fdstat.fs_rights_inheriting & wasi_unstable::RIGHT_PATH_FILESTAT_GET,
|
||||
0,
|
||||
"the scratch directory should have RIGHT_PATH_FILESTAT_GET as base right",
|
||||
);
|
||||
|
||||
// Create a file in the scratch directory.
|
||||
let mut file_fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let filename = "file";
|
||||
let status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
filename,
|
||||
wasi_unstable::O_CREAT,
|
||||
wasi_unstable::RIGHT_FD_READ
|
||||
| wasi_unstable::RIGHT_FD_WRITE
|
||||
| wasi_unstable::RIGHT_PATH_FILESTAT_GET,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
let status = wasi_fd_fdstat_get(file_fd, &mut fdstat);
|
||||
assert_eq!(status, wasi_unstable::raw::__WASI_ESUCCESS, "fd_fdstat_get");
|
||||
|
||||
assert_eq!(
|
||||
fdstat.fs_rights_base & wasi_unstable::RIGHT_PATH_FILESTAT_GET,
|
||||
0,
|
||||
"files shouldn't have rights for path_* syscalls even if manually given",
|
||||
);
|
||||
assert_eq!(
|
||||
fdstat.fs_rights_inheriting & wasi_unstable::RIGHT_PATH_FILESTAT_GET,
|
||||
0,
|
||||
"files shouldn't have rights for path_* syscalls even if manually given",
|
||||
);
|
||||
|
||||
// Check file size
|
||||
let mut stat = wasi_unstable::FileStat {
|
||||
st_dev: 0,
|
||||
st_ino: 0,
|
||||
st_filetype: 0,
|
||||
st_nlink: 0,
|
||||
st_size: 0,
|
||||
st_atim: 0,
|
||||
st_mtim: 0,
|
||||
st_ctim: 0,
|
||||
};
|
||||
let status = wasi_path_filestat_get(dir_fd, 0, filename, filename.len(), &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats"
|
||||
);
|
||||
assert_eq!(stat.st_size, 0, "file size should be 0");
|
||||
|
||||
// Check path_filestat_set_times
|
||||
let old_atim = stat.st_atim;
|
||||
let new_mtim = stat.st_mtim - 100;
|
||||
assert!(
|
||||
wasi_path_filestat_set_times(
|
||||
dir_fd,
|
||||
0,
|
||||
filename,
|
||||
// on purpose: the syscall should not touch atim, because
|
||||
// neither of the ATIM flags is set
|
||||
new_mtim,
|
||||
new_mtim,
|
||||
wasi_unstable::FILESTAT_SET_MTIM,
|
||||
)
|
||||
.is_ok(),
|
||||
"path_filestat_set_times should succeed"
|
||||
);
|
||||
|
||||
let status = wasi_path_filestat_get(dir_fd, 0, filename, filename.len(), &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats after path_filestat_set_times"
|
||||
);
|
||||
assert_eq!(stat.st_mtim, new_mtim, "mtim should change");
|
||||
assert_eq!(stat.st_atim, old_atim, "atim should not change");
|
||||
|
||||
assert_eq!(
|
||||
wasi_path_filestat_set_times(
|
||||
dir_fd,
|
||||
0,
|
||||
filename,
|
||||
new_mtim,
|
||||
new_mtim,
|
||||
wasi_unstable::FILESTAT_SET_MTIM | wasi_unstable::FILESTAT_SET_MTIM_NOW,
|
||||
),
|
||||
Err(wasi_unstable::EINVAL),
|
||||
"MTIM & MTIM_NOW can't both be set"
|
||||
);
|
||||
|
||||
// check if the times were untouched
|
||||
let status = wasi_path_filestat_get(dir_fd, 0, filename, filename.len(), &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats after EINVAL fd_filestat_set_times"
|
||||
);
|
||||
assert_eq!(stat.st_mtim, new_mtim, "mtim should not change");
|
||||
assert_eq!(stat.st_atim, old_atim, "atim should not change");
|
||||
|
||||
let new_atim = old_atim - 100;
|
||||
assert_eq!(
|
||||
wasi_path_filestat_set_times(
|
||||
dir_fd,
|
||||
0,
|
||||
filename,
|
||||
new_atim,
|
||||
new_atim,
|
||||
wasi_unstable::FILESTAT_SET_ATIM | wasi_unstable::FILESTAT_SET_ATIM_NOW,
|
||||
),
|
||||
Err(wasi_unstable::EINVAL),
|
||||
"ATIM & ATIM_NOW can't both be set"
|
||||
);
|
||||
|
||||
// check if the times were untouched
|
||||
let status = wasi_path_filestat_get(dir_fd, 0, filename, filename.len(), &mut stat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading file stats after EINVAL path_filestat_set_times"
|
||||
);
|
||||
assert_eq!(stat.st_mtim, new_mtim, "mtim should not change");
|
||||
assert_eq!(stat.st_atim, old_atim, "atim should not change");
|
||||
|
||||
close_fd(file_fd);
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_path_filestat(dir_fd) }
|
||||
}
|
||||
67
wasi-misc-tests/src/bin/path_open_dirfd_not_dir.rs
Normal file
67
wasi-misc-tests/src/bin/path_open_dirfd_not_dir.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::close_fd;
|
||||
use wasi_misc_tests::wasi_wrappers::wasi_path_open;
|
||||
|
||||
unsafe fn test_dirfd_not_dir(dir_fd: wasi_unstable::Fd) {
|
||||
// Open a file.
|
||||
let mut file_fd: wasi_unstable::Fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let mut status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_CREAT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
|
||||
// Now try to open a file underneath it as if it were a directory.
|
||||
let mut new_file_fd: wasi_unstable::Fd = wasi_unstable::Fd::max_value() - 1;
|
||||
status = wasi_path_open(
|
||||
file_fd,
|
||||
0,
|
||||
"foo",
|
||||
wasi_unstable::O_CREAT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut new_file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOTDIR,
|
||||
"non-directory base fd should get ENOTDIR"
|
||||
);
|
||||
close_fd(file_fd);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_dirfd_not_dir(dir_fd) }
|
||||
}
|
||||
259
wasi-misc-tests/src/bin/path_rename.rs
Normal file
259
wasi-misc-tests/src/bin/path_rename.rs
Normal file
@@ -0,0 +1,259 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_dir, cleanup_file, close_fd, create_dir, create_file};
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_path_open, wasi_path_rename};
|
||||
|
||||
unsafe fn test_path_rename(dir_fd: wasi_unstable::Fd) {
|
||||
// First, try renaming a dir to nonexistent path
|
||||
// Create source directory
|
||||
create_dir(dir_fd, "source");
|
||||
|
||||
// Try renaming the directory
|
||||
assert!(
|
||||
wasi_path_rename(dir_fd, "source", dir_fd, "target").is_ok(),
|
||||
"renaming a directory"
|
||||
);
|
||||
|
||||
// Check that source directory doesn't exist anymore
|
||||
let mut fd: wasi_unstable::Fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let mut status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"source",
|
||||
wasi_unstable::O_DIRECTORY,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOENT,
|
||||
"opening a nonexistent path as a directory"
|
||||
);
|
||||
assert_eq!(
|
||||
fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Check that target directory exists
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"target",
|
||||
wasi_unstable::O_DIRECTORY,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening renamed path as a directory"
|
||||
);
|
||||
assert_gt!(
|
||||
fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
close_fd(fd);
|
||||
cleanup_dir(dir_fd, "target");
|
||||
|
||||
// Now, try renaming renaming a dir to existing empty dir
|
||||
create_dir(dir_fd, "source");
|
||||
create_dir(dir_fd, "target");
|
||||
|
||||
assert!(
|
||||
wasi_path_rename(dir_fd, "source", dir_fd, "target").is_ok(),
|
||||
"renaming a directory"
|
||||
);
|
||||
|
||||
// Check that source directory doesn't exist anymore
|
||||
fd = wasi_unstable::Fd::max_value() - 1;
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"source",
|
||||
wasi_unstable::O_DIRECTORY,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOENT,
|
||||
"opening a nonexistent path as a directory"
|
||||
);
|
||||
assert_eq!(
|
||||
fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Check that target directory exists
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"target",
|
||||
wasi_unstable::O_DIRECTORY,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening renamed path as a directory"
|
||||
);
|
||||
assert_gt!(
|
||||
fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
close_fd(fd);
|
||||
cleanup_dir(dir_fd, "target");
|
||||
|
||||
// Now, try renaming a dir to existing non-empty dir
|
||||
create_dir(dir_fd, "source");
|
||||
create_dir(dir_fd, "target");
|
||||
create_file(dir_fd, "target/file");
|
||||
|
||||
assert_eq!(
|
||||
wasi_path_rename(dir_fd, "source", dir_fd, "target"),
|
||||
Err(wasi_unstable::ENOTEMPTY),
|
||||
"renaming directory to a nonempty directory"
|
||||
);
|
||||
|
||||
// Try renaming dir to a file
|
||||
assert_eq!(
|
||||
wasi_path_rename(dir_fd, "source", dir_fd, "target/file"),
|
||||
Err(wasi_unstable::ENOTDIR),
|
||||
"renaming directory to a file"
|
||||
);
|
||||
|
||||
cleanup_file(dir_fd, "target/file");
|
||||
cleanup_dir(dir_fd, "target");
|
||||
cleanup_dir(dir_fd, "source");
|
||||
|
||||
// Now, try renaming a file to a nonexistent path
|
||||
create_file(dir_fd, "source");
|
||||
|
||||
assert!(
|
||||
wasi_path_rename(dir_fd, "source", dir_fd, "target").is_ok(),
|
||||
"renaming a file"
|
||||
);
|
||||
|
||||
// Check that source file doesn't exist anymore
|
||||
fd = wasi_unstable::Fd::max_value() - 1;
|
||||
status = wasi_path_open(dir_fd, 0, "source", 0, 0, 0, 0, &mut fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOENT,
|
||||
"opening a nonexistent path"
|
||||
);
|
||||
assert_eq!(
|
||||
fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Check that target file exists
|
||||
status = wasi_path_open(dir_fd, 0, "target", 0, 0, 0, 0, &mut fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening renamed path"
|
||||
);
|
||||
assert_gt!(
|
||||
fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
close_fd(fd);
|
||||
cleanup_file(dir_fd, "target");
|
||||
|
||||
// Now, try renaming file to an existing file
|
||||
create_file(dir_fd, "source");
|
||||
create_file(dir_fd, "target");
|
||||
|
||||
assert!(
|
||||
wasi_path_rename(dir_fd, "source", dir_fd, "target").is_ok(),
|
||||
"renaming file to another existing file"
|
||||
);
|
||||
|
||||
// Check that source file doesn't exist anymore
|
||||
fd = wasi_unstable::Fd::max_value() - 1;
|
||||
status = wasi_path_open(dir_fd, 0, "source", 0, 0, 0, 0, &mut fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOENT,
|
||||
"opening a nonexistent path"
|
||||
);
|
||||
assert_eq!(
|
||||
fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
|
||||
// Check that target file exists
|
||||
status = wasi_path_open(dir_fd, 0, "target", 0, 0, 0, 0, &mut fd);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening renamed path"
|
||||
);
|
||||
assert_gt!(
|
||||
fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
close_fd(fd);
|
||||
cleanup_file(dir_fd, "target");
|
||||
|
||||
// Try renaming to an (empty) directory instead
|
||||
create_file(dir_fd, "source");
|
||||
create_dir(dir_fd, "target");
|
||||
|
||||
assert_eq!(
|
||||
wasi_path_rename(dir_fd, "source", dir_fd, "target"),
|
||||
Err(wasi_unstable::EISDIR),
|
||||
"renaming file to existing directory"
|
||||
);
|
||||
|
||||
cleanup_dir(dir_fd, "target");
|
||||
cleanup_file(dir_fd, "source");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_path_rename(dir_fd) }
|
||||
}
|
||||
68
wasi-misc-tests/src/bin/path_rename_trailing_slashes.rs
Normal file
68
wasi-misc-tests/src/bin/path_rename_trailing_slashes.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_dir, cleanup_file, create_dir, create_file};
|
||||
use wasi_misc_tests::wasi_wrappers::wasi_path_rename;
|
||||
|
||||
unsafe fn test_path_rename_trailing_slashes(dir_fd: wasi_unstable::Fd) {
|
||||
// Test renaming a file with a trailing slash in the name.
|
||||
create_file(dir_fd, "source");
|
||||
assert_eq!(
|
||||
wasi_path_rename(dir_fd, "source/", dir_fd, "target"),
|
||||
Err(wasi_unstable::ENOTDIR),
|
||||
"renaming a file with a trailing slash in the source name"
|
||||
);
|
||||
assert_eq!(
|
||||
wasi_path_rename(dir_fd, "source", dir_fd, "target/"),
|
||||
Err(wasi_unstable::ENOTDIR),
|
||||
"renaming a file with a trailing slash in the destination name"
|
||||
);
|
||||
assert_eq!(
|
||||
wasi_path_rename(dir_fd, "source/", dir_fd, "target/"),
|
||||
Err(wasi_unstable::ENOTDIR),
|
||||
"renaming a file with a trailing slash in the source and destination names"
|
||||
);
|
||||
cleanup_file(dir_fd, "source");
|
||||
|
||||
// Test renaming a directory with a trailing slash in the name.
|
||||
create_dir(dir_fd, "source");
|
||||
assert_eq!(
|
||||
wasi_path_rename(dir_fd, "source/", dir_fd, "target"),
|
||||
Ok(()),
|
||||
"renaming a directory with a trailing slash in the source name"
|
||||
);
|
||||
assert_eq!(
|
||||
wasi_path_rename(dir_fd, "target", dir_fd, "source/"),
|
||||
Ok(()),
|
||||
"renaming a directory with a trailing slash in the destination name"
|
||||
);
|
||||
assert_eq!(
|
||||
wasi_path_rename(dir_fd, "source/", dir_fd, "target/"),
|
||||
Ok(()),
|
||||
"renaming a directory with a trailing slash in the source and destination names"
|
||||
);
|
||||
cleanup_dir(dir_fd, "target");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_path_rename_trailing_slashes(dir_fd) }
|
||||
}
|
||||
81
wasi-misc-tests/src/bin/path_symlink_trailing_slashes.rs
Normal file
81
wasi-misc-tests/src/bin/path_symlink_trailing_slashes.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_dir, cleanup_file, create_dir, create_file};
|
||||
use wasi_misc_tests::wasi_wrappers::wasi_path_symlink;
|
||||
|
||||
unsafe fn test_path_symlink_trailing_slashes(dir_fd: wasi_unstable::Fd) {
|
||||
// Link destination shouldn't end with a slash.
|
||||
assert_eq!(
|
||||
wasi_path_symlink("source", dir_fd, "target/"),
|
||||
Err(wasi_unstable::ENOENT),
|
||||
"link destination ending with a slash"
|
||||
);
|
||||
|
||||
// Without the trailing slash, this should succeed.
|
||||
assert_eq!(
|
||||
wasi_path_symlink("source", dir_fd, "target"),
|
||||
Ok(()),
|
||||
"link destination ending with a slash"
|
||||
);
|
||||
cleanup_file(dir_fd, "target");
|
||||
|
||||
// Link destination already exists, target has trailing slash.
|
||||
create_dir(dir_fd, "target");
|
||||
assert_eq!(
|
||||
wasi_path_symlink("source", dir_fd, "target/"),
|
||||
Err(wasi_unstable::EEXIST),
|
||||
"link destination already exists"
|
||||
);
|
||||
cleanup_dir(dir_fd, "target");
|
||||
|
||||
// Link destination already exists, target has no trailing slash.
|
||||
create_dir(dir_fd, "target");
|
||||
assert_eq!(
|
||||
wasi_path_symlink("source", dir_fd, "target"),
|
||||
Err(wasi_unstable::EEXIST),
|
||||
"link destination already exists"
|
||||
);
|
||||
cleanup_dir(dir_fd, "target");
|
||||
|
||||
// Link destination already exists, target has trailing slash.
|
||||
create_file(dir_fd, "target");
|
||||
assert_eq!(
|
||||
wasi_path_symlink("source", dir_fd, "target/"),
|
||||
Err(wasi_unstable::EEXIST),
|
||||
"link destination already exists"
|
||||
);
|
||||
cleanup_file(dir_fd, "target");
|
||||
|
||||
// Link destination already exists, target has no trailing slash.
|
||||
create_file(dir_fd, "target");
|
||||
assert_eq!(
|
||||
wasi_path_symlink("source", dir_fd, "target"),
|
||||
Err(wasi_unstable::EEXIST),
|
||||
"link destination already exists"
|
||||
);
|
||||
cleanup_file(dir_fd, "target");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_path_symlink_trailing_slashes(dir_fd) }
|
||||
}
|
||||
271
wasi-misc-tests/src/bin/poll_oneoff.rs
Normal file
271
wasi-misc-tests/src/bin/poll_oneoff.rs
Normal file
@@ -0,0 +1,271 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, mem::MaybeUninit, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::{
|
||||
open_scratch_directory,
|
||||
utils::{cleanup_file, close_fd},
|
||||
wasi_wrappers::wasi_path_open,
|
||||
};
|
||||
|
||||
const CLOCK_ID: wasi_unstable::Userdata = 0x0123_45678;
|
||||
|
||||
unsafe fn poll_oneoff_impl(
|
||||
in_: &[wasi_unstable::Subscription],
|
||||
nexpected: usize,
|
||||
) -> Vec<wasi_unstable::Event> {
|
||||
let mut out: Vec<wasi_unstable::Event> = Vec::new();
|
||||
out.resize_with(in_.len(), || {
|
||||
MaybeUninit::<wasi_unstable::Event>::zeroed().assume_init()
|
||||
});
|
||||
let res = wasi_unstable::poll_oneoff(&in_, out.as_mut_slice());
|
||||
let res = res.expect("poll_oneoff should succeed");
|
||||
assert_eq!(
|
||||
res, nexpected,
|
||||
"poll_oneoff should return {} events",
|
||||
nexpected
|
||||
);
|
||||
out
|
||||
}
|
||||
|
||||
unsafe fn test_timeout() {
|
||||
let clock = wasi_unstable::raw::__wasi_subscription_u_clock_t {
|
||||
identifier: CLOCK_ID,
|
||||
clock_id: wasi_unstable::CLOCK_MONOTONIC,
|
||||
timeout: 5_000_000u64, // 5 milliseconds
|
||||
precision: 0,
|
||||
flags: 0,
|
||||
};
|
||||
let in_ = [wasi_unstable::Subscription {
|
||||
userdata: CLOCK_ID,
|
||||
type_: wasi_unstable::EVENTTYPE_CLOCK,
|
||||
u: wasi_unstable::raw::__wasi_subscription_u { clock },
|
||||
}];
|
||||
let out = poll_oneoff_impl(&in_, 1);
|
||||
let event = &out[0];
|
||||
assert_eq!(
|
||||
event.userdata, CLOCK_ID,
|
||||
"the event.userdata should contain clock_id specified by the user"
|
||||
);
|
||||
assert_eq!(
|
||||
event.error,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"the event.error should be set to ESUCCESS"
|
||||
);
|
||||
assert_eq!(
|
||||
event.type_,
|
||||
wasi_unstable::EVENTTYPE_CLOCK,
|
||||
"the event.type_ should equal clock"
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn test_stdin_read() {
|
||||
let clock = wasi_unstable::raw::__wasi_subscription_u_clock_t {
|
||||
identifier: CLOCK_ID,
|
||||
clock_id: wasi_unstable::CLOCK_MONOTONIC,
|
||||
timeout: 5_000_000u64, // 5 milliseconds
|
||||
precision: 0,
|
||||
flags: 0,
|
||||
};
|
||||
let fd_readwrite = wasi_unstable::raw::__wasi_subscription_u_fd_readwrite_t {
|
||||
fd: wasi_unstable::STDIN_FD,
|
||||
};
|
||||
let in_ = [
|
||||
wasi_unstable::Subscription {
|
||||
userdata: CLOCK_ID,
|
||||
type_: wasi_unstable::EVENTTYPE_CLOCK,
|
||||
u: wasi_unstable::raw::__wasi_subscription_u { clock },
|
||||
},
|
||||
wasi_unstable::Subscription {
|
||||
userdata: 1,
|
||||
type_: wasi_unstable::EVENTTYPE_FD_READ,
|
||||
u: wasi_unstable::raw::__wasi_subscription_u { fd_readwrite },
|
||||
},
|
||||
];
|
||||
let out = poll_oneoff_impl(&in_, 1);
|
||||
let event = &out[0];
|
||||
assert_eq!(
|
||||
event.userdata, CLOCK_ID,
|
||||
"the event.userdata should contain clock_id specified by the user"
|
||||
);
|
||||
assert_eq!(
|
||||
event.error,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"the event.error should be set to ESUCCESS"
|
||||
);
|
||||
assert_eq!(
|
||||
event.type_,
|
||||
wasi_unstable::EVENTTYPE_CLOCK,
|
||||
"the event.type_ should equal clock"
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn test_stdout_stderr_write() {
|
||||
let stdout_readwrite = wasi_unstable::raw::__wasi_subscription_u_fd_readwrite_t {
|
||||
fd: wasi_unstable::STDOUT_FD,
|
||||
};
|
||||
let stderr_readwrite = wasi_unstable::raw::__wasi_subscription_u_fd_readwrite_t {
|
||||
fd: wasi_unstable::STDERR_FD,
|
||||
};
|
||||
let in_ = [
|
||||
wasi_unstable::Subscription {
|
||||
userdata: 1,
|
||||
type_: wasi_unstable::EVENTTYPE_FD_WRITE,
|
||||
u: wasi_unstable::raw::__wasi_subscription_u {
|
||||
fd_readwrite: stdout_readwrite,
|
||||
},
|
||||
},
|
||||
wasi_unstable::Subscription {
|
||||
userdata: 2,
|
||||
type_: wasi_unstable::EVENTTYPE_FD_WRITE,
|
||||
u: wasi_unstable::raw::__wasi_subscription_u {
|
||||
fd_readwrite: stderr_readwrite,
|
||||
},
|
||||
},
|
||||
];
|
||||
let out = poll_oneoff_impl(&in_, 2);
|
||||
assert_eq!(
|
||||
out[0].userdata, 1,
|
||||
"the event.userdata should contain fd userdata specified by the user"
|
||||
);
|
||||
assert_eq!(
|
||||
out[0].error,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"the event.error should be set to {}",
|
||||
wasi_unstable::raw::__WASI_ESUCCESS
|
||||
);
|
||||
assert_eq!(
|
||||
out[0].type_,
|
||||
wasi_unstable::EVENTTYPE_FD_WRITE,
|
||||
"the event.type_ should equal FD_WRITE"
|
||||
);
|
||||
assert_eq!(
|
||||
out[1].userdata, 2,
|
||||
"the event.userdata should contain fd userdata specified by the user"
|
||||
);
|
||||
assert_eq!(
|
||||
out[1].error,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"the event.error should be set to {}",
|
||||
wasi_unstable::raw::__WASI_ESUCCESS
|
||||
);
|
||||
assert_eq!(
|
||||
out[1].type_,
|
||||
wasi_unstable::EVENTTYPE_FD_WRITE,
|
||||
"the event.type_ should equal FD_WRITE"
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn test_fd_readwrite(fd: wasi_unstable::Fd, error_code: wasi_unstable::raw::__wasi_errno_t) {
|
||||
let fd_readwrite = wasi_unstable::raw::__wasi_subscription_u_fd_readwrite_t { fd };
|
||||
let in_ = [
|
||||
wasi_unstable::Subscription {
|
||||
userdata: 1,
|
||||
type_: wasi_unstable::EVENTTYPE_FD_READ,
|
||||
u: wasi_unstable::raw::__wasi_subscription_u { fd_readwrite },
|
||||
},
|
||||
wasi_unstable::Subscription {
|
||||
userdata: 2,
|
||||
type_: wasi_unstable::EVENTTYPE_FD_WRITE,
|
||||
u: wasi_unstable::raw::__wasi_subscription_u { fd_readwrite },
|
||||
},
|
||||
];
|
||||
let out = poll_oneoff_impl(&in_, 2);
|
||||
assert_eq!(
|
||||
out[0].userdata, 1,
|
||||
"the event.userdata should contain fd userdata specified by the user"
|
||||
);
|
||||
assert_eq!(
|
||||
out[0].error, error_code,
|
||||
"the event.error should be set to {}",
|
||||
error_code
|
||||
);
|
||||
assert_eq!(
|
||||
out[0].type_,
|
||||
wasi_unstable::EVENTTYPE_FD_READ,
|
||||
"the event.type_ should equal FD_READ"
|
||||
);
|
||||
assert_eq!(
|
||||
out[1].userdata, 2,
|
||||
"the event.userdata should contain fd userdata specified by the user"
|
||||
);
|
||||
assert_eq!(
|
||||
out[1].error, error_code,
|
||||
"the event.error should be set to {}",
|
||||
error_code
|
||||
);
|
||||
assert_eq!(
|
||||
out[1].type_,
|
||||
wasi_unstable::EVENTTYPE_FD_WRITE,
|
||||
"the event.type_ should equal FD_WRITE"
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn test_fd_readwrite_valid_fd(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a file in the scratch directory.
|
||||
let mut file_fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_CREAT,
|
||||
wasi_unstable::RIGHT_FD_READ | wasi_unstable::RIGHT_FD_WRITE,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
test_fd_readwrite(file_fd, wasi_unstable::raw::__WASI_ESUCCESS);
|
||||
|
||||
close_fd(file_fd);
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
|
||||
unsafe fn test_fd_readwrite_invalid_fd() {
|
||||
test_fd_readwrite(
|
||||
wasi_unstable::Fd::max_value(),
|
||||
wasi_unstable::raw::__WASI_EBADF,
|
||||
)
|
||||
}
|
||||
|
||||
unsafe fn test_poll_oneoff(dir_fd: wasi_unstable::Fd) {
|
||||
test_timeout();
|
||||
// NB we assume that stdin/stdout/stderr are valid and open
|
||||
// for the duration of the test case
|
||||
test_stdin_read();
|
||||
test_stdout_stderr_write();
|
||||
test_fd_readwrite_valid_fd(dir_fd);
|
||||
test_fd_readwrite_invalid_fd();
|
||||
}
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_poll_oneoff(dir_fd) }
|
||||
}
|
||||
72
wasi-misc-tests/src/bin/readlink.rs
Normal file
72
wasi-misc-tests/src/bin/readlink.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, create_file};
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_path_readlink, wasi_path_symlink};
|
||||
|
||||
unsafe fn test_readlink(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a file in the scratch directory.
|
||||
create_file(dir_fd, "target");
|
||||
|
||||
// Create a symlink
|
||||
assert!(
|
||||
wasi_path_symlink("target", dir_fd, "symlink").is_ok(),
|
||||
"creating a symlink"
|
||||
);
|
||||
|
||||
// Read link into the buffer
|
||||
let buf = &mut [0u8; 10];
|
||||
let mut bufused: usize = 0;
|
||||
let mut status = wasi_path_readlink(dir_fd, "symlink", buf, &mut bufused);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"readlink should succeed"
|
||||
);
|
||||
assert_eq!(bufused, 6, "should use 6 bytes of the buffer");
|
||||
assert_eq!(&buf[..6], b"target", "buffer should contain 'target'");
|
||||
assert_eq!(
|
||||
&buf[6..],
|
||||
&[0u8; 4],
|
||||
"the remaining bytes should be untouched"
|
||||
);
|
||||
|
||||
// Read link into smaller buffer than the actual link's length
|
||||
let buf = &mut [0u8; 4];
|
||||
let mut bufused: usize = 0;
|
||||
status = wasi_path_readlink(dir_fd, "symlink", buf, &mut bufused);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"readlink should succeed"
|
||||
);
|
||||
assert_eq!(bufused, 4, "should use all 4 bytes of the buffer");
|
||||
assert_eq!(buf, b"targ", "buffer should contain 'targ'");
|
||||
|
||||
// Clean up.
|
||||
cleanup_file(dir_fd, "target");
|
||||
cleanup_file(dir_fd, "symlink");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_readlink(dir_fd) }
|
||||
}
|
||||
51
wasi-misc-tests/src/bin/readlink_no_buffer.rs
Normal file
51
wasi-misc-tests/src/bin/readlink_no_buffer.rs
Normal file
@@ -0,0 +1,51 @@
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::cleanup_file;
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_path_readlink, wasi_path_symlink};
|
||||
|
||||
unsafe fn test_readlink_no_buffer(dir_fd: wasi_unstable::Fd) {
|
||||
// First create a dangling symlink.
|
||||
assert!(
|
||||
wasi_path_symlink("target", dir_fd, "symlink").is_ok(),
|
||||
"creating a symlink"
|
||||
);
|
||||
|
||||
// Readlink it into a non-existent buffer.
|
||||
let mut bufused: usize = 1;
|
||||
let status = wasi_path_readlink(dir_fd, "symlink", &mut [], &mut bufused);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"readlink with a 0-sized buffer should succeed"
|
||||
);
|
||||
assert_eq!(
|
||||
bufused, 0,
|
||||
"readlink with a 0-sized buffer should return 'bufused' 0"
|
||||
);
|
||||
|
||||
// Clean up.
|
||||
cleanup_file(dir_fd, "symlink");
|
||||
}
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_readlink_no_buffer(dir_fd) }
|
||||
}
|
||||
68
wasi-misc-tests/src/bin/remove_directory_trailing_slashes.rs
Normal file
68
wasi-misc-tests/src/bin/remove_directory_trailing_slashes.rs
Normal file
@@ -0,0 +1,68 @@
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, create_dir, create_file};
|
||||
use wasi_misc_tests::wasi_wrappers::wasi_path_remove_directory;
|
||||
|
||||
unsafe fn test_remove_directory_trailing_slashes(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a directory in the scratch directory.
|
||||
create_dir(dir_fd, "dir");
|
||||
|
||||
// Test that removing it succeeds.
|
||||
assert_eq!(
|
||||
wasi_path_remove_directory(dir_fd, "dir"),
|
||||
Ok(()),
|
||||
"remove_directory on a directory should succeed"
|
||||
);
|
||||
|
||||
create_dir(dir_fd, "dir");
|
||||
|
||||
// Test that removing it with a trailing flash succeeds.
|
||||
assert_eq!(
|
||||
wasi_path_remove_directory(dir_fd, "dir/"),
|
||||
Ok(()),
|
||||
"remove_directory with a trailing slash on a directory should succeed"
|
||||
);
|
||||
|
||||
// Create a temporary file.
|
||||
create_file(dir_fd, "file");
|
||||
|
||||
// Test that removing it with no trailing flash fails.
|
||||
assert_eq!(
|
||||
wasi_path_remove_directory(dir_fd, "file"),
|
||||
Err(wasi_unstable::ENOTDIR),
|
||||
"remove_directory without a trailing slash on a file should fail"
|
||||
);
|
||||
|
||||
// Test that removing it with a trailing flash fails.
|
||||
assert_eq!(
|
||||
wasi_path_remove_directory(dir_fd, "file/"),
|
||||
Err(wasi_unstable::ENOTDIR),
|
||||
"remove_directory with a trailing slash on a file should fail"
|
||||
);
|
||||
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_remove_directory_trailing_slashes(dir_fd) }
|
||||
}
|
||||
50
wasi-misc-tests/src/bin/remove_nonempty_directory.rs
Normal file
50
wasi-misc-tests/src/bin/remove_nonempty_directory.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_dir, create_dir};
|
||||
use wasi_misc_tests::wasi_wrappers::wasi_path_remove_directory;
|
||||
|
||||
unsafe fn test_remove_nonempty_directory(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a directory in the scratch directory.
|
||||
create_dir(dir_fd, "dir");
|
||||
|
||||
// Create a directory in the directory we just created.
|
||||
create_dir(dir_fd, "dir/nested");
|
||||
|
||||
// Test that attempting to unlink the first directory returns the expected error code.
|
||||
assert_eq!(
|
||||
wasi_path_remove_directory(dir_fd, "dir"),
|
||||
Err(wasi_unstable::ENOTEMPTY),
|
||||
"remove_directory on a directory should return ENOTEMPTY",
|
||||
);
|
||||
|
||||
// Removing the directories.
|
||||
assert!(
|
||||
wasi_path_remove_directory(dir_fd, "dir/nested").is_ok(),
|
||||
"remove_directory on a nested directory should succeed",
|
||||
);
|
||||
cleanup_dir(dir_fd, "dir");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_remove_nonempty_directory(dir_fd) }
|
||||
}
|
||||
131
wasi-misc-tests/src/bin/renumber.rs
Normal file
131
wasi-misc-tests/src/bin/renumber.rs
Normal file
@@ -0,0 +1,131 @@
|
||||
use libc;
|
||||
use more_asserts::assert_gt;
|
||||
use std::{env, mem, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::close_fd;
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_fd_fdstat_get, wasi_path_open};
|
||||
|
||||
unsafe fn test_renumber(dir_fd: wasi_unstable::Fd) {
|
||||
let pre_fd: wasi_unstable::Fd = (libc::STDERR_FILENO + 1) as wasi_unstable::Fd;
|
||||
|
||||
assert_gt!(dir_fd, pre_fd, "dir_fd number");
|
||||
|
||||
// Create a file in the scratch directory.
|
||||
let mut fd_from = wasi_unstable::Fd::max_value() - 1;
|
||||
let mut status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file1",
|
||||
wasi_unstable::O_CREAT,
|
||||
wasi_unstable::RIGHT_FD_READ | wasi_unstable::RIGHT_FD_WRITE,
|
||||
0,
|
||||
0,
|
||||
&mut fd_from,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
fd_from,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
// Get fd_from fdstat attributes
|
||||
let mut fdstat_from: wasi_unstable::FdStat = mem::zeroed();
|
||||
status = wasi_fd_fdstat_get(fd_from, &mut fdstat_from);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"calling fd_fdstat on the open file descriptor"
|
||||
);
|
||||
|
||||
// Create another file in the scratch directory.
|
||||
let mut fd_to = wasi_unstable::Fd::max_value() - 1;
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file2",
|
||||
wasi_unstable::O_CREAT,
|
||||
wasi_unstable::RIGHT_FD_READ | wasi_unstable::RIGHT_FD_WRITE,
|
||||
0,
|
||||
0,
|
||||
&mut fd_to,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"opening a file"
|
||||
);
|
||||
assert_gt!(
|
||||
fd_to,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
|
||||
// Renumber fd of file1 into fd of file2
|
||||
assert!(
|
||||
wasi_unstable::fd_renumber(fd_from, fd_to).is_ok(),
|
||||
"renumbering two descriptors",
|
||||
);
|
||||
|
||||
// Ensure that fd_from is closed
|
||||
assert_eq!(
|
||||
wasi_unstable::fd_close(fd_from),
|
||||
Err(wasi_unstable::EBADF),
|
||||
"closing already closed file descriptor"
|
||||
);
|
||||
|
||||
// Ensure that fd_to is still open.
|
||||
let mut fdstat_to: wasi_unstable::FdStat = mem::zeroed();
|
||||
status = wasi_fd_fdstat_get(fd_to, &mut fdstat_to);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"calling fd_fdstat on the open file descriptor"
|
||||
);
|
||||
assert_eq!(
|
||||
fdstat_from.fs_filetype, fdstat_to.fs_filetype,
|
||||
"expected fd_to have the same fdstat as fd_from"
|
||||
);
|
||||
assert_eq!(
|
||||
fdstat_from.fs_flags, fdstat_to.fs_flags,
|
||||
"expected fd_to have the same fdstat as fd_from"
|
||||
);
|
||||
assert_eq!(
|
||||
fdstat_from.fs_rights_base, fdstat_to.fs_rights_base,
|
||||
"expected fd_to have the same fdstat as fd_from"
|
||||
);
|
||||
assert_eq!(
|
||||
fdstat_from.fs_rights_inheriting, fdstat_to.fs_rights_inheriting,
|
||||
"expected fd_to have the same fdstat as fd_from"
|
||||
);
|
||||
|
||||
close_fd(fd_to);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_renumber(dir_fd) }
|
||||
}
|
||||
10
wasi-misc-tests/src/bin/sched_yield.rs
Normal file
10
wasi-misc-tests/src/bin/sched_yield.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use wasi::wasi_unstable;
|
||||
|
||||
fn test_sched_yield() {
|
||||
assert!(wasi_unstable::sched_yield().is_ok(), "sched_yield");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Run tests
|
||||
test_sched_yield()
|
||||
}
|
||||
47
wasi-misc-tests/src/bin/symlink_loop.rs
Normal file
47
wasi-misc-tests/src/bin/symlink_loop.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::cleanup_file;
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_path_open, wasi_path_symlink};
|
||||
|
||||
unsafe fn test_symlink_loop(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a self-referencing symlink.
|
||||
assert!(
|
||||
wasi_path_symlink("symlink", dir_fd, "symlink").is_ok(),
|
||||
"creating a symlink"
|
||||
);
|
||||
|
||||
// Try to open it.
|
||||
let mut file_fd: wasi_unstable::Fd = wasi_unstable::Fd::max_value() - 1;
|
||||
assert_eq!(
|
||||
wasi_path_open(dir_fd, 0, "symlink", 0, 0, 0, 0, &mut file_fd),
|
||||
wasi_unstable::raw::__WASI_ELOOP,
|
||||
"opening a self-referencing symlink",
|
||||
);
|
||||
|
||||
// Clean up.
|
||||
cleanup_file(dir_fd, "symlink");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_symlink_loop(dir_fd) }
|
||||
}
|
||||
157
wasi-misc-tests/src/bin/truncation_rights.rs
Normal file
157
wasi-misc-tests/src/bin/truncation_rights.rs
Normal file
@@ -0,0 +1,157 @@
|
||||
use std::{env, mem, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_file, close_fd, create_file};
|
||||
use wasi_misc_tests::wasi_wrappers::{wasi_fd_fdstat_get, wasi_path_open};
|
||||
|
||||
unsafe fn test_truncation_rights(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a file in the scratch directory.
|
||||
create_file(dir_fd, "file");
|
||||
|
||||
// Get the rights for the scratch directory.
|
||||
let mut dir_fdstat: wasi_unstable::FdStat = mem::zeroed();
|
||||
let mut status = wasi_fd_fdstat_get(dir_fd, &mut dir_fdstat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"calling fd_fdstat on the scratch directory"
|
||||
);
|
||||
assert_eq!(
|
||||
dir_fdstat.fs_filetype,
|
||||
wasi_unstable::FILETYPE_DIRECTORY,
|
||||
"expected the scratch directory to be a directory",
|
||||
);
|
||||
assert_eq!(
|
||||
dir_fdstat.fs_flags, 0,
|
||||
"expected the scratch directory to have no special flags",
|
||||
);
|
||||
assert_eq!(
|
||||
dir_fdstat.fs_rights_base & wasi_unstable::RIGHT_FD_FILESTAT_SET_SIZE,
|
||||
0,
|
||||
"directories shouldn't have the fd_filestat_set_size right",
|
||||
);
|
||||
|
||||
// If we have the right to set sizes from paths, test that it works.
|
||||
if (dir_fdstat.fs_rights_base & wasi_unstable::RIGHT_PATH_FILESTAT_SET_SIZE) == 0 {
|
||||
eprintln!("implementation doesn't support setting file sizes, skipping");
|
||||
} else {
|
||||
// Test that we can truncate the file.
|
||||
let mut file_fd: wasi_unstable::Fd = wasi_unstable::Fd::max_value() - 1;
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_TRUNC,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"truncating a file"
|
||||
);
|
||||
close_fd(file_fd);
|
||||
|
||||
let mut rights_base: wasi_unstable::Rights = dir_fdstat.fs_rights_base;
|
||||
let mut rights_inheriting: wasi_unstable::Rights = dir_fdstat.fs_rights_inheriting;
|
||||
|
||||
if (rights_inheriting & wasi_unstable::RIGHT_FD_FILESTAT_SET_SIZE) == 0 {
|
||||
eprintln!("implementation doesn't support setting file sizes through file descriptors, skipping");
|
||||
} else {
|
||||
rights_inheriting &= !wasi_unstable::RIGHT_FD_FILESTAT_SET_SIZE;
|
||||
assert!(
|
||||
wasi_unstable::fd_fdstat_set_rights(dir_fd, rights_base, rights_inheriting).is_ok(),
|
||||
"droping fd_filestat_set_size inheriting right on a directory",
|
||||
);
|
||||
}
|
||||
|
||||
// Test that we can truncate the file without the
|
||||
// wasi_unstable::RIGHT_FD_FILESTAT_SET_SIZE right.
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_TRUNC,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"truncating a file without fd_filestat_set_size right",
|
||||
);
|
||||
close_fd(file_fd);
|
||||
|
||||
rights_base &= !wasi_unstable::RIGHT_PATH_FILESTAT_SET_SIZE;
|
||||
assert!(
|
||||
wasi_unstable::fd_fdstat_set_rights(dir_fd, rights_base, rights_inheriting).is_ok(),
|
||||
"droping path_filestat_set_size base right on a directory",
|
||||
);
|
||||
|
||||
// Test that clearing wasi_unstable::RIGHT_PATH_FILESTAT_SET_SIZE actually
|
||||
// took effect.
|
||||
status = wasi_fd_fdstat_get(dir_fd, &mut dir_fdstat);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"reading the fdstat from a directory",
|
||||
);
|
||||
assert_eq!(
|
||||
(dir_fdstat.fs_rights_base & wasi_unstable::RIGHT_PATH_FILESTAT_SET_SIZE),
|
||||
0,
|
||||
"reading the fdstat from a directory",
|
||||
);
|
||||
|
||||
// Test that we can't truncate the file without the
|
||||
// wasi_unstable::RIGHT_PATH_FILESTAT_SET_SIZE right.
|
||||
status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
"file",
|
||||
wasi_unstable::O_TRUNC,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ENOTCAPABLE,
|
||||
"truncating a file without path_filestat_set_size right",
|
||||
);
|
||||
assert_eq!(
|
||||
file_fd,
|
||||
wasi_unstable::Fd::max_value(),
|
||||
"failed open should set the file descriptor to -1",
|
||||
);
|
||||
}
|
||||
|
||||
cleanup_file(dir_fd, "file");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_truncation_rights(dir_fd) }
|
||||
}
|
||||
67
wasi-misc-tests/src/bin/unlink_file_trailing_slashes.rs
Normal file
67
wasi-misc-tests/src/bin/unlink_file_trailing_slashes.rs
Normal file
@@ -0,0 +1,67 @@
|
||||
use std::{env, process};
|
||||
use wasi::wasi_unstable;
|
||||
use wasi_misc_tests::open_scratch_directory;
|
||||
use wasi_misc_tests::utils::{cleanup_dir, create_dir, create_file};
|
||||
use wasi_misc_tests::wasi_wrappers::wasi_path_unlink_file;
|
||||
|
||||
unsafe fn test_unlink_file_trailing_slashes(dir_fd: wasi_unstable::Fd) {
|
||||
// Create a directory in the scratch directory.
|
||||
create_dir(dir_fd, "dir");
|
||||
|
||||
// Test that unlinking it fails.
|
||||
assert_eq!(
|
||||
wasi_path_unlink_file(dir_fd, "dir"),
|
||||
Err(wasi_unstable::EISDIR),
|
||||
"unlink_file on a directory should fail"
|
||||
);
|
||||
|
||||
// Test that unlinking it with a trailing flash fails.
|
||||
assert_eq!(
|
||||
wasi_path_unlink_file(dir_fd, "dir/"),
|
||||
Err(wasi_unstable::EISDIR),
|
||||
"unlink_file on a directory should fail"
|
||||
);
|
||||
|
||||
// Clean up.
|
||||
cleanup_dir(dir_fd, "dir");
|
||||
|
||||
// Create a temporary file.
|
||||
create_file(dir_fd, "file");
|
||||
|
||||
// Test that unlinking it with a trailing flash fails.
|
||||
assert_eq!(
|
||||
wasi_path_unlink_file(dir_fd, "file/"),
|
||||
Err(wasi_unstable::ENOTDIR),
|
||||
"unlink_file with a trailing slash should fail"
|
||||
);
|
||||
|
||||
// Test that unlinking it with no trailing flash succeeds.
|
||||
assert_eq!(
|
||||
wasi_path_unlink_file(dir_fd, "file"),
|
||||
Ok(()),
|
||||
"unlink_file with no trailing slash should succeed"
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = env::args();
|
||||
let prog = args.next().unwrap();
|
||||
let arg = if let Some(arg) = args.next() {
|
||||
arg
|
||||
} else {
|
||||
eprintln!("usage: {} <scratch directory>", prog);
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
// Open scratch directory
|
||||
let dir_fd = match open_scratch_directory(&arg) {
|
||||
Ok(dir_fd) => dir_fd,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
process::exit(1)
|
||||
}
|
||||
};
|
||||
|
||||
// Run the tests.
|
||||
unsafe { test_unlink_file_trailing_slashes(dir_fd) }
|
||||
}
|
||||
25
wasi-misc-tests/src/lib.rs
Normal file
25
wasi-misc-tests/src/lib.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
pub mod utils;
|
||||
pub mod wasi_wrappers;
|
||||
|
||||
use libc;
|
||||
use std::ffi::CString;
|
||||
use std::io;
|
||||
use wasi::wasi_unstable;
|
||||
|
||||
pub fn open_scratch_directory(path: &str) -> Result<wasi_unstable::Fd, String> {
|
||||
// Open the scratch directory.
|
||||
let dir_fd: wasi_unstable::Fd = unsafe {
|
||||
let cstr = CString::new(path.as_bytes()).unwrap();
|
||||
libc::open(cstr.as_ptr(), libc::O_RDONLY | libc::O_DIRECTORY)
|
||||
} as wasi_unstable::Fd;
|
||||
|
||||
if (dir_fd as std::os::raw::c_int) < 0 {
|
||||
Err(format!(
|
||||
"error opening scratch directory '{}': {}",
|
||||
path,
|
||||
io::Error::last_os_error()
|
||||
))
|
||||
} else {
|
||||
Ok(dir_fd)
|
||||
}
|
||||
}
|
||||
54
wasi-misc-tests/src/utils.rs
Normal file
54
wasi-misc-tests/src/utils.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use crate::wasi_wrappers::*;
|
||||
use more_asserts::assert_gt;
|
||||
use wasi::wasi_unstable;
|
||||
|
||||
pub unsafe fn create_dir(dir_fd: wasi_unstable::Fd, dir_name: &str) {
|
||||
assert!(
|
||||
wasi_path_create_directory(dir_fd, dir_name).is_ok(),
|
||||
"creating a directory"
|
||||
);
|
||||
}
|
||||
|
||||
pub unsafe fn cleanup_dir(dir_fd: wasi_unstable::Fd, dir_name: &str) {
|
||||
assert!(
|
||||
wasi_path_remove_directory(dir_fd, dir_name).is_ok(),
|
||||
"remove_directory on an empty directory should succeed"
|
||||
);
|
||||
}
|
||||
|
||||
/// Create an empty file with the given name.
|
||||
pub unsafe fn create_file(dir_fd: wasi_unstable::Fd, file_name: &str) {
|
||||
let mut file_fd = wasi_unstable::Fd::max_value() - 1;
|
||||
let status = wasi_path_open(
|
||||
dir_fd,
|
||||
0,
|
||||
file_name,
|
||||
wasi_unstable::O_CREAT,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&mut file_fd,
|
||||
);
|
||||
assert_eq!(
|
||||
status,
|
||||
wasi_unstable::raw::__WASI_ESUCCESS,
|
||||
"creating a file"
|
||||
);
|
||||
assert_gt!(
|
||||
file_fd,
|
||||
libc::STDERR_FILENO as wasi_unstable::Fd,
|
||||
"file descriptor range check",
|
||||
);
|
||||
close_fd(file_fd);
|
||||
}
|
||||
|
||||
pub unsafe fn cleanup_file(dir_fd: wasi_unstable::Fd, file_name: &str) {
|
||||
assert!(
|
||||
wasi_path_unlink_file(dir_fd, file_name).is_ok(),
|
||||
"unlink_file on a symlink should succeed"
|
||||
);
|
||||
}
|
||||
|
||||
pub unsafe fn close_fd(fd: wasi_unstable::Fd) {
|
||||
assert!(wasi_unstable::fd_close(fd).is_ok(), "closing a file");
|
||||
}
|
||||
217
wasi-misc-tests/src/wasi_wrappers.rs
Normal file
217
wasi-misc-tests/src/wasi_wrappers.rs
Normal file
@@ -0,0 +1,217 @@
|
||||
//! Minimal wrappers around WASI functions to allow use of `&str` rather than
|
||||
//! pointer-length pairs.
|
||||
//!
|
||||
//! Where possible, we use the idiomatic wasi_unstable wrappers rather than the
|
||||
//! raw interfaces, however for functions with out parameters, we use the raw
|
||||
//! interfaces so that we can test whether they are stored to. In the future,
|
||||
//! WASI should switch to multi-value and eliminate out parameters altogether.
|
||||
|
||||
use wasi::wasi_unstable;
|
||||
|
||||
pub unsafe fn wasi_path_create_directory(
|
||||
dir_fd: wasi_unstable::Fd,
|
||||
dir_name: &str,
|
||||
) -> Result<(), wasi_unstable::Error> {
|
||||
wasi_unstable::path_create_directory(dir_fd, dir_name.as_bytes())
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_path_remove_directory(
|
||||
dir_fd: wasi_unstable::Fd,
|
||||
dir_name: &str,
|
||||
) -> Result<(), wasi_unstable::Error> {
|
||||
wasi_unstable::path_remove_directory(dir_fd, dir_name.as_bytes())
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_path_unlink_file(
|
||||
dir_fd: wasi_unstable::Fd,
|
||||
file_name: &str,
|
||||
) -> Result<(), wasi_unstable::Error> {
|
||||
wasi_unstable::path_unlink_file(dir_fd, file_name.as_bytes())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub unsafe fn wasi_path_open(
|
||||
dirfd: wasi_unstable::Fd,
|
||||
dirflags: wasi_unstable::LookupFlags,
|
||||
path: &str,
|
||||
oflags: wasi_unstable::OFlags,
|
||||
fs_rights_base: wasi_unstable::Rights,
|
||||
fs_rights_inheriting: wasi_unstable::Rights,
|
||||
fs_flags: wasi_unstable::FdFlags,
|
||||
fd: &mut wasi_unstable::Fd,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_path_open(
|
||||
dirfd,
|
||||
dirflags,
|
||||
path.as_ptr(),
|
||||
path.len(),
|
||||
oflags,
|
||||
fs_rights_base,
|
||||
fs_rights_inheriting,
|
||||
fs_flags,
|
||||
fd,
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_path_symlink(
|
||||
old_path: &str,
|
||||
dirfd: wasi_unstable::Fd,
|
||||
new_path: &str,
|
||||
) -> Result<(), wasi_unstable::Error> {
|
||||
wasi_unstable::path_symlink(old_path.as_bytes(), dirfd, new_path.as_bytes())
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_path_readlink(
|
||||
dirfd: wasi_unstable::Fd,
|
||||
path: &str,
|
||||
buf: &mut [u8],
|
||||
bufused: &mut usize,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_path_readlink(
|
||||
dirfd,
|
||||
path.as_ptr(),
|
||||
path.len(),
|
||||
buf.as_mut_ptr(),
|
||||
buf.len(),
|
||||
bufused,
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_path_rename(
|
||||
old_dirfd: wasi_unstable::Fd,
|
||||
old_path: &str,
|
||||
new_dirfd: wasi_unstable::Fd,
|
||||
new_path: &str,
|
||||
) -> Result<(), wasi_unstable::Error> {
|
||||
wasi_unstable::path_rename(
|
||||
old_dirfd,
|
||||
old_path.as_bytes(),
|
||||
new_dirfd,
|
||||
new_path.as_bytes(),
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_fd_fdstat_get(
|
||||
fd: wasi_unstable::Fd,
|
||||
fdstat: &mut wasi_unstable::FdStat,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_fd_fdstat_get(fd, fdstat)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_fd_seek(
|
||||
fd: wasi_unstable::Fd,
|
||||
offset: wasi_unstable::FileDelta,
|
||||
whence: wasi_unstable::Whence,
|
||||
newoffset: &mut wasi_unstable::FileSize,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_fd_seek(fd, offset, whence, newoffset)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_fd_tell(
|
||||
fd: wasi_unstable::Fd,
|
||||
offset: &mut wasi_unstable::FileSize,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_fd_tell(fd, offset)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_clock_time_get(
|
||||
clock_id: wasi_unstable::ClockId,
|
||||
precision: wasi_unstable::Timestamp,
|
||||
time: &mut wasi_unstable::Timestamp,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_clock_time_get(clock_id, precision, time)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_fd_filestat_get(
|
||||
fd: wasi_unstable::Fd,
|
||||
filestat: &mut wasi_unstable::FileStat,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_fd_filestat_get(fd, filestat)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_fd_write(
|
||||
fd: wasi_unstable::Fd,
|
||||
iovs: &[wasi_unstable::CIoVec],
|
||||
nwritten: &mut libc::size_t,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_fd_write(fd, iovs.as_ptr(), iovs.len(), nwritten)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_fd_read(
|
||||
fd: wasi_unstable::Fd,
|
||||
iovs: &[wasi_unstable::IoVec],
|
||||
nread: &mut libc::size_t,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_fd_read(fd, iovs.as_ptr(), iovs.len(), nread)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_fd_pread(
|
||||
fd: wasi_unstable::Fd,
|
||||
iovs: &[wasi_unstable::IoVec],
|
||||
offset: wasi_unstable::FileSize,
|
||||
nread: &mut usize,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_fd_pread(fd, iovs.as_ptr(), iovs.len(), offset, nread)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_fd_pwrite(
|
||||
fd: wasi_unstable::Fd,
|
||||
iovs: &mut [wasi_unstable::CIoVec],
|
||||
offset: wasi_unstable::FileSize,
|
||||
nwritten: &mut usize,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_fd_pwrite(fd, iovs.as_ptr(), iovs.len(), offset, nwritten)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_path_filestat_get(
|
||||
fd: wasi_unstable::Fd,
|
||||
dirflags: wasi_unstable::LookupFlags,
|
||||
path: &str,
|
||||
path_len: usize,
|
||||
filestat: &mut wasi_unstable::FileStat,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_path_filestat_get(fd, dirflags, path.as_ptr(), path_len, filestat)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_path_filestat_set_times(
|
||||
fd: wasi_unstable::Fd,
|
||||
dirflags: wasi_unstable::LookupFlags,
|
||||
path: &str,
|
||||
st_atim: wasi_unstable::Timestamp,
|
||||
st_mtim: wasi_unstable::Timestamp,
|
||||
fst_flags: wasi_unstable::FstFlags,
|
||||
) -> Result<(), wasi_unstable::Error> {
|
||||
wasi_unstable::path_filestat_set_times(
|
||||
fd,
|
||||
dirflags,
|
||||
path.as_bytes(),
|
||||
st_atim,
|
||||
st_mtim,
|
||||
fst_flags,
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_fd_readdir(
|
||||
fd: wasi_unstable::Fd,
|
||||
buf: &mut [u8],
|
||||
buf_len: usize,
|
||||
cookie: wasi_unstable::DirCookie,
|
||||
buf_used: &mut usize,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_fd_readdir(
|
||||
fd,
|
||||
buf.as_mut_ptr() as *mut libc::c_void,
|
||||
buf_len,
|
||||
cookie,
|
||||
buf_used,
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn wasi_fd_advise(
|
||||
fd: wasi_unstable::Fd,
|
||||
offset: wasi_unstable::FileSize,
|
||||
len: wasi_unstable::FileSize,
|
||||
advice: wasi_unstable::Advice,
|
||||
) -> wasi_unstable::Errno {
|
||||
wasi_unstable::raw::__wasi_fd_advise(fd, offset, len, advice)
|
||||
}
|
||||
Reference in New Issue
Block a user