即使 Path.is_file true 也没有这样的文件或目录

Ram*_*chi 2 rust

我想删除运行测试用例时存在的数据库文件。所以我尝试了下面的代码,但失败了。你能告诉我这个错误的可能原因吗?

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" }'
}

Run Code Online (Sandbox Code Playgroud)

Sil*_*olo 5

既然您提到了测试用例,Rust 默认情况下会并行运行其测试。因此,一个线程可能正在删除该文件,而另一个线程位于该文件的is_fileremove_file行之间,从而导致竞争条件。“检查文件是否存在,然后删除它”的代码序列应该被视为关键代码路径,并且应该被锁定在互斥体或某种其他类型的线程安全机制后面。

或者,您可以传递命令行标志来按顺序运行测试并仅使用一个线程,但这可能不是一个好的长期解决方案。