blob: fffeb9b49b6b151be2fff508218e2f142eddf876 [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 Kongstad76adff22023-05-08 10:57:24 +020025pub struct TracePoint {
26 pub source: Source,
27 pub state: FlagState,
28 pub permission: Permission,
29}
30
31#[derive(Serialize, Deserialize, Debug)]
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020032pub struct Item {
33 pub id: String,
34 pub description: String,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020035 pub state: FlagState,
Mårten Kongstad416330b2023-05-05 11:10:01 +020036 pub permission: Permission,
Mårten Kongstad76adff22023-05-08 10:57:24 +020037 pub trace: Vec<TracePoint>,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020038}
39
Mårten Kongstad416330b2023-05-05 11:10:01 +020040#[derive(Serialize, Deserialize, Debug)]
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020041pub struct Cache {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020042 build_id: u32,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020043 items: Vec<Item>,
44}
45
46impl Cache {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020047 pub fn new(build_id: u32) -> Cache {
48 Cache { build_id, items: vec![] }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020049 }
50
51 pub fn read_from_reader(reader: impl Read) -> Result<Cache> {
52 serde_json::from_reader(reader).map_err(|e| e.into())
53 }
54
55 pub fn write_to_writer(&self, writer: impl Write) -> Result<()> {
56 serde_json::to_writer(writer, self).map_err(|e| e.into())
57 }
58
59 pub fn add_flag(&mut self, source: Source, flag: Flag) -> Result<()> {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020060 if self.items.iter().any(|item| item.id == flag.id) {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020061 return Err(anyhow!(
Mårten Kongstad09c28d12023-05-04 13:29:26 +020062 "failed to add flag {} from {}: flag already defined",
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020063 flag.id,
64 source,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020065 ));
66 }
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020067 let (state, permission) = flag.resolve(self.build_id);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020068 self.items.push(Item {
69 id: flag.id.clone(),
Mårten Kongstad09c28d12023-05-04 13:29:26 +020070 description: flag.description,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020071 state,
Mårten Kongstad416330b2023-05-05 11:10:01 +020072 permission,
Mårten Kongstad76adff22023-05-08 10:57:24 +020073 trace: vec![TracePoint { source, state, permission }],
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020074 });
75 Ok(())
76 }
77
78 pub fn add_override(&mut self, source: Source, override_: Override) -> Result<()> {
79 let Some(existing_item) = self.items.iter_mut().find(|item| item.id == override_.id) else {
80 return Err(anyhow!("failed to override flag {}: unknown flag", override_.id));
81 };
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +020082 existing_item.state = override_.state;
Mårten Kongstad416330b2023-05-05 11:10:01 +020083 existing_item.permission = override_.permission;
Mårten Kongstad76adff22023-05-08 10:57:24 +020084 existing_item.trace.push(TracePoint {
85 source,
86 state: override_.state,
87 permission: override_.permission,
88 });
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020089 Ok(())
90 }
91
92 pub fn iter(&self) -> impl Iterator<Item = &Item> {
93 self.items.iter()
94 }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020095
Mårten Kongstada1029092023-05-08 11:51:59 +020096 pub fn into_iter(self) -> impl Iterator<Item = Item> {
97 self.items.into_iter()
98 }
99}
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200100
101#[cfg(test)]
102mod tests {
103 use super::*;
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200104 use crate::aconfig::{FlagState, Permission, Value};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200105
106 #[test]
107 fn test_add_flag() {
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200108 let mut cache = Cache::new(1);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200109 cache
110 .add_flag(
111 Source::File("first.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200112 Flag {
113 id: "foo".to_string(),
114 description: "desc".to_string(),
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200115 values: vec![Value::default(FlagState::Enabled, Permission::ReadOnly)],
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200116 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200117 )
118 .unwrap();
119 let error = cache
120 .add_flag(
121 Source::File("second.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200122 Flag {
123 id: "foo".to_string(),
124 description: "desc".to_string(),
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200125 values: vec![Value::default(FlagState::Disabled, Permission::ReadOnly)],
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200126 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200127 )
128 .unwrap_err();
129 assert_eq!(
130 &format!("{:?}", error),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200131 "failed to add flag foo from second.txt: flag already defined"
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200132 );
133 }
134
135 #[test]
136 fn test_add_override() {
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200137 fn check(cache: &Cache, id: &str, expected: (FlagState, Permission)) -> bool {
Mårten Kongstad416330b2023-05-05 11:10:01 +0200138 let item = cache.iter().find(|&item| item.id == id).unwrap();
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200139 item.state == expected.0 && item.permission == expected.1
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200140 }
141
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200142 let mut cache = Cache::new(1);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200143 let error = cache
Mårten Kongstad416330b2023-05-05 11:10:01 +0200144 .add_override(
145 Source::Memory,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200146 Override {
147 id: "foo".to_string(),
148 state: FlagState::Enabled,
149 permission: Permission::ReadOnly,
150 },
Mårten Kongstad416330b2023-05-05 11:10:01 +0200151 )
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200152 .unwrap_err();
153 assert_eq!(&format!("{:?}", error), "failed to override flag foo: unknown flag");
154
155 cache
156 .add_flag(
157 Source::File("first.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200158 Flag {
159 id: "foo".to_string(),
160 description: "desc".to_string(),
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200161 values: vec![Value::default(FlagState::Enabled, Permission::ReadOnly)],
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200162 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200163 )
164 .unwrap();
Mårten Kongstad416330b2023-05-05 11:10:01 +0200165 dbg!(&cache);
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200166 assert!(check(&cache, "foo", (FlagState::Enabled, Permission::ReadOnly)));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200167
168 cache
Mårten Kongstad416330b2023-05-05 11:10:01 +0200169 .add_override(
170 Source::Memory,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200171 Override {
172 id: "foo".to_string(),
173 state: FlagState::Disabled,
174 permission: Permission::ReadWrite,
175 },
Mårten Kongstad416330b2023-05-05 11:10:01 +0200176 )
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200177 .unwrap();
Mårten Kongstad416330b2023-05-05 11:10:01 +0200178 dbg!(&cache);
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200179 assert!(check(&cache, "foo", (FlagState::Disabled, Permission::ReadWrite)));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200180
181 cache
Mårten Kongstad416330b2023-05-05 11:10:01 +0200182 .add_override(
183 Source::Memory,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200184 Override {
185 id: "foo".to_string(),
186 state: FlagState::Enabled,
187 permission: Permission::ReadWrite,
188 },
Mårten Kongstad416330b2023-05-05 11:10:01 +0200189 )
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200190 .unwrap();
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200191 assert!(check(&cache, "foo", (FlagState::Enabled, Permission::ReadWrite)));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200192 }
193}