Reputation: 1540
I want to remove a db file if it exists when running test cases. So I tried below code but it is failing. Can you give me possible reasons to this error?
let db_path = Path::new("./tmp/data/data.mdb");
if db_path.is_file() {
dbg!(db_path.exists()); // db_path.exists() = true
dbg!(db_path.is_file()); // db_path.is_file() = true
dbg!(std::fs::metadata(db_path));
// Ok(
// Metadata {
// file_type: FileType(
// FileType {
// mode: 33152,
// },
// ),
// is_dir: false,
// is_file: true,
// permissions: Permissions(
// FilePermissions {
// mode: 33152,
// },
// ),
// modified: Ok(
// SystemTime {
// tv_sec: 1647472466,
// tv_nsec: 574985772,
// },
// ),
// accessed: Ok(
// SystemTime {
// tv_sec: 1647472466,
// tv_nsec: 274984150,
// },
// ),
// created: Ok(
// SystemTime {
// tv_sec: 1647472466,
// tv_nsec: 274984150,
// },
// ),
// ..
// },
std::fs::remove_file(db_path).unwrap(); // thread 'app::standalone_tests::test_db_created' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }'
}
Upvotes: 2
Views: 1488
Reputation: 70297
Since you mention test cases, Rust runs its tests in parallel by default. So one thread is probably deleting the file while another thread is in between its is_file
and remove_file
lines, leading to a race condition. The code sequence of "check whether file exists, then delete it" should be considered a critical code path and should be locked behind a mutex or some other kind of thread-safety mechanism.
Alternatively, you can pass command line flags to run tests in sequence and only use one thread, but this is probably not a good long-term solution.
Upvotes: 5