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::flag_info::{FlagInfoHeader, FlagInfoList, FlagInfoNode};
18 use crate::flag_table::{FlagTable, FlagTableHeader, FlagTableNode};
19 use crate::flag_value::{FlagValueHeader, FlagValueList};
20 use crate::package_table::{PackageTable, PackageTableHeader, PackageTableNode};
21 use crate::{AconfigStorageError, StorageFileType, StoredFlagType};
22
23 use anyhow::anyhow;
24 use std::io::Write;
25 use tempfile::NamedTempFile;
26
create_test_package_table() -> PackageTable27 pub fn create_test_package_table() -> PackageTable {
28 let header = PackageTableHeader {
29 version: 1,
30 container: String::from("mockup"),
31 file_type: StorageFileType::PackageMap as u8,
32 file_size: 209,
33 num_packages: 3,
34 bucket_offset: 31,
35 node_offset: 59,
36 };
37 let buckets: Vec<Option<u32>> = vec![Some(59), None, None, Some(109), None, None, None];
38 let first_node = PackageTableNode {
39 package_name: String::from("com.android.aconfig.storage.test_2"),
40 package_id: 1,
41 boolean_start_index: 3,
42 next_offset: None,
43 };
44 let second_node = PackageTableNode {
45 package_name: String::from("com.android.aconfig.storage.test_1"),
46 package_id: 0,
47 boolean_start_index: 0,
48 next_offset: Some(159),
49 };
50 let third_node = PackageTableNode {
51 package_name: String::from("com.android.aconfig.storage.test_4"),
52 package_id: 2,
53 boolean_start_index: 6,
54 next_offset: None,
55 };
56 let nodes = vec![first_node, second_node, third_node];
57 PackageTable { header, buckets, nodes }
58 }
59
60 impl FlagTableNode {
61 // create test baseline, syntactic sugar
new_expected( package_id: u32, flag_name: &str, flag_type: u16, flag_index: u16, next_offset: Option<u32>, ) -> Self62 fn new_expected(
63 package_id: u32,
64 flag_name: &str,
65 flag_type: u16,
66 flag_index: u16,
67 next_offset: Option<u32>,
68 ) -> Self {
69 Self {
70 package_id,
71 flag_name: flag_name.to_string(),
72 flag_type: StoredFlagType::try_from(flag_type).unwrap(),
73 flag_index,
74 next_offset,
75 }
76 }
77 }
78
create_test_flag_table() -> FlagTable79 pub fn create_test_flag_table() -> FlagTable {
80 let header = FlagTableHeader {
81 version: 1,
82 container: String::from("mockup"),
83 file_type: StorageFileType::FlagMap as u8,
84 file_size: 321,
85 num_flags: 8,
86 bucket_offset: 31,
87 node_offset: 99,
88 };
89 let buckets: Vec<Option<u32>> = vec![
90 Some(99),
91 Some(125),
92 None,
93 None,
94 None,
95 None,
96 Some(177),
97 Some(204),
98 None,
99 Some(262),
100 None,
101 None,
102 None,
103 None,
104 None,
105 Some(294),
106 None,
107 ];
108 let nodes = vec![
109 FlagTableNode::new_expected(0, "enabled_ro", 1, 1, None),
110 FlagTableNode::new_expected(0, "enabled_rw", 0, 2, Some(151)),
111 FlagTableNode::new_expected(2, "enabled_rw", 0, 1, None),
112 FlagTableNode::new_expected(1, "disabled_rw", 0, 0, None),
113 FlagTableNode::new_expected(1, "enabled_fixed_ro", 2, 1, Some(236)),
114 FlagTableNode::new_expected(1, "enabled_ro", 1, 2, None),
115 FlagTableNode::new_expected(2, "enabled_fixed_ro", 2, 0, None),
116 FlagTableNode::new_expected(0, "disabled_rw", 0, 0, None),
117 ];
118 FlagTable { header, buckets, nodes }
119 }
120
create_test_flag_value_list() -> FlagValueList121 pub fn create_test_flag_value_list() -> FlagValueList {
122 let header = FlagValueHeader {
123 version: 1,
124 container: String::from("mockup"),
125 file_type: StorageFileType::FlagVal as u8,
126 file_size: 35,
127 num_flags: 8,
128 boolean_value_offset: 27,
129 };
130 let booleans: Vec<bool> = vec![false, true, true, false, true, true, true, true];
131 FlagValueList { header, booleans }
132 }
133
create_test_flag_info_list() -> FlagInfoList134 pub fn create_test_flag_info_list() -> FlagInfoList {
135 let header = FlagInfoHeader {
136 version: 1,
137 container: String::from("mockup"),
138 file_type: StorageFileType::FlagInfo as u8,
139 file_size: 35,
140 num_flags: 8,
141 boolean_flag_offset: 27,
142 };
143 let is_flag_rw = [true, false, true, true, false, false, false, true];
144 let nodes = is_flag_rw.iter().map(|&rw| FlagInfoNode::create(rw)).collect();
145 FlagInfoList { header, nodes }
146 }
147
write_bytes_to_temp_file(bytes: &[u8]) -> Result<NamedTempFile, AconfigStorageError>148 pub fn write_bytes_to_temp_file(bytes: &[u8]) -> Result<NamedTempFile, AconfigStorageError> {
149 let mut file = NamedTempFile::new().map_err(|_| {
150 AconfigStorageError::FileCreationFail(anyhow!("Failed to create temp file"))
151 })?;
152 let _ = file.write_all(&bytes);
153 Ok(file)
154 }
155