aconfig: cache: reject empty namespace and name fields

Add invariant to struct Cache: all flag namespace and name fields added
to the cache are required to be non-empty strings.

Bug: 279485059
Test: atest aconfig.test
Change-Id: I5ff34ec8feccc19e52241d4221fc87699518f3ff
This commit is contained in:
Mårten Kongstad
2023-05-16 12:52:43 +02:00
parent 6b9e382eed
commit e17ba5f423
3 changed files with 75 additions and 6 deletions

View File

@@ -52,8 +52,9 @@ pub struct Cache {
} }
impl Cache { impl Cache {
pub fn new(namespace: String) -> Cache { pub fn new(namespace: String) -> Result<Cache> {
Cache { namespace, items: vec![] } ensure!(!namespace.is_empty(), "empty namespace");
Ok(Cache { namespace, items: vec![] })
} }
pub fn read_from_reader(reader: impl Read) -> Result<Cache> { pub fn read_from_reader(reader: impl Read) -> Result<Cache> {
@@ -69,6 +70,8 @@ impl Cache {
source: Source, source: Source,
declaration: FlagDeclaration, declaration: FlagDeclaration,
) -> Result<()> { ) -> Result<()> {
ensure!(!declaration.name.is_empty(), "empty flag name");
ensure!(!declaration.description.is_empty(), "empty flag description");
ensure!( ensure!(
self.items.iter().all(|item| item.name != declaration.name), self.items.iter().all(|item| item.name != declaration.name),
"failed to declare flag {} from {}: flag already declared", "failed to declare flag {} from {}: flag already declared",
@@ -91,6 +94,8 @@ impl Cache {
} }
pub fn add_flag_value(&mut self, source: Source, value: FlagValue) -> Result<()> { pub fn add_flag_value(&mut self, source: Source, value: FlagValue) -> Result<()> {
ensure!(!value.namespace.is_empty(), "empty flag namespace");
ensure!(!value.name.is_empty(), "empty flag name");
ensure!( ensure!(
value.namespace == self.namespace, value.namespace == self.namespace,
"failed to set values for flag {}/{} from {}: expected namespace {}", "failed to set values for flag {}/{} from {}: expected namespace {}",
@@ -121,6 +126,7 @@ impl Cache {
} }
pub fn namespace(&self) -> &str { pub fn namespace(&self) -> &str {
debug_assert!(!self.namespace.is_empty());
&self.namespace &self.namespace
} }
} }
@@ -132,7 +138,7 @@ mod tests {
#[test] #[test]
fn test_add_flag_declaration() { fn test_add_flag_declaration() {
let mut cache = Cache::new("ns".to_string()); let mut cache = Cache::new("ns".to_string()).unwrap();
cache cache
.add_flag_declaration( .add_flag_declaration(
Source::File("first.txt".to_string()), Source::File("first.txt".to_string()),
@@ -158,7 +164,7 @@ mod tests {
item.state == expected.0 && item.permission == expected.1 item.state == expected.0 && item.permission == expected.1
} }
let mut cache = Cache::new("ns".to_string()); let mut cache = Cache::new("ns".to_string()).unwrap();
let error = cache let error = cache
.add_flag_value( .add_flag_value(
Source::Memory, Source::Memory,
@@ -224,4 +230,67 @@ mod tests {
assert_eq!(&format!("{:?}", error), "failed to set values for flag some-other-namespace/foo from <memory>: expected namespace ns"); assert_eq!(&format!("{:?}", error), "failed to set values for flag some-other-namespace/foo from <memory>: expected namespace ns");
assert!(check(&cache, "foo", (FlagState::Enabled, Permission::ReadWrite))); assert!(check(&cache, "foo", (FlagState::Enabled, Permission::ReadWrite)));
} }
#[test]
fn test_reject_empty_cache_namespace() {
Cache::new("".to_string()).unwrap_err();
}
#[test]
fn test_reject_empty_flag_declaration_fields() {
let mut cache = Cache::new("ns".to_string()).unwrap();
let error = cache
.add_flag_declaration(
Source::Memory,
FlagDeclaration { name: "".to_string(), description: "Description".to_string() },
)
.unwrap_err();
assert_eq!(&format!("{:?}", error), "empty flag name");
let error = cache
.add_flag_declaration(
Source::Memory,
FlagDeclaration { name: "foo".to_string(), description: "".to_string() },
)
.unwrap_err();
assert_eq!(&format!("{:?}", error), "empty flag description");
}
#[test]
fn test_reject_empty_flag_value_files() {
let mut cache = Cache::new("ns".to_string()).unwrap();
cache
.add_flag_declaration(
Source::Memory,
FlagDeclaration { name: "foo".to_string(), description: "desc".to_string() },
)
.unwrap();
let error = cache
.add_flag_value(
Source::Memory,
FlagValue {
namespace: "".to_string(),
name: "foo".to_string(),
state: FlagState::Enabled,
permission: Permission::ReadOnly,
},
)
.unwrap_err();
assert_eq!(&format!("{:?}", error), "empty flag namespace");
let error = cache
.add_flag_value(
Source::Memory,
FlagValue {
namespace: "ns".to_string(),
name: "".to_string(),
state: FlagState::Enabled,
permission: Permission::ReadOnly,
},
)
.unwrap_err();
assert_eq!(&format!("{:?}", error), "empty flag name");
}
} }

View File

@@ -88,7 +88,7 @@ mod tests {
#[test] #[test]
fn test_generate_java_code() { fn test_generate_java_code() {
let namespace = "TeSTFlaG"; let namespace = "TeSTFlaG";
let mut cache = Cache::new(namespace.to_string()); let mut cache = Cache::new(namespace.to_string()).unwrap();
cache cache
.add_flag_declaration( .add_flag_declaration(
Source::File("test.txt".to_string()), Source::File("test.txt".to_string()),

View File

@@ -58,7 +58,7 @@ pub fn create_cache(
declarations: Vec<Input>, declarations: Vec<Input>,
values: Vec<Input>, values: Vec<Input>,
) -> Result<Cache> { ) -> Result<Cache> {
let mut cache = Cache::new(namespace.to_owned()); let mut cache = Cache::new(namespace.to_owned())?;
for mut input in declarations { for mut input in declarations {
let mut contents = String::new(); let mut contents = String::new();