summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serial_test/src/file_lock.rs
blob: 20cd99eddbf0bcf4f471eb7169b1f057b2d30220 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use fslock::LockFile;
use std::{env, fs, path::Path};

struct Lock {
    lockfile: LockFile,
}

impl Lock {
    fn unlock(self: &mut Lock) {
        self.lockfile.unlock().unwrap();
        println!("Unlock");
    }
}

fn do_lock(path: &str) -> Lock {
    if !Path::new(path).exists() {
        fs::write(path, "").unwrap_or_else(|_| panic!("Lock file path was {:?}", path))
    }
    let mut lockfile = LockFile::open(path).unwrap();
    println!("Waiting on {:?}", path);
    lockfile.lock().unwrap();
    println!("Locked for {:?}", path);
    Lock { lockfile }
}

fn path_for_name(name: &str) -> String {
    let mut pathbuf = env::temp_dir();
    pathbuf.push(format!("serial-test-{}", name));
    pathbuf.into_os_string().into_string().unwrap()
}

fn make_lock_for_name_and_path(name: &str, path: Option<&str>) -> Lock {
    if let Some(opt_path) = path {
        do_lock(opt_path)
    } else {
        let default_path = path_for_name(name);
        do_lock(&default_path)
    }
}

#[doc(hidden)]
pub fn fs_serial_core(name: &str, path: Option<&str>, function: fn()) {
    let mut lock = make_lock_for_name_and_path(name, path);
    function();
    lock.unlock();
}

#[doc(hidden)]
pub fn fs_serial_core_with_return<E>(
    name: &str,
    path: Option<&str>,
    function: fn() -> Result<(), E>,
) -> Result<(), E> {
    let mut lock = make_lock_for_name_and_path(name, path);
    let ret = function();
    lock.unlock();
    ret
}

#[doc(hidden)]
pub async fn fs_async_serial_core_with_return<E>(
    name: &str,
    path: Option<&str>,
    fut: impl std::future::Future<Output = Result<(), E>>,
) -> Result<(), E> {
    let mut lock = make_lock_for_name_and_path(name, path);
    let ret = fut.await;
    lock.unlock();
    ret
}

#[doc(hidden)]
pub async fn fs_async_serial_core(
    name: &str,
    path: Option<&str>,
    fut: impl std::future::Future<Output = ()>,
) {
    let mut lock = make_lock_for_name_and_path(name, path);
    fut.await;
    lock.unlock();
}

#[test]
fn test_serial() {
    fs_serial_core("test", None, || {});
}