aconfig: introduce namespace, rename proto messages
Flags belong to a namespace. Update the proto files to reflect this.
Config files can only refer to a single namespace. Override files can
refer to multiple namespaces; an override directive for a flag in a
different namespace than the one represented by the cache will be
silently ignored.
Rename the proto messages to make it more clear what they are. Propagate
this change through the wrappers in aconfig.rs and the rest of the code.
Also, settle on Tracepoint instead of TracePoint.
Bug: 279485059
Test: atest aconfig.test
Change-Id: I16e69dd14687bc498b2ba89d6a35879459903801
diff --git a/tools/aconfig/protos/aconfig.proto b/tools/aconfig/protos/aconfig.proto
index f3d6148..a3b1fec 100644
--- a/tools/aconfig/protos/aconfig.proto
+++ b/tools/aconfig/protos/aconfig.proto
@@ -20,56 +20,66 @@
package android.aconfig;
+// messages used in both aconfig input and output
+
enum flag_state {
ENABLED = 1;
DISABLED = 2;
}
-enum permission {
+enum flag_permission {
READ_ONLY = 1;
READ_WRITE = 2;
}
-message value {
+// aconfig input messages: configuration and override data
+
+message flag_value {
required flag_state state = 1;
- required permission permission = 2;
+ required flag_permission permission = 2;
optional uint32 since = 3;
}
-message flag {
- required string id = 1;
+message flag_definition {
+ required string name = 1;
required string description = 2;
- repeated value value = 3;
+ repeated flag_value value = 3;
};
-message android_config {
- repeated flag flag = 1;
+message namespace {
+ required string namespace = 1;
+ repeated flag_definition flag = 2;
};
-message override {
- required string id = 1;
- required flag_state state = 2;
- required permission permission = 3;
+message flag_override {
+ required string namespace = 1;
+ required string name = 2;
+ required flag_state state = 3;
+ required flag_permission permission = 4;
};
-message override_config {
- repeated override override = 1;
+message flag_overrides {
+ repeated flag_override flag_override = 1;
};
-message dump {
- repeated dump_item item = 1;
-}
+// aconfig output messages: parsed and verified configuration and override data
-message dump_trace {
+message tracepoint {
+ // path to config or override file releative to $TOP
required string source = 1;
required flag_state state = 2;
- required permission permission = 3;
+ required flag_permission permission = 3;
}
-message dump_item {
- required string id = 1;
- required string description = 2;
- required flag_state state = 3;
- required permission permission = 4;
- repeated dump_trace trace = 5;
+message parsed_flag {
+ required string namespace = 1;
+ required string name = 2;
+ required string description = 3;
+ required flag_state state = 4;
+ required flag_permission permission = 5;
+ repeated tracepoint trace = 6;
+}
+
+message parsed_flags {
+ repeated parsed_flag parsed_flag = 1;
}
diff --git a/tools/aconfig/src/aconfig.rs b/tools/aconfig/src/aconfig.rs
index edab36c..8fe82b6 100644
--- a/tools/aconfig/src/aconfig.rs
+++ b/tools/aconfig/src/aconfig.rs
@@ -18,10 +18,11 @@
use protobuf::{Enum, EnumOrUnknown};
use serde::{Deserialize, Serialize};
-use crate::cache::{Cache, Item, TracePoint};
+use crate::cache::{Cache, Item, Tracepoint};
use crate::protos::{
- ProtoAndroidConfig, ProtoDump, ProtoDumpItem, ProtoDumpTracePoint, ProtoFlag, ProtoFlagState,
- ProtoOverride, ProtoOverrideConfig, ProtoPermission, ProtoValue,
+ ProtoFlagDefinition, ProtoFlagDefinitionValue, ProtoFlagOverride, ProtoFlagOverrides,
+ ProtoFlagPermission, ProtoFlagState, ProtoNamespace, ProtoParsedFlag, ProtoParsedFlags,
+ ProtoTracepoint,
};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone, Copy)]
@@ -57,23 +58,23 @@
ReadWrite,
}
-impl TryFrom<EnumOrUnknown<ProtoPermission>> for Permission {
+impl TryFrom<EnumOrUnknown<ProtoFlagPermission>> for Permission {
type Error = Error;
- fn try_from(proto: EnumOrUnknown<ProtoPermission>) -> Result<Self, Self::Error> {
- match ProtoPermission::from_i32(proto.value()) {
- Some(ProtoPermission::READ_ONLY) => Ok(Permission::ReadOnly),
- Some(ProtoPermission::READ_WRITE) => Ok(Permission::ReadWrite),
+ fn try_from(proto: EnumOrUnknown<ProtoFlagPermission>) -> Result<Self, Self::Error> {
+ match ProtoFlagPermission::from_i32(proto.value()) {
+ Some(ProtoFlagPermission::READ_ONLY) => Ok(Permission::ReadOnly),
+ Some(ProtoFlagPermission::READ_WRITE) => Ok(Permission::ReadWrite),
None => Err(anyhow!("unknown permission enum value {}", proto.value())),
}
}
}
-impl From<Permission> for ProtoPermission {
+impl From<Permission> for ProtoFlagPermission {
fn from(permission: Permission) -> Self {
match permission {
- Permission::ReadOnly => ProtoPermission::READ_ONLY,
- Permission::ReadWrite => ProtoPermission::READ_WRITE,
+ Permission::ReadOnly => ProtoFlagPermission::READ_ONLY,
+ Permission::ReadWrite => ProtoFlagPermission::READ_WRITE,
}
}
}
@@ -96,10 +97,10 @@
}
}
-impl TryFrom<ProtoValue> for Value {
+impl TryFrom<ProtoFlagDefinitionValue> for Value {
type Error = Error;
- fn try_from(proto: ProtoValue) -> Result<Self, Self::Error> {
+ fn try_from(proto: ProtoFlagDefinitionValue) -> Result<Self, Self::Error> {
let Some(proto_state) = proto.state else {
return Err(anyhow!("missing 'state' field"));
};
@@ -114,7 +115,7 @@
#[derive(Debug, PartialEq, Eq)]
pub struct Flag {
- pub id: String,
+ pub name: String,
pub description: String,
// ordered by Value.since; guaranteed to contain at least one item (the default value, with
@@ -125,17 +126,11 @@
impl Flag {
#[allow(dead_code)] // only used in unit tests
pub fn try_from_text_proto(text_proto: &str) -> Result<Flag> {
- let proto: ProtoFlag = crate::protos::try_from_text_proto(text_proto)
+ let proto: ProtoFlagDefinition = crate::protos::try_from_text_proto(text_proto)
.with_context(|| text_proto.to_owned())?;
proto.try_into()
}
- pub fn try_from_text_proto_list(text_proto: &str) -> Result<Vec<Flag>> {
- let proto: ProtoAndroidConfig = crate::protos::try_from_text_proto(text_proto)
- .with_context(|| text_proto.to_owned())?;
- proto.flag.into_iter().map(|proto_flag| proto_flag.try_into()).collect()
- }
-
pub fn resolve(&self, build_id: u32) -> (FlagState, Permission) {
let mut state = self.values[0].state;
let mut permission = self.values[0].permission;
@@ -150,12 +145,12 @@
}
}
-impl TryFrom<ProtoFlag> for Flag {
+impl TryFrom<ProtoFlagDefinition> for Flag {
type Error = Error;
- fn try_from(proto: ProtoFlag) -> Result<Self, Self::Error> {
- let Some(id) = proto.id else {
- return Err(anyhow!("missing 'id' field"));
+ fn try_from(proto: ProtoFlagDefinition) -> Result<Self, Self::Error> {
+ let Some(name) = proto.name else {
+ return Err(anyhow!("missing 'name' field"));
};
let Some(description) = proto.description else {
return Err(anyhow!("missing 'description' field"));
@@ -169,8 +164,8 @@
let v: Value = proto_value.try_into()?;
if values.iter().any(|w| v.since == w.since) {
let msg = match v.since {
- None => format!("flag {}: multiple default values", id),
- Some(x) => format!("flag {}: multiple values for since={}", id, x),
+ None => format!("flag {}: multiple default values", name),
+ Some(x) => format!("flag {}: multiple values for since={}", name, x),
};
return Err(anyhow!(msg));
}
@@ -178,13 +173,35 @@
}
values.sort_by_key(|v| v.since);
- Ok(Flag { id, description, values })
+ Ok(Flag { name, description, values })
+ }
+}
+
+#[derive(Debug, PartialEq, Eq)]
+pub struct Namespace {
+ pub namespace: String,
+ pub flags: Vec<Flag>,
+}
+
+impl Namespace {
+ pub fn try_from_text_proto(text_proto: &str) -> Result<Namespace> {
+ let proto: ProtoNamespace = crate::protos::try_from_text_proto(text_proto)
+ .with_context(|| text_proto.to_owned())?;
+ let Some(namespace) = proto.namespace else {
+ return Err(anyhow!("missing 'namespace' field"));
+ };
+ let mut flags = vec![];
+ for proto_flag in proto.flag.into_iter() {
+ flags.push(proto_flag.try_into()?);
+ }
+ Ok(Namespace { namespace, flags })
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct Override {
- pub id: String,
+ pub namespace: String,
+ pub name: String,
pub state: FlagState,
pub permission: Permission,
}
@@ -192,22 +209,25 @@
impl Override {
#[allow(dead_code)] // only used in unit tests
pub fn try_from_text_proto(text_proto: &str) -> Result<Override> {
- let proto: ProtoOverride = crate::protos::try_from_text_proto(text_proto)?;
+ let proto: ProtoFlagOverride = crate::protos::try_from_text_proto(text_proto)?;
proto.try_into()
}
pub fn try_from_text_proto_list(text_proto: &str) -> Result<Vec<Override>> {
- let proto: ProtoOverrideConfig = crate::protos::try_from_text_proto(text_proto)?;
- proto.override_.into_iter().map(|proto_flag| proto_flag.try_into()).collect()
+ let proto: ProtoFlagOverrides = crate::protos::try_from_text_proto(text_proto)?;
+ proto.flag_override.into_iter().map(|proto_flag| proto_flag.try_into()).collect()
}
}
-impl TryFrom<ProtoOverride> for Override {
+impl TryFrom<ProtoFlagOverride> for Override {
type Error = Error;
- fn try_from(proto: ProtoOverride) -> Result<Self, Self::Error> {
- let Some(id) = proto.id else {
- return Err(anyhow!("missing 'id' field"));
+ fn try_from(proto: ProtoFlagOverride) -> Result<Self, Self::Error> {
+ let Some(namespace) = proto.namespace else {
+ return Err(anyhow!("missing 'namespace' field"));
+ };
+ let Some(name) = proto.name else {
+ return Err(anyhow!("missing 'name' field"));
};
let Some(proto_state) = proto.state else {
return Err(anyhow!("missing 'state' field"));
@@ -217,41 +237,42 @@
return Err(anyhow!("missing 'permission' field"));
};
let permission = proto_permission.try_into()?;
- Ok(Override { id, state, permission })
+ Ok(Override { namespace, name, state, permission })
}
}
-impl From<Cache> for ProtoDump {
+impl From<Cache> for ProtoParsedFlags {
fn from(cache: Cache) -> Self {
- let mut dump = ProtoDump::new();
+ let mut proto = ProtoParsedFlags::new();
for item in cache.into_iter() {
- dump.item.push(item.into());
+ proto.parsed_flag.push(item.into());
}
- dump
+ proto
}
}
-impl From<Item> for ProtoDumpItem {
+impl From<Item> for ProtoParsedFlag {
fn from(item: Item) -> Self {
- let mut dump_item = crate::protos::ProtoDumpItem::new();
- dump_item.set_id(item.id.clone());
- dump_item.set_description(item.description.clone());
- dump_item.set_state(item.state.into());
- dump_item.set_permission(item.permission.into());
+ let mut proto = crate::protos::ProtoParsedFlag::new();
+ proto.set_namespace(item.namespace.to_owned());
+ proto.set_name(item.name.clone());
+ proto.set_description(item.description.clone());
+ proto.set_state(item.state.into());
+ proto.set_permission(item.permission.into());
for trace in item.trace.into_iter() {
- dump_item.trace.push(trace.into());
+ proto.trace.push(trace.into());
}
- dump_item
+ proto
}
}
-impl From<TracePoint> for ProtoDumpTracePoint {
- fn from(tracepoint: TracePoint) -> Self {
- let mut dump_tracepoint = ProtoDumpTracePoint::new();
- dump_tracepoint.set_source(format!("{}", tracepoint.source));
- dump_tracepoint.set_state(tracepoint.state.into());
- dump_tracepoint.set_permission(tracepoint.permission.into());
- dump_tracepoint
+impl From<Tracepoint> for ProtoTracepoint {
+ fn from(tracepoint: Tracepoint) -> Self {
+ let mut proto = ProtoTracepoint::new();
+ proto.set_source(format!("{}", tracepoint.source));
+ proto.set_state(tracepoint.state.into());
+ proto.set_permission(tracepoint.permission.into());
+ proto
}
}
@@ -262,7 +283,7 @@
#[test]
fn test_flag_try_from_text_proto() {
let expected = Flag {
- id: "1234".to_owned(),
+ name: "1234".to_owned(),
description: "Description of the flag".to_owned(),
values: vec![
Value::default(FlagState::Disabled, Permission::ReadOnly),
@@ -271,7 +292,7 @@
};
let s = r#"
- id: "1234"
+ name: "1234"
description: "Description of the flag"
value {
state: DISABLED
@@ -291,7 +312,7 @@
#[test]
fn test_flag_try_from_text_proto_bad_input() {
let s = r#"
- id: "a"
+ name: "a"
description: "Description of the flag"
"#;
let error = Flag::try_from_text_proto(s).unwrap_err();
@@ -308,7 +329,7 @@
assert!(format!("{:?}", error).contains("Message not initialized"));
let s = r#"
- id: "a"
+ name: "a"
description: "Description of the flag"
value {
state: ENABLED
@@ -324,23 +345,27 @@
}
#[test]
- fn test_flag_try_from_text_proto_list() {
- let expected = vec![
- Flag {
- id: "a".to_owned(),
- description: "A".to_owned(),
- values: vec![Value::default(FlagState::Enabled, Permission::ReadOnly)],
- },
- Flag {
- id: "b".to_owned(),
- description: "B".to_owned(),
- values: vec![Value::default(FlagState::Disabled, Permission::ReadWrite)],
- },
- ];
+ fn test_namespace_try_from_text_proto() {
+ let expected = Namespace {
+ namespace: "ns".to_owned(),
+ flags: vec![
+ Flag {
+ name: "a".to_owned(),
+ description: "A".to_owned(),
+ values: vec![Value::default(FlagState::Enabled, Permission::ReadOnly)],
+ },
+ Flag {
+ name: "b".to_owned(),
+ description: "B".to_owned(),
+ values: vec![Value::default(FlagState::Disabled, Permission::ReadWrite)],
+ },
+ ],
+ };
let s = r#"
+ namespace: "ns"
flag {
- id: "a"
+ name: "a"
description: "A"
value {
state: ENABLED
@@ -348,7 +373,7 @@
}
}
flag {
- id: "b"
+ name: "b"
description: "B"
value {
state: DISABLED
@@ -356,7 +381,7 @@
}
}
"#;
- let actual = Flag::try_from_text_proto_list(s).unwrap();
+ let actual = Namespace::try_from_text_proto(s).unwrap();
assert_eq!(expected, actual);
}
@@ -364,13 +389,15 @@
#[test]
fn test_override_try_from_text_proto_list() {
let expected = Override {
- id: "1234".to_owned(),
+ namespace: "ns".to_owned(),
+ name: "1234".to_owned(),
state: FlagState::Enabled,
permission: Permission::ReadOnly,
};
let s = r#"
- id: "1234"
+ namespace: "ns"
+ name: "1234"
state: ENABLED
permission: READ_ONLY
"#;
@@ -382,7 +409,7 @@
#[test]
fn test_flag_resolve() {
let flag = Flag {
- id: "a".to_owned(),
+ name: "a".to_owned(),
description: "A".to_owned(),
values: vec![
Value::default(FlagState::Disabled, Permission::ReadOnly),
diff --git a/tools/aconfig/src/cache.rs b/tools/aconfig/src/cache.rs
index fffeb9b..4b46c42 100644
--- a/tools/aconfig/src/cache.rs
+++ b/tools/aconfig/src/cache.rs
@@ -22,7 +22,7 @@
use crate::commands::Source;
#[derive(Serialize, Deserialize, Debug)]
-pub struct TracePoint {
+pub struct Tracepoint {
pub source: Source,
pub state: FlagState,
pub permission: Permission,
@@ -30,22 +30,28 @@
#[derive(Serialize, Deserialize, Debug)]
pub struct Item {
- pub id: String,
+ // TODO: duplicating the Cache.namespace as Item.namespace makes the internal representation
+ // closer to the proto message `parsed_flag`; hopefully this will enable us to replace the Item
+ // struct and use a newtype instead once aconfig has matured. Until then, namespace should
+ // really be a Cow<String>.
+ pub namespace: String,
+ pub name: String,
pub description: String,
pub state: FlagState,
pub permission: Permission,
- pub trace: Vec<TracePoint>,
+ pub trace: Vec<Tracepoint>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Cache {
build_id: u32,
+ namespace: String,
items: Vec<Item>,
}
impl Cache {
- pub fn new(build_id: u32) -> Cache {
- Cache { build_id, items: vec![] }
+ pub fn new(build_id: u32, namespace: String) -> Cache {
+ Cache { build_id, namespace, items: vec![] }
}
pub fn read_from_reader(reader: impl Read) -> Result<Cache> {
@@ -57,31 +63,36 @@
}
pub fn add_flag(&mut self, source: Source, flag: Flag) -> Result<()> {
- if self.items.iter().any(|item| item.id == flag.id) {
+ if self.items.iter().any(|item| item.name == flag.name) {
return Err(anyhow!(
"failed to add flag {} from {}: flag already defined",
- flag.id,
+ flag.name,
source,
));
}
let (state, permission) = flag.resolve(self.build_id);
self.items.push(Item {
- id: flag.id.clone(),
+ namespace: self.namespace.clone(),
+ name: flag.name.clone(),
description: flag.description,
state,
permission,
- trace: vec![TracePoint { source, state, permission }],
+ trace: vec![Tracepoint { source, state, permission }],
});
Ok(())
}
pub fn add_override(&mut self, source: Source, override_: Override) -> Result<()> {
- let Some(existing_item) = self.items.iter_mut().find(|item| item.id == override_.id) else {
- return Err(anyhow!("failed to override flag {}: unknown flag", override_.id));
+ if override_.namespace != self.namespace {
+ // TODO: print warning?
+ return Ok(());
+ }
+ let Some(existing_item) = self.items.iter_mut().find(|item| item.name == override_.name) else {
+ return Err(anyhow!("failed to override flag {}: unknown flag", override_.name));
};
existing_item.state = override_.state;
existing_item.permission = override_.permission;
- existing_item.trace.push(TracePoint {
+ existing_item.trace.push(Tracepoint {
source,
state: override_.state,
permission: override_.permission,
@@ -105,12 +116,12 @@
#[test]
fn test_add_flag() {
- let mut cache = Cache::new(1);
+ let mut cache = Cache::new(1, "ns".to_string());
cache
.add_flag(
Source::File("first.txt".to_string()),
Flag {
- id: "foo".to_string(),
+ name: "foo".to_string(),
description: "desc".to_string(),
values: vec![Value::default(FlagState::Enabled, Permission::ReadOnly)],
},
@@ -120,7 +131,7 @@
.add_flag(
Source::File("second.txt".to_string()),
Flag {
- id: "foo".to_string(),
+ name: "foo".to_string(),
description: "desc".to_string(),
values: vec![Value::default(FlagState::Disabled, Permission::ReadOnly)],
},
@@ -134,17 +145,18 @@
#[test]
fn test_add_override() {
- fn check(cache: &Cache, id: &str, expected: (FlagState, Permission)) -> bool {
- let item = cache.iter().find(|&item| item.id == id).unwrap();
+ fn check(cache: &Cache, name: &str, expected: (FlagState, Permission)) -> bool {
+ let item = cache.iter().find(|&item| item.name == name).unwrap();
item.state == expected.0 && item.permission == expected.1
}
- let mut cache = Cache::new(1);
+ let mut cache = Cache::new(1, "ns".to_string());
let error = cache
.add_override(
Source::Memory,
Override {
- id: "foo".to_string(),
+ namespace: "ns".to_string(),
+ name: "foo".to_string(),
state: FlagState::Enabled,
permission: Permission::ReadOnly,
},
@@ -156,7 +168,7 @@
.add_flag(
Source::File("first.txt".to_string()),
Flag {
- id: "foo".to_string(),
+ name: "foo".to_string(),
description: "desc".to_string(),
values: vec![Value::default(FlagState::Enabled, Permission::ReadOnly)],
},
@@ -169,7 +181,8 @@
.add_override(
Source::Memory,
Override {
- id: "foo".to_string(),
+ namespace: "ns".to_string(),
+ name: "foo".to_string(),
state: FlagState::Disabled,
permission: Permission::ReadWrite,
},
@@ -182,12 +195,27 @@
.add_override(
Source::Memory,
Override {
- id: "foo".to_string(),
+ namespace: "ns".to_string(),
+ name: "foo".to_string(),
state: FlagState::Enabled,
permission: Permission::ReadWrite,
},
)
.unwrap();
assert!(check(&cache, "foo", (FlagState::Enabled, Permission::ReadWrite)));
+
+ // different namespace -> no-op
+ cache
+ .add_override(
+ Source::Memory,
+ Override {
+ namespace: "some-other-namespace".to_string(),
+ name: "foo".to_string(),
+ state: FlagState::Enabled,
+ permission: Permission::ReadOnly,
+ },
+ )
+ .unwrap();
+ assert!(check(&cache, "foo", (FlagState::Enabled, Permission::ReadWrite)));
}
}
diff --git a/tools/aconfig/src/commands.rs b/tools/aconfig/src/commands.rs
index 645d395..2c80a4a 100644
--- a/tools/aconfig/src/commands.rs
+++ b/tools/aconfig/src/commands.rs
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-use anyhow::{Context, Result};
+use anyhow::{ensure, Context, Result};
use clap::ValueEnum;
use protobuf::Message;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::io::Read;
-use crate::aconfig::{Flag, Override};
+use crate::aconfig::{Namespace, Override};
use crate::cache::Cache;
-use crate::protos::ProtoDump;
+use crate::protos::ProtoParsedFlags;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum Source {
@@ -46,15 +46,27 @@
pub reader: Box<dyn Read>,
}
-pub fn create_cache(build_id: u32, aconfigs: Vec<Input>, overrides: Vec<Input>) -> Result<Cache> {
- let mut cache = Cache::new(build_id);
+pub fn create_cache(
+ build_id: u32,
+ namespace: &str,
+ aconfigs: Vec<Input>,
+ overrides: Vec<Input>,
+) -> Result<Cache> {
+ let mut cache = Cache::new(build_id, namespace.to_owned());
for mut input in aconfigs {
let mut contents = String::new();
input.reader.read_to_string(&mut contents)?;
- let flags = Flag::try_from_text_proto_list(&contents)
+ let ns = Namespace::try_from_text_proto(&contents)
.with_context(|| format!("Failed to parse {}", input.source))?;
- for flag in flags {
+ ensure!(
+ namespace == ns.namespace,
+ "Failed to parse {}: expected namespace {}, got {}",
+ input.source,
+ namespace,
+ ns.namespace
+ );
+ for flag in ns.flags.into_iter() {
cache.add_flag(input.source.clone(), flag)?;
}
}
@@ -84,7 +96,7 @@
Format::Text => {
let mut lines = vec![];
for item in cache.iter() {
- lines.push(format!("{}: {:?}\n", item.id, item.state));
+ lines.push(format!("{}: {:?}\n", item.name, item.state));
}
Ok(lines.concat().into())
}
@@ -96,9 +108,9 @@
Ok(lines.concat().into())
}
Format::Protobuf => {
- let dump: ProtoDump = cache.into();
+ let parsed_flags: ProtoParsedFlags = cache.into();
let mut output = vec![];
- dump.write_to_vec(&mut output)?;
+ parsed_flags.write_to_vec(&mut output)?;
Ok(output)
}
}
@@ -111,8 +123,9 @@
fn create_test_cache() -> Cache {
let s = r#"
+ namespace: "ns"
flag {
- id: "a"
+ name: "a"
description: "Description of a"
value {
state: ENABLED
@@ -120,7 +133,7 @@
}
}
flag {
- id: "b"
+ name: "b"
description: "Description of b"
value {
state: ENABLED
@@ -130,20 +143,21 @@
"#;
let aconfigs = vec![Input { source: Source::Memory, reader: Box::new(s.as_bytes()) }];
let o = r#"
- override {
- id: "a"
+ flag_override {
+ namespace: "ns"
+ name: "a"
state: DISABLED
permission: READ_ONLY
}
"#;
let overrides = vec![Input { source: Source::Memory, reader: Box::new(o.as_bytes()) }];
- create_cache(1, aconfigs, overrides).unwrap()
+ create_cache(1, "ns", aconfigs, overrides).unwrap()
}
#[test]
fn test_create_cache() {
let cache = create_test_cache(); // calls create_cache
- let item = cache.iter().find(|&item| item.id == "a").unwrap();
+ let item = cache.iter().find(|&item| item.name == "a").unwrap();
assert_eq!(FlagState::Disabled, item.state);
assert_eq!(Permission::ReadOnly, item.permission);
}
@@ -158,15 +172,29 @@
#[test]
fn test_dump_protobuf_format() {
+ use crate::protos::{ProtoFlagPermission, ProtoFlagState, ProtoTracepoint};
use protobuf::Message;
let cache = create_test_cache();
let bytes = dump_cache(cache, Format::Protobuf).unwrap();
- let actual = ProtoDump::parse_from_bytes(&bytes).unwrap();
+ let actual = ProtoParsedFlags::parse_from_bytes(&bytes).unwrap();
assert_eq!(
vec!["a".to_string(), "b".to_string()],
- actual.item.iter().map(|item| item.id.clone().unwrap()).collect::<Vec<_>>()
+ actual.parsed_flag.iter().map(|item| item.name.clone().unwrap()).collect::<Vec<_>>()
);
+
+ let item =
+ actual.parsed_flag.iter().find(|item| item.name == Some("b".to_string())).unwrap();
+ assert_eq!(item.namespace(), "ns");
+ assert_eq!(item.name(), "b");
+ assert_eq!(item.description(), "Description of b");
+ assert_eq!(item.state(), ProtoFlagState::ENABLED);
+ assert_eq!(item.permission(), ProtoFlagPermission::READ_ONLY);
+ let mut tp = ProtoTracepoint::new();
+ tp.set_source("<memory>".to_string());
+ tp.set_state(ProtoFlagState::ENABLED);
+ tp.set_permission(ProtoFlagPermission::READ_ONLY);
+ assert_eq!(item.trace, vec![tp]);
}
}
diff --git a/tools/aconfig/src/main.rs b/tools/aconfig/src/main.rs
index dbff86e..f253735 100644
--- a/tools/aconfig/src/main.rs
+++ b/tools/aconfig/src/main.rs
@@ -41,6 +41,7 @@
.value_parser(clap::value_parser!(u32))
.required(true),
)
+ .arg(Arg::new("namespace").long("namespace").required(true))
.arg(Arg::new("aconfig").long("aconfig").action(ArgAction::Append))
.arg(Arg::new("override").long("override").action(ArgAction::Append))
.arg(Arg::new("cache").long("cache").required(true)),
@@ -72,9 +73,10 @@
match matches.subcommand() {
Some(("create-cache", sub_matches)) => {
let build_id = *sub_matches.get_one::<u32>("build-id").unwrap();
+ let namespace = sub_matches.get_one::<String>("namespace").unwrap();
let aconfigs = open_zero_or_more_files(sub_matches, "aconfig")?;
let overrides = open_zero_or_more_files(sub_matches, "override")?;
- let cache = commands::create_cache(build_id, aconfigs, overrides)?;
+ let cache = commands::create_cache(build_id, namespace, aconfigs, overrides)?;
let path = sub_matches.get_one::<String>("cache").unwrap();
let file = fs::File::create(path)?;
cache.write_to_writer(file)?;
diff --git a/tools/aconfig/src/protos.rs b/tools/aconfig/src/protos.rs
index f18a91d..5965a09 100644
--- a/tools/aconfig/src/protos.rs
+++ b/tools/aconfig/src/protos.rs
@@ -28,68 +28,68 @@
// ---- When building with the Android tool-chain ----
#[cfg(not(feature = "cargo"))]
-pub use aconfig_protos::aconfig::Android_config as ProtoAndroidConfig;
+pub use aconfig_protos::aconfig::Namespace as ProtoNamespace;
#[cfg(not(feature = "cargo"))]
-pub use aconfig_protos::aconfig::Value as ProtoValue;
+pub use aconfig_protos::aconfig::Flag_value as ProtoFlagDefinitionValue;
#[cfg(not(feature = "cargo"))]
-pub use aconfig_protos::aconfig::Flag as ProtoFlag;
+pub use aconfig_protos::aconfig::Flag_definition as ProtoFlagDefinition;
#[cfg(not(feature = "cargo"))]
-pub use aconfig_protos::aconfig::Override_config as ProtoOverrideConfig;
+pub use aconfig_protos::aconfig::Flag_overrides as ProtoFlagOverrides;
#[cfg(not(feature = "cargo"))]
-pub use aconfig_protos::aconfig::Override as ProtoOverride;
+pub use aconfig_protos::aconfig::Flag_override as ProtoFlagOverride;
#[cfg(not(feature = "cargo"))]
-pub use aconfig_protos::aconfig::Permission as ProtoPermission;
+pub use aconfig_protos::aconfig::Flag_permission as ProtoFlagPermission;
#[cfg(not(feature = "cargo"))]
pub use aconfig_protos::aconfig::Flag_state as ProtoFlagState;
#[cfg(not(feature = "cargo"))]
-pub use aconfig_protos::aconfig::Dump as ProtoDump;
+pub use aconfig_protos::aconfig::Parsed_flags as ProtoParsedFlags;
#[cfg(not(feature = "cargo"))]
-pub use aconfig_protos::aconfig::Dump_item as ProtoDumpItem;
+pub use aconfig_protos::aconfig::Parsed_flag as ProtoParsedFlag;
#[cfg(not(feature = "cargo"))]
-pub use aconfig_protos::aconfig::Dump_trace as ProtoDumpTracePoint;
+pub use aconfig_protos::aconfig::Tracepoint as ProtoTracepoint;
// ---- When building with cargo ----
#[cfg(feature = "cargo")]
include!(concat!(env!("OUT_DIR"), "/aconfig_proto/mod.rs"));
#[cfg(feature = "cargo")]
-pub use aconfig::Android_config as ProtoAndroidConfig;
+pub use aconfig::Namespace as ProtoNamespace;
#[cfg(feature = "cargo")]
-pub use aconfig::Value as ProtoValue;
+pub use aconfig::Flag_value as ProtoFlagDefinitionValue;
#[cfg(feature = "cargo")]
-pub use aconfig::Flag as ProtoFlag;
+pub use aconfig::Flag_definition as ProtoFlagDefinition;
#[cfg(feature = "cargo")]
-pub use aconfig::Override_config as ProtoOverrideConfig;
+pub use aconfig::Flag_overrides as ProtoFlagOverrides;
#[cfg(feature = "cargo")]
-pub use aconfig::Override as ProtoOverride;
+pub use aconfig::Flag_override as ProtoFlagOverride;
#[cfg(feature = "cargo")]
-pub use aconfig::Permission as ProtoPermission;
+pub use aconfig::Flag_permission as ProtoFlagPermission;
#[cfg(feature = "cargo")]
pub use aconfig::Flag_state as ProtoFlagState;
#[cfg(feature = "cargo")]
-pub use aconfig::Dump as ProtoDump;
+pub use aconfig::Parsed_flags as ProtoParsedFlags;
#[cfg(feature = "cargo")]
-pub use aconfig::Dump_item as ProtoDumpItem;
+pub use aconfig::Parsed_flag as ProtoParsedFlag;
#[cfg(feature = "cargo")]
-pub use aconfig::Dump_trace as ProtoDumpTracePoint;
+pub use aconfig::Tracepoint as ProtoTracepoint;
// ---- Common for both the Android tool-chain and cargo ----
use anyhow::Result;