blob: 47e90ac67e903c71c9ea672730107dee73ca9109 [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,
60 declarations: Vec<Input>,
61 values: Vec<Input>,
62 default_permission: ProtoFlagPermission,
63) -> Result<Vec<u8>> {
Mårten Kongstad403658f2023-06-14 09:51:56 +020064 let mut parsed_flags = ProtoParsedFlags::new();
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020065
Mårten Kongstadfa23d292023-05-11 14:47:02 +020066 for mut input in declarations {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020067 let mut contents = String::new();
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020068 input
69 .reader
70 .read_to_string(&mut contents)
71 .with_context(|| format!("failed to read {}", input.source))?;
Mårten Kongstad403658f2023-06-14 09:51:56 +020072
73 let flag_declarations = crate::protos::flag_declarations::try_from_text_proto(&contents)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020074 .with_context(|| input.error_context())?;
Mårten Kongstad30950782023-05-09 13:31:29 +020075 ensure!(
Mårten Kongstad403658f2023-06-14 09:51:56 +020076 package == flag_declarations.package(),
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020077 "failed to parse {}: expected package {}, got {}",
Mårten Kongstad30950782023-05-09 13:31:29 +020078 input.source,
Mårten Kongstad9fb58962023-05-31 13:02:13 +020079 package,
Mårten Kongstad403658f2023-06-14 09:51:56 +020080 flag_declarations.package()
Mårten Kongstad30950782023-05-09 13:31:29 +020081 );
Mårten Kongstad403658f2023-06-14 09:51:56 +020082 for mut flag_declaration in flag_declarations.flag.into_iter() {
83 crate::protos::flag_declaration::verify_fields(&flag_declaration)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +020084 .with_context(|| input.error_context())?;
Mårten Kongstad403658f2023-06-14 09:51:56 +020085
86 // create ParsedFlag using FlagDeclaration and default values
87 let mut parsed_flag = ProtoParsedFlag::new();
88 parsed_flag.set_package(package.to_string());
89 parsed_flag.set_name(flag_declaration.take_name());
90 parsed_flag.set_namespace(flag_declaration.take_namespace());
91 parsed_flag.set_description(flag_declaration.take_description());
Mårten Kongstad1b8636b2023-06-22 10:12:24 +020092 parsed_flag.bug.append(&mut flag_declaration.bug);
Mårten Kongstad403658f2023-06-14 09:51:56 +020093 parsed_flag.set_state(DEFAULT_FLAG_STATE);
Zhi Dou71f1b352023-08-21 22:49:46 +000094 let flag_permission = if flag_declaration.is_fixed_read_only() {
95 ProtoFlagPermission::READ_ONLY
96 } else {
97 default_permission
98 };
99 parsed_flag.set_permission(flag_permission);
100 parsed_flag.set_is_fixed_read_only(flag_declaration.is_fixed_read_only());
Oriol Prieto Gasco0b9d2892023-11-20 16:23:51 +0000101 parsed_flag.set_is_exported(flag_declaration.is_exported());
Mårten Kongstad403658f2023-06-14 09:51:56 +0200102 let mut tracepoint = ProtoTracepoint::new();
103 tracepoint.set_source(input.source.clone());
104 tracepoint.set_state(DEFAULT_FLAG_STATE);
Zhi Dou71f1b352023-08-21 22:49:46 +0000105 tracepoint.set_permission(flag_permission);
Mårten Kongstad403658f2023-06-14 09:51:56 +0200106 parsed_flag.trace.push(tracepoint);
107
108 // verify ParsedFlag looks reasonable
109 crate::protos::parsed_flag::verify_fields(&parsed_flag)?;
110
111 // verify ParsedFlag can be added
112 ensure!(
113 parsed_flags.parsed_flag.iter().all(|other| other.name() != parsed_flag.name()),
114 "failed to declare flag {} from {}: flag already declared",
115 parsed_flag.name(),
116 input.source
117 );
118
119 // add ParsedFlag to ParsedFlags
120 parsed_flags.parsed_flag.push(parsed_flag);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200121 }
122 }
123
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200124 for mut input in values {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200125 let mut contents = String::new();
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +0200126 input
127 .reader
128 .read_to_string(&mut contents)
129 .with_context(|| format!("failed to read {}", input.source))?;
Mårten Kongstad403658f2023-06-14 09:51:56 +0200130 let flag_values = crate::protos::flag_values::try_from_text_proto(&contents)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +0200131 .with_context(|| input.error_context())?;
Mårten Kongstad403658f2023-06-14 09:51:56 +0200132 for flag_value in flag_values.flag_value.into_iter() {
133 crate::protos::flag_value::verify_fields(&flag_value)
Mårten Kongstadcd414d4c2023-07-27 14:25:33 +0200134 .with_context(|| input.error_context())?;
Mårten Kongstad403658f2023-06-14 09:51:56 +0200135
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000136 let Some(parsed_flag) = parsed_flags
137 .parsed_flag
138 .iter_mut()
139 .find(|pf| pf.package() == flag_value.package() && pf.name() == flag_value.name())
140 else {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200141 // (silently) skip unknown flags
142 continue;
143 };
144
Zhi Dou71f1b352023-08-21 22:49:46 +0000145 ensure!(
146 !parsed_flag.is_fixed_read_only()
147 || flag_value.permission() == ProtoFlagPermission::READ_ONLY,
148 "failed to set permission of flag {}, since this flag is fixed read only flag",
149 flag_value.name()
150 );
151
Mårten Kongstad403658f2023-06-14 09:51:56 +0200152 parsed_flag.set_state(flag_value.state());
153 parsed_flag.set_permission(flag_value.permission());
154 let mut tracepoint = ProtoTracepoint::new();
155 tracepoint.set_source(input.source.clone());
156 tracepoint.set_state(flag_value.state());
157 tracepoint.set_permission(flag_value.permission());
158 parsed_flag.trace.push(tracepoint);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200159 }
160 }
161
Zhi Dou92cf0ec2023-07-19 19:29:22 +0000162 // Create a sorted parsed_flags
163 crate::protos::parsed_flags::sort_parsed_flags(&mut parsed_flags);
Mårten Kongstad403658f2023-06-14 09:51:56 +0200164 crate::protos::parsed_flags::verify_fields(&parsed_flags)?;
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200165 let mut output = Vec::new();
Mårten Kongstad403658f2023-06-14 09:51:56 +0200166 parsed_flags.write_to_vec(&mut output)?;
167 Ok(output)
168}
169
Zhi Dou8ba6aa72023-06-26 21:03:40 +0000170#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
171pub enum CodegenMode {
172 Production,
173 Test,
Ted Bauer4a6af782023-11-29 15:44:24 +0000174 Exported,
Zhi Dou8ba6aa72023-06-26 21:03:40 +0000175}
176
177pub fn create_java_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200178 let parsed_flags = input.try_parse_flags()?;
179 let Some(package) = find_unique_package(&parsed_flags) else {
180 bail!("no parsed flags, or the parsed flags use different packages");
181 };
Zhi Dou8ba6aa72023-06-26 21:03:40 +0000182 generate_java_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
Mårten Kongstad403658f2023-06-14 09:51:56 +0200183}
184
Dennis Shen8d544f72023-06-29 00:45:42 +0000185pub fn create_cpp_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200186 let parsed_flags = input.try_parse_flags()?;
187 let Some(package) = find_unique_package(&parsed_flags) else {
188 bail!("no parsed flags, or the parsed flags use different packages");
189 };
Dennis Shen8d544f72023-06-29 00:45:42 +0000190 generate_cpp_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
Mårten Kongstad403658f2023-06-14 09:51:56 +0200191}
192
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000193pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<OutputFile> {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200194 let parsed_flags = input.try_parse_flags()?;
195 let Some(package) = find_unique_package(&parsed_flags) else {
196 bail!("no parsed flags, or the parsed flags use different packages");
197 };
Dennis Shen3cfbcf52023-07-17 14:57:23 +0000198 generate_rust_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
Mårten Kongstad403658f2023-06-14 09:51:56 +0200199}
200
201pub fn create_device_config_defaults(mut input: Input) -> Result<Vec<u8>> {
202 let parsed_flags = input.try_parse_flags()?;
203 let mut output = Vec::new();
204 for parsed_flag in parsed_flags
205 .parsed_flag
206 .into_iter()
207 .filter(|pf| pf.permission() == ProtoFlagPermission::READ_WRITE)
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200208 {
209 let line = format!(
Mårten Kongstad202102f2023-06-08 11:22:44 +0200210 "{}:{}.{}={}\n",
Mårten Kongstad403658f2023-06-14 09:51:56 +0200211 parsed_flag.namespace(),
212 parsed_flag.package(),
213 parsed_flag.name(),
214 match parsed_flag.state() {
215 ProtoFlagState::ENABLED => "enabled",
216 ProtoFlagState::DISABLED => "disabled",
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200217 }
218 );
219 output.extend_from_slice(line.as_bytes());
220 }
221 Ok(output)
222}
223
Mårten Kongstad403658f2023-06-14 09:51:56 +0200224pub fn create_device_config_sysprops(mut input: Input) -> Result<Vec<u8>> {
225 let parsed_flags = input.try_parse_flags()?;
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200226 let mut output = Vec::new();
Mårten Kongstad403658f2023-06-14 09:51:56 +0200227 for parsed_flag in parsed_flags
228 .parsed_flag
229 .into_iter()
230 .filter(|pf| pf.permission() == ProtoFlagPermission::READ_WRITE)
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200231 {
232 let line = format!(
233 "persist.device_config.{}.{}={}\n",
Mårten Kongstad403658f2023-06-14 09:51:56 +0200234 parsed_flag.package(),
235 parsed_flag.name(),
236 match parsed_flag.state() {
237 ProtoFlagState::ENABLED => "true",
238 ProtoFlagState::DISABLED => "false",
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200239 }
240 );
241 output.extend_from_slice(line.as_bytes());
242 }
243 Ok(output)
244}
245
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200246#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
Mårten Kongstadba94e6a2023-05-16 11:00:16 +0200247pub enum DumpFormat {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200248 Text,
Mårten Kongstadea498142023-07-20 11:07:35 +0200249 Verbose,
Mårten Kongstada1029092023-05-08 11:51:59 +0200250 Protobuf,
Mårten Kongstad3228b292023-06-26 10:17:42 +0200251 Textproto,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200252}
253
Mårten Kongstad403658f2023-06-14 09:51:56 +0200254pub fn dump_parsed_flags(mut input: Vec<Input>, format: DumpFormat) -> Result<Vec<u8>> {
255 let individually_parsed_flags: Result<Vec<ProtoParsedFlags>> =
256 input.iter_mut().map(|i| i.try_parse_flags()).collect();
257 let parsed_flags: ProtoParsedFlags =
258 crate::protos::parsed_flags::merge(individually_parsed_flags?)?;
259
Mårten Kongstadaf677032023-05-17 16:18:25 +0200260 let mut output = Vec::new();
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200261 match format {
262 DumpFormat::Text => {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200263 for parsed_flag in parsed_flags.parsed_flag.into_iter() {
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200264 let line = format!(
Mårten Kongstad7fa3cb12023-09-22 13:52:40 +0200265 "{}.{}: {:?} + {:?}\n",
Mårten Kongstad403658f2023-06-14 09:51:56 +0200266 parsed_flag.package(),
267 parsed_flag.name(),
Mårten Kongstad3fa2f072023-07-20 09:35:05 +0200268 parsed_flag.permission(),
269 parsed_flag.state()
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200270 );
271 output.extend_from_slice(line.as_bytes());
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200272 }
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200273 }
Mårten Kongstadea498142023-07-20 11:07:35 +0200274 DumpFormat::Verbose => {
275 for parsed_flag in parsed_flags.parsed_flag.into_iter() {
276 let sources: Vec<_> =
277 parsed_flag.trace.iter().map(|tracepoint| tracepoint.source()).collect();
278 let line = format!(
Mårten Kongstad7fa3cb12023-09-22 13:52:40 +0200279 "{}.{}: {:?} + {:?} ({})\n",
Mårten Kongstadea498142023-07-20 11:07:35 +0200280 parsed_flag.package(),
281 parsed_flag.name(),
282 parsed_flag.permission(),
283 parsed_flag.state(),
284 sources.join(", ")
285 );
286 output.extend_from_slice(line.as_bytes());
287 }
288 }
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200289 DumpFormat::Protobuf => {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200290 parsed_flags.write_to_vec(&mut output)?;
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200291 }
Mårten Kongstad3228b292023-06-26 10:17:42 +0200292 DumpFormat::Textproto => {
293 let s = protobuf::text_format::print_to_string_pretty(&parsed_flags);
294 output.extend_from_slice(s.as_bytes());
295 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200296 }
Mårten Kongstadaf677032023-05-17 16:18:25 +0200297 Ok(output)
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200298}
299
Mårten Kongstad403658f2023-06-14 09:51:56 +0200300fn find_unique_package(parsed_flags: &ProtoParsedFlags) -> Option<&str> {
301 let Some(package) = parsed_flags.parsed_flag.first().map(|pf| pf.package()) else {
302 return None;
303 };
304 if parsed_flags.parsed_flag.iter().any(|pf| pf.package() != package) {
305 return None;
306 }
307 Some(package)
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200308}
309
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200310#[cfg(test)]
311mod tests {
312 use super::*;
Mårten Kongstada1029092023-05-08 11:51:59 +0200313
314 #[test]
Mårten Kongstad403658f2023-06-14 09:51:56 +0200315 fn test_parse_flags() {
316 let parsed_flags = crate::test::parse_test_flags(); // calls parse_flags
317 crate::protos::parsed_flags::verify_fields(&parsed_flags).unwrap();
318
319 let enabled_ro =
320 parsed_flags.parsed_flag.iter().find(|pf| pf.name() == "enabled_ro").unwrap();
321 assert!(crate::protos::parsed_flag::verify_fields(enabled_ro).is_ok());
322 assert_eq!("com.android.aconfig.test", enabled_ro.package());
323 assert_eq!("enabled_ro", enabled_ro.name());
324 assert_eq!("This flag is ENABLED + READ_ONLY", enabled_ro.description());
325 assert_eq!(ProtoFlagState::ENABLED, enabled_ro.state());
326 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.permission());
327 assert_eq!(3, enabled_ro.trace.len());
Zhi Dou71f1b352023-08-21 22:49:46 +0000328 assert!(!enabled_ro.is_fixed_read_only());
Mårten Kongstad403658f2023-06-14 09:51:56 +0200329 assert_eq!("tests/test.aconfig", enabled_ro.trace[0].source());
330 assert_eq!(ProtoFlagState::DISABLED, enabled_ro.trace[0].state());
331 assert_eq!(ProtoFlagPermission::READ_WRITE, enabled_ro.trace[0].permission());
332 assert_eq!("tests/first.values", enabled_ro.trace[1].source());
333 assert_eq!(ProtoFlagState::DISABLED, enabled_ro.trace[1].state());
334 assert_eq!(ProtoFlagPermission::READ_WRITE, enabled_ro.trace[1].permission());
335 assert_eq!("tests/second.values", enabled_ro.trace[2].source());
336 assert_eq!(ProtoFlagState::ENABLED, enabled_ro.trace[2].state());
337 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.trace[2].permission());
338
Ted Bauer4a6af782023-11-29 15:44:24 +0000339 assert_eq!(7, parsed_flags.parsed_flag.len());
Mårten Kongstad403658f2023-06-14 09:51:56 +0200340 for pf in parsed_flags.parsed_flag.iter() {
Zhi Dou71f1b352023-08-21 22:49:46 +0000341 if pf.name() == "enabled_fixed_ro" {
342 continue;
343 }
Mårten Kongstad403658f2023-06-14 09:51:56 +0200344 let first = pf.trace.first().unwrap();
345 assert_eq!(DEFAULT_FLAG_STATE, first.state());
346 assert_eq!(DEFAULT_FLAG_PERMISSION, first.permission());
347
348 let last = pf.trace.last().unwrap();
349 assert_eq!(pf.state(), last.state());
350 assert_eq!(pf.permission(), last.permission());
351 }
Zhi Dou71f1b352023-08-21 22:49:46 +0000352
353 let enabled_fixed_ro =
354 parsed_flags.parsed_flag.iter().find(|pf| pf.name() == "enabled_fixed_ro").unwrap();
355 assert!(enabled_fixed_ro.is_fixed_read_only());
356 assert_eq!(ProtoFlagState::ENABLED, enabled_fixed_ro.state());
357 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.permission());
358 assert_eq!(2, enabled_fixed_ro.trace.len());
359 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.trace[0].permission());
360 assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.trace[1].permission());
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200361 }
Mårten Kongstada1029092023-05-08 11:51:59 +0200362
363 #[test]
Zhi Dou24a0b6a2023-08-10 21:39:59 +0000364 fn test_parse_flags_setting_default() {
365 let first_flag = r#"
366 package: "com.first"
367 flag {
368 name: "first"
369 namespace: "first_ns"
370 description: "This is the description of the first flag."
371 bug: "123"
372 }
373 "#;
374 let declaration =
375 vec![Input { source: "momery".to_string(), reader: Box::new(first_flag.as_bytes()) }];
376 let value: Vec<Input> = vec![];
377
378 let flags_bytes = crate::commands::parse_flags(
379 "com.first",
380 declaration,
381 value,
382 ProtoFlagPermission::READ_ONLY,
383 )
384 .unwrap();
385 let parsed_flags =
386 crate::protos::parsed_flags::try_from_binary_proto(&flags_bytes).unwrap();
387 assert_eq!(1, parsed_flags.parsed_flag.len());
388 let parsed_flag = parsed_flags.parsed_flag.first().unwrap();
389 assert_eq!(ProtoFlagState::DISABLED, parsed_flag.state());
390 assert_eq!(ProtoFlagPermission::READ_ONLY, parsed_flag.permission());
391 }
392
393 #[test]
Zhi Dou71f1b352023-08-21 22:49:46 +0000394 fn test_parse_flags_override_fixed_read_only() {
395 let first_flag = r#"
396 package: "com.first"
397 flag {
398 name: "first"
399 namespace: "first_ns"
400 description: "This is the description of the first flag."
401 bug: "123"
402 is_fixed_read_only: true
403 }
404 "#;
405 let declaration =
406 vec![Input { source: "memory".to_string(), reader: Box::new(first_flag.as_bytes()) }];
407
408 let first_flag_value = r#"
409 flag_value {
410 package: "com.first"
411 name: "first"
412 state: DISABLED
413 permission: READ_WRITE
414 }
415 "#;
416 let value = vec![Input {
417 source: "memory".to_string(),
418 reader: Box::new(first_flag_value.as_bytes()),
419 }];
420 let error = crate::commands::parse_flags(
421 "com.first",
422 declaration,
423 value,
424 ProtoFlagPermission::READ_WRITE,
425 )
426 .unwrap_err();
427 assert_eq!(
428 format!("{:?}", error),
429 "failed to set permission of flag first, since this flag is fixed read only flag"
430 );
431 }
432
433 #[test]
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200434 fn test_create_device_config_defaults() {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200435 let input = parse_test_flags_as_input();
436 let bytes = create_device_config_defaults(input).unwrap();
Mårten Kongstadf02734e2023-06-02 11:34:24 +0200437 let text = std::str::from_utf8(&bytes).unwrap();
Ted Bauer4a6af782023-11-29 15:44:24 +0000438 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 +0200439 }
440
441 #[test]
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200442 fn test_create_device_config_sysprops() {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200443 let input = parse_test_flags_as_input();
444 let bytes = create_device_config_sysprops(input).unwrap();
Mårten Kongstadc31a6ff2023-06-02 11:54:36 +0200445 let text = std::str::from_utf8(&bytes).unwrap();
Ted Bauer4a6af782023-11-29 15:44:24 +0000446 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 +0200447 }
448
449 #[test]
Mårten Kongstada1029092023-05-08 11:51:59 +0200450 fn test_dump_text_format() {
Mårten Kongstad403658f2023-06-14 09:51:56 +0200451 let input = parse_test_flags_as_input();
452 let bytes = dump_parsed_flags(vec![input], DumpFormat::Text).unwrap();
Mårten Kongstada1029092023-05-08 11:51:59 +0200453 let text = std::str::from_utf8(&bytes).unwrap();
Mårten Kongstad7fa3cb12023-09-22 13:52:40 +0200454 assert!(text.contains("com.android.aconfig.test.disabled_ro: READ_ONLY + DISABLED"));
Mårten Kongstada1029092023-05-08 11:51:59 +0200455 }
456
Mårten Kongstad1b8636b2023-06-22 10:12:24 +0200457 #[test]
458 fn test_dump_protobuf_format() {
Mårten Kongstad3228b292023-06-26 10:17:42 +0200459 let expected = protobuf::text_format::parse_from_str::<ProtoParsedFlags>(
460 crate::test::TEST_FLAGS_TEXTPROTO,
461 )
462 .unwrap()
463 .write_to_bytes()
464 .unwrap();
Mårten Kongstad1b8636b2023-06-22 10:12:24 +0200465
466 let input = parse_test_flags_as_input();
467 let actual = dump_parsed_flags(vec![input], DumpFormat::Protobuf).unwrap();
468
469 assert_eq!(expected, actual);
470 }
471
Mårten Kongstad3228b292023-06-26 10:17:42 +0200472 #[test]
473 fn test_dump_textproto_format() {
474 let input = parse_test_flags_as_input();
475 let bytes = dump_parsed_flags(vec![input], DumpFormat::Textproto).unwrap();
476 let text = std::str::from_utf8(&bytes).unwrap();
477 assert_eq!(crate::test::TEST_FLAGS_TEXTPROTO.trim(), text.trim());
478 }
479
Mårten Kongstad403658f2023-06-14 09:51:56 +0200480 fn parse_test_flags_as_input() -> Input {
481 let parsed_flags = crate::test::parse_test_flags();
482 let binary_proto = parsed_flags.write_to_bytes().unwrap();
483 let cursor = std::io::Cursor::new(binary_proto);
484 let reader = Box::new(cursor);
485 Input { source: "test.data".to_string(), reader }
Mårten Kongstadaf677032023-05-17 16:18:25 +0200486 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200487}