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