blob: 37ee79e4daa3e994334eb1b6a86db4395e05c316 [file] [log] [blame]
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +02001/*
2 * Copyright (C) 2023 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
Mårten Kongstad403658f2023-06-14 09:51:56 +020017use anyhow::{bail, ensure, Context, Result};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020018use clap::ValueEnum;
Mårten Kongstada1029092023-05-08 11:51:59 +020019use protobuf::Message;
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020020use std::io::Read;
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +020021use std::path::PathBuf;
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020022
Dennis Shen1dc9ad42023-05-12 00:21:55 +000023use crate::codegen_cpp::generate_cpp_code;
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +020024use crate::codegen_java::generate_java_code;
Mårten Kongstadf73b9632023-05-24 15:43:47 +020025use crate::codegen_rust::generate_rust_code;
Mårten Kongstad403658f2023-06-14 09:51:56 +020026use crate::protos::{
27 ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag, ProtoParsedFlags, ProtoTracepoint,
28};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020029
30pub struct Input {
Mårten Kongstad403658f2023-06-14 09:51:56 +020031 pub source: String,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020032 pub reader: Box<dyn Read>,
33}
34
Mårten Kongstad403658f2023-06-14 09:51:56 +020035impl Input {
36 fn try_parse_flags(&mut self) -> Result<ProtoParsedFlags> {
37 let mut buffer = Vec::new();
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020038 self.reader
39 .read_to_end(&mut buffer)
40 .with_context(|| format!("failed to read {}", self.source))?;
Mårten Kongstad403658f2023-06-14 09:51:56 +020041 crate::protos::parsed_flags::try_from_binary_proto(&buffer)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020042 .with_context(|| self.error_context())
43 }
44
45 fn error_context(&self) -> String {
46 format!("failed to parse {}", self.source)
Mårten Kongstad403658f2023-06-14 09:51:56 +020047 }
48}
49
Mårten Kongstadd42eeeb2023-05-12 10:01:00 +020050pub struct OutputFile {
51 pub path: PathBuf, // relative to some root directory only main knows about
52 pub contents: Vec<u8>,
53}
54
Zhi Dou24a0b6a2023-08-10 21:39:59 +000055pub const DEFAULT_FLAG_STATE: ProtoFlagState = ProtoFlagState::DISABLED;
56pub const DEFAULT_FLAG_PERMISSION: ProtoFlagPermission = ProtoFlagPermission::READ_WRITE;
Mårten Kongstad403658f2023-06-14 09:51:56 +020057
Zhi Dou24a0b6a2023-08-10 21:39:59 +000058pub fn parse_flags(
59 package: &str,
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +000060 container: Option<&str>,
Zhi Dou24a0b6a2023-08-10 21:39:59 +000061 declarations: Vec<Input>,
62 values: Vec<Input>,
63 default_permission: ProtoFlagPermission,
64) -> Result<Vec<u8>> {
Mårten Kongstad403658f2023-06-14 09:51:56 +020065 let mut parsed_flags = ProtoParsedFlags::new();
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020066
Mårten Kongstadfa23d292023-05-11 14:47:02 +020067 for mut input in declarations {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020068 let mut contents = String::new();
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020069 input
70 .reader
71 .read_to_string(&mut contents)
72 .with_context(|| format!("failed to read {}", input.source))?;
Mårten Kongstad403658f2023-06-14 09:51:56 +020073
74 let flag_declarations = crate::protos::flag_declarations::try_from_text_proto(&contents)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020075 .with_context(|| input.error_context())?;
Mårten Kongstad30950782023-05-09 13:31:29 +020076 ensure!(
Mårten Kongstad403658f2023-06-14 09:51:56 +020077 package == flag_declarations.package(),
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020078 "failed to parse {}: expected package {}, got {}",
Mårten Kongstad30950782023-05-09 13:31:29 +020079 input.source,
Mårten Kongstad9fb58962023-05-31 13:02:13 +020080 package,
Mårten Kongstad403658f2023-06-14 09:51:56 +020081 flag_declarations.package()
Mårten Kongstad30950782023-05-09 13:31:29 +020082 );
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +000083 if let Some(c) = container {
84 ensure!(
85 c == flag_declarations.container(),
86 "failed to parse {}: expected container {}, got {}",
87 input.source,
88 c,
89 flag_declarations.container()
90 );
91 }
Mårten Kongstad403658f2023-06-14 09:51:56 +020092 for mut flag_declaration in flag_declarations.flag.into_iter() {
93 crate::protos::flag_declaration::verify_fields(&flag_declaration)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020094 .with_context(|| input.error_context())?;
Mårten Kongstad403658f2023-06-14 09:51:56 +020095
96 // create ParsedFlag using FlagDeclaration and default values
97 let mut parsed_flag = ProtoParsedFlag::new();
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +000098 if let Some(c) = container {
99 parsed_flag.set_container(c.to_string());
100 }
Mårten Kongstad403658f2023-06-14 09:51:56 +0200101 parsed_flag.set_package(package.to_string());
102 parsed_flag.set_name(flag_declaration.take_name());
103 parsed_flag.set_namespace(flag_declaration.take_namespace());
104 parsed_flag.set_description(flag_declaration.take_description());
Mårten Kongstad1b8636b2023-06-22 10:12:24 +0200105 parsed_flag.bug.append(&mut flag_declaration.bug);
Mårten Kongstad403658f2023-06-14 09:51:56 +0200106 parsed_flag.set_state(DEFAULT_FLAG_STATE);
Zhi Dou71f1b352023-08-21 22:49:46 +0000107 let flag_permission = if flag_declaration.is_fixed_read_only() {
108 ProtoFlagPermission::READ_ONLY
109 } else {
110 default_permission
111 };
112 parsed_flag.set_permission(flag_permission);
113 parsed_flag.set_is_fixed_read_only(flag_declaration.is_fixed_read_only());
Oriol Prieto Gasco0b9d2892023-11-20 16:23:51 +0000114 parsed_flag.set_is_exported(flag_declaration.is_exported());
Mårten Kongstad403658f2023-06-14 09:51:56 +0200115 let mut tracepoint = ProtoTracepoint::new();
116 tracepoint.set_source(input.source.clone());
117 tracepoint.set_state(DEFAULT_FLAG_STATE);
Zhi Dou71f1b352023-08-21 22:49:46 +0000118 tracepoint.set_permission(flag_permission);
Mårten Kongstad403658f2023-06-14 09:51:56 +0200119 parsed_flag.trace.push(tracepoint);
120
121 // verify ParsedFlag looks reasonable
122 crate::protos::parsed_flag::verify_fields(&parsed_flag)?;
123
124 // verify ParsedFlag can be added
125 ensure!(
126 parsed_flags.parsed_flag.iter().all(|other| other.name() != parsed_flag.name()),
127 "failed to declare flag {} from {}: flag already declared",
128 parsed_flag.name(),
129 input.source
130 );
131
132 // add ParsedFlag to ParsedFlags
133 parsed_flags.parsed_flag.push(parsed_flag);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200134 }
135 }
136
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200137 for mut input in values {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200138 let mut contents = String::new();
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +0200139 input
140 .reader
141 .read_to_string(&mut contents)
142 .with_context(|| format!("failed to read {}", input.source))?;
Mårten Kongstad403658f2023-06-14 09:51:56 +0200143 let flag_values = crate::protos::flag_values::try_from_text_proto(&contents)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +0200144 .with_context(|| input.error_context())?;
Mårten Kongstad403658f2023-06-14 09:51:56 +0200145 for flag_value in flag_values.flag_value.into_iter() {
146 crate::protos::flag_value::verify_fields(&flag_value)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +0200147 .with_context(|| input.error_context())?;
Mårten Kongstad403658f2023-06-14 09:51:56 +0200148
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000149 let Some(parsed_flag) = parsed_flags
150 .parsed_flag
151 .iter_mut()
152 .find(|pf| pf.package() == flag_value.package() && pf.name() == flag_value.name())
153 else {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200154 // (silently) skip unknown flags
155 continue;
156 };
157
Zhi Dou71f1b352023-08-21 22:49:46 +0000158 ensure!(
159 !parsed_flag.is_fixed_read_only()
160 || flag_value.permission() == ProtoFlagPermission::READ_ONLY,
161 "failed to set permission of flag {}, since this flag is fixed read only flag",
162 flag_value.name()
163 );
164
Mårten Kongstad403658f2023-06-14 09:51:56 +0200165 parsed_flag.set_state(flag_value.state());
166 parsed_flag.set_permission(flag_value.permission());
167 let mut tracepoint = ProtoTracepoint::new();
168 tracepoint.set_source(input.source.clone());
169 tracepoint.set_state(flag_value.state());
170 tracepoint.set_permission(flag_value.permission());
171 parsed_flag.trace.push(tracepoint);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200172 }
173 }
174
Zhi Dou92cf0ec2023-07-19 19:29:22 +0000175 // Create a sorted parsed_flags
176 crate::protos::parsed_flags::sort_parsed_flags(&mut parsed_flags);
Mårten Kongstad403658f2023-06-14 09:51:56 +0200177 crate::protos::parsed_flags::verify_fields(&parsed_flags)?;
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200178 let mut output = Vec::new();
Mårten Kongstad403658f2023-06-14 09:51:56 +0200179 parsed_flags.write_to_vec(&mut output)?;
180 Ok(output)
181}
182
Zhi Dou8ba6aa72023-06-26 21:03:40 +0000183#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
184pub enum CodegenMode {
185 Production,
186 Test,
Ted Bauer4a6af782023-11-29 15:44:24 +0000187 Exported,
Zhi Dou8ba6aa72023-06-26 21:03:40 +0000188}
189
190pub fn create_java_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200191 let parsed_flags = input.try_parse_flags()?;
192 let Some(package) = find_unique_package(&parsed_flags) else {
193 bail!("no parsed flags, or the parsed flags use different packages");
194 };
Zhi Dou8ba6aa72023-06-26 21:03:40 +0000195 generate_java_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
Mårten Kongstad403658f2023-06-14 09:51:56 +0200196}
197
Dennis Shen8d544f72023-06-29 00:45:42 +0000198pub fn create_cpp_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200199 let parsed_flags = input.try_parse_flags()?;
200 let Some(package) = find_unique_package(&parsed_flags) else {
201 bail!("no parsed flags, or the parsed flags use different packages");
202 };
Dennis Shen8d544f72023-06-29 00:45:42 +0000203 generate_cpp_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
Mårten Kongstad403658f2023-06-14 09:51:56 +0200204}
205
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000206pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<OutputFile> {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200207 let parsed_flags = input.try_parse_flags()?;
208 let Some(package) = find_unique_package(&parsed_flags) else {
209 bail!("no parsed flags, or the parsed flags use different packages");
210 };
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000211 generate_rust_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
Mårten Kongstad403658f2023-06-14 09:51:56 +0200212}
213
214pub fn create_device_config_defaults(mut input: Input) -> Result<Vec<u8>> {
215 let parsed_flags = input.try_parse_flags()?;
216 let mut output = Vec::new();
217 for parsed_flag in parsed_flags
218 .parsed_flag
219 .into_iter()
220 .filter(|pf| pf.permission() == ProtoFlagPermission::READ_WRITE)
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200221 {
222 let line = format!(
Mårten Kongstad202102f2023-06-08 11:22:44 +0200223 "{}:{}.{}={}\n",
Mårten Kongstad403658f2023-06-14 09:51:56 +0200224 parsed_flag.namespace(),
225 parsed_flag.package(),
226 parsed_flag.name(),
227 match parsed_flag.state() {
228 ProtoFlagState::ENABLED => "enabled",
229 ProtoFlagState::DISABLED => "disabled",
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200230 }
231 );
232 output.extend_from_slice(line.as_bytes());
233 }
234 Ok(output)
235}
236
Mårten Kongstad403658f2023-06-14 09:51:56 +0200237pub fn create_device_config_sysprops(mut input: Input) -> Result<Vec<u8>> {
238 let parsed_flags = input.try_parse_flags()?;
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200239 let mut output = Vec::new();
Mårten Kongstad403658f2023-06-14 09:51:56 +0200240 for parsed_flag in parsed_flags
241 .parsed_flag
242 .into_iter()
243 .filter(|pf| pf.permission() == ProtoFlagPermission::READ_WRITE)
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200244 {
245 let line = format!(
246 "persist.device_config.{}.{}={}\n",
Mårten Kongstad403658f2023-06-14 09:51:56 +0200247 parsed_flag.package(),
248 parsed_flag.name(),
249 match parsed_flag.state() {
250 ProtoFlagState::ENABLED => "true",
251 ProtoFlagState::DISABLED => "false",
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200252 }
253 );
254 output.extend_from_slice(line.as_bytes());
255 }
256 Ok(output)
257}
258
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200259#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
Mårten Kongstadba94e6a2023-05-16 11:00:16 +0200260pub enum DumpFormat {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200261 Text,
Mårten Kongstadea498142023-07-20 11:07:35 +0200262 Verbose,
Mårten Kongstada1029092023-05-08 11:51:59 +0200263 Protobuf,
Mårten Kongstad3228b292023-06-26 10:17:42 +0200264 Textproto,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200265}
266
Colin Cross6befb342023-11-28 15:55:07 -0800267pub fn dump_parsed_flags(mut input: Vec<Input>, format: DumpFormat, dedup: bool) -> Result<Vec<u8>> {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200268 let individually_parsed_flags: Result<Vec<ProtoParsedFlags>> =
269 input.iter_mut().map(|i| i.try_parse_flags()).collect();
270 let parsed_flags: ProtoParsedFlags =
Colin Cross6befb342023-11-28 15:55:07 -0800271 crate::protos::parsed_flags::merge(individually_parsed_flags?, dedup)?;
Mårten Kongstad403658f2023-06-14 09:51:56 +0200272
Mårten Kongstadaf677032023-05-17 16:18:25 +0200273 let mut output = Vec::new();
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200274 match format {
275 DumpFormat::Text => {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200276 for parsed_flag in parsed_flags.parsed_flag.into_iter() {
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200277 let line = format!(
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +0000278 "{}.{} [{}]: {:?} + {:?}\n",
Mårten Kongstad403658f2023-06-14 09:51:56 +0200279 parsed_flag.package(),
280 parsed_flag.name(),
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +0000281 parsed_flag.container(),
Mårten Kongstad3fa2f072023-07-20 09:35:05 +0200282 parsed_flag.permission(),
283 parsed_flag.state()
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200284 );
285 output.extend_from_slice(line.as_bytes());
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200286 }
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200287 }
Mårten Kongstadea498142023-07-20 11:07:35 +0200288 DumpFormat::Verbose => {
289 for parsed_flag in parsed_flags.parsed_flag.into_iter() {
290 let sources: Vec<_> =
291 parsed_flag.trace.iter().map(|tracepoint| tracepoint.source()).collect();
292 let line = format!(
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +0000293 "{}.{} [{}]: {:?} + {:?} ({})\n",
Mårten Kongstadea498142023-07-20 11:07:35 +0200294 parsed_flag.package(),
295 parsed_flag.name(),
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +0000296 parsed_flag.container(),
Mårten Kongstadea498142023-07-20 11:07:35 +0200297 parsed_flag.permission(),
298 parsed_flag.state(),
299 sources.join(", ")
300 );
301 output.extend_from_slice(line.as_bytes());
302 }
303 }
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200304 DumpFormat::Protobuf => {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200305 parsed_flags.write_to_vec(&mut output)?;
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200306 }
Mårten Kongstad3228b292023-06-26 10:17:42 +0200307 DumpFormat::Textproto => {
308 let s = protobuf::text_format::print_to_string_pretty(&parsed_flags);
309 output.extend_from_slice(s.as_bytes());
310 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200311 }
Mårten Kongstadaf677032023-05-17 16:18:25 +0200312 Ok(output)
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200313}
314
Mårten Kongstad403658f2023-06-14 09:51:56 +0200315fn find_unique_package(parsed_flags: &ProtoParsedFlags) -> Option<&str> {
316 let Some(package) = parsed_flags.parsed_flag.first().map(|pf| pf.package()) else {
317 return None;
318 };
319 if parsed_flags.parsed_flag.iter().any(|pf| pf.package() != package) {
320 return None;
321 }
322 Some(package)
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200323}
324
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200325#[cfg(test)]
326mod tests {
327 use super::*;
Mårten Kongstada1029092023-05-08 11:51:59 +0200328
329 #[test]
Mårten Kongstad403658f2023-06-14 09:51:56 +0200330 fn test_parse_flags() {
331 let parsed_flags = crate::test::parse_test_flags(); // calls parse_flags
332 crate::protos::parsed_flags::verify_fields(&parsed_flags).unwrap();
333
334 let enabled_ro =
335 parsed_flags.parsed_flag.iter().find(|pf| pf.name() == "enabled_ro").unwrap();
336 assert!(crate::protos::parsed_flag::verify_fields(enabled_ro).is_ok());
337 assert_eq!("com.android.aconfig.test", enabled_ro.package());
338 assert_eq!("enabled_ro", enabled_ro.name());
339 assert_eq!("This flag is ENABLED + READ_ONLY", enabled_ro.description());
340 assert_eq!(ProtoFlagState::ENABLED, enabled_ro.state());
341 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.permission());
342 assert_eq!(3, enabled_ro.trace.len());
Zhi Dou71f1b352023-08-21 22:49:46 +0000343 assert!(!enabled_ro.is_fixed_read_only());
Mårten Kongstad403658f2023-06-14 09:51:56 +0200344 assert_eq!("tests/test.aconfig", enabled_ro.trace[0].source());
345 assert_eq!(ProtoFlagState::DISABLED, enabled_ro.trace[0].state());
346 assert_eq!(ProtoFlagPermission::READ_WRITE, enabled_ro.trace[0].permission());
347 assert_eq!("tests/first.values", enabled_ro.trace[1].source());
348 assert_eq!(ProtoFlagState::DISABLED, enabled_ro.trace[1].state());
349 assert_eq!(ProtoFlagPermission::READ_WRITE, enabled_ro.trace[1].permission());
350 assert_eq!("tests/second.values", enabled_ro.trace[2].source());
351 assert_eq!(ProtoFlagState::ENABLED, enabled_ro.trace[2].state());
352 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.trace[2].permission());
353
Ted Bauer4a6af782023-11-29 15:44:24 +0000354 assert_eq!(7, parsed_flags.parsed_flag.len());
Mårten Kongstad403658f2023-06-14 09:51:56 +0200355 for pf in parsed_flags.parsed_flag.iter() {
Zhi Dou71f1b352023-08-21 22:49:46 +0000356 if pf.name() == "enabled_fixed_ro" {
357 continue;
358 }
Mårten Kongstad403658f2023-06-14 09:51:56 +0200359 let first = pf.trace.first().unwrap();
360 assert_eq!(DEFAULT_FLAG_STATE, first.state());
361 assert_eq!(DEFAULT_FLAG_PERMISSION, first.permission());
362
363 let last = pf.trace.last().unwrap();
364 assert_eq!(pf.state(), last.state());
365 assert_eq!(pf.permission(), last.permission());
366 }
Zhi Dou71f1b352023-08-21 22:49:46 +0000367
368 let enabled_fixed_ro =
369 parsed_flags.parsed_flag.iter().find(|pf| pf.name() == "enabled_fixed_ro").unwrap();
370 assert!(enabled_fixed_ro.is_fixed_read_only());
371 assert_eq!(ProtoFlagState::ENABLED, enabled_fixed_ro.state());
372 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.permission());
373 assert_eq!(2, enabled_fixed_ro.trace.len());
374 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.trace[0].permission());
375 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.trace[1].permission());
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200376 }
Mårten Kongstada1029092023-05-08 11:51:59 +0200377
378 #[test]
Zhi Dou24a0b6a2023-08-10 21:39:59 +0000379 fn test_parse_flags_setting_default() {
380 let first_flag = r#"
381 package: "com.first"
382 flag {
383 name: "first"
384 namespace: "first_ns"
385 description: "This is the description of the first flag."
386 bug: "123"
387 }
388 "#;
389 let declaration =
390 vec![Input { source: "momery".to_string(), reader: Box::new(first_flag.as_bytes()) }];
391 let value: Vec<Input> = vec![];
392
393 let flags_bytes = crate::commands::parse_flags(
394 "com.first",
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +0000395 None,
Zhi Dou24a0b6a2023-08-10 21:39:59 +0000396 declaration,
397 value,
398 ProtoFlagPermission::READ_ONLY,
399 )
400 .unwrap();
401 let parsed_flags =
402 crate::protos::parsed_flags::try_from_binary_proto(&flags_bytes).unwrap();
403 assert_eq!(1, parsed_flags.parsed_flag.len());
404 let parsed_flag = parsed_flags.parsed_flag.first().unwrap();
405 assert_eq!(ProtoFlagState::DISABLED, parsed_flag.state());
406 assert_eq!(ProtoFlagPermission::READ_ONLY, parsed_flag.permission());
407 }
408
409 #[test]
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +0000410 fn test_parse_flags_package_mismatch_between_declaration_and_command_line() {
411 let first_flag = r#"
412 package: "com.declaration.package"
413 container: "first.container"
414 flag {
415 name: "first"
416 namespace: "first_ns"
417 description: "This is the description of the first flag."
418 bug: "123"
419 }
420 "#;
421 let declaration =
422 vec![Input { source: "memory".to_string(), reader: Box::new(first_flag.as_bytes()) }];
423
424 let value: Vec<Input> = vec![];
425
426 let error = crate::commands::parse_flags(
427 "com.argument.package",
428 Some("first.container"),
429 declaration,
430 value,
431 ProtoFlagPermission::READ_WRITE,
432 )
433 .unwrap_err();
434 assert_eq!(
435 format!("{:?}", error),
436 "failed to parse memory: expected package com.argument.package, got com.declaration.package"
437 );
438 }
439
440 #[test]
441 fn test_parse_flags_container_mismatch_between_declaration_and_command_line() {
442 let first_flag = r#"
443 package: "com.first"
444 container: "declaration.container"
445 flag {
446 name: "first"
447 namespace: "first_ns"
448 description: "This is the description of the first flag."
449 bug: "123"
450 }
451 "#;
452 let declaration =
453 vec![Input { source: "memory".to_string(), reader: Box::new(first_flag.as_bytes()) }];
454
455 let value: Vec<Input> = vec![];
456
457 let error = crate::commands::parse_flags(
458 "com.first",
459 Some("argument.container"),
460 declaration,
461 value,
462 ProtoFlagPermission::READ_WRITE,
463 )
464 .unwrap_err();
465 assert_eq!(
466 format!("{:?}", error),
467 "failed to parse memory: expected container argument.container, got declaration.container"
468 );
469 }
470
471 #[test]
Zhi Dou71f1b352023-08-21 22:49:46 +0000472 fn test_parse_flags_override_fixed_read_only() {
473 let first_flag = r#"
474 package: "com.first"
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +0000475 container: "com.first.container"
Zhi Dou71f1b352023-08-21 22:49:46 +0000476 flag {
477 name: "first"
478 namespace: "first_ns"
479 description: "This is the description of the first flag."
480 bug: "123"
481 is_fixed_read_only: true
482 }
483 "#;
484 let declaration =
485 vec![Input { source: "memory".to_string(), reader: Box::new(first_flag.as_bytes()) }];
486
487 let first_flag_value = r#"
488 flag_value {
489 package: "com.first"
490 name: "first"
491 state: DISABLED
492 permission: READ_WRITE
493 }
494 "#;
495 let value = vec![Input {
496 source: "memory".to_string(),
497 reader: Box::new(first_flag_value.as_bytes()),
498 }];
499 let error = crate::commands::parse_flags(
500 "com.first",
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +0000501 Some("com.first.container"),
Zhi Dou71f1b352023-08-21 22:49:46 +0000502 declaration,
503 value,
504 ProtoFlagPermission::READ_WRITE,
505 )
506 .unwrap_err();
507 assert_eq!(
508 format!("{:?}", error),
509 "failed to set permission of flag first, since this flag is fixed read only flag"
510 );
511 }
512
513 #[test]
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200514 fn test_create_device_config_defaults() {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200515 let input = parse_test_flags_as_input();
516 let bytes = create_device_config_defaults(input).unwrap();
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200517 let text = std::str::from_utf8(&bytes).unwrap();
Ted Bauer4a6af782023-11-29 15:44:24 +0000518 assert_eq!("aconfig_test:com.android.aconfig.test.disabled_rw=disabled\naconfig_test:com.android.aconfig.test.disabled_rw_exported=disabled\nother_namespace:com.android.aconfig.test.disabled_rw_in_other_namespace=disabled\naconfig_test:com.android.aconfig.test.enabled_rw=enabled\n", text);
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200519 }
520
521 #[test]
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200522 fn test_create_device_config_sysprops() {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200523 let input = parse_test_flags_as_input();
524 let bytes = create_device_config_sysprops(input).unwrap();
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200525 let text = std::str::from_utf8(&bytes).unwrap();
Ted Bauer4a6af782023-11-29 15:44:24 +0000526 assert_eq!("persist.device_config.com.android.aconfig.test.disabled_rw=false\npersist.device_config.com.android.aconfig.test.disabled_rw_exported=false\npersist.device_config.com.android.aconfig.test.disabled_rw_in_other_namespace=false\npersist.device_config.com.android.aconfig.test.enabled_rw=true\n", text);
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200527 }
528
529 #[test]
Mårten Kongstada1029092023-05-08 11:51:59 +0200530 fn test_dump_text_format() {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200531 let input = parse_test_flags_as_input();
Colin Cross6befb342023-11-28 15:55:07 -0800532 let bytes = dump_parsed_flags(vec![input], DumpFormat::Text, false).unwrap();
Mårten Kongstada1029092023-05-08 11:51:59 +0200533 let text = std::str::from_utf8(&bytes).unwrap();
Oriol Prieto Gasco7afc7e72023-11-22 13:26:02 +0000534 assert!(
535 text.contains("com.android.aconfig.test.disabled_ro [system]: READ_ONLY + DISABLED")
536 );
Mårten Kongstada1029092023-05-08 11:51:59 +0200537 }
538
Mårten Kongstad1b8636b2023-06-22 10:12:24 +0200539 #[test]
540 fn test_dump_protobuf_format() {
Mårten Kongstad3228b292023-06-26 10:17:42 +0200541 let expected = protobuf::text_format::parse_from_str::<ProtoParsedFlags>(
542 crate::test::TEST_FLAGS_TEXTPROTO,
543 )
544 .unwrap()
545 .write_to_bytes()
546 .unwrap();
Mårten Kongstad1b8636b2023-06-22 10:12:24 +0200547
548 let input = parse_test_flags_as_input();
Colin Cross6befb342023-11-28 15:55:07 -0800549 let actual = dump_parsed_flags(vec![input], DumpFormat::Protobuf, false).unwrap();
Mårten Kongstad1b8636b2023-06-22 10:12:24 +0200550
551 assert_eq!(expected, actual);
552 }
553
Mårten Kongstad3228b292023-06-26 10:17:42 +0200554 #[test]
555 fn test_dump_textproto_format() {
556 let input = parse_test_flags_as_input();
Colin Cross6befb342023-11-28 15:55:07 -0800557 let bytes = dump_parsed_flags(vec![input], DumpFormat::Textproto, false).unwrap();
558 let text = std::str::from_utf8(&bytes).unwrap();
559 assert_eq!(crate::test::TEST_FLAGS_TEXTPROTO.trim(), text.trim());
560 }
561
562 #[test]
563 fn test_dump_textproto_format_dedup() {
564 let input = parse_test_flags_as_input();
565 let input2 = parse_test_flags_as_input();
566 let bytes = dump_parsed_flags(vec![input, input2], DumpFormat::Textproto, true).unwrap();
Mårten Kongstad3228b292023-06-26 10:17:42 +0200567 let text = std::str::from_utf8(&bytes).unwrap();
568 assert_eq!(crate::test::TEST_FLAGS_TEXTPROTO.trim(), text.trim());
569 }
570
Mårten Kongstad403658f2023-06-14 09:51:56 +0200571 fn parse_test_flags_as_input() -> Input {
572 let parsed_flags = crate::test::parse_test_flags();
573 let binary_proto = parsed_flags.write_to_bytes().unwrap();
574 let cursor = std::io::Cursor::new(binary_proto);
575 let reader = Box::new(cursor);
576 Input { source: "test.data".to_string(), reader }
Mårten Kongstadaf677032023-05-17 16:18:25 +0200577 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200578}