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