xref: /aosp_15_r20/build/make/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1 #[cfg(not(feature = "cargo"))]
2 mod aconfig_storage_rust_test {
3     use aconfig_storage_file::{FlagInfoBit, FlagValueType, StorageFileType, StoredFlagType};
4     use aconfig_storage_read_api::{
5         get_boolean_flag_value, get_flag_attribute, get_flag_read_context,
6         get_package_read_context, get_storage_file_version, mapped_file::get_mapped_file,
7         PackageReadContext,
8     };
9     use rand::Rng;
10     use std::fs;
11 
create_test_storage_files(version: u32) -> String12     fn create_test_storage_files(version: u32) -> String {
13         let mut rng = rand::thread_rng();
14         let number: u32 = rng.gen();
15         let storage_dir = String::from("/tmp/") + &number.to_string();
16         if std::fs::metadata(&storage_dir).is_ok() {
17             fs::remove_dir_all(&storage_dir).unwrap();
18         }
19         let maps_dir = storage_dir.clone() + "/maps";
20         let boot_dir = storage_dir.clone() + "/boot";
21         fs::create_dir(&storage_dir).unwrap();
22         fs::create_dir(maps_dir).unwrap();
23         fs::create_dir(boot_dir).unwrap();
24 
25         let package_map = storage_dir.clone() + "/maps/mockup.package.map";
26         let flag_map = storage_dir.clone() + "/maps/mockup.flag.map";
27         let flag_val = storage_dir.clone() + "/boot/mockup.val";
28         let flag_info = storage_dir.clone() + "/boot/mockup.info";
29         fs::copy(format!("./data/v{0}/package_v{0}.map", version), package_map).unwrap();
30         fs::copy(format!("./data/v{0}/flag_v{0}.map", version), flag_map).unwrap();
31         fs::copy(format!("./data/v{}/flag_v{0}.val", version), flag_val).unwrap();
32         fs::copy(format!("./data/v{}/flag_v{0}.info", version), flag_info).unwrap();
33 
34         storage_dir
35     }
36 
37     #[test]
test_unavailable_storage()38     fn test_unavailable_storage() {
39         let storage_dir = create_test_storage_files(1);
40         // SAFETY:
41         // The safety here is ensured as the test process will not write to temp storage file
42         let err = unsafe {
43             get_mapped_file(&storage_dir, "vendor", StorageFileType::PackageMap).unwrap_err()
44         };
45         assert_eq!(
46             format!("{:?}", err),
47             format!(
48                 "StorageFileNotFound(storage file {}/maps/vendor.package.map does not exist)",
49                 storage_dir
50             )
51         );
52     }
53 
54     #[test]
test_package_context_query()55     fn test_package_context_query() {
56         let storage_dir = create_test_storage_files(1);
57         // SAFETY:
58         // The safety here is ensured as the test process will not write to temp storage file
59         let package_mapped_file = unsafe {
60             get_mapped_file(&storage_dir, "mockup", StorageFileType::PackageMap).unwrap()
61         };
62 
63         let package_context =
64             get_package_read_context(&package_mapped_file, "com.android.aconfig.storage.test_1")
65                 .unwrap()
66                 .unwrap();
67         let expected_package_context =
68             PackageReadContext { package_id: 0, boolean_start_index: 0, fingerprint: 0 };
69         assert_eq!(package_context, expected_package_context);
70 
71         let package_context =
72             get_package_read_context(&package_mapped_file, "com.android.aconfig.storage.test_2")
73                 .unwrap()
74                 .unwrap();
75         let expected_package_context =
76             PackageReadContext { package_id: 1, boolean_start_index: 3, fingerprint: 0 };
77         assert_eq!(package_context, expected_package_context);
78 
79         let package_context =
80             get_package_read_context(&package_mapped_file, "com.android.aconfig.storage.test_4")
81                 .unwrap()
82                 .unwrap();
83         let expected_package_context =
84             PackageReadContext { package_id: 2, boolean_start_index: 6, fingerprint: 0 };
85         assert_eq!(package_context, expected_package_context);
86     }
87 
88     #[test]
test_package_context_query_with_fingerprint()89     fn test_package_context_query_with_fingerprint() {
90         let storage_dir = create_test_storage_files(2);
91         // SAFETY:
92         // The safety here is ensured as the test process will not write to temp storage file
93         let package_mapped_file = unsafe {
94             get_mapped_file(&storage_dir, "mockup", StorageFileType::PackageMap).unwrap()
95         };
96 
97         let package_context =
98             get_package_read_context(&package_mapped_file, "com.android.aconfig.storage.test_1")
99                 .unwrap()
100                 .unwrap();
101         let expected_package_context = PackageReadContext {
102             package_id: 0,
103             boolean_start_index: 0,
104             fingerprint: 15248948510590158086u64,
105         };
106         assert_eq!(package_context, expected_package_context);
107 
108         let package_context =
109             get_package_read_context(&package_mapped_file, "com.android.aconfig.storage.test_2")
110                 .unwrap()
111                 .unwrap();
112         let expected_package_context = PackageReadContext {
113             package_id: 1,
114             boolean_start_index: 3,
115             fingerprint: 4431940502274857964u64,
116         };
117         assert_eq!(package_context, expected_package_context);
118 
119         let package_context =
120             get_package_read_context(&package_mapped_file, "com.android.aconfig.storage.test_4")
121                 .unwrap()
122                 .unwrap();
123         let expected_package_context = PackageReadContext {
124             package_id: 2,
125             boolean_start_index: 6,
126             fingerprint: 16233229917711622375u64,
127         };
128         assert_eq!(package_context, expected_package_context);
129     }
130 
131     #[test]
test_none_exist_package_context_query()132     fn test_none_exist_package_context_query() {
133         let storage_dir = create_test_storage_files(1);
134         // SAFETY:
135         // The safety here is ensured as the test process will not write to temp storage file
136         let package_mapped_file = unsafe {
137             get_mapped_file(&storage_dir, "mockup", StorageFileType::PackageMap).unwrap()
138         };
139 
140         let package_context_option =
141             get_package_read_context(&package_mapped_file, "com.android.aconfig.storage.test_3")
142                 .unwrap();
143         assert_eq!(package_context_option, None);
144     }
145 
146     #[test]
test_flag_context_query()147     fn test_flag_context_query() {
148         let storage_dir = create_test_storage_files(1);
149         // SAFETY:
150         // The safety here is ensured as the test process will not write to temp storage file
151         let flag_mapped_file =
152             unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagMap).unwrap() };
153 
154         let baseline = vec![
155             (0, "enabled_ro", StoredFlagType::ReadOnlyBoolean, 1u16),
156             (0, "enabled_rw", StoredFlagType::ReadWriteBoolean, 2u16),
157             (2, "enabled_rw", StoredFlagType::ReadWriteBoolean, 1u16),
158             (1, "disabled_rw", StoredFlagType::ReadWriteBoolean, 0u16),
159             (1, "enabled_fixed_ro", StoredFlagType::FixedReadOnlyBoolean, 1u16),
160             (1, "enabled_ro", StoredFlagType::ReadOnlyBoolean, 2u16),
161             (2, "enabled_fixed_ro", StoredFlagType::FixedReadOnlyBoolean, 0u16),
162             (0, "disabled_rw", StoredFlagType::ReadWriteBoolean, 0u16),
163         ];
164         for (package_id, flag_name, flag_type, flag_index) in baseline.into_iter() {
165             let flag_context =
166                 get_flag_read_context(&flag_mapped_file, package_id, flag_name).unwrap().unwrap();
167             assert_eq!(flag_context.flag_type, flag_type);
168             assert_eq!(flag_context.flag_index, flag_index);
169         }
170     }
171 
172     #[test]
test_none_exist_flag_context_query()173     fn test_none_exist_flag_context_query() {
174         let storage_dir = create_test_storage_files(1);
175         // SAFETY:
176         // The safety here is ensured as the test process will not write to temp storage file
177         let flag_mapped_file =
178             unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagMap).unwrap() };
179         let flag_context_option =
180             get_flag_read_context(&flag_mapped_file, 0, "none_exist").unwrap();
181         assert_eq!(flag_context_option, None);
182 
183         let flag_context_option =
184             get_flag_read_context(&flag_mapped_file, 3, "enabled_ro").unwrap();
185         assert_eq!(flag_context_option, None);
186     }
187 
188     #[test]
test_boolean_flag_value_query()189     fn test_boolean_flag_value_query() {
190         let storage_dir = create_test_storage_files(1);
191         // SAFETY:
192         // The safety here is ensured as the test process will not write to temp storage file
193         let flag_value_file =
194             unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagVal).unwrap() };
195         let baseline: Vec<bool> = vec![false, true, true, false, true, true, true, true];
196         for (offset, expected_value) in baseline.into_iter().enumerate() {
197             let flag_value = get_boolean_flag_value(&flag_value_file, offset as u32).unwrap();
198             assert_eq!(flag_value, expected_value);
199         }
200     }
201 
202     #[test]
test_invalid_boolean_flag_value_query()203     fn test_invalid_boolean_flag_value_query() {
204         let storage_dir = create_test_storage_files(1);
205         // SAFETY:
206         // The safety here is ensured as the test process will not write to temp storage file
207         let flag_value_file =
208             unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagVal).unwrap() };
209         let err = get_boolean_flag_value(&flag_value_file, 8u32).unwrap_err();
210         assert_eq!(
211             format!("{:?}", err),
212             "InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)"
213         );
214     }
215 
216     #[test]
test_flag_info_query()217     fn test_flag_info_query() {
218         let storage_dir = create_test_storage_files(1);
219         // SAFETY:
220         // The safety here is ensured as the test process will not write to temp storage file
221         let flag_info_file =
222             unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagInfo).unwrap() };
223         let is_rw: Vec<bool> = vec![true, false, true, true, false, false, false, true];
224         for (offset, expected_value) in is_rw.into_iter().enumerate() {
225             let attribute =
226                 get_flag_attribute(&flag_info_file, FlagValueType::Boolean, offset as u32).unwrap();
227             assert!((attribute & FlagInfoBit::HasServerOverride as u8) == 0u8);
228             assert_eq!((attribute & FlagInfoBit::IsReadWrite as u8) != 0u8, expected_value);
229             assert!((attribute & FlagInfoBit::HasLocalOverride as u8) == 0u8);
230         }
231     }
232 
233     #[test]
test_invalid_boolean_flag_info_query()234     fn test_invalid_boolean_flag_info_query() {
235         let storage_dir = create_test_storage_files(1);
236         // SAFETY:
237         // The safety here is ensured as the test process will not write to temp storage file
238         let flag_info_file =
239             unsafe { get_mapped_file(&storage_dir, "mockup", StorageFileType::FlagInfo).unwrap() };
240         let err = get_flag_attribute(&flag_info_file, FlagValueType::Boolean, 8u32).unwrap_err();
241         assert_eq!(
242             format!("{:?}", err),
243             "InvalidStorageFileOffset(Flag info offset goes beyond the end of the file.)"
244         );
245     }
246 
247     #[test]
test_storage_version_query_v1()248     fn test_storage_version_query_v1() {
249         assert_eq!(get_storage_file_version("./data/v1/package_v1.map").unwrap(), 1);
250         assert_eq!(get_storage_file_version("./data/v1/flag_v1.map").unwrap(), 1);
251         assert_eq!(get_storage_file_version("./data/v1/flag_v1.val").unwrap(), 1);
252         assert_eq!(get_storage_file_version("./data/v1/flag_v1.info").unwrap(), 1);
253     }
254 
255     #[test]
test_storage_version_query_v2()256     fn test_storage_version_query_v2() {
257         assert_eq!(get_storage_file_version("./data/v2/package_v2.map").unwrap(), 2);
258         assert_eq!(get_storage_file_version("./data/v2/flag_v2.map").unwrap(), 2);
259         assert_eq!(get_storage_file_version("./data/v2/flag_v2.val").unwrap(), 2);
260         assert_eq!(get_storage_file_version("./data/v2/flag_v2.info").unwrap(), 2);
261     }
262 }
263