-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Port more tests from Wasmtime's testsuite
Following up on ac32f57, port several more tests from Wasmtime's testsuite to wasi-testsuite. It is likely that at least some of these tests are testing behavior which differs between Wasm engine implementations. The intent here is not to instate these as authoritative, but to help surface these differences so that we can discuss whether it's best to change the test, or add documentation to the spec. Other Wasm engines are welcome to submit their tests to wasi-testsuite as well.
- Loading branch information
1 parent
ad174d5
commit 385cb01
Showing
59 changed files
with
2,756 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
use std::{env, process}; | ||
use wasi_tests::{create_tmp_dir, open_scratch_directory, TESTCONFIG}; | ||
|
||
unsafe fn test_file_allocate(dir_fd: wasi::Fd) { | ||
// Create a file in the scratch directory. | ||
let file_fd = wasi::path_open( | ||
dir_fd, | ||
0, | ||
"file", | ||
wasi::OFLAGS_CREAT, | ||
wasi::RIGHTS_FD_READ | ||
| wasi::RIGHTS_FD_WRITE | ||
| wasi::RIGHTS_FD_ALLOCATE | ||
| wasi::RIGHTS_FD_FILESTAT_GET, | ||
0, | ||
0, | ||
) | ||
.expect("opening a file"); | ||
assert!( | ||
file_fd > libc::STDERR_FILENO as wasi::Fd, | ||
"file descriptor range check", | ||
); | ||
|
||
// Check file size | ||
let mut stat = wasi::fd_filestat_get(file_fd).expect("reading file stats"); | ||
assert_eq!(stat.size, 0, "file size should be 0"); | ||
|
||
if TESTCONFIG.support_fd_allocate() { | ||
// Allocate some size | ||
wasi::fd_allocate(file_fd, 0, 100).expect("allocating size"); | ||
stat = wasi::fd_filestat_get(file_fd).expect("reading file stats"); | ||
assert_eq!(stat.size, 100, "file size should be 100"); | ||
|
||
// Allocate should not modify if less than current size | ||
wasi::fd_allocate(file_fd, 10, 10).expect("allocating size less than current size"); | ||
stat = wasi::fd_filestat_get(file_fd).expect("reading file stats"); | ||
assert_eq!(stat.size, 100, "file size should remain unchanged at 100"); | ||
|
||
// Allocate should modify if offset+len > current_len | ||
wasi::fd_allocate(file_fd, 90, 20).expect("allocating size larger than current size"); | ||
stat = wasi::fd_filestat_get(file_fd).expect("reading file stats"); | ||
assert_eq!(stat.size, 110, "file size should increase from 100 to 110"); | ||
} | ||
wasi::fd_close(file_fd).expect("closing a file"); | ||
wasi::path_unlink_file(dir_fd, "file").expect("removing a 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 base_dir_fd = match open_scratch_directory(&arg) { | ||
Ok(dir_fd) => dir_fd, | ||
Err(err) => { | ||
eprintln!("{}", err); | ||
process::exit(1) | ||
} | ||
}; | ||
|
||
const DIR_NAME: &str = "file_allocate_dir.cleanup"; | ||
let dir_fd; | ||
unsafe { | ||
dir_fd = create_tmp_dir(base_dir_fd, DIR_NAME); | ||
} | ||
|
||
// Run the tests. | ||
unsafe { test_file_allocate(dir_fd) } | ||
|
||
unsafe { wasi::path_remove_directory(base_dir_fd, DIR_NAME).expect("failed to remove dir") } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
use std::convert::TryInto; | ||
use std::{env, process}; | ||
use wasi_tests::{create_tmp_dir, open_scratch_directory}; | ||
|
||
unsafe fn test_file_pread_pwrite(dir_fd: wasi::Fd) { | ||
// Create a file in the scratch directory. | ||
let file_fd = wasi::path_open( | ||
dir_fd, | ||
0, | ||
"file", | ||
wasi::OFLAGS_CREAT, | ||
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_SEEK | wasi::RIGHTS_FD_WRITE, | ||
0, | ||
0, | ||
) | ||
.expect("opening a file"); | ||
assert!( | ||
file_fd > libc::STDERR_FILENO as wasi::Fd, | ||
"file descriptor range check", | ||
); | ||
|
||
let contents = &[0u8, 1, 2, 3]; | ||
let ciovec = wasi::Ciovec { | ||
buf: contents.as_ptr() as *const _, | ||
buf_len: contents.len(), | ||
}; | ||
let mut nwritten = | ||
wasi::fd_pwrite(file_fd, &mut [ciovec], 0).expect("writing bytes at offset 0"); | ||
assert_eq!(nwritten, 4, "nwritten bytes check"); | ||
|
||
let contents = &mut [0u8; 4]; | ||
let iovec = wasi::Iovec { | ||
buf: contents.as_mut_ptr() as *mut _, | ||
buf_len: contents.len(), | ||
}; | ||
let mut nread = wasi::fd_pread(file_fd, &[iovec], 0).expect("reading bytes at offset 0"); | ||
assert_eq!(nread, 4, "nread bytes check"); | ||
assert_eq!(contents, &[0u8, 1, 2, 3], "written bytes equal read bytes"); | ||
|
||
// Write all the data through multiple iovecs. | ||
// | ||
// Note that this needs to be done with a loop, because some | ||
// platforms do not support writing multiple iovecs at once. | ||
// See https://github.com/rust-lang/rust/issues/74825. | ||
let contents = &[0u8, 1, 2, 3]; | ||
let mut offset = 0usize; | ||
loop { | ||
let mut ciovecs: Vec<wasi::Ciovec> = Vec::new(); | ||
let mut remaining = contents.len() - offset; | ||
if remaining > 2 { | ||
ciovecs.push(wasi::Ciovec { | ||
buf: contents[offset..].as_ptr() as *const _, | ||
buf_len: 2, | ||
}); | ||
remaining -= 2; | ||
} | ||
ciovecs.push(wasi::Ciovec { | ||
buf: contents[contents.len() - remaining..].as_ptr() as *const _, | ||
buf_len: remaining, | ||
}); | ||
|
||
nwritten = wasi::fd_pwrite(file_fd, ciovecs.as_slice(), offset.try_into().unwrap()) | ||
.expect("writing bytes at offset 0"); | ||
|
||
offset += nwritten; | ||
if offset == contents.len() { | ||
break; | ||
} | ||
} | ||
assert_eq!(offset, 4, "nread bytes check"); | ||
|
||
// Read all the data through multiple iovecs. | ||
// | ||
// Note that this needs to be done with a loop, because some | ||
// platforms do not support reading multiple iovecs at once. | ||
// See https://github.com/rust-lang/rust/issues/74825. | ||
let contents = &mut [0u8; 4]; | ||
let mut offset = 0usize; | ||
loop { | ||
let buffer = &mut [0u8; 4]; | ||
let iovecs = &[ | ||
wasi::Iovec { | ||
buf: buffer.as_mut_ptr() as *mut _, | ||
buf_len: 2, | ||
}, | ||
wasi::Iovec { | ||
buf: buffer[2..].as_mut_ptr() as *mut _, | ||
buf_len: 2, | ||
}, | ||
]; | ||
nread = wasi::fd_pread(file_fd, iovecs, offset as _).expect("reading bytes at offset 0"); | ||
if nread == 0 { | ||
break; | ||
} | ||
contents[offset..offset + nread].copy_from_slice(&buffer[0..nread]); | ||
offset += nread; | ||
} | ||
assert_eq!(offset, 4, "nread bytes check"); | ||
assert_eq!(contents, &[0u8, 1, 2, 3], "file cursor was overwritten"); | ||
|
||
let contents = &mut [0u8; 4]; | ||
let iovec = wasi::Iovec { | ||
buf: contents.as_mut_ptr() as *mut _, | ||
buf_len: contents.len(), | ||
}; | ||
nread = wasi::fd_pread(file_fd, &[iovec], 2).expect("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::Ciovec { | ||
buf: contents.as_ptr() as *const _, | ||
buf_len: contents.len(), | ||
}; | ||
nwritten = wasi::fd_pwrite(file_fd, &mut [ciovec], 2).expect("writing bytes at offset 2"); | ||
assert_eq!(nwritten, 2, "nwritten bytes check"); | ||
|
||
let contents = &mut [0u8; 4]; | ||
let iovec = wasi::Iovec { | ||
buf: contents.as_mut_ptr() as *mut _, | ||
buf_len: contents.len(), | ||
}; | ||
nread = wasi::fd_pread(file_fd, &[iovec], 0).expect("reading bytes at offset 0"); | ||
assert_eq!(nread, 4, "nread bytes check"); | ||
assert_eq!(contents, &[0u8, 1, 1, 0], "file cursor was overwritten"); | ||
|
||
wasi::fd_close(file_fd).expect("closing a file"); | ||
wasi::path_unlink_file(dir_fd, "file").expect("removing a 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 base_dir_fd = match open_scratch_directory(&arg) { | ||
Ok(dir_fd) => dir_fd, | ||
Err(err) => { | ||
eprintln!("{}", err); | ||
process::exit(1) | ||
} | ||
}; | ||
|
||
const DIR_NAME: &str = "file_pread_pwrite_dir.cleanup"; | ||
let dir_fd; | ||
unsafe { | ||
dir_fd = create_tmp_dir(base_dir_fd, DIR_NAME); | ||
} | ||
|
||
// Run the tests. | ||
unsafe { test_file_pread_pwrite(dir_fd) } | ||
|
||
unsafe { wasi::path_remove_directory(base_dir_fd, DIR_NAME).expect("failed to remove dir") } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
use std::{env, process}; | ||
use wasi_tests::{assert_errno, create_tmp_dir, open_scratch_directory}; | ||
|
||
unsafe fn test_file_seek_tell(dir_fd: wasi::Fd) { | ||
// Create a file in the scratch directory. | ||
let file_fd = wasi::path_open( | ||
dir_fd, | ||
0, | ||
"file", | ||
wasi::OFLAGS_CREAT, | ||
wasi::RIGHTS_FD_READ | wasi::RIGHTS_FD_WRITE | wasi::RIGHTS_FD_SEEK | wasi::RIGHTS_FD_TELL, | ||
0, | ||
0, | ||
) | ||
.expect("opening a file"); | ||
assert!( | ||
file_fd > libc::STDERR_FILENO as wasi::Fd, | ||
"file descriptor range check", | ||
); | ||
|
||
// Check current offset | ||
let mut offset = wasi::fd_tell(file_fd).expect("getting initial file offset"); | ||
assert_eq!(offset, 0, "current offset should be 0"); | ||
|
||
// Write to file | ||
let data = &[0u8; 100]; | ||
let iov = wasi::Ciovec { | ||
buf: data.as_ptr() as *const _, | ||
buf_len: data.len(), | ||
}; | ||
let nwritten = wasi::fd_write(file_fd, &[iov]).expect("writing to a file"); | ||
assert_eq!(nwritten, 100, "should write 100 bytes to file"); | ||
|
||
// Check current offset | ||
offset = wasi::fd_tell(file_fd).expect("getting file offset after writing"); | ||
assert_eq!(offset, 100, "offset after writing should be 100"); | ||
|
||
// Seek to middle of the file | ||
let mut newoffset = | ||
wasi::fd_seek(file_fd, -50, wasi::WHENCE_CUR).expect("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 | ||
newoffset = | ||
wasi::fd_seek(file_fd, 0, wasi::WHENCE_SET).expect("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 | ||
wasi::fd_seek(file_fd, 1000, wasi::WHENCE_CUR).expect("seeking beyond the end of the file"); | ||
|
||
// Seek before byte 0 is an error though | ||
assert_errno!( | ||
wasi::fd_seek(file_fd, -2000, wasi::WHENCE_CUR) | ||
.expect_err("seeking before byte 0 should be an error"), | ||
wasi::ERRNO_INVAL | ||
); | ||
|
||
// Check that fd_read properly updates the file offset | ||
wasi::fd_seek(file_fd, 0, wasi::WHENCE_SET) | ||
.expect("seeking to the beginning of the file again"); | ||
|
||
let buffer = &mut [0u8; 100]; | ||
let iovec = wasi::Iovec { | ||
buf: buffer.as_mut_ptr(), | ||
buf_len: buffer.len(), | ||
}; | ||
let nread = wasi::fd_read(file_fd, &[iovec]).expect("reading file"); | ||
assert_eq!(nread, buffer.len(), "should read {} bytes", buffer.len()); | ||
|
||
offset = wasi::fd_tell(file_fd).expect("getting file offset after reading"); | ||
assert_eq!(offset, 100, "offset after reading should be 100"); | ||
|
||
wasi::fd_close(file_fd).expect("closing a file"); | ||
wasi::path_unlink_file(dir_fd, "file").expect("deleting a 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 base_dir_fd = match open_scratch_directory(&arg) { | ||
Ok(dir_fd) => dir_fd, | ||
Err(err) => { | ||
eprintln!("{}", err); | ||
process::exit(1) | ||
} | ||
}; | ||
|
||
const DIR_NAME: &str = "file_seek_tell_dir.cleanup"; | ||
let dir_fd; | ||
unsafe { | ||
dir_fd = create_tmp_dir(base_dir_fd, DIR_NAME); | ||
} | ||
|
||
// Run the tests. | ||
unsafe { test_file_seek_tell(dir_fd) } | ||
|
||
unsafe { wasi::path_remove_directory(base_dir_fd, DIR_NAME).expect("failed to remove dir") } | ||
} |
Oops, something went wrong.