• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

xd009642 / tarpaulin / #717

16 Jan 2026 10:32PM UTC coverage: 85.498% (+0.4%) from 85.116%
#717

push

xd009642
Release 0.35.1

91 of 93 new or added lines in 7 files covered. (97.85%)

2 existing lines in 1 file now uncovered.

4793 of 5606 relevant lines covered (85.5%)

249079.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.33
/src/path_utils.rs
1
use crate::config::Config;
2
use std::env::var;
3
use std::ffi::OsStr;
4
use std::path::{Component, Path, PathBuf};
5
use walkdir::{DirEntry, WalkDir};
6

7
/// On windows removes the `\\?\\` prefix to UNC paths. For other operation systems just turns the
8
/// `Path` into a `PathBuf`
9
pub fn fix_unc_path(res: &Path) -> PathBuf {
726,681✔
10
    if cfg!(windows) {
11
        let res_str = res.display().to_string();
×
12
        if res_str.starts_with(r#"\\?"#) {
×
13
            PathBuf::from(res_str.replace(r#"\\?\"#, ""))
×
14
        } else {
15
            res.to_path_buf()
×
16
        }
17
    } else {
18
        res.to_path_buf()
1,453,362✔
19
    }
20
}
21

22
/// Returns true if the file is a rust source file
23
pub fn is_profraw_file(entry: &DirEntry) -> bool {
46✔
24
    let p = entry.path();
138✔
25
    p.is_file() && p.extension() == Some(OsStr::new("profraw"))
144✔
26
}
27

28
/// Returns true if the file is a rust source file
29
pub fn is_source_file(entry: &DirEntry) -> bool {
2,386✔
30
    let p = entry.path();
7,158✔
31
    p.is_file() && p.extension() == Some(OsStr::new("rs"))
7,584✔
32
}
33

34
/// Returns true if the folder is a target folder
35
fn is_target_folder(entry: &Path, target: &Path) -> bool {
212,091✔
36
    entry.starts_with(target)
636,273✔
37
}
38

39
/// Returns true if the file or folder is hidden
40
fn is_hidden(entry: &Path, root: &Path) -> bool {
211,478✔
41
    let check_hidden = |e: &Path| e.iter().any(|x| x.to_string_lossy().starts_with('.'));
3,528,930✔
42
    match entry.strip_prefix(root) {
422,956✔
43
        Ok(e) => check_hidden(e),
419,210✔
44
        Err(_) => check_hidden(entry),
1,873✔
45
    }
46
}
47

48
/// If `CARGO_HOME` is set filters out all folders within `CARGO_HOME`
49
fn is_cargo_home(entry: &Path, root: &Path) -> bool {
207,180✔
50
    match var("CARGO_HOME") {
207,180✔
51
        Ok(s) => {
207,180✔
52
            let path = Path::new(&s);
621,540✔
53
            if path.is_absolute() && entry.starts_with(path) {
1,035,900✔
54
                true
168,800✔
55
            } else {
56
                let home = root.join(path);
153,520✔
57
                entry.starts_with(home)
115,140✔
58
            }
59
        }
60
        _ => false,
×
61
    }
62
}
63

64
fn is_part_of_project(e: &Path, root: &Path) -> bool {
38,380✔
65
    if e.is_absolute() && root.is_absolute() {
153,520✔
66
        e.starts_with(root)
115,140✔
67
    } else if root.is_absolute() {
×
68
        root.join(e).is_file()
×
69
    } else {
70
        // they're both relative and this isn't hit a lot - only really with FFI code
71
        true
×
72
    }
73
}
74

75
pub fn is_coverable_file_path(
212,091✔
76
    path: impl AsRef<Path>,
77
    root: impl AsRef<Path>,
78
    target: impl AsRef<Path>,
79
) -> bool {
80
    let e = path.as_ref();
636,273✔
81
    let ignorable_paths = !(is_target_folder(e, target.as_ref())
848,364✔
82
        || is_hidden(e, root.as_ref())
634,422✔
83
        || is_cargo_home(e, root.as_ref()));
621,540✔
84

85
    ignorable_paths && is_part_of_project(e, root.as_ref())
327,231✔
86
}
87

88
pub fn get_source_walker(config: &Config) -> impl Iterator<Item = DirEntry> + '_ {
236✔
89
    let root = config.root();
708✔
90
    let target = config.target_dir();
708✔
91

92
    let walker = WalkDir::new(&root).into_iter();
944✔
93
    walker
236✔
94
        .filter_entry(move |e| {
3,072✔
95
            if !config.include_tests() && is_tests_folder_package(&root, e.path()) {
6,382✔
NEW
96
                return false; //Removes entire tests folder at once
×
97
            }
98
            is_coverable_file_path(e.path(), &root, &target)
14,180✔
99
        })
100
        .filter_map(Result::ok)
236✔
101
        .filter(move |e| !(config.exclude_path(e.path())))
7,394✔
102
        .filter(move |e| config.include_path(e.path()))
7,394✔
103
        .filter(is_source_file)
236✔
104
}
105

106
fn is_tests_folder_package(root: &Path, path: &Path) -> bool {
1,187✔
107
    let mut is_pkg_tests: bool = false;
3,561✔
108
    let tests_folder_name = "tests";
2,374✔
109

110
    // Ensure `path` is under `root`
111
    let relative = match path.strip_prefix(root) {
3,561✔
112
        Ok(p) => p,
2,374✔
NEW
113
        Err(_) => return false,
×
114
    };
115

116
    // check if the path contains a `tests` folder (platform independent)
117
    let has_tests_component = relative
2,374✔
118
        .components()
119
        .any(|c| matches!(c, Component::Normal(name) if name == tests_folder_name));
5,397✔
120

121
    if has_tests_component {
1,187✔
122
        // Locate the actual `tests` directory in the ancestor chain. stopping at root
123
        if let Some(tests_dir) = path.ancestors().take_while(|anc| *anc != root).find(|anc| {
33✔
124
            anc.file_name()
12✔
125
                .map(|n| n == tests_folder_name)
18✔
126
                .unwrap_or(false)
6✔
127
        }) {
128
            if let Some(pkg_dir) = tests_dir.parent() {
6✔
129
                is_pkg_tests = pkg_dir.join("Cargo.toml").is_file() && pkg_dir.join("src").is_dir();
5✔
130
            }
131
        }
132
    }
133

134
    is_pkg_tests
1,187✔
135
}
136

137
pub fn get_profile_walker(config: &Config) -> impl Iterator<Item = DirEntry> {
28✔
138
    let walker = WalkDir::new(config.profraw_dir()).into_iter();
140✔
139
    walker.filter_map(Result::ok).filter(is_profraw_file)
84✔
140
}
141

142
#[cfg(test)]
143
mod tests {
144
    use super::*;
145
    use std::fs::{self, File};
146
    use std::io::Write;
147
    use std::path::PathBuf;
148
    use std::time::{SystemTime, UNIX_EPOCH};
149

150
    fn make_temp_dir(prefix: &str) -> PathBuf {
5✔
151
        let n = SystemTime::now()
15✔
152
            .duration_since(UNIX_EPOCH)
5✔
153
            .unwrap()
154
            .as_nanos();
155
        let dir = std::env::temp_dir().join(format!("{}_{}", prefix, n));
15✔
156
        let _ = fs::create_dir_all(&dir);
5✔
157
        dir
5✔
158
    }
159

160
    #[test]
161
    fn is_tests_folder_package_no_tests_component_returns_false() {
1✔
162
        let base = make_temp_dir("no_tests_component");
3✔
163
        let p = base.join("some").join("path").join("lib.rs");
2✔
164
        assert!(!is_tests_folder_package(&base, &p));
3✔
165
        let _ = fs::remove_dir_all(base);
1✔
166
    }
167

168
    #[test]
169
    fn is_tests_folder_package_testsx_component_returns_false() {
1✔
170
        let base = make_temp_dir("testsx_component");
3✔
171
        let p = base.join("some").join("testsX").join("file.rs");
2✔
172
        let _ = fs::create_dir_all(p.parent().unwrap());
2✔
173
        assert!(!is_tests_folder_package(&base, &p));
3✔
174
        let _ = fs::remove_dir_all(base);
1✔
175
    }
176

177
    #[test]
178
    fn is_tests_folder_package_tests_without_src_returns_false() {
1✔
179
        let base = make_temp_dir("tests_no_src");
3✔
180
        let pkg = base.join("pkg");
2✔
181
        let tests = pkg.join("tests");
2✔
182
        let _ = fs::create_dir_all(&tests);
1✔
183
        let test_file = tests.join("a.rs");
2✔
184
        let _ = File::create(&test_file);
1✔
185
        let cargo = pkg.join("Cargo.toml");
2✔
186
        let mut f = File::create(&cargo).expect("create Cargo.toml");
5✔
187
        let _ = f.write_all(b"[package]\nname = \"pkg3\"\nversion = \"0.0.0\"");
2✔
188
        // Ensure no src dir and no Cargo.toml
189
        assert!(!pkg.join("src").exists());
2✔
190
        assert!(pkg.join("Cargo.toml").exists());
2✔
191
        assert!(!is_tests_folder_package(&base, &test_file));
3✔
192
        let _ = fs::remove_dir_all(base);
1✔
193
    }
194

195
    #[test]
196
    fn is_tests_folder_package_tests_without_cargo_returns_false() {
1✔
197
        let base = make_temp_dir("tests_no_cargo");
3✔
198
        let pkg = base.join("pkg2");
2✔
199
        let tests = pkg.join("tests");
2✔
200
        let src = pkg.join("src");
2✔
201
        let _ = fs::create_dir_all(&src);
1✔
202
        let _ = fs::create_dir_all(&tests);
1✔
203
        let test_file = tests.join("b.rs");
2✔
204
        let _ = File::create(&test_file);
1✔
205
        // src exists but Cargo.toml does not
206
        assert!(src.is_dir());
2✔
207
        assert!(!pkg.join("Cargo.toml").exists());
2✔
208
        assert!(!is_tests_folder_package(&base, &test_file));
3✔
209
        let _ = fs::remove_dir_all(base);
1✔
210
    }
211

212
    #[test]
213
    fn is_tests_folder_package_tests_with_src_and_cargo_returns_true() {
1✔
214
        let base = make_temp_dir("tests_with_both");
3✔
215
        let pkg = base.join("pkg3");
2✔
216
        let tests = pkg.join("tests");
2✔
217
        let src = pkg.join("src");
2✔
218
        let _ = fs::create_dir_all(&src);
1✔
219
        let _ = fs::create_dir_all(&tests);
1✔
220
        let cargo = pkg.join("Cargo.toml");
2✔
221
        let mut f = File::create(&cargo).expect("create Cargo.toml");
5✔
222
        let _ = f.write_all(b"[package]\nname = \"pkg3\"\nversion = \"0.0.0\"");
2✔
223
        let test_file = tests.join("c.rs");
2✔
224
        let _ = File::create(&test_file);
1✔
225
        assert!(is_tests_folder_package(&base, &test_file));
4✔
226
        let _ = fs::remove_dir_all(base);
1✔
227
    }
228

229
    #[test]
230
    #[cfg(unix)]
231
    fn system_headers_not_coverable() {
1✔
232
        assert!(!is_coverable_file_path(
2✔
233
            "/usr/include/c++/9/iostream",
1✔
234
            "/home/ferris/rust/project",
1✔
235
            "/home/ferris/rust/project/target"
1✔
236
        ));
237
    }
238

239
    #[test]
240
    #[cfg(windows)]
241
    fn system_headers_not_coverable() {
242
        assert!(!is_coverable_file_path(
243
            "C:/Program Files/Visual Studio/include/c++/9/iostream",
244
            "C:/User/ferris/rust/project",
245
            "C:/User/ferris/rust/project/target"
246
        ));
247
    }
248

249
    #[test]
250
    fn basic_coverable_checks() {
1✔
251
        assert!(is_coverable_file_path(
2✔
252
            "/foo/src/lib.rs",
253
            "/foo",
254
            "/foo/target"
255
        ));
256
        assert!(!is_coverable_file_path(
2✔
257
            "/foo/target/lib.rs",
1✔
258
            "/foo",
1✔
259
            "/foo/target"
1✔
260
        ));
261
    }
262

263
    #[test]
264
    fn is_hidden_check() {
1✔
265
        // From issue#682
266
        let hidden_root = Path::new("/home/.jenkins/project/");
3✔
267
        let visible_root = Path::new("/home/jenkins/project/");
3✔
268

269
        let hidden_file = Path::new(".cargo/src/hello.rs");
3✔
270
        let visible_file = Path::new("src/hello.rs");
3✔
271

272
        assert!(is_hidden(&hidden_root.join(hidden_file), hidden_root));
5✔
273
        assert!(is_hidden(&visible_root.join(hidden_file), visible_root));
5✔
274

275
        assert!(!is_hidden(&hidden_root.join(visible_file), hidden_root));
4✔
276
        assert!(!is_hidden(&visible_root.join(visible_file), visible_root));
4✔
277
    }
278
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc