blob: c02fe07bd2d782598bf9a9afb260b77af038b3c8 [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 Kongstad30950782023-05-09 13:31:29 +020017use anyhow::{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 Kongstad76adff22023-05-08 10:57:24 +020020use serde::{Deserialize, Serialize};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020021use std::fmt;
22use std::io::Read;
23
Mårten Kongstadfa23d292023-05-11 14:47:02 +020024use crate::aconfig::{FlagDeclarations, FlagValue};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020025use crate::cache::Cache;
Zhi Doueb744892023-05-10 04:02:33 +000026use crate::codegen_java::{generate_java_code, GeneratedFile};
Mårten Kongstad30950782023-05-09 13:31:29 +020027use crate::protos::ProtoParsedFlags;
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020028
Mårten Kongstad76adff22023-05-08 10:57:24 +020029#[derive(Serialize, Deserialize, Clone, Debug)]
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020030pub enum Source {
31 #[allow(dead_code)] // only used in unit tests
32 Memory,
33 File(String),
34}
35
36impl fmt::Display for Source {
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 match self {
39 Self::Memory => write!(f, "<memory>"),
40 Self::File(path) => write!(f, "{}", path),
41 }
42 }
43}
44
45pub struct Input {
46 pub source: Source,
47 pub reader: Box<dyn Read>,
48}
49
Mårten Kongstad30950782023-05-09 13:31:29 +020050pub fn create_cache(
Mårten Kongstad30950782023-05-09 13:31:29 +020051 namespace: &str,
Mårten Kongstadfa23d292023-05-11 14:47:02 +020052 declarations: Vec<Input>,
53 values: Vec<Input>,
Mårten Kongstad30950782023-05-09 13:31:29 +020054) -> Result<Cache> {
Mårten Kongstadfa23d292023-05-11 14:47:02 +020055 let mut cache = Cache::new(namespace.to_owned());
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020056
Mårten Kongstadfa23d292023-05-11 14:47:02 +020057 for mut input in declarations {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020058 let mut contents = String::new();
59 input.reader.read_to_string(&mut contents)?;
Mårten Kongstadfa23d292023-05-11 14:47:02 +020060 let dec_list = FlagDeclarations::try_from_text_proto(&contents)
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020061 .with_context(|| format!("Failed to parse {}", input.source))?;
Mårten Kongstad30950782023-05-09 13:31:29 +020062 ensure!(
Mårten Kongstadfa23d292023-05-11 14:47:02 +020063 namespace == dec_list.namespace,
Mårten Kongstad30950782023-05-09 13:31:29 +020064 "Failed to parse {}: expected namespace {}, got {}",
65 input.source,
66 namespace,
Mårten Kongstadfa23d292023-05-11 14:47:02 +020067 dec_list.namespace
Mårten Kongstad30950782023-05-09 13:31:29 +020068 );
Mårten Kongstadfa23d292023-05-11 14:47:02 +020069 for d in dec_list.flags.into_iter() {
70 cache.add_flag_declaration(input.source.clone(), d)?;
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020071 }
72 }
73
Mårten Kongstadfa23d292023-05-11 14:47:02 +020074 for mut input in values {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020075 let mut contents = String::new();
76 input.reader.read_to_string(&mut contents)?;
Mårten Kongstadfa23d292023-05-11 14:47:02 +020077 let values_list = FlagValue::try_from_text_proto_list(&contents)
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020078 .with_context(|| format!("Failed to parse {}", input.source))?;
Mårten Kongstadfa23d292023-05-11 14:47:02 +020079 for v in values_list {
80 // TODO: warn about flag values that do not take effect?
81 let _ = cache.add_flag_value(input.source.clone(), v);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020082 }
83 }
84
85 Ok(cache)
86}
87
Zhi Doueb744892023-05-10 04:02:33 +000088pub fn generate_code(cache: &Cache) -> Result<GeneratedFile> {
89 generate_java_code(cache)
90}
91
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020092#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
93pub enum Format {
94 Text,
95 Debug,
Mårten Kongstada1029092023-05-08 11:51:59 +020096 Protobuf,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020097}
98
Mårten Kongstada1029092023-05-08 11:51:59 +020099pub fn dump_cache(cache: Cache, format: Format) -> Result<Vec<u8>> {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200100 match format {
101 Format::Text => {
Mårten Kongstada1029092023-05-08 11:51:59 +0200102 let mut lines = vec![];
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200103 for item in cache.iter() {
Mårten Kongstad30950782023-05-09 13:31:29 +0200104 lines.push(format!("{}: {:?}\n", item.name, item.state));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200105 }
Mårten Kongstada1029092023-05-08 11:51:59 +0200106 Ok(lines.concat().into())
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200107 }
108 Format::Debug => {
Mårten Kongstada1029092023-05-08 11:51:59 +0200109 let mut lines = vec![];
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200110 for item in cache.iter() {
Mårten Kongstada1029092023-05-08 11:51:59 +0200111 lines.push(format!("{:?}\n", item));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200112 }
Mårten Kongstada1029092023-05-08 11:51:59 +0200113 Ok(lines.concat().into())
114 }
115 Format::Protobuf => {
Mårten Kongstad30950782023-05-09 13:31:29 +0200116 let parsed_flags: ProtoParsedFlags = cache.into();
Mårten Kongstada1029092023-05-08 11:51:59 +0200117 let mut output = vec![];
Mårten Kongstad30950782023-05-09 13:31:29 +0200118 parsed_flags.write_to_vec(&mut output)?;
Mårten Kongstada1029092023-05-08 11:51:59 +0200119 Ok(output)
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200120 }
121 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200127 use crate::aconfig::{FlagState, Permission};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200128
Mårten Kongstada1029092023-05-08 11:51:59 +0200129 fn create_test_cache() -> Cache {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200130 let s = r#"
Mårten Kongstad30950782023-05-09 13:31:29 +0200131 namespace: "ns"
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200132 flag {
Mårten Kongstad30950782023-05-09 13:31:29 +0200133 name: "a"
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200134 description: "Description of a"
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200135 }
Mårten Kongstada1029092023-05-08 11:51:59 +0200136 flag {
Mårten Kongstad30950782023-05-09 13:31:29 +0200137 name: "b"
Mårten Kongstada1029092023-05-08 11:51:59 +0200138 description: "Description of b"
Mårten Kongstada1029092023-05-08 11:51:59 +0200139 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200140 "#;
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200141 let declarations = vec![Input { source: Source::Memory, reader: Box::new(s.as_bytes()) }];
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200142 let o = r#"
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200143 flag_value {
Mårten Kongstad30950782023-05-09 13:31:29 +0200144 namespace: "ns"
145 name: "a"
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200146 state: DISABLED
Mårten Kongstad416330b2023-05-05 11:10:01 +0200147 permission: READ_ONLY
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200148 }
149 "#;
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200150 let values = vec![Input { source: Source::Memory, reader: Box::new(o.as_bytes()) }];
151 create_cache("ns", declarations, values).unwrap()
Mårten Kongstada1029092023-05-08 11:51:59 +0200152 }
153
154 #[test]
155 fn test_create_cache() {
156 let cache = create_test_cache(); // calls create_cache
Mårten Kongstad30950782023-05-09 13:31:29 +0200157 let item = cache.iter().find(|&item| item.name == "a").unwrap();
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200158 assert_eq!(FlagState::Disabled, item.state);
159 assert_eq!(Permission::ReadOnly, item.permission);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200160 }
Mårten Kongstada1029092023-05-08 11:51:59 +0200161
162 #[test]
163 fn test_dump_text_format() {
164 let cache = create_test_cache();
165 let bytes = dump_cache(cache, Format::Text).unwrap();
166 let text = std::str::from_utf8(&bytes).unwrap();
167 assert!(text.contains("a: Disabled"));
168 }
169
170 #[test]
171 fn test_dump_protobuf_format() {
Mårten Kongstad30950782023-05-09 13:31:29 +0200172 use crate::protos::{ProtoFlagPermission, ProtoFlagState, ProtoTracepoint};
Mårten Kongstada1029092023-05-08 11:51:59 +0200173 use protobuf::Message;
174
175 let cache = create_test_cache();
176 let bytes = dump_cache(cache, Format::Protobuf).unwrap();
Mårten Kongstad30950782023-05-09 13:31:29 +0200177 let actual = ProtoParsedFlags::parse_from_bytes(&bytes).unwrap();
Mårten Kongstada1029092023-05-08 11:51:59 +0200178
179 assert_eq!(
180 vec!["a".to_string(), "b".to_string()],
Mårten Kongstad30950782023-05-09 13:31:29 +0200181 actual.parsed_flag.iter().map(|item| item.name.clone().unwrap()).collect::<Vec<_>>()
Mårten Kongstada1029092023-05-08 11:51:59 +0200182 );
Mårten Kongstad30950782023-05-09 13:31:29 +0200183
184 let item =
185 actual.parsed_flag.iter().find(|item| item.name == Some("b".to_string())).unwrap();
186 assert_eq!(item.namespace(), "ns");
187 assert_eq!(item.name(), "b");
188 assert_eq!(item.description(), "Description of b");
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200189 assert_eq!(item.state(), ProtoFlagState::DISABLED);
190 assert_eq!(item.permission(), ProtoFlagPermission::READ_WRITE);
Mårten Kongstad30950782023-05-09 13:31:29 +0200191 let mut tp = ProtoTracepoint::new();
192 tp.set_source("<memory>".to_string());
Mårten Kongstadfa23d292023-05-11 14:47:02 +0200193 tp.set_state(ProtoFlagState::DISABLED);
194 tp.set_permission(ProtoFlagPermission::READ_WRITE);
Mårten Kongstad30950782023-05-09 13:31:29 +0200195 assert_eq!(item.trace, vec![tp]);
Mårten Kongstada1029092023-05-08 11:51:59 +0200196 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200197}