Merge "proguard: add keep rules for @TestApi" into main
diff --git a/tools/aconfig/aconfig_storage_file/Android.bp b/tools/aconfig/aconfig_storage_file/Android.bp
index 8c1e2cb..8922ba4 100644
--- a/tools/aconfig/aconfig_storage_file/Android.bp
+++ b/tools/aconfig/aconfig_storage_file/Android.bp
@@ -47,38 +47,14 @@
cmd: "rm -f $(out);cp -f $(in) $(out);chmod -w $(out)",
}
-genrule {
- name: "rw.package.map",
- out: ["tests/tmp.rw.package.map"],
- srcs: ["tests/package.map"],
- cmd: "rm -f $(out);cp -f $(in) $(out);chmod +w $(out)",
-}
-
-genrule {
- name: "rw.flag.map",
- out: ["tests/tmp.rw.flag.map"],
- srcs: ["tests/flag.map"],
- cmd: "rm -f $(out);cp -f $(in) $(out);chmod +w $(out)",
-}
-
-genrule {
- name: "rw.flag.val",
- out: ["tests/tmp.rw.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: [
- ":ro.package.map",
- ":ro.flag.map",
- ":ro.flag.val",
- ":rw.package.map",
- ":rw.flag.map",
- ":rw.flag.val",
+ "tests/package.map",
+ "tests/flag.map",
+ "tests/flag.val",
],
}
@@ -89,3 +65,52 @@
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"],
+}
diff --git a/tools/aconfig/aconfig_storage_file/Cargo.toml b/tools/aconfig/aconfig_storage_file/Cargo.toml
index 296d068..c4e2670 100644
--- a/tools/aconfig/aconfig_storage_file/Cargo.toml
+++ b/tools/aconfig/aconfig_storage_file/Cargo.toml
@@ -18,3 +18,4 @@
[build-dependencies]
protobuf-codegen = "3.2.0"
+cxx-build = "1.0"
diff --git a/tools/aconfig/aconfig_storage_file/aconfig_storage.cpp b/tools/aconfig/aconfig_storage_file/aconfig_storage.cpp
new file mode 100644
index 0000000..ac64093
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/aconfig_storage.cpp
@@ -0,0 +1,106 @@
+#include "aconfig_storage/aconfig_storage.hpp"
+
+#include "rust/cxx.h"
+#include "aconfig_storage/lib.rs.h"
+
+namespace aconfig_storage {
+
+/// Get package offset
+PackageOffsetQuery get_package_offset(
+ std::string const& container,
+ std::string const& package) {
+ auto offset_cxx = get_package_offset_cxx(
+ rust::Str(container.c_str()),
+ rust::Str(package.c_str()));
+ auto offset = PackageOffsetQuery();
+ offset.query_success = offset_cxx.query_success;
+ offset.error_message = std::string(offset_cxx.error_message.c_str());
+ offset.package_exists = offset_cxx.package_exists;
+ offset.package_id = offset_cxx.package_id;
+ offset.boolean_offset = offset_cxx.boolean_offset;
+ return offset;
+}
+
+/// Get flag offset
+FlagOffsetQuery get_flag_offset(
+ std::string const& container,
+ uint32_t package_id,
+ std::string const& flag_name) {
+ auto offset_cxx = get_flag_offset_cxx(
+ rust::Str(container.c_str()),
+ package_id,
+ rust::Str(flag_name.c_str()));
+ auto offset = FlagOffsetQuery();
+ offset.query_success = offset_cxx.query_success;
+ offset.error_message = std::string(offset_cxx.error_message.c_str());
+ offset.flag_exists = offset_cxx.flag_exists;
+ offset.flag_offset = offset_cxx.flag_offset;
+ return offset;
+}
+
+/// Get boolean flag value
+BooleanFlagValueQuery get_boolean_flag_value(
+ std::string const& container,
+ uint32_t offset) {
+ auto value_cxx = get_boolean_flag_value_cxx(
+ rust::Str(container.c_str()),
+ offset);
+ auto value = BooleanFlagValueQuery();
+ value.query_success = value_cxx.query_success;
+ value.error_message = std::string(value_cxx.error_message.c_str());
+ value.flag_value = value_cxx.flag_value;
+ return value;
+}
+
+namespace test_only_api {
+PackageOffsetQuery get_package_offset_impl(
+ std::string const& pb_file,
+ std::string const& container,
+ std::string const& package) {
+ auto offset_cxx = get_package_offset_cxx_impl(
+ rust::Str(pb_file.c_str()),
+ rust::Str(container.c_str()),
+ rust::Str(package.c_str()));
+ auto offset = PackageOffsetQuery();
+ offset.query_success = offset_cxx.query_success;
+ offset.error_message = std::string(offset_cxx.error_message.c_str());
+ offset.package_exists = offset_cxx.package_exists;
+ offset.package_id = offset_cxx.package_id;
+ offset.boolean_offset = offset_cxx.boolean_offset;
+ return offset;
+}
+
+FlagOffsetQuery get_flag_offset_impl(
+ std::string const& pb_file,
+ std::string const& container,
+ uint32_t package_id,
+ std::string const& flag_name) {
+ auto offset_cxx = get_flag_offset_cxx_impl(
+ rust::Str(pb_file.c_str()),
+ rust::Str(container.c_str()),
+ package_id,
+ rust::Str(flag_name.c_str()));
+ auto offset = FlagOffsetQuery();
+ offset.query_success = offset_cxx.query_success;
+ offset.error_message = std::string(offset_cxx.error_message.c_str());
+ offset.flag_exists = offset_cxx.flag_exists;
+ offset.flag_offset = offset_cxx.flag_offset;
+ return offset;
+}
+
+BooleanFlagValueQuery get_boolean_flag_value_impl(
+ std::string const& pb_file,
+ std::string const& container,
+ uint32_t offset) {
+ auto value_cxx = get_boolean_flag_value_cxx_impl(
+ rust::Str(pb_file.c_str()),
+ rust::Str(container.c_str()),
+ offset);
+ auto value = BooleanFlagValueQuery();
+ value.query_success = value_cxx.query_success;
+ value.error_message = std::string(value_cxx.error_message.c_str());
+ value.flag_value = value_cxx.flag_value;
+ return value;
+}
+} // namespace test_only_api
+} // namespace aconfig_storage
diff --git a/tools/aconfig/aconfig_storage_file/build.rs b/tools/aconfig/aconfig_storage_file/build.rs
index 1feeb60..894b71c 100644
--- a/tools/aconfig/aconfig_storage_file/build.rs
+++ b/tools/aconfig/aconfig_storage_file/build.rs
@@ -14,4 +14,7 @@
.inputs(proto_files)
.cargo_out_dir("aconfig_storage_protos")
.run_from_script();
+
+ let _ = cxx_build::bridge("src/lib.rs");
+ println!("cargo:rerun-if-changed=src/lib.rs");
}
diff --git a/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage.hpp b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage.hpp
new file mode 100644
index 0000000..636fb7e
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage.hpp
@@ -0,0 +1,76 @@
+#pragma once
+
+#include <stdint.h>
+#include <string>
+
+namespace aconfig_storage {
+
+/// Package offset query result
+struct PackageOffsetQuery {
+ bool query_success;
+ std::string error_message;
+ bool package_exists;
+ uint32_t package_id;
+ uint32_t boolean_offset;
+};
+
+/// Flag offset query result
+struct FlagOffsetQuery {
+ bool query_success;
+ std::string error_message;
+ bool flag_exists;
+ uint16_t flag_offset;
+};
+
+/// Boolean flag value query result
+struct BooleanFlagValueQuery {
+ bool query_success;
+ std::string error_message;
+ bool flag_value;
+};
+
+/// Get package offset
+/// \input container: the flag container name
+/// \input package: the flag package name
+/// \returns a PackageOffsetQuery
+PackageOffsetQuery get_package_offset(
+ std::string const& container,
+ std::string const& package);
+
+/// Get flag offset
+/// \input container: the flag container name
+/// \input package_id: the flag package id obtained from package offset query
+/// \input flag_name: flag name
+/// \returns a FlagOffsetQuery
+FlagOffsetQuery get_flag_offset(
+ std::string const& container,
+ uint32_t package_id,
+ std::string const& flag_name);
+
+/// Get boolean flag value
+/// \input container: the flag container name
+/// \input offset: the boolean flag value byte offset in the file
+/// \returns a BooleanFlagValueQuery
+BooleanFlagValueQuery get_boolean_flag_value(
+ std::string const& container,
+ uint32_t offset);
+
+/// DO NOT USE APIS IN THE FOLLOWING NAMESPACE, TEST ONLY
+namespace test_only_api {
+PackageOffsetQuery get_package_offset_impl(
+ std::string const& pb_file,
+ std::string const& container,
+ std::string const& package);
+
+FlagOffsetQuery get_flag_offset_impl(
+ std::string const& pb_file,
+ std::string const& container,
+ uint32_t package_id,
+ std::string const& flag_name);
+
+BooleanFlagValueQuery get_boolean_flag_value_impl(
+ std::string const& pb_file,
+ std::string const& container,
+ uint32_t offset);
+} // namespace test_only_api
+} // namespace aconfig_storage
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index e87207a..84e0e90 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -256,35 +256,220 @@
get_boolean_flag_value_impl(STORAGE_LOCATION_FILE, container, offset)
}
+#[cxx::bridge]
+mod ffi {
+ // Package table query return for cc interlop
+ pub struct PackageOffsetQueryCXX {
+ pub query_success: bool,
+ pub error_message: String,
+ pub package_exists: bool,
+ pub package_id: u32,
+ pub boolean_offset: u32,
+ }
+
+ // Flag table query return for cc interlop
+ pub struct FlagOffsetQueryCXX {
+ pub query_success: bool,
+ pub error_message: String,
+ pub flag_exists: bool,
+ pub flag_offset: u16,
+ }
+
+ // Flag value query return for cc interlop
+ pub struct BooleanFlagValueQueryCXX {
+ pub query_success: bool,
+ pub error_message: String,
+ pub flag_value: bool,
+ }
+
+ // Rust export to c++
+ extern "Rust" {
+ pub fn get_package_offset_cxx_impl(
+ pb_file: &str,
+ container: &str,
+ package: &str,
+ ) -> PackageOffsetQueryCXX;
+
+ pub fn get_flag_offset_cxx_impl(
+ pb_file: &str,
+ container: &str,
+ package_id: u32,
+ flag: &str,
+ ) -> FlagOffsetQueryCXX;
+
+ pub fn get_boolean_flag_value_cxx_impl(
+ pb_file: &str,
+ container: &str,
+ offset: u32,
+ ) -> BooleanFlagValueQueryCXX;
+
+ pub fn get_package_offset_cxx(container: &str, package: &str) -> PackageOffsetQueryCXX;
+
+ pub fn get_flag_offset_cxx(
+ container: &str,
+ package_id: u32,
+ flag: &str,
+ ) -> FlagOffsetQueryCXX;
+
+ pub fn get_boolean_flag_value_cxx(container: &str, offset: u32)
+ -> BooleanFlagValueQueryCXX;
+ }
+}
+
+/// Get package start offset impl cc interlop
+pub fn get_package_offset_cxx_impl(
+ pb_file: &str,
+ container: &str,
+ package: &str,
+) -> ffi::PackageOffsetQueryCXX {
+ ffi::PackageOffsetQueryCXX::new(get_package_offset_impl(pb_file, container, package))
+}
+
+/// Get flag start offset impl cc interlop
+pub fn get_flag_offset_cxx_impl(
+ pb_file: &str,
+ container: &str,
+ package_id: u32,
+ flag: &str,
+) -> ffi::FlagOffsetQueryCXX {
+ ffi::FlagOffsetQueryCXX::new(get_flag_offset_impl(pb_file, container, package_id, flag))
+}
+
+/// Get boolean flag value impl cc interlop
+pub fn get_boolean_flag_value_cxx_impl(
+ pb_file: &str,
+ container: &str,
+ offset: u32,
+) -> ffi::BooleanFlagValueQueryCXX {
+ ffi::BooleanFlagValueQueryCXX::new(get_boolean_flag_value_impl(pb_file, container, offset))
+}
+
+/// Get package start offset cc interlop
+pub fn get_package_offset_cxx(container: &str, package: &str) -> ffi::PackageOffsetQueryCXX {
+ ffi::PackageOffsetQueryCXX::new(get_package_offset(container, package))
+}
+
+/// Get flag start offset cc interlop
+pub fn get_flag_offset_cxx(
+ container: &str,
+ package_id: u32,
+ flag: &str,
+) -> ffi::FlagOffsetQueryCXX {
+ ffi::FlagOffsetQueryCXX::new(get_flag_offset(container, package_id, flag))
+}
+
+/// Get boolean flag value cc interlop
+pub fn get_boolean_flag_value_cxx(container: &str, offset: u32) -> ffi::BooleanFlagValueQueryCXX {
+ ffi::BooleanFlagValueQueryCXX::new(get_boolean_flag_value(container, offset))
+}
+
+impl ffi::PackageOffsetQueryCXX {
+ pub(crate) fn new(offset_result: Result<Option<PackageOffset>, AconfigStorageError>) -> Self {
+ match offset_result {
+ Ok(offset_opt) => match offset_opt {
+ Some(offset) => Self {
+ query_success: true,
+ error_message: String::from(""),
+ package_exists: true,
+ package_id: offset.package_id,
+ boolean_offset: offset.boolean_offset,
+ },
+ None => Self {
+ query_success: true,
+ error_message: String::from(""),
+ package_exists: false,
+ package_id: 0,
+ boolean_offset: 0,
+ },
+ },
+ Err(errmsg) => Self {
+ query_success: false,
+ error_message: format!("{:?}", errmsg),
+ package_exists: false,
+ package_id: 0,
+ boolean_offset: 0,
+ },
+ }
+ }
+}
+
+impl ffi::FlagOffsetQueryCXX {
+ pub(crate) fn new(offset_result: Result<Option<FlagOffset>, AconfigStorageError>) -> Self {
+ match offset_result {
+ Ok(offset_opt) => match offset_opt {
+ Some(offset) => Self {
+ query_success: true,
+ error_message: String::from(""),
+ flag_exists: true,
+ flag_offset: offset,
+ },
+ None => Self {
+ query_success: true,
+ error_message: String::from(""),
+ flag_exists: false,
+ flag_offset: 0,
+ },
+ },
+ Err(errmsg) => Self {
+ query_success: false,
+ error_message: format!("{:?}", errmsg),
+ flag_exists: false,
+ flag_offset: 0,
+ },
+ }
+ }
+}
+
+impl ffi::BooleanFlagValueQueryCXX {
+ pub(crate) fn new(value_result: Result<bool, AconfigStorageError>) -> Self {
+ match value_result {
+ Ok(value) => {
+ Self { query_success: true, error_message: String::from(""), flag_value: value }
+ }
+ Err(errmsg) => Self {
+ query_success: false,
+ error_message: format!("{:?}", errmsg),
+ flag_value: false,
+ },
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
- use crate::test_utils::{
- create_temp_storage_files_for_test, get_binary_storage_proto_bytes,
- set_temp_storage_files_to_read_only, write_bytes_to_temp_file,
- };
+ use crate::test_utils::{write_storage_text_to_temp_file, TestStorageFileSet};
+
+ fn create_test_storage_files(read_only: bool) -> TestStorageFileSet {
+ TestStorageFileSet::new(
+ "./tests/package.map",
+ "./tests/flag.map",
+ "./tests/flag.val",
+ read_only,
+ )
+ .unwrap()
+ }
#[test]
// this test point locks down flag package offset query
fn test_package_offset_query() {
- #[cfg(feature = "cargo")]
- create_temp_storage_files_for_test();
-
- set_temp_storage_files_to_read_only();
- let text_proto = r#"
-files {
+ let ro_files = create_test_storage_files(true);
+ let text_proto = format!(
+ r#"
+files {{
version: 0
container: "system"
- package_map: "./tests/tmp.ro.package.map"
- flag_map: "./tests/tmp.ro.flag.map"
- flag_val: "./tests/tmp.ro.flag.val"
+ package_map: "{}"
+ flag_map: "{}"
+ flag_val: "{}"
timestamp: 12345
-}
-"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
- let file_full_path = file.path().display().to_string();
+}}
+"#,
+ ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
+ );
+ let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file_full_path = file.path().display().to_string();
let package_offset = get_package_offset_impl(
&file_full_path,
"system",
@@ -319,24 +504,23 @@
#[test]
// this test point locks down flag offset query
fn test_flag_offset_query() {
- #[cfg(feature = "cargo")]
- create_temp_storage_files_for_test();
-
- set_temp_storage_files_to_read_only();
- let text_proto = r#"
-files {
+ let ro_files = create_test_storage_files(true);
+ let text_proto = format!(
+ r#"
+files {{
version: 0
container: "system"
- package_map: "./tests/tmp.ro.package.map"
- flag_map: "./tests/tmp.ro.flag.map"
- flag_val: "./tests/tmp.ro.flag.val"
+ package_map: "{}"
+ flag_map: "{}"
+ flag_val: "{}"
timestamp: 12345
-}
-"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
- let file_full_path = file.path().display().to_string();
+}}
+"#,
+ ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
+ );
+ let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file_full_path = file.path().display().to_string();
let baseline = vec![
(0, "enabled_ro", 1u16),
(0, "enabled_rw", 2u16),
@@ -359,24 +543,23 @@
#[test]
// this test point locks down flag offset query
fn test_flag_value_query() {
- #[cfg(feature = "cargo")]
- create_temp_storage_files_for_test();
-
- set_temp_storage_files_to_read_only();
- let text_proto = r#"
-files {
+ let ro_files = create_test_storage_files(true);
+ let text_proto = format!(
+ r#"
+files {{
version: 0
container: "system"
- package_map: "./tests/tmp.ro.package.map"
- flag_map: "./tests/tmp.ro.flag.map"
- flag_val: "./tests/tmp.ro.flag.val"
+ package_map: "{}"
+ flag_map: "{}"
+ flag_val: "{}"
timestamp: 12345
-}
-"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
- let file_full_path = file.path().display().to_string();
+}}
+"#,
+ ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
+ );
+ let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file_full_path = file.path().display().to_string();
let baseline: Vec<bool> = vec![false; 8];
for (offset, expected_value) in baseline.into_iter().enumerate() {
let flag_value =
diff --git a/tools/aconfig/aconfig_storage_file/src/mapped_file.rs b/tools/aconfig/aconfig_storage_file/src/mapped_file.rs
index ad0c66f..d8f2570 100644
--- a/tools/aconfig/aconfig_storage_file/src/mapped_file.rs
+++ b/tools/aconfig/aconfig_storage_file/src/mapped_file.rs
@@ -148,10 +148,7 @@
#[cfg(test)]
mod tests {
use super::*;
- use crate::test_utils::{
- create_temp_storage_files_for_test, get_binary_storage_proto_bytes,
- set_temp_storage_files_to_read_only, write_bytes_to_temp_file,
- };
+ use crate::test_utils::{write_storage_text_to_temp_file, TestStorageFileSet};
#[test]
fn test_find_storage_file_location() {
@@ -173,10 +170,8 @@
timestamp: 54321
}
"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
+ let file = write_storage_text_to_temp_file(text_proto).unwrap();
let file_full_path = file.path().display().to_string();
-
let file_info = find_container_storage_location(&file_full_path, "system").unwrap();
assert_eq!(file_info.version(), 0);
assert_eq!(file_info.container(), "system");
@@ -213,99 +208,121 @@
assert_eq!(mmaped_file[..], content[..]);
}
+ fn create_test_storage_files(read_only: bool) -> TestStorageFileSet {
+ TestStorageFileSet::new(
+ "./tests/package.map",
+ "./tests/flag.map",
+ "./tests/flag.val",
+ read_only,
+ )
+ .unwrap()
+ }
+
#[test]
fn test_mapped_file_contents() {
- #[cfg(feature = "cargo")]
- create_temp_storage_files_for_test();
-
- set_temp_storage_files_to_read_only();
- let text_proto = r#"
-files {
+ let ro_files = create_test_storage_files(true);
+ let text_proto = format!(
+ r#"
+files {{
version: 0
container: "system"
- package_map: "./tests/tmp.ro.package.map"
- flag_map: "./tests/tmp.ro.flag.map"
- flag_val: "./tests/tmp.ro.flag.val"
+ package_map: "{}"
+ flag_map: "{}"
+ flag_val: "{}"
timestamp: 12345
-}
-"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
- let file_full_path = file.path().display().to_string();
+}}
+"#,
+ ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
+ );
+ let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file_full_path = file.path().display().to_string();
map_and_verify(
&file_full_path,
StorageFileSelection::PackageMap,
- "./tests/tmp.ro.package.map",
+ &ro_files.package_map.name,
);
- map_and_verify(&file_full_path, StorageFileSelection::FlagMap, "./tests/tmp.ro.flag.map");
- map_and_verify(&file_full_path, StorageFileSelection::FlagVal, "./tests/tmp.ro.flag.val");
+ map_and_verify(&file_full_path, StorageFileSelection::FlagMap, &ro_files.flag_map.name);
+ map_and_verify(&file_full_path, StorageFileSelection::FlagVal, &ro_files.flag_val.name);
}
#[test]
fn test_map_non_read_only_file() {
- #[cfg(feature = "cargo")]
- create_temp_storage_files_for_test();
-
- set_temp_storage_files_to_read_only();
- let text_proto = r#"
-files {
+ let ro_files = create_test_storage_files(true);
+ let rw_files = create_test_storage_files(false);
+ let text_proto = format!(
+ r#"
+files {{
version: 0
container: "system"
- package_map: "./tests/tmp.rw.package.map"
- flag_map: "./tests/tmp.rw.flag.map"
- flag_val: "./tests/tmp.rw.flag.val"
+ package_map: "{}"
+ flag_map: "{}"
+ flag_val: "{}"
timestamp: 12345
-}
-"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
- let file_full_path = file.path().display().to_string();
-
- let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
- assert_eq!(
- format!("{:?}", error),
- "MapFileFail(fail to map non read only storage file ./tests/tmp.rw.package.map)"
+}}
+"#,
+ rw_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
);
- let text_proto = r#"
-files {
- version: 0
- container: "system"
- package_map: "./tests/tmp.ro.package.map"
- flag_map: "./tests/tmp.rw.flag.map"
- flag_val: "./tests/tmp.rw.flag.val"
- timestamp: 12345
-}
-"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
+ let file = write_storage_text_to_temp_file(&text_proto).unwrap();
let file_full_path = file.path().display().to_string();
-
let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
assert_eq!(
format!("{:?}", error),
- "MapFileFail(fail to map non read only storage file ./tests/tmp.rw.flag.map)"
+ format!(
+ "MapFileFail(fail to map non read only storage file {})",
+ rw_files.package_map.name
+ )
);
- let text_proto = r#"
-files {
+ let text_proto = format!(
+ r#"
+files {{
version: 0
container: "system"
- package_map: "./tests/tmp.ro.package.map"
- flag_map: "./tests/tmp.ro.flag.map"
- flag_val: "./tests/tmp.rw.flag.val"
+ package_map: "{}"
+ flag_map: "{}"
+ flag_val: "{}"
timestamp: 12345
-}
-"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
- let file_full_path = file.path().display().to_string();
+}}
+"#,
+ ro_files.package_map.name, rw_files.flag_map.name, ro_files.flag_val.name
+ );
+ let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file_full_path = file.path().display().to_string();
let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
assert_eq!(
format!("{:?}", error),
- "MapFileFail(fail to map non read only storage file ./tests/tmp.rw.flag.val)"
+ format!(
+ "MapFileFail(fail to map non read only storage file {})",
+ rw_files.flag_map.name
+ )
+ );
+
+ let text_proto = format!(
+ r#"
+files {{
+ version: 0
+ container: "system"
+ package_map: "{}"
+ flag_map: "{}"
+ flag_val: "{}"
+ timestamp: 12345
+}}
+"#,
+ ro_files.package_map.name, ro_files.flag_map.name, rw_files.flag_val.name
+ );
+
+ let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file_full_path = file.path().display().to_string();
+ let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
+ assert_eq!(
+ format!("{:?}", error),
+ format!(
+ "MapFileFail(fail to map non read only storage file {})",
+ rw_files.flag_val.name
+ )
);
}
}
diff --git a/tools/aconfig/aconfig_storage_file/src/test_utils.rs b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
index 6fe5a27..7905d51 100644
--- a/tools/aconfig/aconfig_storage_file/src/test_utils.rs
+++ b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
@@ -19,12 +19,8 @@
use protobuf::Message;
use std::fs;
use std::io::Write;
-use std::path::Path;
-use std::sync::Once;
use tempfile::NamedTempFile;
-static INIT: Once = Once::new();
-
pub(crate) fn get_binary_storage_proto_bytes(text_proto: &str) -> Result<Vec<u8>> {
let storage_files: ProtoStorageFiles = protobuf::text_format::parse_from_str(text_proto)?;
let mut binary_proto = Vec::new();
@@ -32,59 +28,65 @@
Ok(binary_proto)
}
-pub(crate) fn write_bytes_to_temp_file(bytes: &[u8]) -> Result<NamedTempFile> {
+pub(crate) fn write_storage_text_to_temp_file(text_proto: &str) -> Result<NamedTempFile> {
+ let bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
let mut file = NamedTempFile::new()?;
let _ = file.write_all(&bytes);
Ok(file)
}
-fn has_same_content(file1: &Path, file2: &Path) -> Result<bool> {
- let bytes1 = fs::read(file1)?;
- let bytes2 = fs::read(file2)?;
- if bytes1.len() != bytes2.len() {
- return Ok(false);
+fn set_file_read_only(file: &NamedTempFile) {
+ let mut perms = fs::metadata(file.path()).unwrap().permissions();
+ if !perms.readonly() {
+ perms.set_readonly(true);
+ fs::set_permissions(file.path(), perms).unwrap();
}
- for (i, &b1) in bytes1.iter().enumerate() {
- if b1 != bytes2[i] {
- return Ok(false);
- }
- }
- Ok(true)
}
-pub(crate) fn create_temp_storage_files_for_test() {
- INIT.call_once(|| {
- let file_paths = [
- ("./tests/package.map", "./tests/tmp.ro.package.map"),
- ("./tests/flag.map", "./tests/tmp.ro.flag.map"),
- ("./tests/flag.val", "./tests/tmp.ro.flag.val"),
- ("./tests/package.map", "./tests/tmp.rw.package.map"),
- ("./tests/flag.map", "./tests/tmp.rw.flag.map"),
- ("./tests/flag.val", "./tests/tmp.rw.flag.val"),
- ];
- for (file_path, copied_file_path) in file_paths.into_iter() {
- let file_path = Path::new(&file_path);
- let copied_file_path = Path::new(&copied_file_path);
- if copied_file_path.exists() && !has_same_content(file_path, copied_file_path).unwrap()
- {
- fs::remove_file(copied_file_path).unwrap();
- }
- if !copied_file_path.exists() {
- fs::copy(file_path, copied_file_path).unwrap();
- }
- }
- });
+fn set_file_read_write(file: &NamedTempFile) {
+ let mut perms = fs::metadata(file.path()).unwrap().permissions();
+ if perms.readonly() {
+ perms.set_readonly(false);
+ fs::set_permissions(file.path(), perms).unwrap();
+ }
}
-pub(crate) fn set_temp_storage_files_to_read_only() {
- let file_paths =
- ["./tests/tmp.ro.package.map", "./tests/tmp.ro.flag.map", "./tests/tmp.ro.flag.val"];
- for file_path in file_paths.into_iter() {
- let file_path = Path::new(&file_path);
- let mut perms = fs::metadata(file_path).unwrap().permissions();
- if !perms.readonly() {
- perms.set_readonly(true);
- fs::set_permissions(file_path, perms).unwrap();
+pub(crate) struct TestStorageFile {
+ pub file: NamedTempFile,
+ pub name: String,
+}
+
+impl TestStorageFile {
+ pub(crate) fn new(source_file: &str, read_only: bool) -> Result<Self> {
+ let file = NamedTempFile::new()?;
+ fs::copy(source_file, file.path())?;
+ if read_only {
+ set_file_read_only(&file);
+ } else {
+ set_file_read_write(&file);
}
+ let name = file.path().display().to_string();
+ Ok(Self { file, name })
+ }
+}
+
+pub(crate) struct TestStorageFileSet {
+ pub package_map: TestStorageFile,
+ pub flag_map: TestStorageFile,
+ pub flag_val: TestStorageFile,
+}
+
+impl TestStorageFileSet {
+ pub(crate) fn new(
+ package_map_path: &str,
+ flag_map_path: &str,
+ flag_val_path: &str,
+ read_only: bool,
+ ) -> Result<Self> {
+ Ok(Self {
+ package_map: TestStorageFile::new(package_map_path, read_only)?,
+ flag_map: TestStorageFile::new(flag_map_path, read_only)?,
+ flag_val: TestStorageFile::new(flag_val_path, read_only)?,
+ })
}
}
diff --git a/tools/aconfig/aconfig_storage_file/tests/Android.bp b/tools/aconfig/aconfig_storage_file/tests/Android.bp
new file mode 100644
index 0000000..8cee611
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/Android.bp
@@ -0,0 +1,18 @@
+rust_test {
+ name: "aconfig_storage.test.rust",
+ srcs: [
+ "storage_lib_rust_test.rs"
+ ],
+ rustlibs: [
+ "libanyhow",
+ "libaconfig_storage_file",
+ "libprotobuf",
+ "libtempfile",
+ ],
+ data: [
+ ":ro.package.map",
+ ":ro.flag.map",
+ ":ro.flag.val",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/tools/aconfig/aconfig_storage_file/tests/storage_lib_rust_test.rs b/tools/aconfig/aconfig_storage_file/tests/storage_lib_rust_test.rs
new file mode 100644
index 0000000..9916915
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/tests/storage_lib_rust_test.rs
@@ -0,0 +1,174 @@
+#[cfg(not(feature = "cargo"))]
+mod aconfig_storage_rust_test {
+ use aconfig_storage_file::{
+ get_boolean_flag_value_impl, get_flag_offset_impl, get_package_offset_impl, PackageOffset,
+ ProtoStorageFiles,
+ };
+ use protobuf::Message;
+ use std::io::Write;
+ use tempfile::NamedTempFile;
+
+ fn write_storage_location_file() -> NamedTempFile {
+ let text_proto = r#"
+files {
+ version: 0
+ container: "system"
+ package_map: "./tests/tmp.ro.package.map"
+ flag_map: "./tests/tmp.ro.flag.map"
+ flag_val: "./tests/tmp.ro.flag.val"
+ timestamp: 12345
+}
+"#;
+ let storage_files: ProtoStorageFiles =
+ protobuf::text_format::parse_from_str(text_proto).unwrap();
+ let mut binary_proto_bytes = Vec::new();
+ storage_files.write_to_vec(&mut binary_proto_bytes).unwrap();
+ let mut file = NamedTempFile::new().unwrap();
+ file.write_all(&binary_proto_bytes).unwrap();
+ file
+ }
+
+ #[test]
+ fn test_package_offset_query() {
+ let file = write_storage_location_file();
+ let file_full_path = file.path().display().to_string();
+
+ let package_offset = get_package_offset_impl(
+ &file_full_path,
+ "system",
+ "com.android.aconfig.storage.test_1",
+ )
+ .unwrap()
+ .unwrap();
+ let expected_package_offset = PackageOffset { package_id: 0, boolean_offset: 0 };
+ assert_eq!(package_offset, expected_package_offset);
+
+ let package_offset = get_package_offset_impl(
+ &file_full_path,
+ "system",
+ "com.android.aconfig.storage.test_2",
+ )
+ .unwrap()
+ .unwrap();
+ let expected_package_offset = PackageOffset { package_id: 1, boolean_offset: 3 };
+ assert_eq!(package_offset, expected_package_offset);
+
+ let package_offset = get_package_offset_impl(
+ &file_full_path,
+ "system",
+ "com.android.aconfig.storage.test_4",
+ )
+ .unwrap()
+ .unwrap();
+ let expected_package_offset = PackageOffset { package_id: 2, boolean_offset: 6 };
+ assert_eq!(package_offset, expected_package_offset);
+
+ let package_offset = get_package_offset_impl(
+ &file_full_path,
+ "system",
+ "com.android.aconfig.storage.test_3",
+ )
+ .unwrap();
+ assert_eq!(package_offset, None);
+ }
+
+ #[test]
+ fn test_invalid_package_offset_query() {
+ let file = write_storage_location_file();
+ let file_full_path = file.path().display().to_string();
+
+ let package_offset_option = get_package_offset_impl(
+ &file_full_path,
+ "system",
+ "com.android.aconfig.storage.test_3",
+ )
+ .unwrap();
+ assert_eq!(package_offset_option, None);
+
+ let err = get_package_offset_impl(
+ &file_full_path,
+ "vendor",
+ "com.android.aconfig.storage.test_1",
+ )
+ .unwrap_err();
+ assert_eq!(
+ format!("{:?}", err),
+ "StorageFileNotFound(Storage file does not exist for vendor)"
+ );
+ }
+
+ #[test]
+ fn test_flag_offset_query() {
+ let file = write_storage_location_file();
+ let file_full_path = file.path().display().to_string();
+
+ 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 =
+ get_flag_offset_impl(&file_full_path, "system", package_id, flag_name)
+ .unwrap()
+ .unwrap();
+ assert_eq!(flag_offset, expected_offset);
+ }
+ }
+
+ #[test]
+ fn test_invalid_flag_offset_query() {
+ let file = write_storage_location_file();
+ let file_full_path = file.path().display().to_string();
+
+ let flag_offset_option =
+ get_flag_offset_impl(&file_full_path, "system", 0, "none_exist").unwrap();
+ assert_eq!(flag_offset_option, None);
+
+ let flag_offset_option =
+ get_flag_offset_impl(&file_full_path, "system", 3, "enabled_ro").unwrap();
+ assert_eq!(flag_offset_option, None);
+
+ let err = get_flag_offset_impl(&file_full_path, "vendor", 0, "enabled_ro").unwrap_err();
+ assert_eq!(
+ format!("{:?}", err),
+ "StorageFileNotFound(Storage file does not exist for vendor)"
+ );
+ }
+
+ #[test]
+ fn test_boolean_flag_value_query() {
+ let file = write_storage_location_file();
+ let file_full_path = file.path().display().to_string();
+
+ let baseline: Vec<bool> = vec![false; 8];
+ for (offset, expected_value) in baseline.into_iter().enumerate() {
+ let flag_value =
+ get_boolean_flag_value_impl(&file_full_path, "system", offset as u32).unwrap();
+ assert_eq!(flag_value, expected_value);
+ }
+ }
+
+ #[test]
+ fn test_invalid_boolean_flag_value_query() {
+ let file = write_storage_location_file();
+ let file_full_path = file.path().display().to_string();
+
+ let err = get_boolean_flag_value_impl(&file_full_path, "vendor", 0u32).unwrap_err();
+ assert_eq!(
+ format!("{:?}", err),
+ "StorageFileNotFound(Storage file does not exist for vendor)"
+ );
+
+ let err = get_boolean_flag_value_impl(&file_full_path, "system", 8u32).unwrap_err();
+ assert_eq!(
+ format!("{:?}", err),
+ "InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)"
+ );
+ }
+}