xref: /aosp_15_r20/build/make/tools/aconfig/aconfig_storage_write_api/src/flag_value_update.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 update module defines the flag value file write to mapped bytes
18 
19 use aconfig_storage_file::{AconfigStorageError, FlagValueHeader, MAX_SUPPORTED_FILE_VERSION};
20 use anyhow::anyhow;
21 
22 /// Set flag value
update_boolean_flag_value( buf: &mut [u8], flag_index: u32, flag_value: bool, ) -> Result<usize, AconfigStorageError>23 pub fn update_boolean_flag_value(
24     buf: &mut [u8],
25     flag_index: u32,
26     flag_value: bool,
27 ) -> Result<usize, AconfigStorageError> {
28     let interpreted_header = FlagValueHeader::from_bytes(buf)?;
29     if interpreted_header.version > MAX_SUPPORTED_FILE_VERSION {
30         return Err(AconfigStorageError::HigherStorageFileVersion(anyhow!(
31             "Cannot write to storage file with a higher version of {} with lib version {}",
32             interpreted_header.version,
33             MAX_SUPPORTED_FILE_VERSION
34         )));
35     }
36 
37     // get byte offset to the flag
38     let head = (interpreted_header.boolean_value_offset + flag_index) as usize;
39     if head >= interpreted_header.file_size as usize {
40         return Err(AconfigStorageError::InvalidStorageFileOffset(anyhow!(
41             "Flag value offset goes beyond the end of the file."
42         )));
43     }
44 
45     buf[head] = u8::from(flag_value).to_le_bytes()[0];
46     Ok(head)
47 }
48 
49 #[cfg(test)]
50 mod tests {
51     use super::*;
52     use aconfig_storage_file::{test_utils::create_test_flag_value_list, DEFAULT_FILE_VERSION};
53 
54     #[test]
55     // this test point locks down flag value update
test_boolean_flag_value_update()56     fn test_boolean_flag_value_update() {
57         let flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION);
58         let value_offset = flag_value_list.header.boolean_value_offset;
59         let mut content = flag_value_list.into_bytes();
60         let true_byte = u8::from(true).to_le_bytes()[0];
61         let false_byte = u8::from(false).to_le_bytes()[0];
62 
63         for i in 0..flag_value_list.header.num_flags {
64             let offset = (value_offset + i) as usize;
65             update_boolean_flag_value(&mut content, i, true).unwrap();
66             assert_eq!(content[offset], true_byte);
67             update_boolean_flag_value(&mut content, i, false).unwrap();
68             assert_eq!(content[offset], false_byte);
69         }
70     }
71 
72     #[test]
73     // this test point locks down update beyond the end of boolean section
test_boolean_out_of_range()74     fn test_boolean_out_of_range() {
75         let mut flag_value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION).into_bytes();
76         let error = update_boolean_flag_value(&mut flag_value_list[..], 8, true).unwrap_err();
77         assert_eq!(
78             format!("{:?}", error),
79             "InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)"
80         );
81     }
82 
83     #[test]
84     // this test point locks down query error when file has a higher version
test_higher_version_storage_file()85     fn test_higher_version_storage_file() {
86         let mut value_list = create_test_flag_value_list(DEFAULT_FILE_VERSION);
87         value_list.header.version = MAX_SUPPORTED_FILE_VERSION + 1;
88         let mut flag_value = value_list.into_bytes();
89         let error = update_boolean_flag_value(&mut flag_value[..], 4, true).unwrap_err();
90         assert_eq!(
91             format!("{:?}", error),
92             format!(
93                 "HigherStorageFileVersion(Cannot write to storage file with a higher version of {} with lib version {})",
94                 MAX_SUPPORTED_FILE_VERSION + 1,
95                 MAX_SUPPORTED_FILE_VERSION
96             )
97         );
98     }
99 }
100