xref: /aosp_15_r20/build/make/tools/aconfig/aconfig_storage_read_api/src/flag_value_query.rs (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! flag value query module defines the flag value file read from mapped bytes
18 
19 use crate::AconfigStorageError;
20 use aconfig_storage_file::{
21     flag_value::FlagValueHeader, read_u8_from_bytes, MAX_SUPPORTED_FILE_VERSION,
22 };
23 use anyhow::anyhow;
24 
25 /// Query flag value
find_boolean_flag_value(buf: &[u8], flag_index: u32) -> Result<bool, AconfigStorageError>26 pub fn find_boolean_flag_value(buf: &[u8], flag_index: u32) -> Result<bool, AconfigStorageError> {
27     let interpreted_header = FlagValueHeader::from_bytes(buf)?;
28     if interpreted_header.version > MAX_SUPPORTED_FILE_VERSION {
29         return Err(AconfigStorageError::HigherStorageFileVersion(anyhow!(
30             "Cannot read storage file with a higher version of {} with lib version {}",
31             interpreted_header.version,
32             MAX_SUPPORTED_FILE_VERSION
33         )));
34     }
35 
36     // Find byte offset to the flag value, each boolean flag cost one byte to store
37     let mut head = (interpreted_header.boolean_value_offset + flag_index) as usize;
38     if head >= interpreted_header.file_size as usize {
39         return Err(AconfigStorageError::InvalidStorageFileOffset(anyhow!(
40             "Flag value offset goes beyond the end of the file."
41         )));
42     }
43 
44     let val = read_u8_from_bytes(buf, &mut head)?;
45     Ok(val == 1)
46 }
47 
48 #[cfg(test)]
49 mod tests {
50     use super::*;
51     use aconfig_storage_file::{test_utils::create_test_flag_value_list, DEFAULT_FILE_VERSION};
52 
53     #[test]
54     // this test point locks down flag value query
test_flag_value_query()55     fn test_flag_value_query() {
56         let flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION).into_bytes();
57         let baseline: Vec<bool> = vec![false, true, true, false, true, true, true, true];
58         for (offset, expected_value) in baseline.into_iter().enumerate() {
59             let flag_value = find_boolean_flag_value(&flag_value_list[..], offset as u32).unwrap();
60             assert_eq!(flag_value, expected_value);
61         }
62     }
63 
64     #[test]
65     // this test point locks down query beyond the end of boolean section
test_boolean_out_of_range()66     fn test_boolean_out_of_range() {
67         let flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION).into_bytes();
68         let error = find_boolean_flag_value(&flag_value_list[..], 8).unwrap_err();
69         assert_eq!(
70             format!("{:?}", error),
71             "InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)"
72         );
73     }
74 
75     #[test]
76     // this test point locks down query error when file has a higher version
test_higher_version_storage_file()77     fn test_higher_version_storage_file() {
78         let mut value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION);
79         value_list.header.version = MAX_SUPPORTED_FILE_VERSION + 1;
80         let flag_value = value_list.into_bytes();
81         let error = find_boolean_flag_value(&flag_value[..], 4).unwrap_err();
82         assert_eq!(
83             format!("{:?}", error),
84             format!(
85                 "HigherStorageFileVersion(Cannot read storage file with a higher version of {} with lib version {})",
86                 MAX_SUPPORTED_FILE_VERSION + 1,
87                 MAX_SUPPORTED_FILE_VERSION
88             )
89         );
90     }
91 }
92