Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Commit 2dd212e

Browse files
committed
Add tests, anchor rules
1 parent cbd6f11 commit 2dd212e

File tree

8 files changed

+142
-29
lines changed

8 files changed

+142
-29
lines changed

src/agent/coverage/src/allowlist.rs

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,27 @@ impl TargetAllowList {
2525
}
2626
}
2727

28-
#[derive(Clone, Debug, Default)]
28+
#[derive(Clone, Debug)]
2929
pub struct AllowList {
30-
allow: Option<RegexSet>,
31-
deny: Option<RegexSet>,
30+
allow: RegexSet,
31+
deny: RegexSet,
3232
}
3333

3434
impl AllowList {
35-
pub fn new(allow: impl Into<Option<RegexSet>>, deny: impl Into<Option<RegexSet>>) -> Self {
36-
let allow = allow.into();
37-
let deny = deny.into();
38-
35+
pub fn new(allow: RegexSet, deny: RegexSet) -> Self {
3936
Self { allow, deny }
4037
}
4138

4239
pub fn load(path: impl AsRef<Path>) -> Result<Self> {
43-
use std::fs::File;
44-
use std::io::{BufRead, BufReader};
45-
4640
let path = path.as_ref();
41+
let text = std::fs::read_to_string(path)?;
42+
Self::parse(&text)
43+
}
44+
45+
pub fn parse(text: &str) -> Result<Self> {
46+
use std::io::{BufRead, BufReader};
4747

48-
let file = File::open(path)?;
49-
let reader = BufReader::new(file);
48+
let reader = BufReader::new(text.as_bytes());
5049

5150
let mut allow = vec![];
5251
let mut deny = vec![];
@@ -91,21 +90,18 @@ impl AllowList {
9190
pub fn is_allowed(&self, path: impl AsRef<str>) -> bool {
9291
let path = path.as_ref();
9392

94-
match (&self.allow, &self.deny) {
95-
(Some(allow), Some(deny)) => allow.is_match(path) && !deny.is_match(path),
96-
(Some(allow), None) => {
97-
// Deny unless rule-allowed.
98-
allow.is_match(path)
99-
}
100-
(None, Some(deny)) => {
101-
// Allow unless rule-denied.
102-
!deny.is_match(path)
103-
}
104-
(None, None) => {
105-
// Allow all.
106-
true
107-
}
108-
}
93+
// Allowed if rule-allowed but not excluded by a negative (deny) rule.
94+
self.allow.is_match(path) && !self.deny.is_match(path)
95+
}
96+
}
97+
98+
impl Default for AllowList {
99+
fn default() -> Self {
100+
// Unwrap-safe due to valid constant expr.
101+
let allow = RegexSet::new([".*"]).unwrap();
102+
let deny = RegexSet::empty();
103+
104+
AllowList::new(allow, deny)
109105
}
110106
}
111107

@@ -150,8 +146,11 @@ fn glob_to_regex(expr: &str) -> Result<Regex> {
150146
// Translate glob wildcards into quantified regexes.
151147
let expr = expr.replace("*", ".*");
152148

153-
// Anchor to line start.
154-
let expr = format!("^{expr}");
149+
// Anchor to line start and end.
150+
let expr = format!("^{expr}$");
155151

156152
Ok(Regex::new(&expr)?)
157153
}
154+
155+
#[cfg(test)]
156+
mod tests;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
a/*
2+
! a/c
3+
# c
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
a/*
2+
! a/c
3+
c
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
a
2+
a/b
3+
b
4+
c
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
a
2+
b

src/agent/coverage/src/allowlist/test-data/empty.txt

Whitespace-only changes.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
use anyhow::Result;
2+
3+
use super::AllowList;
4+
5+
#[test]
6+
fn test_default() -> Result<()> {
7+
let allowlist = AllowList::default();
8+
9+
// All allowed.
10+
assert!(allowlist.is_allowed("a"));
11+
assert!(allowlist.is_allowed("a/b"));
12+
assert!(allowlist.is_allowed("b"));
13+
assert!(allowlist.is_allowed("c"));
14+
15+
Ok(())
16+
}
17+
18+
#[test]
19+
fn test_empty() -> Result<()> {
20+
let text = include_str!("test-data/empty.txt");
21+
let allowlist = AllowList::parse(text)?;
22+
23+
// All excluded.
24+
assert!(!allowlist.is_allowed("a"));
25+
assert!(!allowlist.is_allowed("a/b"));
26+
assert!(!allowlist.is_allowed("b"));
27+
assert!(!allowlist.is_allowed("c"));
28+
29+
Ok(())
30+
}
31+
32+
#[test]
33+
fn test_allow_some() -> Result<()> {
34+
let text = include_str!("test-data/allow-some.txt");
35+
let allowlist = AllowList::parse(text)?;
36+
37+
assert!(allowlist.is_allowed("a"));
38+
assert!(!allowlist.is_allowed("a/b"));
39+
assert!(allowlist.is_allowed("b"));
40+
assert!(!allowlist.is_allowed("c"));
41+
42+
Ok(())
43+
}
44+
45+
#[test]
46+
fn test_allow_all() -> Result<()> {
47+
let text = include_str!("test-data/allow-all.txt");
48+
let allowlist = AllowList::parse(text)?;
49+
50+
assert!(allowlist.is_allowed("a"));
51+
assert!(allowlist.is_allowed("a/b"));
52+
assert!(allowlist.is_allowed("b"));
53+
assert!(allowlist.is_allowed("c"));
54+
55+
Ok(())
56+
}
57+
58+
#[test]
59+
fn test_allow_all_glob() -> Result<()> {
60+
let text = include_str!("test-data/allow-all-glob.txt");
61+
let allowlist = AllowList::parse(text)?;
62+
63+
assert!(allowlist.is_allowed("a"));
64+
assert!(allowlist.is_allowed("a/b"));
65+
assert!(allowlist.is_allowed("b"));
66+
assert!(allowlist.is_allowed("c"));
67+
68+
Ok(())
69+
}
70+
71+
#[test]
72+
fn test_allow_glob_except() -> Result<()> {
73+
let text = include_str!("test-data/allow-all-glob-except.txt");
74+
let allowlist = AllowList::parse(text)?;
75+
76+
assert!(!allowlist.is_allowed("a"));
77+
assert!(allowlist.is_allowed("a/b"));
78+
assert!(!allowlist.is_allowed("a/c"));
79+
assert!(allowlist.is_allowed("a/d"));
80+
assert!(!allowlist.is_allowed("b"));
81+
assert!(allowlist.is_allowed("c"));
82+
83+
Ok(())
84+
}
85+
86+
#[test]
87+
fn test_allow_glob_except_commented() -> Result<()> {
88+
let text = include_str!("test-data/allow-all-glob-except-commented.txt");
89+
let allowlist = AllowList::parse(text)?;
90+
91+
assert!(!allowlist.is_allowed("a"));
92+
assert!(allowlist.is_allowed("a/b"));
93+
assert!(!allowlist.is_allowed("a/c"));
94+
assert!(allowlist.is_allowed("a/d"));
95+
assert!(!allowlist.is_allowed("b"));
96+
97+
// Allowed by the rule `c`, but not allowed because `# c` is a comment.
98+
assert!(!allowlist.is_allowed("c"));
99+
100+
Ok(())
101+
}

0 commit comments

Comments
 (0)