Skip to content

Commit 624af51

Browse files
committed
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``
2 parents c7b86fc + 04a69e4 commit 624af51

File tree

2 files changed

+71
-5
lines changed

2 files changed

+71
-5
lines changed

src/tools/miri/CONTRIBUTING.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,22 @@ For example, you can (cross-)run the driver on a particular file by doing
6464
./miri run tests/pass/hello.rs --target i686-unknown-linux-gnu
6565
```
6666

67-
and you can (cross-)run the entire test suite using:
67+
Tests in ``pass-dep`` need to be run using ``./miri run --dep <filename>``.
68+
For example:
69+
```sh
70+
./miri run --dep tests/pass-dep/shims/libc-fs.rs
71+
```
72+
73+
You can (cross-)run the entire test suite using:
6874

6975
```
7076
./miri test
7177
MIRI_TEST_TARGET=i686-unknown-linux-gnu ./miri test
7278
```
7379

74-
If your target doesn't support libstd that should usually just work. However, if you are using a
75-
custom target file, you might have to set `MIRI_NO_STD=1`.
76-
7780
`./miri test FILTER` only runs those tests that contain `FILTER` in their filename (including the
7881
base directory, e.g. `./miri test fail` will run all compile-fail tests). These filters are passed
79-
to `cargo test`, so for multiple filers you need to use `./miri test -- FILTER1 FILTER2`.
82+
to `cargo test`, so for multiple filters you need to use `./miri test -- FILTER1 FILTER2`.
8083

8184
#### Fine grained logging
8285

src/tools/miri/tests/pass-dep/shims/libc-fs.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ mod utils;
1616
fn main() {
1717
test_dup_stdout_stderr();
1818
test_canonicalize_too_long();
19+
test_rename();
20+
test_ftruncate::<libc::off_t>(libc::ftruncate);
21+
#[cfg(target_os = "linux")]
22+
test_ftruncate::<libc::off64_t>(libc::ftruncate64);
1923
test_readlink();
2024
test_file_open_unix_allow_two_args();
2125
test_file_open_unix_needs_three_args();
@@ -133,6 +137,65 @@ fn test_readlink() {
133137
assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
134138
}
135139

140+
fn test_rename() {
141+
let path1 = prepare("miri_test_libc_fs_source.txt");
142+
let path2 = prepare("miri_test_libc_fs_rename_destination.txt");
143+
144+
let file = File::create(&path1).unwrap();
145+
drop(file);
146+
147+
let c_path1 = CString::new(path1.as_os_str().as_bytes()).expect("CString::new failed");
148+
let c_path2 = CString::new(path2.as_os_str().as_bytes()).expect("CString::new failed");
149+
150+
// Renaming should succeed
151+
unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) };
152+
// Check that old file path isn't present
153+
assert_eq!(ErrorKind::NotFound, path1.metadata().unwrap_err().kind());
154+
// Check that the file has moved successfully
155+
assert!(path2.metadata().unwrap().is_file());
156+
157+
// Renaming a nonexistent file should fail
158+
let res = unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) };
159+
assert_eq!(res, -1);
160+
assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound);
161+
162+
remove_file(&path2).unwrap();
163+
}
164+
165+
fn test_ftruncate<T: From<i32>>(
166+
ftruncate: unsafe extern "C" fn(fd: libc::c_int, length: T) -> libc::c_int,
167+
) {
168+
// libc::off_t is i32 in target i686-unknown-linux-gnu
169+
// https://docs.rs/libc/latest/i686-unknown-linux-gnu/libc/type.off_t.html
170+
171+
let bytes = b"hello";
172+
let path = prepare("miri_test_libc_fs_ftruncate.txt");
173+
let mut file = File::create(&path).unwrap();
174+
file.write(bytes).unwrap();
175+
file.sync_all().unwrap();
176+
assert_eq!(file.metadata().unwrap().len(), 5);
177+
178+
let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed");
179+
let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR) };
180+
181+
// Truncate to a bigger size
182+
let mut res = unsafe { ftruncate(fd, T::from(10)) };
183+
assert_eq!(res, 0);
184+
assert_eq!(file.metadata().unwrap().len(), 10);
185+
186+
// Write after truncate
187+
file.write(b"dup").unwrap();
188+
file.sync_all().unwrap();
189+
assert_eq!(file.metadata().unwrap().len(), 10);
190+
191+
// Truncate to smaller size
192+
res = unsafe { ftruncate(fd, T::from(2)) };
193+
assert_eq!(res, 0);
194+
assert_eq!(file.metadata().unwrap().len(), 2);
195+
196+
remove_file(&path).unwrap();
197+
}
198+
136199
#[cfg(target_os = "linux")]
137200
fn test_o_tmpfile_flag() {
138201
use std::fs::{create_dir, OpenOptions};

0 commit comments

Comments
 (0)