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, FILE_VERSION};
20 use aconfig_storage_file::{flag_value::FlagValueHeader, read_u8_from_bytes};
21 use anyhow::anyhow;
22
23 /// Query flag value
find_boolean_flag_value(buf: &[u8], flag_index: u32) -> Result<bool, AconfigStorageError>24 pub fn find_boolean_flag_value(buf: &[u8], flag_index: u32) -> Result<bool, AconfigStorageError> {
25 let interpreted_header = FlagValueHeader::from_bytes(buf)?;
26 if interpreted_header.version > crate::FILE_VERSION {
27 return Err(AconfigStorageError::HigherStorageFileVersion(anyhow!(
28 "Cannot read storage file with a higher version of {} with lib version {}",
29 interpreted_header.version,
30 FILE_VERSION
31 )));
32 }
33
34 // Find byte offset to the flag value, each boolean flag cost one byte to store
35 let mut head = (interpreted_header.boolean_value_offset + flag_index) as usize;
36 if head >= interpreted_header.file_size as usize {
37 return Err(AconfigStorageError::InvalidStorageFileOffset(anyhow!(
38 "Flag value offset goes beyond the end of the file."
39 )));
40 }
41
42 let val = read_u8_from_bytes(buf, &mut head)?;
43 Ok(val == 1)
44 }
45
46 #[cfg(test)]
47 mod tests {
48 use super::*;
49 use aconfig_storage_file::test_utils::create_test_flag_value_list;
50
51 #[test]
52 // this test point locks down flag value query
test_flag_value_query()53 fn test_flag_value_query() {
54 let flag_value_list = create_test_flag_value_list().into_bytes();
55 let baseline: Vec<bool> = vec![false, true, true, false, true, true, true, true];
56 for (offset, expected_value) in baseline.into_iter().enumerate() {
57 let flag_value = find_boolean_flag_value(&flag_value_list[..], offset as u32).unwrap();
58 assert_eq!(flag_value, expected_value);
59 }
60 }
61
62 #[test]
63 // this test point locks down query beyond the end of boolean section
test_boolean_out_of_range()64 fn test_boolean_out_of_range() {
65 let flag_value_list = create_test_flag_value_list().into_bytes();
66 let error = find_boolean_flag_value(&flag_value_list[..], 8).unwrap_err();
67 assert_eq!(
68 format!("{:?}", error),
69 "InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)"
70 );
71 }
72
73 #[test]
74 // this test point locks down query error when file has a higher version
test_higher_version_storage_file()75 fn test_higher_version_storage_file() {
76 let mut value_list = create_test_flag_value_list();
77 value_list.header.version = crate::FILE_VERSION + 1;
78 let flag_value = value_list.into_bytes();
79 let error = find_boolean_flag_value(&flag_value[..], 4).unwrap_err();
80 assert_eq!(
81 format!("{:?}", error),
82 format!(
83 "HigherStorageFileVersion(Cannot read storage file with a higher version of {} with lib version {})",
84 crate::FILE_VERSION + 1,
85 crate::FILE_VERSION
86 )
87 );
88 }
89 }
90