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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
use crate::defs::*;

pub fn is_covered(result: &CovResult) -> bool {
    // For C/C++ source files, we can consider a file as being uncovered
    // when all its source lines are uncovered.
    let any_line_covered = result
        .lines
        .values()
        .any(|&execution_count| execution_count != 0);
    if !any_line_covered {
        return false;
    }
    // For JavaScript files, we can't do the same, as the top-level is always
    // executed, even if it just contains declarations. So, we need to check if
    // all its functions, except the top-level, are uncovered.
    let any_function_covered = result
        .functions
        .iter()
        .any(|(name, function)| function.executed && name != "top-level");
    result.functions.len() <= 1 || any_function_covered
}

#[cfg(test)]
mod tests {
    use super::*;
    use rustc_hash::FxHashMap;

    #[test]
    fn test_covered() {
        let mut functions: FunctionMap = FxHashMap::default();
        functions.insert(
            "f1".to_string(),
            Function {
                start: 1,
                executed: true,
            },
        );
        functions.insert(
            "f2".to_string(),
            Function {
                start: 2,
                executed: false,
            },
        );
        let result = CovResult {
            lines: [(1, 21), (2, 7), (7, 0)].iter().cloned().collect(),
            branches: [].iter().cloned().collect(),
            functions,
        };

        assert!(is_covered(&result));
    }

    #[test]
    fn test_covered_no_functions() {
        let result = CovResult {
            lines: [(1, 21), (2, 7), (7, 0)].iter().cloned().collect(),
            branches: [].iter().cloned().collect(),
            functions: FxHashMap::default(),
        };

        assert!(is_covered(&result));
    }

    #[test]
    fn test_uncovered_no_lines_executed() {
        let mut functions: FunctionMap = FxHashMap::default();
        functions.insert(
            "f1".to_string(),
            Function {
                start: 1,
                executed: true,
            },
        );
        functions.insert(
            "f2".to_string(),
            Function {
                start: 2,
                executed: false,
            },
        );
        let result = CovResult {
            lines: [(1, 0), (2, 0), (7, 0)].iter().cloned().collect(),
            branches: [].iter().cloned().collect(),
            functions: FxHashMap::default(),
        };

        assert!(!is_covered(&result));
    }

    #[test]
    fn test_covered_functions_executed() {
        let mut functions: FunctionMap = FxHashMap::default();
        functions.insert(
            "top-level".to_string(),
            Function {
                start: 1,
                executed: true,
            },
        );
        functions.insert(
            "f".to_string(),
            Function {
                start: 2,
                executed: true,
            },
        );
        let result = CovResult {
            lines: [(1, 21), (2, 7), (7, 0)].iter().cloned().collect(),
            branches: [].iter().cloned().collect(),
            functions,
        };

        assert!(is_covered(&result));
    }

    #[test]
    fn test_covered_toplevel_executed() {
        let mut functions: FunctionMap = FxHashMap::default();
        functions.insert(
            "top-level".to_string(),
            Function {
                start: 1,
                executed: true,
            },
        );
        let result = CovResult {
            lines: [(1, 21), (2, 7), (7, 0)].iter().cloned().collect(),
            branches: [].iter().cloned().collect(),
            functions,
        };

        assert!(is_covered(&result));
    }

    #[test]
    fn test_uncovered_functions_not_executed() {
        let mut functions: FunctionMap = FxHashMap::default();
        functions.insert(
            "top-level".to_string(),
            Function {
                start: 1,
                executed: true,
            },
        );
        functions.insert(
            "f".to_string(),
            Function {
                start: 7,
                executed: false,
            },
        );
        let result = CovResult {
            lines: [(1, 21), (2, 7), (7, 0)].iter().cloned().collect(),
            branches: [].iter().cloned().collect(),
            functions,
        };

        assert!(!is_covered(&result));
    }
}