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

Commit 5adaadd

Browse files
authored
Support allowlist extension (#2756)
* Support allowlist extension * Address lint
1 parent 0cdb0c3 commit 5adaadd

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

src/agent/coverage/src/allowlist.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ impl TargetAllowList {
2323
source_files,
2424
}
2525
}
26+
27+
#[allow(clippy::field_reassign_with_default)]
28+
pub fn extend(&self, other: &Self) -> Self {
29+
let mut new = Self::default();
30+
31+
new.functions = self.functions.extend(&other.functions);
32+
new.modules = self.modules.extend(&other.modules);
33+
new.source_files = self.source_files.extend(&other.source_files);
34+
35+
new
36+
}
2637
}
2738

2839
#[derive(Clone, Debug)]
@@ -93,6 +104,22 @@ impl AllowList {
93104
// Allowed if rule-allowed but not excluded by a negative (deny) rule.
94105
self.allow.is_match(path) && !self.deny.is_match(path)
95106
}
107+
108+
/// Build a new `Allowlist` that adds the allow and deny rules of `other` to `self`.
109+
pub fn extend(&self, other: &Self) -> Self {
110+
let allow = add_regexsets(&self.allow, &other.allow);
111+
let deny = add_regexsets(&self.deny, &other.deny);
112+
113+
AllowList::new(allow, deny)
114+
}
115+
}
116+
117+
fn add_regexsets(lhs: &RegexSet, rhs: &RegexSet) -> RegexSet {
118+
let mut patterns = lhs.patterns().to_vec();
119+
patterns.extend(rhs.patterns().iter().map(|s| s.to_owned()));
120+
121+
// Can't panic: patterns were accepted by input `RegexSet` ctors.
122+
RegexSet::new(patterns).unwrap()
96123
}
97124

98125
impl Default for AllowList {

src/agent/coverage/src/allowlist/tests.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,48 @@ fn test_allow_glob_extension() -> Result<()> {
116116

117117
Ok(())
118118
}
119+
120+
#[test]
121+
fn test_allowlist_extend() -> Result<()> {
122+
let baseline_text = "! bad/*
123+
other/*";
124+
let baseline = AllowList::parse(baseline_text)?;
125+
126+
assert!(!baseline.is_allowed("bad/a"));
127+
assert!(!baseline.is_allowed("bad/b"));
128+
assert!(!baseline.is_allowed("good/a"));
129+
assert!(!baseline.is_allowed("good/b"));
130+
assert!(!baseline.is_allowed("good/bad/c"));
131+
assert!(baseline.is_allowed("other/a"));
132+
assert!(baseline.is_allowed("other/b"));
133+
134+
let provided_text = "good/*
135+
bad/*
136+
! other/*";
137+
let provided = AllowList::parse(provided_text)?;
138+
139+
assert!(provided.is_allowed("bad/a"));
140+
assert!(provided.is_allowed("bad/b"));
141+
assert!(provided.is_allowed("good/a"));
142+
assert!(provided.is_allowed("good/b"));
143+
assert!(provided.is_allowed("good/bad/c"));
144+
assert!(!provided.is_allowed("other/a"));
145+
assert!(!provided.is_allowed("other/b"));
146+
147+
let extended = baseline.extend(&provided);
148+
149+
// Deny rules from `baseline` should not be overridden by `provided`, but
150+
// allow rules should be.
151+
//
152+
// A provided allowlist can deny patterns that are baseline-allowed, but
153+
// cannot allow patterns that are baseline-denied.
154+
assert!(!extended.is_allowed("bad/a"));
155+
assert!(!extended.is_allowed("bad/b"));
156+
assert!(extended.is_allowed("good/a"));
157+
assert!(extended.is_allowed("good/b"));
158+
assert!(extended.is_allowed("good/bad/c"));
159+
assert!(!extended.is_allowed("other/a"));
160+
assert!(!extended.is_allowed("other/b"));
161+
162+
Ok(())
163+
}

0 commit comments

Comments
 (0)