• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 use crate::utils::{
18     copy_file, copy_file_without_fsync, get_files_digest, read_pb_from_file, remove_file,
19     write_pb_to_file,
20 };
21 use crate::AconfigdError;
22 use aconfig_storage_file::{
23     list_flags, list_flags_with_info, FlagInfoBit, FlagValueSummary, FlagValueType,
24 };
25 use aconfig_storage_read_api::{
26     get_boolean_flag_value, get_flag_read_context, get_package_read_context,
27     get_storage_file_version, map_file,
28 };
29 use aconfig_storage_write_api::{
30     map_mutable_storage_file, set_boolean_flag_value, set_flag_has_local_override,
31     set_flag_has_server_override,
32 };
33 use aconfigd_protos::{ProtoFlagOverride, ProtoLocalFlagOverrides, ProtoPersistStorageRecord};
34 use anyhow::anyhow;
35 use log::debug;
36 use memmap2::{Mmap, MmapMut};
37 use std::collections::HashMap;
38 use std::path::{Path, PathBuf};
39 
40 // In memory data structure for storage file locations for each container
41 #[derive(PartialEq, Debug, Clone)]
42 pub(crate) struct StorageRecord {
43     pub version: u32,
44     pub container: String,            // container name
45     pub default_package_map: PathBuf, // default package map file
46     pub default_flag_map: PathBuf,    // default flag map file
47     pub default_flag_val: PathBuf,    // default flag val file
48     pub default_flag_info: PathBuf,   // default flag info file
49     pub persist_package_map: PathBuf, // persist package.map file
50     pub persist_flag_map: PathBuf,    // persist flag.map file
51     pub persist_flag_val: PathBuf,    // persist flag.val file
52     pub persist_flag_info: PathBuf,   // persist flag.info file
53     pub local_overrides: PathBuf,     // local overrides pb file
54     pub boot_flag_val: PathBuf,       // boot flag.val file
55     pub boot_flag_info: PathBuf,      // boot flag.info file
56     pub digest: String,               // hash for all default storage files
57 }
58 
59 // Storage files for a particular container
60 #[derive(Debug)]
61 pub(crate) struct StorageFiles {
62     pub storage_record: StorageRecord,
63     pub package_map: Option<Mmap>,
64     pub flag_map: Option<Mmap>,
65     pub flag_val: Option<Mmap>,                  // default flag value file
66     pub boot_flag_val: Option<Mmap>,             // boot flag value file
67     pub boot_flag_info: Option<Mmap>,            // boot flag info file
68     pub persist_flag_val: Option<MmapMut>,       // persist flag value file
69     pub persist_flag_info: Option<MmapMut>,      // persist flag info file
70     pub mutable_boot_flag_val: Option<MmapMut>,  // mutable boot flag value file
71     pub mutable_boot_flag_info: Option<MmapMut>, // mutable boot flag info file
72 }
73 
74 // Compare two options of mmap/mmapmut
same_mmap_contents<T: std::ops::Deref<Target = [u8]>>( opt_a: &Option<T>, opt_b: &Option<T>, ) -> bool75 fn same_mmap_contents<T: std::ops::Deref<Target = [u8]>>(
76     opt_a: &Option<T>,
77     opt_b: &Option<T>,
78 ) -> bool {
79     match (opt_a, opt_b) {
80         (Some(map_a), Some(map_b)) => map_a[..] == map_b[..],
81         (None, None) => true,
82         _ => false,
83     }
84 }
85 
86 impl PartialEq for StorageFiles {
eq(&self, other: &Self) -> bool87     fn eq(&self, other: &Self) -> bool {
88         self.storage_record == other.storage_record
89             && same_mmap_contents(&self.package_map, &other.package_map)
90             && same_mmap_contents(&self.flag_map, &other.flag_map)
91             && same_mmap_contents(&self.flag_val, &other.flag_val)
92             && same_mmap_contents(&self.boot_flag_val, &other.boot_flag_val)
93             && same_mmap_contents(&self.boot_flag_info, &other.boot_flag_info)
94             && same_mmap_contents(&self.persist_flag_val, &other.persist_flag_val)
95             && same_mmap_contents(&self.persist_flag_info, &other.persist_flag_info)
96             && same_mmap_contents(&self.mutable_boot_flag_val, &other.mutable_boot_flag_val)
97             && same_mmap_contents(&self.mutable_boot_flag_info, &other.mutable_boot_flag_info)
98     }
99 }
100 
101 // Package and flag query context
102 #[derive(PartialEq, Debug)]
103 pub(crate) struct PackageFlagContext {
104     pub package: String,
105     pub flag: String,
106     pub package_exists: bool,
107     pub flag_exists: bool,
108     pub value_type: FlagValueType,
109     pub flag_index: u32,
110 }
111 
112 // Flag snapshot in storage
113 #[derive(PartialEq, Debug)]
114 pub(crate) struct FlagSnapshot {
115     pub container: String,
116     pub package: String,
117     pub flag: String,
118     pub server_value: String,
119     pub local_value: String,
120     pub boot_value: String,
121     pub default_value: String,
122     pub is_readwrite: bool,
123     pub has_server_override: bool,
124     pub has_local_override: bool,
125     pub has_boot_local_override: bool,
126 }
127 
128 impl StorageFiles {
129     /// Constructor from a container
from_container( container: &str, package_map: &Path, flag_map: &Path, flag_val: &Path, flag_info: &Path, root_dir: &Path, ) -> Result<Self, AconfigdError>130     pub(crate) fn from_container(
131         container: &str,
132         package_map: &Path,
133         flag_map: &Path,
134         flag_val: &Path,
135         flag_info: &Path,
136         root_dir: &Path,
137     ) -> Result<Self, AconfigdError> {
138         debug!("create storage files object from container {}", container);
139         let version =
140             get_storage_file_version(&flag_val.display().to_string()).map_err(|errmsg| {
141                 AconfigdError::FailToGetFileVersion { file: flag_val.display().to_string(), errmsg }
142             })?;
143 
144         let record = StorageRecord {
145             version,
146             container: container.to_string(),
147             default_package_map: package_map.to_path_buf(),
148             default_flag_map: flag_map.to_path_buf(),
149             default_flag_val: flag_val.to_path_buf(),
150             default_flag_info: flag_info.to_path_buf(),
151             persist_package_map: root_dir.join("maps").join(container.to_string() + ".package.map"),
152             persist_flag_map: root_dir.join("maps").join(container.to_string() + ".flag.map"),
153             persist_flag_val: root_dir.join("flags").join(container.to_string() + ".val"),
154             persist_flag_info: root_dir.join("flags").join(container.to_string() + ".info"),
155             local_overrides: root_dir
156                 .join("flags")
157                 .join(container.to_string() + "_local_overrides.pb"),
158             boot_flag_val: root_dir.join("boot").join(container.to_string() + ".val"),
159             boot_flag_info: root_dir.join("boot").join(container.to_string() + ".info"),
160             digest: get_files_digest(&[package_map, flag_map, flag_val, flag_info][..])?,
161         };
162 
163         debug!("copy {} storage files to persist and boot directories", container);
164         copy_file(package_map, &record.persist_package_map, 0o444)?;
165         copy_file(flag_map, &record.persist_flag_map, 0o444)?;
166         copy_file(flag_val, &record.persist_flag_val, 0o644)?;
167         copy_file(flag_info, &record.persist_flag_info, 0o644)?;
168         copy_file(flag_val, &record.boot_flag_val, 0o644)?;
169         copy_file(flag_info, &record.boot_flag_info, 0o644)?;
170 
171         let pb = ProtoLocalFlagOverrides::new();
172         write_pb_to_file::<ProtoLocalFlagOverrides>(&pb, &record.local_overrides)?;
173 
174         let files = Self {
175             storage_record: record,
176             package_map: None,
177             flag_map: None,
178             flag_val: None,
179             boot_flag_val: None,
180             boot_flag_info: None,
181             persist_flag_val: None,
182             persist_flag_info: None,
183             mutable_boot_flag_val: None,
184             mutable_boot_flag_info: None,
185         };
186 
187         Ok(files)
188     }
189 
190     /// Constructor from a pb record
from_pb( pb: &ProtoPersistStorageRecord, root_dir: &Path, ) -> Result<Self, AconfigdError>191     pub(crate) fn from_pb(
192         pb: &ProtoPersistStorageRecord,
193         root_dir: &Path,
194     ) -> Result<Self, AconfigdError> {
195         debug!("create {} storage files object from pb entry", pb.container());
196         let record = StorageRecord {
197             version: pb.version(),
198             container: pb.container().to_string(),
199             default_package_map: PathBuf::from(pb.package_map()),
200             default_flag_map: PathBuf::from(pb.flag_map()),
201             default_flag_val: PathBuf::from(pb.flag_val()),
202             default_flag_info: PathBuf::from(pb.flag_info()),
203             persist_package_map: root_dir
204                 .join("maps")
205                 .join(pb.container().to_string() + ".package.map"),
206             persist_flag_map: root_dir.join("maps").join(pb.container().to_string() + ".flag.map"),
207             persist_flag_val: root_dir.join("flags").join(pb.container().to_string() + ".val"),
208             persist_flag_info: root_dir.join("flags").join(pb.container().to_string() + ".info"),
209             local_overrides: root_dir
210                 .join("flags")
211                 .join(pb.container().to_string() + "_local_overrides.pb"),
212             boot_flag_val: root_dir.join("boot").join(pb.container().to_string() + ".val"),
213             boot_flag_info: root_dir.join("boot").join(pb.container().to_string() + ".info"),
214             digest: pb.digest().to_string(),
215         };
216 
217         Ok(Self {
218             storage_record: record,
219             package_map: None,
220             flag_map: None,
221             flag_val: None,
222             boot_flag_val: None,
223             boot_flag_info: None,
224             persist_flag_val: None,
225             persist_flag_info: None,
226             mutable_boot_flag_val: None,
227             mutable_boot_flag_info: None,
228         })
229     }
230 
231     /// Get immutable file mapping of a file.
232     ///
233     /// # Safety
234     ///
235     /// The memory mapped file may have undefined behavior if there are writes to the underlying
236     /// file after being mapped. Ensure no writes can happen to the underlying file that is memory
237     /// mapped while this mapping stays alive to guarantee safety.
get_immutable_file_mapping(file_path: &Path) -> Result<Mmap, AconfigdError>238     unsafe fn get_immutable_file_mapping(file_path: &Path) -> Result<Mmap, AconfigdError> {
239         // SAFETY: As per the safety comment, there are no other writes to the underlying file.
240         unsafe {
241             map_file(&file_path.display().to_string()).map_err(|errmsg| {
242                 AconfigdError::FailToMapFile { file: file_path.display().to_string(), errmsg }
243             })
244         }
245     }
246 
247     /// Get package map memory mapping.
get_package_map(&mut self) -> Result<&Mmap, AconfigdError>248     fn get_package_map(&mut self) -> Result<&Mmap, AconfigdError> {
249         if self.package_map.is_none() {
250             // SAFETY: Here it is safe as package map files are always read only.
251             self.package_map = unsafe {
252                 Some(Self::get_immutable_file_mapping(&self.storage_record.persist_package_map)?)
253             };
254         }
255         Ok(self.package_map.as_ref().unwrap())
256     }
257 
258     /// Get flag map memory mapping.
get_flag_map(&mut self) -> Result<&Mmap, AconfigdError>259     fn get_flag_map(&mut self) -> Result<&Mmap, AconfigdError> {
260         if self.flag_map.is_none() {
261             // SAFETY: Here it is safe as flag map files are always read only.
262             self.flag_map = unsafe {
263                 Some(Self::get_immutable_file_mapping(&self.storage_record.persist_flag_map)?)
264             };
265         }
266         Ok(self.flag_map.as_ref().unwrap())
267     }
268 
269     /// Get default flag value memory mapping.
get_flag_val(&mut self) -> Result<&Mmap, AconfigdError>270     fn get_flag_val(&mut self) -> Result<&Mmap, AconfigdError> {
271         if self.flag_val.is_none() {
272             // SAFETY: Here it is safe as default flag value files are always read only.
273             self.flag_val = unsafe {
274                 Some(Self::get_immutable_file_mapping(&self.storage_record.default_flag_val)?)
275             };
276         }
277         Ok(self.flag_val.as_ref().unwrap())
278     }
279 
280     /// Get boot flag value memory mapping.
281     ///
282     /// # Safety
283     ///
284     /// The memory mapped file may have undefined behavior if there are writes to the underlying
285     /// file after being mapped. Ensure no writes can happen to the underlying file that is memory
286     /// mapped while this mapping stays alive to guarantee safety.
get_boot_flag_val(&mut self) -> Result<&Mmap, AconfigdError>287     unsafe fn get_boot_flag_val(&mut self) -> Result<&Mmap, AconfigdError> {
288         if self.boot_flag_val.is_none() {
289             // SAFETY: As per the safety comment, there are no other writes to the underlying file.
290             self.boot_flag_val = unsafe {
291                 Some(Self::get_immutable_file_mapping(&self.storage_record.boot_flag_val)?)
292             };
293         }
294         Ok(self.boot_flag_val.as_ref().unwrap())
295     }
296 
297     /// Get boot flag info memory mapping.
298     ///
299     /// # Safety
300     ///
301     /// The memory mapped file may have undefined behavior if there are writes to the underlying
302     /// file after being mapped. Ensure no writes can happen to the underlying file that is memory
303     /// mapped while this mapping stays alive to guarantee safety.
get_boot_flag_info(&mut self) -> Result<&Mmap, AconfigdError>304     unsafe fn get_boot_flag_info(&mut self) -> Result<&Mmap, AconfigdError> {
305         if self.boot_flag_info.is_none() {
306             // SAFETY: As per the safety comment, there are no other writes to the underlying file.
307             self.boot_flag_info = unsafe {
308                 Some(Self::get_immutable_file_mapping(&self.storage_record.boot_flag_info)?)
309             };
310         }
311         Ok(self.boot_flag_info.as_ref().unwrap())
312     }
313 
314     /// Get mutable file mapping of a file.
315     ///
316     /// # Safety
317     ///
318     /// The memory mapped file may have undefined behavior if there are writes to this
319     /// file not thru this memory mapped file or there are concurrent writes to this
320     /// memory mapped file. Ensure all writes to the underlying file are thru this memory
321     /// mapped file and there are no concurrent writes.
get_mutable_file_mapping( file_path: &Path, ) -> Result<MmapMut, AconfigdError>322     pub(crate) unsafe fn get_mutable_file_mapping(
323         file_path: &Path,
324     ) -> Result<MmapMut, AconfigdError> {
325         // SAFETY: As per the safety comment, there are no other writes to the underlying file.
326         unsafe {
327             map_mutable_storage_file(&file_path.display().to_string()).map_err(|errmsg| {
328                 AconfigdError::FailToMapFile { file: file_path.display().to_string(), errmsg }
329             })
330         }
331     }
332 
333     /// Get persist flag value memory mapping.
get_persist_flag_val(&mut self) -> Result<&mut MmapMut, AconfigdError>334     fn get_persist_flag_val(&mut self) -> Result<&mut MmapMut, AconfigdError> {
335         if self.persist_flag_val.is_none() {
336             // SAFETY: safety is ensured that all writes to the persist file is thru this
337             // memory mapping, and there are no concurrent writes
338             self.persist_flag_val = unsafe {
339                 Some(Self::get_mutable_file_mapping(&self.storage_record.persist_flag_val)?)
340             };
341         }
342         Ok(self.persist_flag_val.as_mut().unwrap())
343     }
344 
345     /// Get persist flag info memory mapping.
get_persist_flag_info(&mut self) -> Result<&mut MmapMut, AconfigdError>346     fn get_persist_flag_info(&mut self) -> Result<&mut MmapMut, AconfigdError> {
347         if self.persist_flag_info.is_none() {
348             // SAFETY: safety is ensured that all writes to the persist file is thru this
349             // memory mapping, and there are no concurrent writes
350             self.persist_flag_info = unsafe {
351                 Some(Self::get_mutable_file_mapping(&self.storage_record.persist_flag_info)?)
352             };
353         }
354         Ok(self.persist_flag_info.as_mut().unwrap())
355     }
356 
357     /// Get mutable boot flag value memory mapping.
get_mutable_boot_flag_val(&mut self) -> Result<&mut MmapMut, AconfigdError>358     fn get_mutable_boot_flag_val(&mut self) -> Result<&mut MmapMut, AconfigdError> {
359         if self.mutable_boot_flag_val.is_none() {
360             // SAFETY: safety is ensured that all writes to the persist file is thru this
361             // memory mapping, and there are no concurrent writes
362             self.mutable_boot_flag_val = unsafe {
363                 Some(Self::get_mutable_file_mapping(&self.storage_record.boot_flag_val)?)
364             };
365         }
366         Ok(self.mutable_boot_flag_val.as_mut().unwrap())
367     }
368 
369     /// Get mutable boot flag info memory mapping.
get_mutable_boot_flag_info(&mut self) -> Result<&mut MmapMut, AconfigdError>370     fn get_mutable_boot_flag_info(&mut self) -> Result<&mut MmapMut, AconfigdError> {
371         if self.mutable_boot_flag_info.is_none() {
372             // SAFETY: safety is ensured that all writes to the persist file is thru this
373             // memory mapping, and there are no concurrent writes
374             self.mutable_boot_flag_info = unsafe {
375                 Some(Self::get_mutable_file_mapping(&self.storage_record.boot_flag_info)?)
376             };
377         }
378         Ok(self.mutable_boot_flag_info.as_mut().unwrap())
379     }
380 
381     /// Get package and flag query context
get_package_flag_context( &mut self, package: &str, flag: &str, ) -> Result<PackageFlagContext, AconfigdError>382     pub(crate) fn get_package_flag_context(
383         &mut self,
384         package: &str,
385         flag: &str,
386     ) -> Result<PackageFlagContext, AconfigdError> {
387         let mut context = PackageFlagContext {
388             package: package.to_string(),
389             flag: flag.to_string(),
390             package_exists: false,
391             flag_exists: false,
392             value_type: FlagValueType::Boolean,
393             flag_index: 0,
394         };
395 
396         if package.is_empty() {
397             return Ok(context);
398         }
399 
400         let package_context =
401             get_package_read_context(self.get_package_map()?, package).map_err(|errmsg| {
402                 AconfigdError::FailToGetPackageContext { package: package.to_string(), errmsg }
403             })?;
404 
405         if let Some(pkg) = package_context {
406             context.package_exists = true;
407             if flag.is_empty() {
408                 return Ok(context);
409             }
410 
411             let flag_context = get_flag_read_context(self.get_flag_map()?, pkg.package_id, flag)
412                 .map_err(|errmsg| AconfigdError::FailToGetFlagContext {
413                     flag: package.to_string() + "." + flag,
414                     errmsg,
415                 })?;
416 
417             if let Some(flg) = flag_context {
418                 context.flag_exists = true;
419                 context.value_type = FlagValueType::try_from(flg.flag_type).map_err(|errmsg| {
420                     AconfigdError::InvalidFlagValueType {
421                         flag: package.to_string() + "." + flag,
422                         errmsg,
423                     }
424                 })?;
425                 context.flag_index = pkg.boolean_start_index + flg.flag_index as u32;
426             }
427         } else {
428             debug!(
429                 "failed to find package {} in container {}",
430                 package, self.storage_record.container
431             );
432         }
433 
434         Ok(context)
435     }
436 
437     /// Check if has an aconfig package
has_package(&mut self, package: &str) -> Result<bool, AconfigdError>438     pub(crate) fn has_package(&mut self, package: &str) -> Result<bool, AconfigdError> {
439         let context = self.get_package_flag_context(package, "")?;
440         Ok(context.package_exists)
441     }
442 
443     /// Get flag attribute bitfield
get_flag_attribute( &mut self, context: &PackageFlagContext, ) -> Result<u8, AconfigdError>444     pub(crate) fn get_flag_attribute(
445         &mut self,
446         context: &PackageFlagContext,
447     ) -> Result<u8, AconfigdError> {
448         if !context.flag_exists {
449             return Err(AconfigdError::FlagDoesNotExist {
450                 flag: context.package.to_string() + "." + &context.flag,
451             });
452         }
453 
454         let flag_info_file = self.get_persist_flag_info()?;
455         Ok(aconfig_storage_read_api::get_flag_attribute(
456             flag_info_file,
457             context.value_type,
458             context.flag_index,
459         )
460         .map_err(|errmsg| AconfigdError::FailToGetFlagAttribute {
461             flag: context.package.to_string() + "." + &context.flag,
462             errmsg,
463         })?)
464     }
465 
466     /// Get flag value from a mapped file
get_flag_value_from_file( file: &[u8], context: &PackageFlagContext, ) -> Result<String, AconfigdError>467     fn get_flag_value_from_file(
468         file: &[u8],
469         context: &PackageFlagContext,
470     ) -> Result<String, AconfigdError> {
471         if !context.flag_exists {
472             return Err(AconfigdError::FlagDoesNotExist {
473                 flag: context.package.to_string() + "." + &context.flag,
474             });
475         }
476 
477         match context.value_type {
478             FlagValueType::Boolean => {
479                 let value = get_boolean_flag_value(file, context.flag_index).map_err(|errmsg| {
480                     AconfigdError::FailToGetFlagValue {
481                         flag: context.package.to_string() + "." + &context.flag,
482                         errmsg,
483                     }
484                 })?;
485                 if value {
486                     Ok(String::from("true"))
487                 } else {
488                     Ok(String::from("false"))
489                 }
490             }
491         }
492     }
493 
494     /// Get server flag value
get_server_flag_value( &mut self, context: &PackageFlagContext, ) -> Result<String, AconfigdError>495     pub(crate) fn get_server_flag_value(
496         &mut self,
497         context: &PackageFlagContext,
498     ) -> Result<String, AconfigdError> {
499         let attribute = self.get_flag_attribute(context)?;
500         if (attribute & FlagInfoBit::HasServerOverride as u8) == 0 {
501             return Ok(String::new());
502         }
503 
504         let flag_val_file = self.get_persist_flag_val()?;
505         Self::get_flag_value_from_file(flag_val_file, context)
506     }
507 
508     /// Get boot flag value
get_boot_flag_value( &mut self, context: &PackageFlagContext, ) -> Result<String, AconfigdError>509     pub(crate) fn get_boot_flag_value(
510         &mut self,
511         context: &PackageFlagContext,
512     ) -> Result<String, AconfigdError> {
513         // SAFETY: safety is ensured as we are only read from the memory mapping
514         let flag_val_file = unsafe { self.get_boot_flag_val()? };
515         Self::get_flag_value_from_file(flag_val_file, context)
516     }
517 
518     /// Get default flag value
get_default_flag_value( &mut self, context: &PackageFlagContext, ) -> Result<String, AconfigdError>519     pub(crate) fn get_default_flag_value(
520         &mut self,
521         context: &PackageFlagContext,
522     ) -> Result<String, AconfigdError> {
523         let flag_val_file = self.get_flag_val()?;
524         Self::get_flag_value_from_file(flag_val_file, context)
525     }
526 
527     /// Get local flag value
get_local_flag_value( &mut self, context: &PackageFlagContext, ) -> Result<String, AconfigdError>528     pub(crate) fn get_local_flag_value(
529         &mut self,
530         context: &PackageFlagContext,
531     ) -> Result<String, AconfigdError> {
532         let attribute = self.get_flag_attribute(context)?;
533         if (attribute & FlagInfoBit::HasLocalOverride as u8) == 0 {
534             return Ok(String::new());
535         }
536 
537         let pb =
538             read_pb_from_file::<ProtoLocalFlagOverrides>(&self.storage_record.local_overrides)?;
539 
540         for entry in pb.overrides {
541             if entry.package_name() == context.package && entry.flag_name() == context.flag {
542                 return Ok(String::from(entry.flag_value()));
543             }
544         }
545 
546         Err(AconfigdError::FlagHasNoLocalOverride {
547             flag: context.package.to_string() + "." + &context.flag,
548         })
549     }
550 
551     /// Set flag value to file
set_flag_value_to_file( file: &mut MmapMut, context: &PackageFlagContext, value: &str, ) -> Result<(), AconfigdError>552     pub(crate) fn set_flag_value_to_file(
553         file: &mut MmapMut,
554         context: &PackageFlagContext,
555         value: &str,
556     ) -> Result<(), AconfigdError> {
557         match context.value_type {
558             FlagValueType::Boolean => {
559                 if value != "true" && value != "false" {
560                     return Err(AconfigdError::InvalidFlagValue {
561                         flag: context.package.to_string() + "." + &context.flag,
562                         value: value.to_string(),
563                     });
564                 }
565                 set_boolean_flag_value(file, context.flag_index, value == "true").map_err(
566                     |errmsg| AconfigdError::FailToSetFlagValue {
567                         flag: context.package.to_string() + "." + &context.flag,
568                         errmsg,
569                     },
570                 )?;
571             }
572         }
573 
574         Ok(())
575     }
576 
577     /// Set flag has server override to file
set_flag_has_server_override_to_file( file: &mut MmapMut, context: &PackageFlagContext, value: bool, ) -> Result<(), AconfigdError>578     fn set_flag_has_server_override_to_file(
579         file: &mut MmapMut,
580         context: &PackageFlagContext,
581         value: bool,
582     ) -> Result<(), AconfigdError> {
583         set_flag_has_server_override(file, context.value_type, context.flag_index, value).map_err(
584             |errmsg| AconfigdError::FailToSetFlagHasServerOverride {
585                 flag: context.package.to_string() + "." + &context.flag,
586                 errmsg,
587             },
588         )?;
589 
590         Ok(())
591     }
592 
593     /// Set flag has local override to file
set_flag_has_local_override_to_file( file: &mut MmapMut, context: &PackageFlagContext, value: bool, ) -> Result<(), AconfigdError>594     pub(crate) fn set_flag_has_local_override_to_file(
595         file: &mut MmapMut,
596         context: &PackageFlagContext,
597         value: bool,
598     ) -> Result<(), AconfigdError> {
599         set_flag_has_local_override(file, context.value_type, context.flag_index, value).map_err(
600             |errmsg| AconfigdError::FailToSetFlagHasLocalOverride {
601                 flag: context.package.to_string() + "." + &context.flag,
602                 errmsg,
603             },
604         )?;
605 
606         Ok(())
607     }
608 
609     /// Server override a flag
stage_server_override( &mut self, context: &PackageFlagContext, value: &str, ) -> Result<(), AconfigdError>610     pub(crate) fn stage_server_override(
611         &mut self,
612         context: &PackageFlagContext,
613         value: &str,
614     ) -> Result<(), AconfigdError> {
615         debug!(
616             "staging server override for flag {} with value {}",
617             context.package.to_string() + "." + &context.flag,
618             value
619         );
620         let attribute = self.get_flag_attribute(context)?;
621         if (attribute & FlagInfoBit::IsReadWrite as u8) == 0 {
622             return Err(AconfigdError::FlagIsReadOnly {
623                 flag: context.package.to_string() + "." + &context.flag,
624             });
625         }
626 
627         let flag_val_file = self.get_persist_flag_val()?;
628         Self::set_flag_value_to_file(flag_val_file, context, value)?;
629 
630         let flag_info_file = self.get_persist_flag_info()?;
631         Self::set_flag_has_server_override_to_file(flag_info_file, context, true)?;
632 
633         Ok(())
634     }
635 
636     /// Stage local override of a flag
stage_local_override( &mut self, context: &PackageFlagContext, value: &str, ) -> Result<(), AconfigdError>637     pub(crate) fn stage_local_override(
638         &mut self,
639         context: &PackageFlagContext,
640         value: &str,
641     ) -> Result<(), AconfigdError> {
642         debug!(
643             "staging local override for flag {} with value {}",
644             context.package.to_string() + "." + &context.flag,
645             value
646         );
647         let attribute = self.get_flag_attribute(context)?;
648         if (attribute & FlagInfoBit::IsReadWrite as u8) == 0 {
649             return Err(AconfigdError::FlagIsReadOnly {
650                 flag: context.package.to_string() + "." + &context.flag,
651             });
652         }
653 
654         let mut exist = false;
655         let mut pb =
656             read_pb_from_file::<ProtoLocalFlagOverrides>(&self.storage_record.local_overrides)?;
657         for entry in &mut pb.overrides {
658             if entry.package_name() == context.package && entry.flag_name() == context.flag {
659                 entry.set_flag_value(String::from(value));
660                 exist = true;
661                 break;
662             }
663         }
664         if !exist {
665             let mut new_entry = ProtoFlagOverride::new();
666             new_entry.set_package_name(context.package.clone());
667             new_entry.set_flag_name(context.flag.clone());
668             new_entry.set_flag_value(String::from(value));
669             pb.overrides.push(new_entry);
670         }
671 
672         write_pb_to_file::<ProtoLocalFlagOverrides>(&pb, &self.storage_record.local_overrides)?;
673 
674         let flag_info_file = self.get_persist_flag_info()?;
675         Self::set_flag_has_local_override_to_file(flag_info_file, context, true)?;
676 
677         Ok(())
678     }
679 
680     /// Stage and apply local override of a flag
stage_and_apply_local_override( &mut self, context: &PackageFlagContext, value: &str, ) -> Result<(), AconfigdError>681     pub(crate) fn stage_and_apply_local_override(
682         &mut self,
683         context: &PackageFlagContext,
684         value: &str,
685     ) -> Result<(), AconfigdError> {
686         self.stage_local_override(&context, value)?;
687 
688         debug!(
689             "apply local override for flag {} with value {}",
690             context.package.to_string() + "." + &context.flag,
691             value
692         );
693         let mut mut_boot_flag_val = self.get_mutable_boot_flag_val()?;
694         Self::set_flag_value_to_file(&mut mut_boot_flag_val, &context, value)?;
695         let mut mut_boot_flag_info = self.get_mutable_boot_flag_info()?;
696         Self::set_flag_has_local_override_to_file(&mut mut_boot_flag_info, &context, true)?;
697         Ok(())
698     }
699 
700     /// Apply all staged local overrides
apply_staged_local_overrides(&mut self) -> Result<(), AconfigdError>701     fn apply_staged_local_overrides(&mut self) -> Result<(), AconfigdError> {
702         debug!("apply staged local overrides for container {}", &self.storage_record.container);
703         let pb =
704             read_pb_from_file::<ProtoLocalFlagOverrides>(&self.storage_record.local_overrides)?;
705 
706         for entry in pb.overrides {
707             let context = self.get_package_flag_context(entry.package_name(), entry.flag_name())?;
708             let mut flag_val_file = self.get_mutable_boot_flag_val()?;
709             Self::set_flag_value_to_file(&mut flag_val_file, &context, entry.flag_value())?;
710         }
711 
712         Ok(())
713     }
714 
715     /// Apply both server and local overrides
apply_all_staged_overrides(&mut self) -> Result<(), AconfigdError>716     pub(crate) fn apply_all_staged_overrides(&mut self) -> Result<(), AconfigdError> {
717         debug!("apply staged server overrides for container {}", &self.storage_record.container);
718         copy_file_without_fsync(
719             &self.storage_record.persist_flag_val,
720             &self.storage_record.boot_flag_val,
721             0o644,
722         )?;
723         copy_file_without_fsync(
724             &self.storage_record.persist_flag_info,
725             &self.storage_record.boot_flag_info,
726             0o644,
727         )?;
728         self.apply_staged_local_overrides()?;
729         Ok(())
730     }
731 
732     /// Get all current server overrides
get_all_server_overrides( &mut self, ) -> Result<Vec<FlagValueSummary>, AconfigdError>733     pub(crate) fn get_all_server_overrides(
734         &mut self,
735     ) -> Result<Vec<FlagValueSummary>, AconfigdError> {
736         debug!("get all staged server overrides for container {}", &self.storage_record.container);
737         let listed_flags = list_flags_with_info(
738             &self.storage_record.persist_package_map.display().to_string(),
739             &self.storage_record.persist_flag_map.display().to_string(),
740             &self.storage_record.persist_flag_val.display().to_string(),
741             &self.storage_record.persist_flag_info.display().to_string(),
742         )
743         .map_err(|errmsg| AconfigdError::FailToListFlagsWithInfo {
744             container: self.storage_record.container.clone(),
745             errmsg,
746         })?;
747 
748         Ok(listed_flags
749             .into_iter()
750             .filter(|f| f.has_server_override)
751             .map(|f| FlagValueSummary {
752                 package_name: f.package_name,
753                 flag_name: f.flag_name,
754                 flag_value: f.flag_value,
755                 value_type: f.value_type,
756             })
757             .collect())
758     }
759 
760     /// Get all local overrides
get_all_local_overrides( &mut self, ) -> Result<Vec<ProtoFlagOverride>, AconfigdError>761     pub(crate) fn get_all_local_overrides(
762         &mut self,
763     ) -> Result<Vec<ProtoFlagOverride>, AconfigdError> {
764         debug!("get all staged local overrides for container {}", &self.storage_record.container);
765         let pb =
766             read_pb_from_file::<ProtoLocalFlagOverrides>(&self.storage_record.local_overrides)?;
767         Ok(pb.overrides)
768     }
769 
770     /// Remove a local flag override
remove_local_override( &mut self, context: &PackageFlagContext, immediate: bool, ) -> Result<(), AconfigdError>771     pub(crate) fn remove_local_override(
772         &mut self,
773         context: &PackageFlagContext,
774         immediate: bool,
775     ) -> Result<(), AconfigdError> {
776         debug!(
777             "remove local override for flag {}",
778             context.package.to_string() + "." + &context.flag
779         );
780         let attribute = self.get_flag_attribute(context)?;
781         if (attribute & FlagInfoBit::HasLocalOverride as u8) == 0 {
782             return Err(AconfigdError::FlagHasNoLocalOverride {
783                 flag: context.package.to_string() + "." + &context.flag,
784             });
785         }
786 
787         let mut pb =
788             read_pb_from_file::<ProtoLocalFlagOverrides>(&self.storage_record.local_overrides)?;
789         pb.overrides = pb
790             .overrides
791             .into_iter()
792             .filter(|f| f.package_name() != context.package || f.flag_name() != context.flag)
793             .collect();
794         write_pb_to_file::<ProtoLocalFlagOverrides>(&pb, &self.storage_record.local_overrides)?;
795 
796         let flag_info_file = self.get_persist_flag_info()?;
797         Self::set_flag_has_local_override_to_file(flag_info_file, context, false)?;
798 
799         if configinfra_framework_flags_rust::enable_immediate_clear_override_bugfix() && immediate {
800             let value = if (attribute & FlagInfoBit::HasServerOverride as u8) == 1 {
801                 self.get_server_flag_value(&context)?
802             } else {
803                 self.get_default_flag_value(&context)?
804             };
805 
806             let mut mut_boot_flag_val = self.get_mutable_boot_flag_val()?;
807             Self::set_flag_value_to_file(&mut mut_boot_flag_val, &context, &value)?;
808 
809             let mut mut_boot_flag_info = self.get_mutable_boot_flag_info()?;
810             Self::set_flag_has_local_override_to_file(&mut mut_boot_flag_info, &context, false)?;
811         }
812 
813         Ok(())
814     }
815 
816     /// Remove all local flag overrides
remove_all_local_overrides(&mut self) -> Result<(), AconfigdError>817     pub(crate) fn remove_all_local_overrides(&mut self) -> Result<(), AconfigdError> {
818         debug!("remove all local overrides for container {}", &self.storage_record.container);
819         let pb =
820             read_pb_from_file::<ProtoLocalFlagOverrides>(&self.storage_record.local_overrides)?;
821 
822         for entry in pb.overrides {
823             let context = self.get_package_flag_context(entry.package_name(), entry.flag_name())?;
824             let attribute = self.get_flag_attribute(&context)?;
825             if (attribute & FlagInfoBit::HasLocalOverride as u8) == 0 {
826                 return Err(AconfigdError::FlagHasNoLocalOverride {
827                     flag: context.package.to_string() + "." + &context.flag,
828                 });
829             }
830 
831             let flag_info_file = self.get_persist_flag_info()?;
832             Self::set_flag_has_local_override_to_file(flag_info_file, &context, false)?;
833         }
834 
835         write_pb_to_file::<ProtoLocalFlagOverrides>(
836             &ProtoLocalFlagOverrides::new(),
837             &self.storage_record.local_overrides,
838         )?;
839 
840         Ok(())
841     }
842 
843     /// Clean up, it cannot be implemented as the drop trait as it needs to return a Result
remove_persist_files(&mut self) -> Result<(), AconfigdError>844     pub(crate) fn remove_persist_files(&mut self) -> Result<(), AconfigdError> {
845         debug!(
846             "remove all persistent storage files for container {}",
847             &self.storage_record.container
848         );
849         remove_file(&self.storage_record.persist_package_map)?;
850         remove_file(&self.storage_record.persist_flag_map)?;
851         remove_file(&self.storage_record.persist_flag_val)?;
852         remove_file(&self.storage_record.persist_flag_info)?;
853         remove_file(&self.storage_record.local_overrides)
854     }
855 
856     /// get flag snapshot
get_flag_snapshot( &mut self, package: &str, flag: &str, ) -> Result<Option<FlagSnapshot>, AconfigdError>857     pub(crate) fn get_flag_snapshot(
858         &mut self,
859         package: &str,
860         flag: &str,
861     ) -> Result<Option<FlagSnapshot>, AconfigdError> {
862         let context = self.get_package_flag_context(package, flag)?;
863         if !context.flag_exists {
864             return Ok(None);
865         }
866 
867         let attribute = self.get_flag_attribute(&context)?;
868         let server_value = self.get_server_flag_value(&context)?;
869         let local_value = self.get_local_flag_value(&context)?;
870         let boot_value = self.get_boot_flag_value(&context)?;
871         let default_value = self.get_default_flag_value(&context)?;
872 
873         Ok(Some(FlagSnapshot {
874             container: self.storage_record.container.clone(),
875             package: package.to_string(),
876             flag: flag.to_string(),
877             server_value,
878             local_value,
879             boot_value,
880             default_value,
881             is_readwrite: attribute & FlagInfoBit::IsReadWrite as u8 != 0,
882             has_server_override: attribute & FlagInfoBit::HasServerOverride as u8 != 0,
883             has_local_override: attribute & FlagInfoBit::HasLocalOverride as u8 != 0,
884             has_boot_local_override: false, // This is unsupported for get_flag_snapshot.
885         }))
886     }
887 
888     /// list flags in a package
list_flags_in_package( &mut self, package: &str, ) -> Result<Vec<FlagSnapshot>, AconfigdError>889     pub(crate) fn list_flags_in_package(
890         &mut self,
891         package: &str,
892     ) -> Result<Vec<FlagSnapshot>, AconfigdError> {
893         debug!("list all flags in package {}", &package);
894         if !self.has_package(package)? {
895             return Ok(Vec::new());
896         }
897 
898         let mut snapshots: Vec<_> = list_flags_with_info(
899             &self.storage_record.persist_package_map.display().to_string(),
900             &self.storage_record.persist_flag_map.display().to_string(),
901             &self.storage_record.persist_flag_val.display().to_string(),
902             &self.storage_record.persist_flag_info.display().to_string(),
903         )
904         .map_err(|errmsg| AconfigdError::FailToListFlagsWithInfo {
905             container: self.storage_record.container.clone(),
906             errmsg,
907         })?
908         .into_iter()
909         .filter(|f| f.package_name == package)
910         .map(|f| FlagSnapshot {
911             container: self.storage_record.container.clone(),
912             package: f.package_name.clone(),
913             flag: f.flag_name.clone(),
914             server_value: if f.has_server_override { f.flag_value.clone() } else { String::new() },
915             local_value: String::new(),
916             boot_value: String::new(),
917             default_value: String::new(),
918             is_readwrite: f.is_readwrite,
919             has_server_override: f.has_server_override,
920             has_local_override: f.has_local_override,
921             has_boot_local_override: false, // Placeholder; this is mutated and set below.
922         })
923         .collect();
924 
925         let mut flag_index = HashMap::new();
926         for (i, f) in snapshots.iter().enumerate() {
927             flag_index.insert(f.package.clone() + "/" + &f.flag, i);
928         }
929 
930         let mut flags: Vec<_> = list_flags_with_info(
931             &self.storage_record.persist_package_map.display().to_string(),
932             &self.storage_record.persist_flag_map.display().to_string(),
933             &self.storage_record.boot_flag_val.display().to_string(),
934             &self.storage_record.boot_flag_info.display().to_string(),
935         )
936         .map_err(|errmsg| AconfigdError::FailToListFlags {
937             container: self.storage_record.container.clone(),
938             errmsg,
939         })?
940         .into_iter()
941         .filter(|f| f.package_name == package)
942         .collect();
943 
944         for f in flags.iter() {
945             let full_flag_name = f.package_name.clone() + "/" + &f.flag_name;
946             let index =
947                 flag_index.get(&full_flag_name).ok_or(AconfigdError::InternalError(anyhow!(
948                     "Flag {}.{} appears in boot files but not in persist fliles",
949                     &f.package_name,
950                     &f.flag_name,
951                 )))?;
952             snapshots[*index].boot_value = f.flag_value.clone();
953             snapshots[*index].has_boot_local_override = f.has_local_override;
954         }
955 
956         let flags: Vec<_> = list_flags(
957             &self.storage_record.persist_package_map.display().to_string(),
958             &self.storage_record.persist_flag_map.display().to_string(),
959             &self.storage_record.default_flag_val.display().to_string(),
960         )
961         .map_err(|errmsg| AconfigdError::FailToListFlags {
962             container: self.storage_record.container.clone(),
963             errmsg,
964         })?
965         .into_iter()
966         .filter(|f| f.package_name == package)
967         .collect();
968 
969         for f in flags.iter() {
970             let full_flag_name = f.package_name.clone() + "/" + &f.flag_name;
971             let index =
972                 flag_index.get(&full_flag_name).ok_or(AconfigdError::InternalError(anyhow!(
973                     "Flag {}.{} appears in default files but not in persist fliles",
974                     &f.package_name,
975                     &f.flag_name,
976                 )))?;
977             snapshots[*index].default_value = f.flag_value.clone();
978         }
979 
980         let pb =
981             read_pb_from_file::<ProtoLocalFlagOverrides>(&self.storage_record.local_overrides)?;
982 
983         for entry in pb.overrides {
984             let full_flag_name = entry.package_name().to_string() + "/" + entry.flag_name();
985             if let Some(index) = flag_index.get(&full_flag_name) {
986                 snapshots[*index].local_value = entry.flag_value().to_string();
987             }
988         }
989 
990         Ok(snapshots)
991     }
992 
993     /// list all flags in a container
list_all_flags(&mut self) -> Result<Vec<FlagSnapshot>, AconfigdError>994     pub(crate) fn list_all_flags(&mut self) -> Result<Vec<FlagSnapshot>, AconfigdError> {
995         debug!("list all flags in container {}", &self.storage_record.container);
996         let mut snapshots: Vec<_> = list_flags_with_info(
997             &self.storage_record.persist_package_map.display().to_string(),
998             &self.storage_record.persist_flag_map.display().to_string(),
999             &self.storage_record.persist_flag_val.display().to_string(),
1000             &self.storage_record.persist_flag_info.display().to_string(),
1001         )
1002         .map_err(|errmsg| AconfigdError::FailToListFlagsWithInfo {
1003             container: self.storage_record.container.clone(),
1004             errmsg,
1005         })?
1006         .into_iter()
1007         .map(|f| FlagSnapshot {
1008             container: self.storage_record.container.clone(),
1009             package: f.package_name.clone(),
1010             flag: f.flag_name.clone(),
1011             server_value: if f.has_server_override { f.flag_value.clone() } else { String::new() },
1012             local_value: String::new(),
1013             boot_value: String::new(),
1014             default_value: String::new(),
1015             is_readwrite: f.is_readwrite,
1016             has_server_override: f.has_server_override,
1017             has_local_override: f.has_local_override,
1018             has_boot_local_override: false, // Placeholder value; this is mutated and set below.
1019         })
1020         .collect();
1021 
1022         let mut flag_index = HashMap::new();
1023         for (i, f) in snapshots.iter().enumerate() {
1024             flag_index.insert(f.package.clone() + "/" + &f.flag, i);
1025         }
1026 
1027         let mut flags: Vec<_> = list_flags_with_info(
1028             &self.storage_record.persist_package_map.display().to_string(),
1029             &self.storage_record.persist_flag_map.display().to_string(),
1030             &self.storage_record.boot_flag_val.display().to_string(),
1031             &self.storage_record.boot_flag_info.display().to_string(),
1032         )
1033         .map_err(|errmsg| AconfigdError::FailToListFlags {
1034             container: self.storage_record.container.clone(),
1035             errmsg,
1036         })?
1037         .into_iter()
1038         .collect();
1039 
1040         for f in flags.iter() {
1041             let full_flag_name = f.package_name.clone() + "/" + &f.flag_name;
1042             let index =
1043                 flag_index.get(&full_flag_name).ok_or(AconfigdError::InternalError(anyhow!(
1044                     "Flag {}.{} appears in boot files but not in persist fliles",
1045                     &f.package_name,
1046                     &f.flag_name,
1047                 )))?;
1048             snapshots[*index].boot_value = f.flag_value.clone();
1049             snapshots[*index].has_boot_local_override = f.has_local_override;
1050         }
1051 
1052         let flags: Vec<_> = list_flags(
1053             &self.storage_record.persist_package_map.display().to_string(),
1054             &self.storage_record.persist_flag_map.display().to_string(),
1055             &self.storage_record.default_flag_val.display().to_string(),
1056         )
1057         .map_err(|errmsg| AconfigdError::FailToListFlags {
1058             container: self.storage_record.container.clone(),
1059             errmsg,
1060         })?
1061         .into_iter()
1062         .collect();
1063 
1064         for f in flags.iter() {
1065             let full_flag_name = f.package_name.clone() + "/" + &f.flag_name;
1066             let index =
1067                 flag_index.get(&full_flag_name).ok_or(AconfigdError::InternalError(anyhow!(
1068                     "Flag {}.{} appears in default files but not in persist fliles",
1069                     &f.package_name,
1070                     &f.flag_name,
1071                 )))?;
1072             snapshots[*index].default_value = f.flag_value.clone();
1073         }
1074 
1075         let pb =
1076             read_pb_from_file::<ProtoLocalFlagOverrides>(&self.storage_record.local_overrides)?;
1077 
1078         for entry in pb.overrides {
1079             let full_flag_name = entry.package_name().to_string() + "/" + entry.flag_name();
1080             if let Some(index) = flag_index.get(&full_flag_name) {
1081                 snapshots[*index].local_value = entry.flag_value().to_string();
1082             }
1083         }
1084 
1085         Ok(snapshots)
1086     }
1087 }
1088 
1089 #[cfg(test)]
1090 mod tests {
1091     use super::*;
1092     use crate::test_utils::{has_same_content, ContainerMock, StorageRootDirMock};
1093     use aconfig_storage_file::StoredFlagType;
1094 
create_mock_storage_files( container: &ContainerMock, root_dir: &StorageRootDirMock, ) -> StorageFiles1095     fn create_mock_storage_files(
1096         container: &ContainerMock,
1097         root_dir: &StorageRootDirMock,
1098     ) -> StorageFiles {
1099         StorageFiles::from_container(
1100             &container.name,
1101             &container.package_map,
1102             &container.flag_map,
1103             &container.flag_val,
1104             &container.flag_info,
1105             &root_dir.tmp_dir.path(),
1106         )
1107         .unwrap()
1108     }
1109 
1110     #[test]
test_create_storage_file_from_container()1111     fn test_create_storage_file_from_container() {
1112         let container = ContainerMock::new();
1113         let root_dir = StorageRootDirMock::new();
1114         let storage_files = create_mock_storage_files(&container, &root_dir);
1115 
1116         let expected_record = StorageRecord {
1117             version: 1,
1118             container: String::from("mockup"),
1119             default_package_map: container.package_map.clone(),
1120             default_flag_map: container.flag_map.clone(),
1121             default_flag_val: container.flag_val.clone(),
1122             default_flag_info: container.flag_info.clone(),
1123             persist_package_map: root_dir.maps_dir.join("mockup.package.map"),
1124             persist_flag_map: root_dir.maps_dir.join("mockup.flag.map"),
1125             persist_flag_val: root_dir.flags_dir.join("mockup.val"),
1126             persist_flag_info: root_dir.flags_dir.join("mockup.info"),
1127             local_overrides: root_dir.flags_dir.join("mockup_local_overrides.pb"),
1128             boot_flag_val: root_dir.boot_dir.join("mockup.val"),
1129             boot_flag_info: root_dir.boot_dir.join("mockup.info"),
1130             digest: get_files_digest(
1131                 &[
1132                     container.package_map.as_path(),
1133                     container.flag_map.as_path(),
1134                     container.flag_val.as_path(),
1135                     container.flag_info.as_path(),
1136                 ][..],
1137             )
1138             .unwrap(),
1139         };
1140 
1141         let expected_storage_files = StorageFiles {
1142             storage_record: expected_record,
1143             package_map: None,
1144             flag_map: None,
1145             flag_val: None,
1146             boot_flag_val: None,
1147             boot_flag_info: None,
1148             persist_flag_val: None,
1149             persist_flag_info: None,
1150             mutable_boot_flag_val: None,
1151             mutable_boot_flag_info: None,
1152         };
1153 
1154         assert_eq!(storage_files, expected_storage_files);
1155 
1156         assert!(has_same_content(
1157             &container.package_map,
1158             &storage_files.storage_record.persist_package_map
1159         ));
1160         assert!(has_same_content(
1161             &container.flag_map,
1162             &storage_files.storage_record.persist_flag_map
1163         ));
1164         assert!(has_same_content(
1165             &container.flag_val,
1166             &storage_files.storage_record.persist_flag_val
1167         ));
1168         assert!(has_same_content(
1169             &container.flag_info,
1170             &storage_files.storage_record.persist_flag_info
1171         ));
1172         assert!(has_same_content(&container.flag_val, &storage_files.storage_record.boot_flag_val));
1173         assert!(has_same_content(
1174             &container.flag_info,
1175             &storage_files.storage_record.boot_flag_info
1176         ));
1177         assert!(storage_files.storage_record.local_overrides.exists());
1178     }
1179 
1180     #[test]
test_create_storage_file_from_pb()1181     fn test_create_storage_file_from_pb() {
1182         let root_dir = StorageRootDirMock::new();
1183         let container = ContainerMock::new();
1184 
1185         let persist_package_map = root_dir.maps_dir.join("mockup.package.map");
1186         let persist_flag_map = root_dir.maps_dir.join("mockup.flag.map");
1187         let persist_flag_val = root_dir.flags_dir.join("mockup.val");
1188         let persist_flag_info = root_dir.flags_dir.join("mockup.info");
1189         copy_file(&container.package_map, &persist_package_map, 0o444).unwrap();
1190         copy_file(&container.flag_map, &persist_flag_map, 0o444).unwrap();
1191         copy_file(&container.flag_val, &persist_flag_val, 0o644).unwrap();
1192         copy_file(&container.flag_info, &persist_flag_info, 0o644).unwrap();
1193 
1194         let mut pb = ProtoPersistStorageRecord::new();
1195         pb.set_version(123);
1196         pb.set_container("mockup".to_string());
1197         pb.set_package_map(container.package_map.display().to_string());
1198         pb.set_flag_map(container.flag_map.display().to_string());
1199         pb.set_flag_val(container.flag_val.display().to_string());
1200         pb.set_flag_info(container.flag_info.display().to_string());
1201         pb.set_digest(String::from("abc"));
1202 
1203         let storage_files = StorageFiles::from_pb(&pb, &root_dir.tmp_dir.path()).unwrap();
1204 
1205         let expected_record = StorageRecord {
1206             version: 123,
1207             container: String::from("mockup"),
1208             default_package_map: container.package_map.clone(),
1209             default_flag_map: container.flag_map.clone(),
1210             default_flag_val: container.flag_val.clone(),
1211             default_flag_info: container.flag_info.clone(),
1212             persist_package_map: root_dir.maps_dir.join("mockup.package.map"),
1213             persist_flag_map: root_dir.maps_dir.join("mockup.flag.map"),
1214             persist_flag_val: root_dir.flags_dir.join("mockup.val"),
1215             persist_flag_info: root_dir.flags_dir.join("mockup.info"),
1216             local_overrides: root_dir.flags_dir.join("mockup_local_overrides.pb"),
1217             boot_flag_val: root_dir.boot_dir.join("mockup.val"),
1218             boot_flag_info: root_dir.boot_dir.join("mockup.info"),
1219             digest: String::from("abc"),
1220         };
1221 
1222         let expected_storage_files = StorageFiles {
1223             storage_record: expected_record,
1224             package_map: None,
1225             flag_map: None,
1226             flag_val: None,
1227             boot_flag_val: None,
1228             boot_flag_info: None,
1229             persist_flag_val: None,
1230             persist_flag_info: None,
1231             mutable_boot_flag_val: None,
1232             mutable_boot_flag_info: None,
1233         };
1234 
1235         assert_eq!(storage_files, expected_storage_files);
1236     }
1237 
1238     #[test]
test_get_package_flag_context()1239     fn test_get_package_flag_context() {
1240         let container = ContainerMock::new();
1241         let root_dir = StorageRootDirMock::new();
1242         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1243 
1244         let mut context = PackageFlagContext {
1245             package: String::from("not_exist"),
1246             flag: String::new(),
1247             package_exists: false,
1248             flag_exists: false,
1249             value_type: FlagValueType::Boolean,
1250             flag_index: 0,
1251         };
1252         let mut actual_context = storage_files.get_package_flag_context("not_exist", "").unwrap();
1253         assert_eq!(context, actual_context);
1254 
1255         context.package = String::from("com.android.aconfig.storage.test_1");
1256         context.package_exists = true;
1257         actual_context = storage_files
1258             .get_package_flag_context("com.android.aconfig.storage.test_1", "")
1259             .unwrap();
1260         assert_eq!(context, actual_context);
1261 
1262         context.flag = String::from("not_exist");
1263         actual_context = storage_files
1264             .get_package_flag_context("com.android.aconfig.storage.test_1", "not_exist")
1265             .unwrap();
1266         assert_eq!(context, actual_context);
1267 
1268         context.flag = String::from("enabled_rw");
1269         context.flag_exists = true;
1270         context.flag_index = 2;
1271         actual_context = storage_files
1272             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1273             .unwrap();
1274         assert_eq!(context, actual_context);
1275 
1276         context.package = String::from("com.android.aconfig.storage.test_2");
1277         context.flag = String::from("disabled_rw");
1278         context.flag_index = 3;
1279         actual_context = storage_files
1280             .get_package_flag_context("com.android.aconfig.storage.test_2", "disabled_rw")
1281             .unwrap();
1282         assert_eq!(context, actual_context);
1283     }
1284 
1285     #[test]
test_has_package()1286     fn test_has_package() {
1287         let container = ContainerMock::new();
1288         let root_dir = StorageRootDirMock::new();
1289         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1290         assert!(!storage_files.has_package("not_exist").unwrap());
1291         assert!(storage_files.has_package("com.android.aconfig.storage.test_1").unwrap());
1292     }
1293 
1294     #[test]
test_get_flag_attribute()1295     fn test_get_flag_attribute() {
1296         let container = ContainerMock::new();
1297         let root_dir = StorageRootDirMock::new();
1298         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1299         let mut context = storage_files
1300             .get_package_flag_context("com.android.aconfig.storage.test_1", "not_exist")
1301             .unwrap();
1302         assert!(storage_files.get_flag_attribute(&context).is_err());
1303 
1304         context = storage_files
1305             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1306             .unwrap();
1307         let attribute = storage_files.get_flag_attribute(&context).unwrap();
1308         assert!(attribute & (FlagInfoBit::IsReadWrite as u8) != 0);
1309         assert!(attribute & (FlagInfoBit::HasServerOverride as u8) == 0);
1310         assert!(attribute & (FlagInfoBit::HasLocalOverride as u8) == 0);
1311     }
1312 
1313     #[test]
test_get_server_flag_value()1314     fn test_get_server_flag_value() {
1315         let container = ContainerMock::new();
1316         let root_dir = StorageRootDirMock::new();
1317         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1318         let context = storage_files
1319             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1320             .unwrap();
1321 
1322         assert_eq!(&storage_files.get_server_flag_value(&context).unwrap(), "");
1323         storage_files.stage_server_override(&context, "false").unwrap();
1324         assert_eq!(&storage_files.get_server_flag_value(&context).unwrap(), "false");
1325         storage_files.stage_server_override(&context, "true").unwrap();
1326         assert_eq!(&storage_files.get_server_flag_value(&context).unwrap(), "true");
1327     }
1328 
1329     #[test]
test_get_boot_flag_value()1330     fn test_get_boot_flag_value() {
1331         let container = ContainerMock::new();
1332         let root_dir = StorageRootDirMock::new();
1333         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1334         let mut context = storage_files
1335             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1336             .unwrap();
1337         assert_eq!(storage_files.get_boot_flag_value(&context).unwrap(), "true");
1338         context = storage_files
1339             .get_package_flag_context("com.android.aconfig.storage.test_2", "disabled_rw")
1340             .unwrap();
1341         assert_eq!(storage_files.get_boot_flag_value(&context).unwrap(), "false");
1342     }
1343 
1344     #[test]
test_get_default_flag_value()1345     fn test_get_default_flag_value() {
1346         let container = ContainerMock::new();
1347         let root_dir = StorageRootDirMock::new();
1348         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1349         let mut context = storage_files
1350             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1351             .unwrap();
1352         assert_eq!(storage_files.get_default_flag_value(&context).unwrap(), "true");
1353         context = storage_files
1354             .get_package_flag_context("com.android.aconfig.storage.test_2", "disabled_rw")
1355             .unwrap();
1356         assert_eq!(storage_files.get_default_flag_value(&context).unwrap(), "false");
1357     }
1358 
1359     #[test]
test_get_local_flag_value()1360     fn test_get_local_flag_value() {
1361         let container = ContainerMock::new();
1362         let root_dir = StorageRootDirMock::new();
1363         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1364         let context = storage_files
1365             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1366             .unwrap();
1367         assert_eq!(&storage_files.get_local_flag_value(&context).unwrap(), "");
1368         storage_files.stage_local_override(&context, "false").unwrap();
1369         assert_eq!(&storage_files.get_local_flag_value(&context).unwrap(), "false");
1370         storage_files.stage_local_override(&context, "true").unwrap();
1371         assert_eq!(&storage_files.get_local_flag_value(&context).unwrap(), "true");
1372     }
1373 
1374     #[test]
test_stage_server_override()1375     fn test_stage_server_override() {
1376         let container = ContainerMock::new();
1377         let root_dir = StorageRootDirMock::new();
1378         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1379         let context = storage_files
1380             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1381             .unwrap();
1382         storage_files.stage_server_override(&context, "false").unwrap();
1383         assert_eq!(&storage_files.get_server_flag_value(&context).unwrap(), "false");
1384         let attribute = storage_files.get_flag_attribute(&context).unwrap();
1385         assert!(attribute & (FlagInfoBit::HasServerOverride as u8) != 0);
1386     }
1387 
1388     #[test]
test_stage_local_override()1389     fn test_stage_local_override() {
1390         let container = ContainerMock::new();
1391         let root_dir = StorageRootDirMock::new();
1392         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1393         let context = storage_files
1394             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1395             .unwrap();
1396         storage_files.stage_local_override(&context, "false").unwrap();
1397         assert_eq!(&storage_files.get_local_flag_value(&context).unwrap(), "false");
1398         let attribute = storage_files.get_flag_attribute(&context).unwrap();
1399         assert!(attribute & (FlagInfoBit::HasLocalOverride as u8) != 0);
1400     }
1401 
1402     #[test]
test_stage_and_apply_local_override()1403     fn test_stage_and_apply_local_override() {
1404         let container = ContainerMock::new();
1405         let root_dir = StorageRootDirMock::new();
1406         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1407         let context = storage_files
1408             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1409             .unwrap();
1410         storage_files.stage_and_apply_local_override(&context, "false").unwrap();
1411         assert_eq!(&storage_files.get_local_flag_value(&context).unwrap(), "false");
1412         assert_eq!(&storage_files.get_boot_flag_value(&context).unwrap(), "false");
1413         let attribute = storage_files.get_flag_attribute(&context).unwrap();
1414         assert!(attribute & (FlagInfoBit::HasLocalOverride as u8) != 0);
1415     }
1416 
1417     #[test]
test_apply_all_staged_overrides()1418     fn test_apply_all_staged_overrides() {
1419         let container = ContainerMock::new();
1420         let root_dir = StorageRootDirMock::new();
1421         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1422 
1423         let context_one = storage_files
1424             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1425             .unwrap();
1426         storage_files.stage_server_override(&context_one, "false").unwrap();
1427 
1428         let context_two = storage_files
1429             .get_package_flag_context("com.android.aconfig.storage.test_2", "disabled_rw")
1430             .unwrap();
1431         storage_files.stage_server_override(&context_two, "false").unwrap();
1432         storage_files.stage_local_override(&context_two, "true").unwrap();
1433 
1434         storage_files.apply_all_staged_overrides().unwrap();
1435 
1436         assert!(storage_files.storage_record.boot_flag_val.exists());
1437         assert!(storage_files.storage_record.boot_flag_info.exists());
1438 
1439         assert_eq!(storage_files.get_boot_flag_value(&context_one).unwrap(), "false");
1440         assert_eq!(storage_files.get_boot_flag_value(&context_two).unwrap(), "true");
1441     }
1442 
1443     #[test]
test_get_all_server_overrides()1444     fn test_get_all_server_overrides() {
1445         let container = ContainerMock::new();
1446         let root_dir = StorageRootDirMock::new();
1447         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1448         let mut context = storage_files
1449             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1450             .unwrap();
1451         storage_files.stage_server_override(&context, "false").unwrap();
1452         context = storage_files
1453             .get_package_flag_context("com.android.aconfig.storage.test_2", "disabled_rw")
1454             .unwrap();
1455         storage_files.stage_server_override(&context, "true").unwrap();
1456         let server_overrides = storage_files.get_all_server_overrides().unwrap();
1457         assert_eq!(server_overrides.len(), 2);
1458         assert_eq!(
1459             server_overrides[0],
1460             FlagValueSummary {
1461                 package_name: "com.android.aconfig.storage.test_1".to_string(),
1462                 flag_name: "enabled_rw".to_string(),
1463                 flag_value: "false".to_string(),
1464                 value_type: StoredFlagType::ReadWriteBoolean,
1465             }
1466         );
1467         assert_eq!(
1468             server_overrides[1],
1469             FlagValueSummary {
1470                 package_name: "com.android.aconfig.storage.test_2".to_string(),
1471                 flag_name: "disabled_rw".to_string(),
1472                 flag_value: "true".to_string(),
1473                 value_type: StoredFlagType::ReadWriteBoolean,
1474             }
1475         );
1476     }
1477 
1478     #[test]
test_get_all_local_overrides()1479     fn test_get_all_local_overrides() {
1480         let container = ContainerMock::new();
1481         let root_dir = StorageRootDirMock::new();
1482         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1483 
1484         let context_one = storage_files
1485             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1486             .unwrap();
1487         storage_files.stage_local_override(&context_one, "false").unwrap();
1488 
1489         let context_two = storage_files
1490             .get_package_flag_context("com.android.aconfig.storage.test_2", "disabled_rw")
1491             .unwrap();
1492         storage_files.stage_local_override(&context_two, "false").unwrap();
1493 
1494         let local_overrides = storage_files.get_all_local_overrides().unwrap();
1495         assert_eq!(local_overrides.len(), 2);
1496 
1497         let mut override_proto = ProtoFlagOverride::new();
1498         override_proto.set_package_name("com.android.aconfig.storage.test_1".to_string());
1499         override_proto.set_flag_name("enabled_rw".to_string());
1500         override_proto.set_flag_value("false".to_string());
1501         assert_eq!(local_overrides[0], override_proto);
1502 
1503         override_proto.set_package_name("com.android.aconfig.storage.test_2".to_string());
1504         override_proto.set_flag_name("disabled_rw".to_string());
1505         assert_eq!(local_overrides[1], override_proto);
1506     }
1507 
1508     #[test]
test_remove_local_override()1509     fn test_remove_local_override() {
1510         let container = ContainerMock::new();
1511         let root_dir = StorageRootDirMock::new();
1512         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1513         let context = storage_files
1514             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1515             .unwrap();
1516 
1517         assert!(storage_files.remove_local_override(&context, false).is_err());
1518         storage_files.stage_local_override(&context, "false").unwrap();
1519         storage_files.remove_local_override(&context, false).unwrap();
1520         assert_eq!(&storage_files.get_local_flag_value(&context).unwrap(), "");
1521         let attribute = storage_files.get_flag_attribute(&context).unwrap();
1522         assert!(attribute & (FlagInfoBit::HasLocalOverride as u8) == 0);
1523     }
1524 
1525     #[test]
test_remove_all_local_overrides()1526     fn test_remove_all_local_overrides() {
1527         let container = ContainerMock::new();
1528         let root_dir = StorageRootDirMock::new();
1529         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1530 
1531         let context_one = storage_files
1532             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1533             .unwrap();
1534         storage_files.stage_local_override(&context_one, "false").unwrap();
1535 
1536         let context_two = storage_files
1537             .get_package_flag_context("com.android.aconfig.storage.test_2", "disabled_rw")
1538             .unwrap();
1539         storage_files.stage_local_override(&context_two, "false").unwrap();
1540 
1541         let mut pb = read_pb_from_file::<ProtoLocalFlagOverrides>(
1542             &storage_files.storage_record.local_overrides,
1543         )
1544         .unwrap();
1545         assert_eq!(pb.overrides.len(), 2);
1546 
1547         storage_files.remove_all_local_overrides().unwrap();
1548 
1549         assert_eq!(&storage_files.get_local_flag_value(&context_one).unwrap(), "");
1550         let mut attribute = storage_files.get_flag_attribute(&context_one).unwrap();
1551         assert!(attribute & (FlagInfoBit::HasLocalOverride as u8) == 0);
1552 
1553         assert_eq!(&storage_files.get_local_flag_value(&context_two).unwrap(), "");
1554         attribute = storage_files.get_flag_attribute(&context_one).unwrap();
1555         assert!(attribute & (FlagInfoBit::HasLocalOverride as u8) == 0);
1556 
1557         pb = read_pb_from_file::<ProtoLocalFlagOverrides>(
1558             &storage_files.storage_record.local_overrides,
1559         )
1560         .unwrap();
1561         assert_eq!(pb.overrides.len(), 0);
1562     }
1563 
1564     #[test]
test_remove_persist_files()1565     fn test_remove_persist_files() {
1566         let container = ContainerMock::new();
1567         let root_dir = StorageRootDirMock::new();
1568         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1569         write_pb_to_file::<ProtoLocalFlagOverrides>(
1570             &ProtoLocalFlagOverrides::new(),
1571             &storage_files.storage_record.local_overrides,
1572         )
1573         .unwrap();
1574         assert!(storage_files.storage_record.persist_package_map.exists());
1575         assert!(storage_files.storage_record.persist_flag_map.exists());
1576         assert!(storage_files.storage_record.persist_flag_val.exists());
1577         assert!(storage_files.storage_record.persist_flag_info.exists());
1578         assert!(storage_files.storage_record.local_overrides.exists());
1579 
1580         storage_files.remove_persist_files().unwrap();
1581         assert!(!storage_files.storage_record.persist_package_map.exists());
1582         assert!(!storage_files.storage_record.persist_flag_map.exists());
1583         assert!(!storage_files.storage_record.persist_flag_val.exists());
1584         assert!(!storage_files.storage_record.persist_flag_info.exists());
1585         assert!(!storage_files.storage_record.local_overrides.exists());
1586     }
1587 
1588     #[test]
test_get_flag_snapshot()1589     fn test_get_flag_snapshot() {
1590         let container = ContainerMock::new();
1591         let root_dir = StorageRootDirMock::new();
1592         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1593 
1594         let mut flag = storage_files
1595             .get_flag_snapshot("com.android.aconfig.storage.test_1", "not_exist")
1596             .unwrap();
1597         assert_eq!(flag, None);
1598 
1599         let context = storage_files
1600             .get_package_flag_context("com.android.aconfig.storage.test_1", "disabled_rw")
1601             .unwrap();
1602         storage_files.stage_server_override(&context, "false").unwrap();
1603         storage_files.stage_local_override(&context, "true").unwrap();
1604         storage_files.apply_all_staged_overrides().unwrap();
1605 
1606         flag = storage_files
1607             .get_flag_snapshot("com.android.aconfig.storage.test_1", "disabled_rw")
1608             .unwrap();
1609 
1610         let expected_flag = FlagSnapshot {
1611             container: String::from("mockup"),
1612             package: String::from("com.android.aconfig.storage.test_1"),
1613             flag: String::from("disabled_rw"),
1614             server_value: String::from("false"),
1615             local_value: String::from("true"),
1616             boot_value: String::from("true"),
1617             default_value: String::from("false"),
1618             is_readwrite: true,
1619             has_server_override: true,
1620             has_local_override: true,
1621             has_boot_local_override: false,
1622         };
1623 
1624         assert_eq!(flag, Some(expected_flag));
1625     }
1626 
1627     #[test]
test_list_flags_in_package()1628     fn test_list_flags_in_package() {
1629         let container = ContainerMock::new();
1630         let root_dir = StorageRootDirMock::new();
1631         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1632 
1633         let context_one = storage_files
1634             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1635             .unwrap();
1636         storage_files.stage_server_override(&context_one, "false").unwrap();
1637         let context_two = storage_files
1638             .get_package_flag_context("com.android.aconfig.storage.test_1", "disabled_rw")
1639             .unwrap();
1640         storage_files.stage_server_override(&context_two, "false").unwrap();
1641         storage_files.stage_local_override(&context_two, "true").unwrap();
1642         storage_files.apply_all_staged_overrides().unwrap();
1643 
1644         let flags =
1645             storage_files.list_flags_in_package("com.android.aconfig.storage.test_1").unwrap();
1646 
1647         let mut flag = FlagSnapshot {
1648             container: String::from("mockup"),
1649             package: String::from("com.android.aconfig.storage.test_1"),
1650             flag: String::from("disabled_rw"),
1651             server_value: String::from("false"),
1652             local_value: String::from("true"),
1653             boot_value: String::from("true"),
1654             default_value: String::from("false"),
1655             is_readwrite: true,
1656             has_server_override: true,
1657             has_local_override: true,
1658             has_boot_local_override: false,
1659         };
1660         assert_eq!(flags[0], flag);
1661 
1662         flag = FlagSnapshot {
1663             container: String::from("mockup"),
1664             package: String::from("com.android.aconfig.storage.test_1"),
1665             flag: String::from("enabled_ro"),
1666             server_value: String::new(),
1667             local_value: String::new(),
1668             boot_value: String::from("true"),
1669             default_value: String::from("true"),
1670             is_readwrite: false,
1671             has_server_override: false,
1672             has_local_override: false,
1673             has_boot_local_override: false,
1674         };
1675         assert_eq!(flags[1], flag);
1676 
1677         flag = FlagSnapshot {
1678             container: String::from("mockup"),
1679             package: String::from("com.android.aconfig.storage.test_1"),
1680             flag: String::from("enabled_rw"),
1681             server_value: String::from("false"),
1682             local_value: String::new(),
1683             boot_value: String::from("false"),
1684             default_value: String::from("true"),
1685             is_readwrite: true,
1686             has_server_override: true,
1687             has_local_override: false,
1688             has_boot_local_override: false,
1689         };
1690         assert_eq!(flags[2], flag);
1691     }
1692 
1693     #[test]
test_list_all_flags()1694     fn test_list_all_flags() {
1695         let container = ContainerMock::new();
1696         let root_dir = StorageRootDirMock::new();
1697         let mut storage_files = create_mock_storage_files(&container, &root_dir);
1698 
1699         let context_one = storage_files
1700             .get_package_flag_context("com.android.aconfig.storage.test_1", "enabled_rw")
1701             .unwrap();
1702         storage_files.stage_server_override(&context_one, "false").unwrap();
1703         let context_two = storage_files
1704             .get_package_flag_context("com.android.aconfig.storage.test_2", "disabled_rw")
1705             .unwrap();
1706         storage_files.stage_server_override(&context_two, "false").unwrap();
1707         storage_files.stage_local_override(&context_two, "true").unwrap();
1708         storage_files.apply_all_staged_overrides().unwrap();
1709 
1710         let flags = storage_files.list_all_flags().unwrap();
1711         assert_eq!(flags.len(), 8);
1712 
1713         let mut flag = FlagSnapshot {
1714             container: String::from("mockup"),
1715             package: String::from("com.android.aconfig.storage.test_1"),
1716             flag: String::from("enabled_rw"),
1717             server_value: String::from("false"),
1718             local_value: String::new(),
1719             boot_value: String::from("false"),
1720             default_value: String::from("true"),
1721             is_readwrite: true,
1722             has_server_override: true,
1723             has_local_override: false,
1724             has_boot_local_override: false,
1725         };
1726         assert_eq!(flags[2], flag);
1727 
1728         flag = FlagSnapshot {
1729             container: String::from("mockup"),
1730             package: String::from("com.android.aconfig.storage.test_2"),
1731             flag: String::from("disabled_rw"),
1732             server_value: String::from("false"),
1733             local_value: String::from("true"),
1734             boot_value: String::from("true"),
1735             default_value: String::from("false"),
1736             is_readwrite: true,
1737             has_server_override: true,
1738             has_local_override: true,
1739             has_boot_local_override: false,
1740         };
1741         assert_eq!(flags[3], flag);
1742     }
1743 }
1744