blob: 94443d730923d0729bc0b048f5b15d767d38ff7f [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 }
95}
96
Mårten Kongstad09c28d12023-05-04 13:29:26 +020097impl Item {}
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020098
99#[cfg(test)]
100mod tests {
101 use super::*;
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200102 use crate::aconfig::{FlagState, Permission, Value};
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200103
104 #[test]
105 fn test_add_flag() {
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200106 let mut cache = Cache::new(1);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200107 cache
108 .add_flag(
109 Source::File("first.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200110 Flag {
111 id: "foo".to_string(),
112 description: "desc".to_string(),
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200113 values: vec![Value::default(FlagState::Enabled, Permission::ReadOnly)],
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200114 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200115 )
116 .unwrap();
117 let error = cache
118 .add_flag(
119 Source::File("second.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200120 Flag {
121 id: "foo".to_string(),
122 description: "desc".to_string(),
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200123 values: vec![Value::default(FlagState::Disabled, Permission::ReadOnly)],
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200124 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200125 )
126 .unwrap_err();
127 assert_eq!(
128 &format!("{:?}", error),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200129 "failed to add flag foo from second.txt: flag already defined"
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200130 );
131 }
132
133 #[test]
134 fn test_add_override() {
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200135 fn check(cache: &Cache, id: &str, expected: (FlagState, Permission)) -> bool {
Mårten Kongstad416330b2023-05-05 11:10:01 +0200136 let item = cache.iter().find(|&item| item.id == id).unwrap();
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200137 item.state == expected.0 && item.permission == expected.1
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200138 }
139
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200140 let mut cache = Cache::new(1);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200141 let error = cache
Mårten Kongstad416330b2023-05-05 11:10:01 +0200142 .add_override(
143 Source::Memory,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200144 Override {
145 id: "foo".to_string(),
146 state: FlagState::Enabled,
147 permission: Permission::ReadOnly,
148 },
Mårten Kongstad416330b2023-05-05 11:10:01 +0200149 )
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200150 .unwrap_err();
151 assert_eq!(&format!("{:?}", error), "failed to override flag foo: unknown flag");
152
153 cache
154 .add_flag(
155 Source::File("first.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200156 Flag {
157 id: "foo".to_string(),
158 description: "desc".to_string(),
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200159 values: vec![Value::default(FlagState::Enabled, Permission::ReadOnly)],
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200160 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200161 )
162 .unwrap();
Mårten Kongstad416330b2023-05-05 11:10:01 +0200163 dbg!(&cache);
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200164 assert!(check(&cache, "foo", (FlagState::Enabled, Permission::ReadOnly)));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200165
166 cache
Mårten Kongstad416330b2023-05-05 11:10:01 +0200167 .add_override(
168 Source::Memory,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200169 Override {
170 id: "foo".to_string(),
171 state: FlagState::Disabled,
172 permission: Permission::ReadWrite,
173 },
Mårten Kongstad416330b2023-05-05 11:10:01 +0200174 )
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200175 .unwrap();
Mårten Kongstad416330b2023-05-05 11:10:01 +0200176 dbg!(&cache);
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200177 assert!(check(&cache, "foo", (FlagState::Disabled, Permission::ReadWrite)));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200178
179 cache
Mårten Kongstad416330b2023-05-05 11:10:01 +0200180 .add_override(
181 Source::Memory,
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200182 Override {
183 id: "foo".to_string(),
184 state: FlagState::Enabled,
185 permission: Permission::ReadWrite,
186 },
Mårten Kongstad416330b2023-05-05 11:10:01 +0200187 )
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200188 .unwrap();
Mårten Kongstadc68c4ea2023-05-05 16:20:09 +0200189 assert!(check(&cache, "foo", (FlagState::Enabled, Permission::ReadWrite)));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200190 }
191}