aconfig: add flag info read rust api
Bug: b/321077378 Test: atest aconfig_storage_read_api.test; atest aconfig_storage_read_api.test.rust Change-Id: I382ac0145c5d91827952b3ddb01cabefd1539854
This commit is contained in:
parent
eff5363e2d
commit
2ac7a4c2bd
10 changed files with 219 additions and 45 deletions
|
@ -91,9 +91,9 @@ impl FlagInfoHeader {
|
||||||
/// bit field for flag info
|
/// bit field for flag info
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum FlagInfoBit {
|
pub enum FlagInfoBit {
|
||||||
IsSticky = 0,
|
IsSticky = 1 << 0,
|
||||||
IsReadWrite = 1,
|
IsReadWrite = 1 << 1,
|
||||||
HasOverride = 2,
|
HasOverride = 1 << 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flag info node struct
|
/// Flag info node struct
|
||||||
|
@ -108,9 +108,9 @@ impl fmt::Debug for FlagInfoNode {
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
"sticky: {}, readwrite: {}, override: {}",
|
"sticky: {}, readwrite: {}, override: {}",
|
||||||
self.attributes & (FlagInfoBit::IsSticky as u8),
|
self.attributes & (FlagInfoBit::IsSticky as u8) != 0,
|
||||||
self.attributes & (FlagInfoBit::IsReadWrite as u8),
|
self.attributes & (FlagInfoBit::IsReadWrite as u8) != 0,
|
||||||
self.attributes & (FlagInfoBit::HasOverride as u8),
|
self.attributes & (FlagInfoBit::HasOverride as u8) != 0,
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ use std::fs::File;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
pub use crate::flag_info::{FlagInfoHeader, FlagInfoList, FlagInfoNode};
|
pub use crate::flag_info::{FlagInfoHeader, FlagInfoList, FlagInfoNode, FlagInfoBit};
|
||||||
pub use crate::flag_table::{FlagTable, FlagTableHeader, FlagTableNode};
|
pub use crate::flag_table::{FlagTable, FlagTableHeader, FlagTableNode};
|
||||||
pub use crate::flag_value::{FlagValueHeader, FlagValueList};
|
pub use crate::flag_value::{FlagValueHeader, FlagValueList};
|
||||||
pub use crate::package_table::{PackageTable, PackageTableHeader, PackageTableNode};
|
pub use crate::package_table::{PackageTable, PackageTableHeader, PackageTableNode};
|
||||||
|
|
|
@ -38,6 +38,7 @@ rust_test_host {
|
||||||
"tests/package.map",
|
"tests/package.map",
|
||||||
"tests/flag.map",
|
"tests/flag.map",
|
||||||
"tests/flag.val",
|
"tests/flag.val",
|
||||||
|
"tests/flag.info",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
115
tools/aconfig/aconfig_storage_read_api/src/flag_info_query.rs
Normal file
115
tools/aconfig/aconfig_storage_read_api/src/flag_info_query.rs
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//! flag value query module defines the flag value file read from mapped bytes
|
||||||
|
|
||||||
|
use crate::{AconfigStorageError, FILE_VERSION};
|
||||||
|
use aconfig_storage_file::{flag_info::FlagInfoHeader, read_u8_from_bytes};
|
||||||
|
use anyhow::anyhow;
|
||||||
|
|
||||||
|
/// Get flag attribute bitfield
|
||||||
|
pub fn find_boolean_flag_attribute(
|
||||||
|
buf: &[u8],
|
||||||
|
flag_offset: u32,
|
||||||
|
) -> Result<u8, AconfigStorageError> {
|
||||||
|
let interpreted_header = FlagInfoHeader::from_bytes(buf)?;
|
||||||
|
if interpreted_header.version > crate::FILE_VERSION {
|
||||||
|
return Err(AconfigStorageError::HigherStorageFileVersion(anyhow!(
|
||||||
|
"Cannot read storage file with a higher version of {} with lib version {}",
|
||||||
|
interpreted_header.version,
|
||||||
|
FILE_VERSION
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut head = (interpreted_header.boolean_flag_offset + flag_offset) as usize;
|
||||||
|
|
||||||
|
if head >= interpreted_header.file_size as usize {
|
||||||
|
return Err(AconfigStorageError::InvalidStorageFileOffset(anyhow!(
|
||||||
|
"Flag info offset goes beyond the end of the file."
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let val = read_u8_from_bytes(buf, &mut head)?;
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use aconfig_storage_file::{test_utils::create_test_flag_info_list, FlagInfoBit};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// this test point locks down query if flag is sticky
|
||||||
|
fn test_is_flag_sticky() {
|
||||||
|
let flag_info_list = create_test_flag_info_list().into_bytes();
|
||||||
|
for offset in 0..8 {
|
||||||
|
let attribute = find_boolean_flag_attribute(&flag_info_list[..], offset).unwrap();
|
||||||
|
assert_eq!((attribute & FlagInfoBit::IsSticky as u8) != 0u8, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// this test point locks down query if flag is readwrite
|
||||||
|
fn test_is_flag_readwrite() {
|
||||||
|
let flag_info_list = create_test_flag_info_list().into_bytes();
|
||||||
|
let baseline: Vec<bool> = vec![true, false, true, false, false, false, false, false];
|
||||||
|
for offset in 0..8 {
|
||||||
|
let attribute = find_boolean_flag_attribute(&flag_info_list[..], offset).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
(attribute & FlagInfoBit::IsReadWrite as u8) != 0u8,
|
||||||
|
baseline[offset as usize]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// this test point locks down query if flag has override
|
||||||
|
fn test_flag_has_override() {
|
||||||
|
let flag_info_list = create_test_flag_info_list().into_bytes();
|
||||||
|
for offset in 0..8 {
|
||||||
|
let attribute = find_boolean_flag_attribute(&flag_info_list[..], offset).unwrap();
|
||||||
|
assert_eq!((attribute & FlagInfoBit::HasOverride as u8) != 0u8, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// this test point locks down query beyond the end of boolean section
|
||||||
|
fn test_boolean_out_of_range() {
|
||||||
|
let flag_info_list = create_test_flag_info_list().into_bytes();
|
||||||
|
let error = find_boolean_flag_attribute(&flag_info_list[..], 8).unwrap_err();
|
||||||
|
assert_eq!(
|
||||||
|
format!("{:?}", error),
|
||||||
|
"InvalidStorageFileOffset(Flag info 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 info_list = create_test_flag_info_list();
|
||||||
|
info_list.header.version = crate::FILE_VERSION + 1;
|
||||||
|
let flag_info = info_list.into_bytes();
|
||||||
|
let error = find_boolean_flag_attribute(&flag_info[..], 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
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,26 +48,13 @@ pub fn find_boolean_flag_value(buf: &[u8], flag_offset: u32) -> Result<bool, Aco
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use aconfig_storage_file::{FlagValueList, StorageFileType};
|
use aconfig_storage_file::test_utils::create_test_flag_value_list;
|
||||||
|
|
||||||
pub fn create_test_flag_value_list() -> FlagValueList {
|
|
||||||
let header = FlagValueHeader {
|
|
||||||
version: crate::FILE_VERSION,
|
|
||||||
container: String::from("system"),
|
|
||||||
file_type: StorageFileType::FlagVal as u8,
|
|
||||||
file_size: 35,
|
|
||||||
num_flags: 8,
|
|
||||||
boolean_value_offset: 27,
|
|
||||||
};
|
|
||||||
let booleans: Vec<bool> = vec![false, true, false, false, true, true, false, true];
|
|
||||||
FlagValueList { header, booleans }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
// this test point locks down flag value query
|
// this test point locks down flag value query
|
||||||
fn test_flag_value_query() {
|
fn test_flag_value_query() {
|
||||||
let flag_value_list = create_test_flag_value_list().into_bytes();
|
let flag_value_list = create_test_flag_value_list().into_bytes();
|
||||||
let baseline: Vec<bool> = vec![false, true, false, false, true, true, false, true];
|
let baseline: Vec<bool> = vec![false, true, true, false, true, true, true, true];
|
||||||
for (offset, expected_value) in baseline.into_iter().enumerate() {
|
for (offset, expected_value) in baseline.into_iter().enumerate() {
|
||||||
let flag_value = find_boolean_flag_value(&flag_value_list[..], offset as u32).unwrap();
|
let flag_value = find_boolean_flag_value(&flag_value_list[..], offset as u32).unwrap();
|
||||||
assert_eq!(flag_value, expected_value);
|
assert_eq!(flag_value, expected_value);
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
//! apis. DO NOT DIRECTLY USE THESE APIS IN YOUR SOURCE CODE. For auto generated flag apis
|
//! apis. DO NOT DIRECTLY USE THESE APIS IN YOUR SOURCE CODE. For auto generated flag apis
|
||||||
//! please refer to the g3doc go/android-flags
|
//! please refer to the g3doc go/android-flags
|
||||||
|
|
||||||
|
pub mod flag_info_query;
|
||||||
pub mod flag_table_query;
|
pub mod flag_table_query;
|
||||||
pub mod flag_value_query;
|
pub mod flag_value_query;
|
||||||
pub mod mapped_file;
|
pub mod mapped_file;
|
||||||
|
@ -47,6 +48,7 @@ pub use flag_table_query::FlagOffset;
|
||||||
pub use package_table_query::PackageOffset;
|
pub use package_table_query::PackageOffset;
|
||||||
|
|
||||||
use aconfig_storage_file::{read_u32_from_bytes, FILE_VERSION};
|
use aconfig_storage_file::{read_u32_from_bytes, FILE_VERSION};
|
||||||
|
use flag_info_query::find_boolean_flag_attribute;
|
||||||
use flag_table_query::find_flag_offset;
|
use flag_table_query::find_flag_offset;
|
||||||
use flag_value_query::find_boolean_flag_value;
|
use flag_value_query::find_boolean_flag_value;
|
||||||
use package_table_query::find_package_offset;
|
use package_table_query::find_package_offset;
|
||||||
|
@ -145,6 +147,18 @@ pub fn get_storage_file_version(file_path: &str) -> Result<u32, AconfigStorageEr
|
||||||
read_u32_from_bytes(&buffer, &mut head)
|
read_u32_from_bytes(&buffer, &mut head)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the boolean flag attribute.
|
||||||
|
///
|
||||||
|
/// \input file: mapped flag info file
|
||||||
|
/// \input offset: boolean flag offset
|
||||||
|
///
|
||||||
|
/// \return
|
||||||
|
/// If the provide offset is valid, it returns the boolean flag attribute bitfiled, otherwise it
|
||||||
|
/// returns the error message.
|
||||||
|
pub fn get_boolean_flag_attribute(file: &Mmap, offset: u32) -> Result<u8, AconfigStorageError> {
|
||||||
|
find_boolean_flag_attribute(file, offset)
|
||||||
|
}
|
||||||
|
|
||||||
// *************************************** //
|
// *************************************** //
|
||||||
// CC INTERLOP
|
// CC INTERLOP
|
||||||
// *************************************** //
|
// *************************************** //
|
||||||
|
@ -315,12 +329,14 @@ mod tests {
|
||||||
use crate::mapped_file::get_mapped_file;
|
use crate::mapped_file::get_mapped_file;
|
||||||
use crate::test_utils::copy_to_temp_file;
|
use crate::test_utils::copy_to_temp_file;
|
||||||
use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
|
use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
|
||||||
|
use aconfig_storage_file::FlagInfoBit;
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
fn create_test_storage_files() -> [NamedTempFile; 4] {
|
fn create_test_storage_files() -> [NamedTempFile; 5] {
|
||||||
let package_map = copy_to_temp_file("./tests/package.map").unwrap();
|
let package_map = copy_to_temp_file("./tests/package.map").unwrap();
|
||||||
let flag_map = copy_to_temp_file("./tests/flag.map").unwrap();
|
let flag_map = copy_to_temp_file("./tests/flag.map").unwrap();
|
||||||
let flag_val = copy_to_temp_file("./tests/flag.val").unwrap();
|
let flag_val = copy_to_temp_file("./tests/flag.val").unwrap();
|
||||||
|
let flag_info = copy_to_temp_file("./tests/flag.info").unwrap();
|
||||||
|
|
||||||
let text_proto = format!(
|
let text_proto = format!(
|
||||||
r#"
|
r#"
|
||||||
|
@ -330,21 +346,23 @@ files {{
|
||||||
package_map: "{}"
|
package_map: "{}"
|
||||||
flag_map: "{}"
|
flag_map: "{}"
|
||||||
flag_val: "{}"
|
flag_val: "{}"
|
||||||
|
flag_info: "{}"
|
||||||
timestamp: 12345
|
timestamp: 12345
|
||||||
}}
|
}}
|
||||||
"#,
|
"#,
|
||||||
package_map.path().display(),
|
package_map.path().display(),
|
||||||
flag_map.path().display(),
|
flag_map.path().display(),
|
||||||
flag_val.path().display()
|
flag_val.path().display(),
|
||||||
|
flag_info.path().display()
|
||||||
);
|
);
|
||||||
let pb_file = write_proto_to_temp_file(&text_proto).unwrap();
|
let pb_file = write_proto_to_temp_file(&text_proto).unwrap();
|
||||||
[package_map, flag_map, flag_val, pb_file]
|
[package_map, flag_map, flag_val, flag_info, pb_file]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
// this test point locks down flag package offset query
|
// this test point locks down flag package offset query
|
||||||
fn test_package_offset_query() {
|
fn test_package_offset_query() {
|
||||||
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
let pb_file_path = pb_file.path().display().to_string();
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
let package_mapped_file = unsafe {
|
let package_mapped_file = unsafe {
|
||||||
get_mapped_file(&pb_file_path, "mockup", StorageFileType::PackageMap).unwrap()
|
get_mapped_file(&pb_file_path, "mockup", StorageFileType::PackageMap).unwrap()
|
||||||
|
@ -375,7 +393,7 @@ files {{
|
||||||
#[test]
|
#[test]
|
||||||
// this test point locks down flag offset query
|
// this test point locks down flag offset query
|
||||||
fn test_flag_offset_query() {
|
fn test_flag_offset_query() {
|
||||||
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
let pb_file_path = pb_file.path().display().to_string();
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
let flag_mapped_file =
|
let flag_mapped_file =
|
||||||
unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagMap).unwrap() };
|
unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagMap).unwrap() };
|
||||||
|
@ -398,9 +416,9 @@ files {{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
// this test point locks down flag offset query
|
// this test point locks down flag value query
|
||||||
fn test_flag_value_query() {
|
fn test_flag_value_query() {
|
||||||
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
let pb_file_path = pb_file.path().display().to_string();
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
let flag_value_file =
|
let flag_value_file =
|
||||||
unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagVal).unwrap() };
|
unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagVal).unwrap() };
|
||||||
|
@ -411,11 +429,28 @@ files {{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// this test point locks donw flag info query
|
||||||
|
fn test_flag_info_query() {
|
||||||
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
|
let flag_info_file =
|
||||||
|
unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagInfo).unwrap() };
|
||||||
|
let is_rw: Vec<bool> = vec![true, false, true, false, false, false, false, false];
|
||||||
|
for (offset, expected_value) in is_rw.into_iter().enumerate() {
|
||||||
|
let attribute = get_boolean_flag_attribute(&flag_info_file, offset as u32).unwrap();
|
||||||
|
assert!((attribute & FlagInfoBit::IsSticky as u8) == 0u8);
|
||||||
|
assert_eq!((attribute & FlagInfoBit::IsReadWrite as u8) != 0u8, expected_value);
|
||||||
|
assert!((attribute & FlagInfoBit::HasOverride as u8) == 0u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
// this test point locks down flag storage file version number query api
|
// this test point locks down flag storage file version number query api
|
||||||
fn test_storage_version_query() {
|
fn test_storage_version_query() {
|
||||||
assert_eq!(get_storage_file_version("./tests/package.map").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./tests/package.map").unwrap(), 1);
|
||||||
assert_eq!(get_storage_file_version("./tests/flag.map").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./tests/flag.map").unwrap(), 1);
|
||||||
assert_eq!(get_storage_file_version("./tests/flag.val").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./tests/flag.val").unwrap(), 1);
|
||||||
|
assert_eq!(get_storage_file_version("./tests/flag.info").unwrap(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,9 +91,7 @@ pub unsafe fn get_mapped_file(
|
||||||
StorageFileType::PackageMap => unsafe { map_file(files_location.package_map()) },
|
StorageFileType::PackageMap => unsafe { map_file(files_location.package_map()) },
|
||||||
StorageFileType::FlagMap => unsafe { map_file(files_location.flag_map()) },
|
StorageFileType::FlagMap => unsafe { map_file(files_location.flag_map()) },
|
||||||
StorageFileType::FlagVal => unsafe { map_file(files_location.flag_val()) },
|
StorageFileType::FlagVal => unsafe { map_file(files_location.flag_val()) },
|
||||||
StorageFileType::FlagInfo => {
|
StorageFileType::FlagInfo => unsafe { map_file(files_location.flag_info()) },
|
||||||
Err(MapFileFail(anyhow!("TODO: add support for flag info file")))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ rust_test {
|
||||||
"package.map",
|
"package.map",
|
||||||
"flag.map",
|
"flag.map",
|
||||||
"flag.val",
|
"flag.val",
|
||||||
|
"flag.info",
|
||||||
],
|
],
|
||||||
test_suites: ["general-tests"],
|
test_suites: ["general-tests"],
|
||||||
}
|
}
|
||||||
|
@ -35,6 +36,7 @@ cc_test {
|
||||||
"package.map",
|
"package.map",
|
||||||
"flag.map",
|
"flag.map",
|
||||||
"flag.val",
|
"flag.val",
|
||||||
|
"flag.info",
|
||||||
],
|
],
|
||||||
test_suites: [
|
test_suites: [
|
||||||
"device-tests",
|
"device-tests",
|
||||||
|
|
BIN
tools/aconfig/aconfig_storage_read_api/tests/flag.info
Normal file
BIN
tools/aconfig/aconfig_storage_read_api/tests/flag.info
Normal file
Binary file not shown.
|
@ -1,10 +1,10 @@
|
||||||
#[cfg(not(feature = "cargo"))]
|
#[cfg(not(feature = "cargo"))]
|
||||||
mod aconfig_storage_rust_test {
|
mod aconfig_storage_rust_test {
|
||||||
use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
|
use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
|
||||||
use aconfig_storage_file::StorageFileType;
|
use aconfig_storage_file::{FlagInfoBit, StorageFileType};
|
||||||
use aconfig_storage_read_api::{
|
use aconfig_storage_read_api::{
|
||||||
get_boolean_flag_value, get_flag_offset, get_package_offset, get_storage_file_version,
|
get_boolean_flag_attribute, get_boolean_flag_value, get_flag_offset, get_package_offset,
|
||||||
mapped_file::get_mapped_file, PackageOffset,
|
get_storage_file_version, mapped_file::get_mapped_file, PackageOffset,
|
||||||
};
|
};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
@ -15,10 +15,11 @@ mod aconfig_storage_rust_test {
|
||||||
file
|
file
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_test_storage_files() -> [NamedTempFile; 4] {
|
fn create_test_storage_files() -> [NamedTempFile; 5] {
|
||||||
let package_map = copy_to_temp_file("./package.map");
|
let package_map = copy_to_temp_file("./package.map");
|
||||||
let flag_map = copy_to_temp_file("./flag.map");
|
let flag_map = copy_to_temp_file("./flag.map");
|
||||||
let flag_val = copy_to_temp_file("./flag.val");
|
let flag_val = copy_to_temp_file("./flag.val");
|
||||||
|
let flag_info = copy_to_temp_file("./flag.info");
|
||||||
|
|
||||||
let text_proto = format!(
|
let text_proto = format!(
|
||||||
r#"
|
r#"
|
||||||
|
@ -28,20 +29,22 @@ files {{
|
||||||
package_map: "{}"
|
package_map: "{}"
|
||||||
flag_map: "{}"
|
flag_map: "{}"
|
||||||
flag_val: "{}"
|
flag_val: "{}"
|
||||||
|
flag_info: "{}"
|
||||||
timestamp: 12345
|
timestamp: 12345
|
||||||
}}
|
}}
|
||||||
"#,
|
"#,
|
||||||
package_map.path().display(),
|
package_map.path().display(),
|
||||||
flag_map.path().display(),
|
flag_map.path().display(),
|
||||||
flag_val.path().display()
|
flag_val.path().display(),
|
||||||
|
flag_info.path().display()
|
||||||
);
|
);
|
||||||
let pb_file = write_proto_to_temp_file(&text_proto).unwrap();
|
let pb_file = write_proto_to_temp_file(&text_proto).unwrap();
|
||||||
[package_map, flag_map, flag_val, pb_file]
|
[package_map, flag_map, flag_val, flag_info, pb_file]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_unavailable_stoarge() {
|
fn test_unavailable_stoarge() {
|
||||||
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
let pb_file_path = pb_file.path().display().to_string();
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// The safety here is ensured as the test process will not write to temp storage file
|
// The safety here is ensured as the test process will not write to temp storage file
|
||||||
|
@ -56,7 +59,7 @@ files {{
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_package_offset_query() {
|
fn test_package_offset_query() {
|
||||||
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
let pb_file_path = pb_file.path().display().to_string();
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// The safety here is ensured as the test process will not write to temp storage file
|
// The safety here is ensured as the test process will not write to temp storage file
|
||||||
|
@ -88,7 +91,7 @@ files {{
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_none_exist_package_offset_query() {
|
fn test_none_exist_package_offset_query() {
|
||||||
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
let pb_file_path = pb_file.path().display().to_string();
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// The safety here is ensured as the test process will not write to temp storage file
|
// The safety here is ensured as the test process will not write to temp storage file
|
||||||
|
@ -103,7 +106,7 @@ files {{
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flag_offset_query() {
|
fn test_flag_offset_query() {
|
||||||
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
let pb_file_path = pb_file.path().display().to_string();
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// The safety here is ensured as the test process will not write to temp storage file
|
// The safety here is ensured as the test process will not write to temp storage file
|
||||||
|
@ -129,7 +132,7 @@ files {{
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_none_exist_flag_offset_query() {
|
fn test_none_exist_flag_offset_query() {
|
||||||
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
let pb_file_path = pb_file.path().display().to_string();
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// The safety here is ensured as the test process will not write to temp storage file
|
// The safety here is ensured as the test process will not write to temp storage file
|
||||||
|
@ -144,7 +147,7 @@ files {{
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_boolean_flag_value_query() {
|
fn test_boolean_flag_value_query() {
|
||||||
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
let pb_file_path = pb_file.path().display().to_string();
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// The safety here is ensured as the test process will not write to temp storage file
|
// The safety here is ensured as the test process will not write to temp storage file
|
||||||
|
@ -159,7 +162,7 @@ files {{
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_invalid_boolean_flag_value_query() {
|
fn test_invalid_boolean_flag_value_query() {
|
||||||
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
let pb_file_path = pb_file.path().display().to_string();
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// The safety here is ensured as the test process will not write to temp storage file
|
// The safety here is ensured as the test process will not write to temp storage file
|
||||||
|
@ -172,10 +175,43 @@ files {{
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_flag_info_query() {
|
||||||
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
|
// SAFETY:
|
||||||
|
// The safety here is ensured as the test process will not write to temp storage file
|
||||||
|
let flag_info_file =
|
||||||
|
unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagInfo).unwrap() };
|
||||||
|
let is_rw: Vec<bool> = vec![true, false, true, false, false, false, false, false];
|
||||||
|
for (offset, expected_value) in is_rw.into_iter().enumerate() {
|
||||||
|
let attribute = get_boolean_flag_attribute(&flag_info_file, offset as u32).unwrap();
|
||||||
|
assert!((attribute & FlagInfoBit::IsSticky as u8) == 0u8);
|
||||||
|
assert_eq!((attribute & FlagInfoBit::IsReadWrite as u8) != 0u8, expected_value);
|
||||||
|
assert!((attribute & FlagInfoBit::HasOverride as u8) == 0u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_boolean_flag_info_query() {
|
||||||
|
let [_package_map, _flag_map, _flag_val, _flag_info, pb_file] = create_test_storage_files();
|
||||||
|
let pb_file_path = pb_file.path().display().to_string();
|
||||||
|
// SAFETY:
|
||||||
|
// The safety here is ensured as the test process will not write to temp storage file
|
||||||
|
let flag_info_file =
|
||||||
|
unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagInfo).unwrap() };
|
||||||
|
let err = get_boolean_flag_attribute(&flag_info_file, 8u32).unwrap_err();
|
||||||
|
assert_eq!(
|
||||||
|
format!("{:?}", err),
|
||||||
|
"InvalidStorageFileOffset(Flag info offset goes beyond the end of the file.)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_storage_version_query() {
|
fn test_storage_version_query() {
|
||||||
assert_eq!(get_storage_file_version("./package.map").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./package.map").unwrap(), 1);
|
||||||
assert_eq!(get_storage_file_version("./flag.map").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./flag.map").unwrap(), 1);
|
||||||
assert_eq!(get_storage_file_version("./flag.val").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./flag.val").unwrap(), 1);
|
||||||
|
assert_eq!(get_storage_file_version("./flag.info").unwrap(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue