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

Commit

Permalink
Support allowlist extension
Browse files Browse the repository at this point in the history
  • Loading branch information
ranweiler committed Jan 21, 2023
1 parent 0cdb0c3 commit 48dd9b3
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/agent/coverage/src/allowlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ impl TargetAllowList {
source_files,
}
}

pub fn extend(&self, other: &Self) -> Self {
let mut new = Self::default();

new.functions = self.functions.extend(&other.functions);
new.modules = self.modules.extend(&other.modules);
new.source_files = self.source_files.extend(&other.source_files);

new
}
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -93,6 +103,22 @@ impl AllowList {
// Allowed if rule-allowed but not excluded by a negative (deny) rule.
self.allow.is_match(path) && !self.deny.is_match(path)
}

/// Build a new `Allowlist` that adds the allow and deny rules of `other` to `self`.
pub fn extend(&self, other: &Self) -> Self {
let allow = add_regexsets(&self.allow, &other.allow);
let deny = add_regexsets(&self.deny, &other.deny);

AllowList::new(allow, deny)
}
}

fn add_regexsets(lhs: &RegexSet, rhs: &RegexSet) -> RegexSet {
let mut patterns = lhs.patterns().to_vec();
patterns.extend(rhs.patterns().iter().map(|s| s.to_owned()));

// Can't panic: patterns were accepted by input `RegexSet` ctors.
RegexSet::new(patterns).unwrap()
}

impl Default for AllowList {
Expand Down
45 changes: 45 additions & 0 deletions src/agent/coverage/src/allowlist/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,48 @@ fn test_allow_glob_extension() -> Result<()> {

Ok(())
}

#[test]
fn test_allowlist_extend() -> Result<()> {
let baseline_text = "! bad/*
other/*";
let baseline = AllowList::parse(baseline_text)?;

assert!(!baseline.is_allowed("bad/a"));
assert!(!baseline.is_allowed("bad/b"));
assert!(!baseline.is_allowed("good/a"));
assert!(!baseline.is_allowed("good/b"));
assert!(!baseline.is_allowed("good/bad/c"));
assert!(baseline.is_allowed("other/a"));
assert!(baseline.is_allowed("other/b"));

let provided_text = "good/*
bad/*
! other/*";
let provided = AllowList::parse(provided_text)?;

assert!(provided.is_allowed("bad/a"));
assert!(provided.is_allowed("bad/b"));
assert!(provided.is_allowed("good/a"));
assert!(provided.is_allowed("good/b"));
assert!(provided.is_allowed("good/bad/c"));
assert!(!provided.is_allowed("other/a"));
assert!(!provided.is_allowed("other/b"));

let extended = baseline.extend(&provided);

// Deny rules from `baseline` should not be overridden by `provided`, but
// allow rules should be.
//
// A provided allowlist can deny patterns that are baseline-allowed, but
// cannot allow patterns that are baseline-denied.
assert!(!extended.is_allowed("bad/a"));
assert!(!extended.is_allowed("bad/b"));
assert!(extended.is_allowed("good/a"));
assert!(extended.is_allowed("good/b"));
assert!(extended.is_allowed("good/bad/c"));
assert!(!extended.is_allowed("other/a"));
assert!(!extended.is_allowed("other/b"));

Ok(())
}

0 comments on commit 48dd9b3

Please sign in to comment.