1
use std::error::Error;
2
use std::path::Path;
3

            
4
pub use duct::cmd;
5

            
6
#[allow(clippy::ptr_arg)]
7
fn add_target_flag(_arguments: &mut Vec<String>) {
8
    #[cfg(target_os = "linux")]
9
    {
10
        _arguments.push("--target".to_string());
11
        _arguments.push("x86_64-unknown-linux-gnu".to_string());
12
    }
13

            
14
    #[cfg(target_os = "macos")]
15
    {
16
        _arguments.push("--target".to_string());
17
        _arguments.push("x86_64-apple-darwin".to_string());
18
    }
19
}
20

            
21
///
22
/// Run the tests with the address sanitizer enabled to detect memory issues in unsafe code.
23
///
24
/// This only works under Linux and MacOS currently and requires the nightly toolchain.
25
///
26
pub fn address_sanitizer(mut arguments: Vec<String>) -> Result<(), Box<dyn Error>> {
27
    arguments.extend(vec!["-Zbuild-std".to_string()]);
28

            
29
    add_target_flag(&mut arguments);
30

            
31
    let leak_sanitizer_suppress = Path::new(env!("CARGO_MANIFEST_DIR")).join("data/leak_sanitizer.suppress");
32

            
33
    cmd("cargo", arguments)
34
        .env(
35
            "LSAN_OPTIONS",
36
            format!("suppressions={}", leak_sanitizer_suppress.to_string_lossy()),
37
        )
38
        .env("RUSTFLAGS", "-Zsanitizer=address,leak")
39
        .env("RUSTDOCFLAGS", "-Zsanitizer=address,leak")
40
        .env("CFLAGS", "-fsanitize=address,leak")
41
        .env("CXXFLAGS", "-fsanitize=address,leak")
42
        .run()?;
43
    println!("ok.");
44

            
45
    Ok(())
46
}
47

            
48
///
49
/// Run the tests with the thread sanitizer enabled to detect data race conditions.
50
///
51
/// This only works under Linux and MacOS currently and requires the nightly toolchain.
52
///
53
pub fn thread_sanitizer(mut arguments: Vec<String>) -> Result<(), Box<dyn Error>> {
54
    arguments.extend(vec!["-Zbuild-std".to_string()]);
55

            
56
    add_target_flag(&mut arguments);
57

            
58
    let thread_sanitizer_suppress = Path::new(env!("CARGO_MANIFEST_DIR")).join("data/thread_sanitizer.suppress");
59

            
60
    cmd("cargo", arguments)
61
        .env(
62
            "TSAN_OPTIONS",
63
            format!("suppressions={}", thread_sanitizer_suppress.to_string_lossy()),
64
        )
65
        .env("RUSTFLAGS", "-Zsanitizer=thread")
66
        .env("RUSTDOCFLAGS", "-Zsanitizer=thread")
67
        .env("CFLAGS", "-fsanitize=thread")
68
        .env("CXXFLAGS", "-fsanitize=thread")
69
        .run()?;
70
    println!("ok.");
71

            
72
    Ok(())
73
}