Auto merge of #3398 - tiif:add_libc_fs_test, r=RalfJung

Add libc direct test for shims and update CONTRIBUTING.md

Add more ``libc`` direct test for shims as mentioned in #3179.

Changes:
- Added ``libc`` direct tests for ``rename`` and ``ftruncate64``
- Added the command for running ``pass-dep`` test in ``CONTRIBUTING.md``
This commit is contained in:
bors 2024-03-24 14:16:48 +00:00
commit 624af51813
2 changed files with 71 additions and 5 deletions

View File

@ -64,19 +64,22 @@ For example, you can (cross-)run the driver on a particular file by doing
./miri run tests/pass/hello.rs --target i686-unknown-linux-gnu
```
and you can (cross-)run the entire test suite using:
Tests in ``pass-dep`` need to be run using ``./miri run --dep <filename>``.
For example:
```sh
./miri run --dep tests/pass-dep/shims/libc-fs.rs
```
You can (cross-)run the entire test suite using:
```
./miri test
MIRI_TEST_TARGET=i686-unknown-linux-gnu ./miri test
```
If your target doesn't support libstd that should usually just work. However, if you are using a
custom target file, you might have to set `MIRI_NO_STD=1`.
`./miri test FILTER` only runs those tests that contain `FILTER` in their filename (including the
base directory, e.g. `./miri test fail` will run all compile-fail tests). These filters are passed
to `cargo test`, so for multiple filers you need to use `./miri test -- FILTER1 FILTER2`.
to `cargo test`, so for multiple filters you need to use `./miri test -- FILTER1 FILTER2`.
#### Fine grained logging

View File

@ -16,6 +16,10 @@ mod utils;
fn main() {
test_dup_stdout_stderr();
test_canonicalize_too_long();
test_rename();
test_ftruncate::<libc::off_t>(libc::ftruncate);
#[cfg(target_os = "linux")]
test_ftruncate::<libc::off64_t>(libc::ftruncate64);
test_readlink();
test_file_open_unix_allow_two_args();
test_file_open_unix_needs_three_args();
@ -133,6 +137,65 @@ fn test_readlink() {
assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
}
fn test_rename() {
let path1 = prepare("miri_test_libc_fs_source.txt");
let path2 = prepare("miri_test_libc_fs_rename_destination.txt");
let file = File::create(&path1).unwrap();
drop(file);
let c_path1 = CString::new(path1.as_os_str().as_bytes()).expect("CString::new failed");
let c_path2 = CString::new(path2.as_os_str().as_bytes()).expect("CString::new failed");
// Renaming should succeed
unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) };
// Check that old file path isn't present
assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
// Check that the file has moved successfully
assert!(path2.metadata().unwrap().is_file());
// Renaming a nonexistent file should fail
let res = unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) };
assert_eq!(res, -1);
assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
remove_file(&path2).unwrap();
}
fn test_ftruncate<T: From<i32>>(
ftruncate: unsafe extern "C" fn(fd: libc::c_int, length: T) -> libc::c_int,
) {
// libc::off_t is i32 in target i686-unknown-linux-gnu
// https://docs.rs/libc/latest/i686-unknown-linux-gnu/libc/type.off_t.html
let bytes = b"hello";
let path = prepare("miri_test_libc_fs_ftruncate.txt");
let mut file = File::create(&path).unwrap();
file.write(bytes).unwrap();
file.sync_all().unwrap();
assert_eq!(file.metadata().unwrap().len(), 5);
let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed");
let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR) };
// Truncate to a bigger size
let mut res = unsafe { ftruncate(fd, T::from(10)) };
assert_eq!(res, 0);
assert_eq!(file.metadata().unwrap().len(), 10);
// Write after truncate
file.write(b"dup").unwrap();
file.sync_all().unwrap();
assert_eq!(file.metadata().unwrap().len(), 10);
// Truncate to smaller size
res = unsafe { ftruncate(fd, T::from(2)) };
assert_eq!(res, 0);
assert_eq!(file.metadata().unwrap().len(), 2);
remove_file(&path).unwrap();
}
#[cfg(target_os = "linux")]
fn test_o_tmpfile_flag() {
use std::fs::{create_dir, OpenOptions};