blob: 20c5de5dd53b349c5c9ed2e3290a87eefa2544ce [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
17use anyhow::{anyhow, Result};
18use serde::{Deserialize, Serialize};
19use std::io::{Read, Write};
20
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020021use crate::aconfig::{Flag, FlagState, Override, Permission};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020022use crate::commands::Source;
23
Mårten Kongstad416330b2023-05-05 11:10:01 +020024#[derive(Serialize, Deserialize, Debug)]
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020025pub struct Item {
26 pub id: String,
27 pub description: String,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020028 pub state: FlagState,
Mårten Kongstad416330b2023-05-05 11:10:01 +020029 pub permission: Permission,
Mårten Kongstad09c28d12023-05-04 13:29:26 +020030 pub debug: Vec<String>,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020031}
32
Mårten Kongstad416330b2023-05-05 11:10:01 +020033#[derive(Serialize, Deserialize, Debug)]
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020034pub struct Cache {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020035 build_id: u32,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020036 items: Vec<Item>,
37}
38
39impl Cache {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020040 pub fn new(build_id: u32) -> Cache {
41 Cache { build_id, items: vec![] }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020042 }
43
44 pub fn read_from_reader(reader: impl Read) -> Result<Cache> {
45 serde_json::from_reader(reader).map_err(|e| e.into())
46 }
47
48 pub fn write_to_writer(&self, writer: impl Write) -> Result<()> {
49 serde_json::to_writer(writer, self).map_err(|e| e.into())
50 }
51
52 pub fn add_flag(&mut self, source: Source, flag: Flag) -> Result<()> {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020053 if self.items.iter().any(|item| item.id == flag.id) {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020054 return Err(anyhow!(
Mårten Kongstad09c28d12023-05-04 13:29:26 +020055 "failed to add flag {} from {}: flag already defined",
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020056 flag.id,
57 source,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020058 ));
59 }
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020060 let (state, permission) = flag.resolve(self.build_id);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020061 self.items.push(Item {
62 id: flag.id.clone(),
Mårten Kongstad09c28d12023-05-04 13:29:26 +020063 description: flag.description,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020064 state,
Mårten Kongstad416330b2023-05-05 11:10:01 +020065 permission,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020066 debug: vec![format!("{}:{:?} {:?}", source, state, permission)],
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020067 });
68 Ok(())
69 }
70
71 pub fn add_override(&mut self, source: Source, override_: Override) -> Result<()> {
72 let Some(existing_item) = self.items.iter_mut().find(|item| item.id == override_.id) else {
73 return Err(anyhow!("failed to override flag {}: unknown flag", override_.id));
74 };
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020075 existing_item.state = override_.state;
Mårten Kongstad416330b2023-05-05 11:10:01 +020076 existing_item.permission = override_.permission;
77 existing_item
78 .debug
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020079 .push(format!("{}:{:?} {:?}", source, override_.state, override_.permission));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020080 Ok(())
81 }
82
83 pub fn iter(&self) -> impl Iterator<Item = &Item> {
84 self.items.iter()
85 }
86}
87
Mårten Kongstad09c28d12023-05-04 13:29:26 +020088impl Item {}
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020089
90#[cfg(test)]
91mod tests {
92 use super::*;
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020093 use crate::aconfig::{FlagState, Permission, Value};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020094
95 #[test]
96 fn test_add_flag() {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020097 let mut cache = Cache::new(1);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020098 cache
99 .add_flag(
100 Source::File("first.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200101 Flag {
102 id: "foo".to_string(),
103 description: "desc".to_string(),
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200104 values: vec![Value::default(FlagState::Enabled, Permission::ReadOnly)],
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200105 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200106 )
107 .unwrap();
108 let error = cache
109 .add_flag(
110 Source::File("second.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200111 Flag {
112 id: "foo".to_string(),
113 description: "desc".to_string(),
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200114 values: vec![Value::default(FlagState::Disabled, Permission::ReadOnly)],
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200115 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200116 )
117 .unwrap_err();
118 assert_eq!(
119 &format!("{:?}", error),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200120 "failed to add flag foo from second.txt: flag already defined"
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200121 );
122 }
123
124 #[test]
125 fn test_add_override() {
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200126 fn check(cache: &Cache, id: &str, expected: (FlagState, Permission)) -> bool {
Mårten Kongstad416330b2023-05-05 11:10:01 +0200127 let item = cache.iter().find(|&item| item.id == id).unwrap();
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200128 item.state == expected.0 && item.permission == expected.1
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200129 }
130
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200131 let mut cache = Cache::new(1);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200132 let error = cache
Mårten Kongstad416330b2023-05-05 11:10:01 +0200133 .add_override(
134 Source::Memory,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200135 Override {
136 id: "foo".to_string(),
137 state: FlagState::Enabled,
138 permission: Permission::ReadOnly,
139 },
Mårten Kongstad416330b2023-05-05 11:10:01 +0200140 )
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200141 .unwrap_err();
142 assert_eq!(&format!("{:?}", error), "failed to override flag foo: unknown flag");
143
144 cache
145 .add_flag(
146 Source::File("first.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200147 Flag {
148 id: "foo".to_string(),
149 description: "desc".to_string(),
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200150 values: vec![Value::default(FlagState::Enabled, Permission::ReadOnly)],
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200151 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200152 )
153 .unwrap();
Mårten Kongstad416330b2023-05-05 11:10:01 +0200154 dbg!(&cache);
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200155 assert!(check(&cache, "foo", (FlagState::Enabled, Permission::ReadOnly)));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200156
157 cache
Mårten Kongstad416330b2023-05-05 11:10:01 +0200158 .add_override(
159 Source::Memory,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200160 Override {
161 id: "foo".to_string(),
162 state: FlagState::Disabled,
163 permission: Permission::ReadWrite,
164 },
Mårten Kongstad416330b2023-05-05 11:10:01 +0200165 )
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200166 .unwrap();
Mårten Kongstad416330b2023-05-05 11:10:01 +0200167 dbg!(&cache);
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200168 assert!(check(&cache, "foo", (FlagState::Disabled, Permission::ReadWrite)));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200169
170 cache
Mårten Kongstad416330b2023-05-05 11:10:01 +0200171 .add_override(
172 Source::Memory,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200173 Override {
174 id: "foo".to_string(),
175 state: FlagState::Enabled,
176 permission: Permission::ReadWrite,
177 },
Mårten Kongstad416330b2023-05-05 11:10:01 +0200178 )
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200179 .unwrap();
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200180 assert!(check(&cache, "foo", (FlagState::Enabled, Permission::ReadWrite)));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200181 }
182}