Loading tools/aconfig/Cargo.toml +1 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ members = [ "aconfig", "aconfig_protos", "aconfig_storage_file", "aconfig_storage_read_api", "aflags", "printflags" ] Loading tools/aconfig/TEST_MAPPING +6 −2 Original line number Diff line number Diff line Loading @@ -69,13 +69,17 @@ } ], "postsubmit": [ { // aconfig_storage_read_api unit tests "name": "aconfig_storage_read_api.test" }, { // aconfig_storage read api rust integration tests "name": "aconfig_storage.test.rust" "name": "aconfig_storage_read_api.test.rust" }, { // aconfig_storage read api cpp integration tests "name": "aconfig_storage.test.cpp" "name": "aconfig_storage_read_api.test.cpp" }, { // aflags CLI unit tests Loading tools/aconfig/aconfig_storage_file/Android.bp +0 −89 Original line number Diff line number Diff line Loading @@ -9,12 +9,6 @@ rust_defaults { srcs: ["src/lib.rs"], rustlibs: [ "libanyhow", "libaconfig_storage_protos", "libonce_cell", "libprotobuf", "libtempfile", "libmemmap2", "libcxx", "libthiserror", ], } Loading @@ -26,91 +20,8 @@ rust_library { defaults: ["aconfig_storage_file.defaults"], } genrule { name: "ro.package.map", out: ["tests/tmp.ro.package.map"], srcs: ["tests/package.map"], cmd: "rm -f $(out);cp -f $(in) $(out);chmod -w $(out)", } genrule { name: "ro.flag.map", out: ["tests/tmp.ro.flag.map"], srcs: ["tests/flag.map"], cmd: "rm -f $(out);cp -f $(in) $(out);chmod -w $(out)", } genrule { name: "ro.flag.val", out: ["tests/tmp.ro.flag.val"], srcs: ["tests/flag.val"], cmd: "rm -f $(out);cp -f $(in) $(out);chmod -w $(out)", } rust_test_host { name: "aconfig_storage_file.test", test_suites: ["general-tests"], defaults: ["aconfig_storage_file.defaults"], data: [ "tests/package.map", "tests/flag.map", "tests/flag.val", ], } rust_protobuf { name: "libaconfig_storage_protos", protos: ["protos/aconfig_storage_metadata.proto"], crate_name: "aconfig_storage_protos", source_stem: "aconfig_storage_protos", host_supported: true, } cc_library_static { name: "libaconfig_storage_protos_cc", proto: { export_proto_headers: true, type: "lite", }, srcs: ["protos/aconfig_storage_metadata.proto"], apex_available: [ "//apex_available:platform", "//apex_available:anyapex", ], host_supported: true, } genrule { name: "libcxx_aconfig_storage_bridge_code", tools: ["cxxbridge"], cmd: "$(location cxxbridge) $(in) > $(out)", srcs: ["src/lib.rs"], out: ["aconfig_storage/lib.rs.cc"], } genrule { name: "libcxx_aconfig_storage_bridge_header", tools: ["cxxbridge"], cmd: "$(location cxxbridge) $(in) --header > $(out)", srcs: ["src/lib.rs"], out: ["aconfig_storage/lib.rs.h"], } rust_ffi_static { name: "libaconfig_storage_cxx_bridge", crate_name: "aconfig_storage_cxx_bridge", host_supported: true, defaults: ["aconfig_storage_file.defaults"], } cc_library_static { name: "libaconfig_storage_cc", srcs: ["aconfig_storage.cpp"], generated_headers: [ "cxx-bridge-header", "libcxx_aconfig_storage_bridge_header" ], generated_sources: ["libcxx_aconfig_storage_bridge_code"], whole_static_libs: ["libaconfig_storage_cxx_bridge"], export_include_dirs: ["include"], } tools/aconfig/aconfig_storage_file/src/flag_table.rs +1 −88 Original line number Diff line number Diff line Loading @@ -17,10 +17,9 @@ //! flag table module defines the flag table file format and methods for serialization //! and deserialization use crate::AconfigStorageError::{self, BytesParseFail, HigherStorageFileVersion}; use crate::AconfigStorageError::{self, BytesParseFail}; use crate::{get_bucket_index, read_str_from_bytes, read_u16_from_bytes, read_u32_from_bytes}; use anyhow::anyhow; pub type FlagOffset = u16; /// Flag table header struct #[derive(PartialEq, Debug)] Loading Loading @@ -154,44 +153,6 @@ impl FlagTable { } } /// Query flag within package offset pub fn find_flag_offset( buf: &[u8], package_id: u32, flag: &str, ) -> Result<Option<FlagOffset>, AconfigStorageError> { let interpreted_header = FlagTableHeader::from_bytes(buf)?; if interpreted_header.version > crate::FILE_VERSION { return Err(HigherStorageFileVersion(anyhow!( "Cannot read storage file with a higher version of {} with lib version {}", interpreted_header.version, crate::FILE_VERSION ))); } let num_buckets = (interpreted_header.node_offset - interpreted_header.bucket_offset) / 4; let bucket_index = FlagTableNode::find_bucket_index(package_id, flag, num_buckets); let mut pos = (interpreted_header.bucket_offset + 4 * bucket_index) as usize; let mut flag_node_offset = read_u32_from_bytes(buf, &mut pos)? as usize; if flag_node_offset < interpreted_header.node_offset as usize || flag_node_offset >= interpreted_header.file_size as usize { return Ok(None); } loop { let interpreted_node = FlagTableNode::from_bytes(&buf[flag_node_offset..])?; if interpreted_node.package_id == package_id && interpreted_node.flag_name == flag { return Ok(Some(interpreted_node.flag_id)); } match interpreted_node.next_offset { Some(offset) => flag_node_offset = offset as usize, None => return Ok(None), } } } #[cfg(test)] mod tests { use super::*; Loading Loading @@ -270,52 +231,4 @@ mod tests { assert!(reinterpreted_table.is_ok()); assert_eq!(&flag_table, &reinterpreted_table.unwrap()); } #[test] // this test point locks down table query fn test_flag_query() { let flag_table = create_test_flag_table().as_bytes(); let baseline = vec![ (0, "enabled_ro", 1u16), (0, "enabled_rw", 2u16), (1, "disabled_ro", 0u16), (2, "enabled_ro", 1u16), (1, "enabled_fixed_ro", 1u16), (1, "enabled_ro", 2u16), (2, "enabled_fixed_ro", 0u16), (0, "disabled_rw", 0u16), ]; for (package_id, flag_name, expected_offset) in baseline.into_iter() { let flag_offset = find_flag_offset(&flag_table[..], package_id, flag_name).unwrap().unwrap(); assert_eq!(flag_offset, expected_offset); } } #[test] // this test point locks down table query of a non exist flag fn test_not_existed_flag_query() { let flag_table = create_test_flag_table().as_bytes(); let flag_offset = find_flag_offset(&flag_table[..], 1, "disabled_fixed_ro").unwrap(); assert_eq!(flag_offset, None); let flag_offset = find_flag_offset(&flag_table[..], 2, "disabled_rw").unwrap(); assert_eq!(flag_offset, None); } #[test] // this test point locks down query error when file has a higher version fn test_higher_version_storage_file() { let mut table = create_test_flag_table(); table.header.version = crate::FILE_VERSION + 1; let flag_table = table.as_bytes(); let error = find_flag_offset(&flag_table[..], 0, "enabled_ro").unwrap_err(); assert_eq!( format!("{:?}", error), format!( "HigherStorageFileVersion(Cannot read storage file with a higher version of {} with lib version {})", crate::FILE_VERSION + 1, crate::FILE_VERSION ) ); } } tools/aconfig/aconfig_storage_file/src/flag_value.rs +1 −66 Original line number Diff line number Diff line Loading @@ -17,9 +17,8 @@ //! flag value module defines the flag value file format and methods for serialization //! and deserialization use crate::AconfigStorageError::{self, HigherStorageFileVersion, InvalidStorageFileOffset}; use crate::AconfigStorageError; use crate::{read_str_from_bytes, read_u32_from_bytes, read_u8_from_bytes}; use anyhow::anyhow; /// Flag value header struct #[derive(PartialEq, Debug)] Loading Loading @@ -87,31 +86,6 @@ impl FlagValueList { } } /// Query flag value pub fn find_boolean_flag_value(buf: &[u8], flag_offset: u32) -> Result<bool, AconfigStorageError> { let interpreted_header = FlagValueHeader::from_bytes(buf)?; if interpreted_header.version > crate::FILE_VERSION { return Err(HigherStorageFileVersion(anyhow!( "Cannot read storage file with a higher version of {} with lib version {}", interpreted_header.version, crate::FILE_VERSION ))); } let mut head = (interpreted_header.boolean_value_offset + flag_offset) as usize; // TODO: right now, there is only boolean flags, with more flag value types added // later, the end of boolean flag value section should be updated (b/322826265). if head >= interpreted_header.file_size as usize { return Err(InvalidStorageFileOffset(anyhow!( "Flag value offset goes beyond the end of the file." ))); } let val = read_u8_from_bytes(buf, &mut head)?; Ok(val == 1) } #[cfg(test)] mod tests { use super::*; Loading Loading @@ -142,43 +116,4 @@ mod tests { assert!(reinterpreted_value_list.is_ok()); assert_eq!(&flag_value_list, &reinterpreted_value_list.unwrap()); } #[test] // this test point locks down flag value query fn test_flag_value_query() { let flag_value_list = create_test_flag_value_list().as_bytes(); let baseline: Vec<bool> = vec![false, true, false, false, true, true, false, true]; for (offset, expected_value) in baseline.into_iter().enumerate() { let flag_value = find_boolean_flag_value(&flag_value_list[..], offset as u32).unwrap(); assert_eq!(flag_value, expected_value); } } #[test] // this test point locks down query beyond the end of boolean section fn test_boolean_out_of_range() { let flag_value_list = create_test_flag_value_list().as_bytes(); let error = find_boolean_flag_value(&flag_value_list[..], 8).unwrap_err(); assert_eq!( format!("{:?}", error), "InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)" ); } #[test] // this test point locks down query error when file has a higher version fn test_higher_version_storage_file() { let mut value_list = create_test_flag_value_list(); value_list.header.version = crate::FILE_VERSION + 1; let flag_value = value_list.as_bytes(); let error = find_boolean_flag_value(&flag_value[..], 4).unwrap_err(); assert_eq!( format!("{:?}", error), format!( "HigherStorageFileVersion(Cannot read storage file with a higher version of {} with lib version {})", crate::FILE_VERSION + 1, crate::FILE_VERSION ) ); } } Loading
tools/aconfig/Cargo.toml +1 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ members = [ "aconfig", "aconfig_protos", "aconfig_storage_file", "aconfig_storage_read_api", "aflags", "printflags" ] Loading
tools/aconfig/TEST_MAPPING +6 −2 Original line number Diff line number Diff line Loading @@ -69,13 +69,17 @@ } ], "postsubmit": [ { // aconfig_storage_read_api unit tests "name": "aconfig_storage_read_api.test" }, { // aconfig_storage read api rust integration tests "name": "aconfig_storage.test.rust" "name": "aconfig_storage_read_api.test.rust" }, { // aconfig_storage read api cpp integration tests "name": "aconfig_storage.test.cpp" "name": "aconfig_storage_read_api.test.cpp" }, { // aflags CLI unit tests Loading
tools/aconfig/aconfig_storage_file/Android.bp +0 −89 Original line number Diff line number Diff line Loading @@ -9,12 +9,6 @@ rust_defaults { srcs: ["src/lib.rs"], rustlibs: [ "libanyhow", "libaconfig_storage_protos", "libonce_cell", "libprotobuf", "libtempfile", "libmemmap2", "libcxx", "libthiserror", ], } Loading @@ -26,91 +20,8 @@ rust_library { defaults: ["aconfig_storage_file.defaults"], } genrule { name: "ro.package.map", out: ["tests/tmp.ro.package.map"], srcs: ["tests/package.map"], cmd: "rm -f $(out);cp -f $(in) $(out);chmod -w $(out)", } genrule { name: "ro.flag.map", out: ["tests/tmp.ro.flag.map"], srcs: ["tests/flag.map"], cmd: "rm -f $(out);cp -f $(in) $(out);chmod -w $(out)", } genrule { name: "ro.flag.val", out: ["tests/tmp.ro.flag.val"], srcs: ["tests/flag.val"], cmd: "rm -f $(out);cp -f $(in) $(out);chmod -w $(out)", } rust_test_host { name: "aconfig_storage_file.test", test_suites: ["general-tests"], defaults: ["aconfig_storage_file.defaults"], data: [ "tests/package.map", "tests/flag.map", "tests/flag.val", ], } rust_protobuf { name: "libaconfig_storage_protos", protos: ["protos/aconfig_storage_metadata.proto"], crate_name: "aconfig_storage_protos", source_stem: "aconfig_storage_protos", host_supported: true, } cc_library_static { name: "libaconfig_storage_protos_cc", proto: { export_proto_headers: true, type: "lite", }, srcs: ["protos/aconfig_storage_metadata.proto"], apex_available: [ "//apex_available:platform", "//apex_available:anyapex", ], host_supported: true, } genrule { name: "libcxx_aconfig_storage_bridge_code", tools: ["cxxbridge"], cmd: "$(location cxxbridge) $(in) > $(out)", srcs: ["src/lib.rs"], out: ["aconfig_storage/lib.rs.cc"], } genrule { name: "libcxx_aconfig_storage_bridge_header", tools: ["cxxbridge"], cmd: "$(location cxxbridge) $(in) --header > $(out)", srcs: ["src/lib.rs"], out: ["aconfig_storage/lib.rs.h"], } rust_ffi_static { name: "libaconfig_storage_cxx_bridge", crate_name: "aconfig_storage_cxx_bridge", host_supported: true, defaults: ["aconfig_storage_file.defaults"], } cc_library_static { name: "libaconfig_storage_cc", srcs: ["aconfig_storage.cpp"], generated_headers: [ "cxx-bridge-header", "libcxx_aconfig_storage_bridge_header" ], generated_sources: ["libcxx_aconfig_storage_bridge_code"], whole_static_libs: ["libaconfig_storage_cxx_bridge"], export_include_dirs: ["include"], }
tools/aconfig/aconfig_storage_file/src/flag_table.rs +1 −88 Original line number Diff line number Diff line Loading @@ -17,10 +17,9 @@ //! flag table module defines the flag table file format and methods for serialization //! and deserialization use crate::AconfigStorageError::{self, BytesParseFail, HigherStorageFileVersion}; use crate::AconfigStorageError::{self, BytesParseFail}; use crate::{get_bucket_index, read_str_from_bytes, read_u16_from_bytes, read_u32_from_bytes}; use anyhow::anyhow; pub type FlagOffset = u16; /// Flag table header struct #[derive(PartialEq, Debug)] Loading Loading @@ -154,44 +153,6 @@ impl FlagTable { } } /// Query flag within package offset pub fn find_flag_offset( buf: &[u8], package_id: u32, flag: &str, ) -> Result<Option<FlagOffset>, AconfigStorageError> { let interpreted_header = FlagTableHeader::from_bytes(buf)?; if interpreted_header.version > crate::FILE_VERSION { return Err(HigherStorageFileVersion(anyhow!( "Cannot read storage file with a higher version of {} with lib version {}", interpreted_header.version, crate::FILE_VERSION ))); } let num_buckets = (interpreted_header.node_offset - interpreted_header.bucket_offset) / 4; let bucket_index = FlagTableNode::find_bucket_index(package_id, flag, num_buckets); let mut pos = (interpreted_header.bucket_offset + 4 * bucket_index) as usize; let mut flag_node_offset = read_u32_from_bytes(buf, &mut pos)? as usize; if flag_node_offset < interpreted_header.node_offset as usize || flag_node_offset >= interpreted_header.file_size as usize { return Ok(None); } loop { let interpreted_node = FlagTableNode::from_bytes(&buf[flag_node_offset..])?; if interpreted_node.package_id == package_id && interpreted_node.flag_name == flag { return Ok(Some(interpreted_node.flag_id)); } match interpreted_node.next_offset { Some(offset) => flag_node_offset = offset as usize, None => return Ok(None), } } } #[cfg(test)] mod tests { use super::*; Loading Loading @@ -270,52 +231,4 @@ mod tests { assert!(reinterpreted_table.is_ok()); assert_eq!(&flag_table, &reinterpreted_table.unwrap()); } #[test] // this test point locks down table query fn test_flag_query() { let flag_table = create_test_flag_table().as_bytes(); let baseline = vec![ (0, "enabled_ro", 1u16), (0, "enabled_rw", 2u16), (1, "disabled_ro", 0u16), (2, "enabled_ro", 1u16), (1, "enabled_fixed_ro", 1u16), (1, "enabled_ro", 2u16), (2, "enabled_fixed_ro", 0u16), (0, "disabled_rw", 0u16), ]; for (package_id, flag_name, expected_offset) in baseline.into_iter() { let flag_offset = find_flag_offset(&flag_table[..], package_id, flag_name).unwrap().unwrap(); assert_eq!(flag_offset, expected_offset); } } #[test] // this test point locks down table query of a non exist flag fn test_not_existed_flag_query() { let flag_table = create_test_flag_table().as_bytes(); let flag_offset = find_flag_offset(&flag_table[..], 1, "disabled_fixed_ro").unwrap(); assert_eq!(flag_offset, None); let flag_offset = find_flag_offset(&flag_table[..], 2, "disabled_rw").unwrap(); assert_eq!(flag_offset, None); } #[test] // this test point locks down query error when file has a higher version fn test_higher_version_storage_file() { let mut table = create_test_flag_table(); table.header.version = crate::FILE_VERSION + 1; let flag_table = table.as_bytes(); let error = find_flag_offset(&flag_table[..], 0, "enabled_ro").unwrap_err(); assert_eq!( format!("{:?}", error), format!( "HigherStorageFileVersion(Cannot read storage file with a higher version of {} with lib version {})", crate::FILE_VERSION + 1, crate::FILE_VERSION ) ); } }
tools/aconfig/aconfig_storage_file/src/flag_value.rs +1 −66 Original line number Diff line number Diff line Loading @@ -17,9 +17,8 @@ //! flag value module defines the flag value file format and methods for serialization //! and deserialization use crate::AconfigStorageError::{self, HigherStorageFileVersion, InvalidStorageFileOffset}; use crate::AconfigStorageError; use crate::{read_str_from_bytes, read_u32_from_bytes, read_u8_from_bytes}; use anyhow::anyhow; /// Flag value header struct #[derive(PartialEq, Debug)] Loading Loading @@ -87,31 +86,6 @@ impl FlagValueList { } } /// Query flag value pub fn find_boolean_flag_value(buf: &[u8], flag_offset: u32) -> Result<bool, AconfigStorageError> { let interpreted_header = FlagValueHeader::from_bytes(buf)?; if interpreted_header.version > crate::FILE_VERSION { return Err(HigherStorageFileVersion(anyhow!( "Cannot read storage file with a higher version of {} with lib version {}", interpreted_header.version, crate::FILE_VERSION ))); } let mut head = (interpreted_header.boolean_value_offset + flag_offset) as usize; // TODO: right now, there is only boolean flags, with more flag value types added // later, the end of boolean flag value section should be updated (b/322826265). if head >= interpreted_header.file_size as usize { return Err(InvalidStorageFileOffset(anyhow!( "Flag value offset goes beyond the end of the file." ))); } let val = read_u8_from_bytes(buf, &mut head)?; Ok(val == 1) } #[cfg(test)] mod tests { use super::*; Loading Loading @@ -142,43 +116,4 @@ mod tests { assert!(reinterpreted_value_list.is_ok()); assert_eq!(&flag_value_list, &reinterpreted_value_list.unwrap()); } #[test] // this test point locks down flag value query fn test_flag_value_query() { let flag_value_list = create_test_flag_value_list().as_bytes(); let baseline: Vec<bool> = vec![false, true, false, false, true, true, false, true]; for (offset, expected_value) in baseline.into_iter().enumerate() { let flag_value = find_boolean_flag_value(&flag_value_list[..], offset as u32).unwrap(); assert_eq!(flag_value, expected_value); } } #[test] // this test point locks down query beyond the end of boolean section fn test_boolean_out_of_range() { let flag_value_list = create_test_flag_value_list().as_bytes(); let error = find_boolean_flag_value(&flag_value_list[..], 8).unwrap_err(); assert_eq!( format!("{:?}", error), "InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)" ); } #[test] // this test point locks down query error when file has a higher version fn test_higher_version_storage_file() { let mut value_list = create_test_flag_value_list(); value_list.header.version = crate::FILE_VERSION + 1; let flag_value = value_list.as_bytes(); let error = find_boolean_flag_value(&flag_value[..], 4).unwrap_err(); assert_eq!( format!("{:?}", error), format!( "HigherStorageFileVersion(Cannot read storage file with a higher version of {} with lib version {})", crate::FILE_VERSION + 1, crate::FILE_VERSION ) ); } }