blob: d27459dcf529f9e7138c8d07d3683f5fc0e4814d [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
21use crate::aconfig::{Flag, Override};
22use crate::commands::Source;
23
24#[derive(Serialize, Deserialize)]
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020025pub struct Item {
26 pub id: String,
27 pub description: String,
Mårten Kongstad09c28d12023-05-04 13:29:26 +020028 pub value: bool,
29 pub debug: Vec<String>,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020030}
31
32#[derive(Serialize, Deserialize)]
33pub struct Cache {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020034 build_id: u32,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020035 items: Vec<Item>,
36}
37
38impl Cache {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020039 pub fn new(build_id: u32) -> Cache {
40 Cache { build_id, items: vec![] }
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020041 }
42
43 pub fn read_from_reader(reader: impl Read) -> Result<Cache> {
44 serde_json::from_reader(reader).map_err(|e| e.into())
45 }
46
47 pub fn write_to_writer(&self, writer: impl Write) -> Result<()> {
48 serde_json::to_writer(writer, self).map_err(|e| e.into())
49 }
50
51 pub fn add_flag(&mut self, source: Source, flag: Flag) -> Result<()> {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020052 if self.items.iter().any(|item| item.id == flag.id) {
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020053 return Err(anyhow!(
Mårten Kongstad09c28d12023-05-04 13:29:26 +020054 "failed to add flag {} from {}: flag already defined",
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020055 flag.id,
56 source,
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020057 ));
58 }
Mårten Kongstad09c28d12023-05-04 13:29:26 +020059 let value = flag.resolve_value(self.build_id);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020060 self.items.push(Item {
61 id: flag.id.clone(),
Mårten Kongstad09c28d12023-05-04 13:29:26 +020062 description: flag.description,
63 value,
64 debug: vec![format!("{}:{}", source, value)],
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020065 });
66 Ok(())
67 }
68
69 pub fn add_override(&mut self, source: Source, override_: Override) -> Result<()> {
70 let Some(existing_item) = self.items.iter_mut().find(|item| item.id == override_.id) else {
71 return Err(anyhow!("failed to override flag {}: unknown flag", override_.id));
72 };
Mårten Kongstad09c28d12023-05-04 13:29:26 +020073 existing_item.value = override_.value;
74 existing_item.debug.push(format!("{}:{}", source, override_.value));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020075 Ok(())
76 }
77
78 pub fn iter(&self) -> impl Iterator<Item = &Item> {
79 self.items.iter()
80 }
81}
82
Mårten Kongstad09c28d12023-05-04 13:29:26 +020083impl Item {}
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020084
85#[cfg(test)]
86mod tests {
87 use super::*;
Mårten Kongstad09c28d12023-05-04 13:29:26 +020088 use crate::aconfig::Value;
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020089
90 #[test]
91 fn test_add_flag() {
Mårten Kongstad09c28d12023-05-04 13:29:26 +020092 let mut cache = Cache::new(1);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +020093 cache
94 .add_flag(
95 Source::File("first.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +020096 Flag {
97 id: "foo".to_string(),
98 description: "desc".to_string(),
99 values: vec![Value::default(true)],
100 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200101 )
102 .unwrap();
103 let error = cache
104 .add_flag(
105 Source::File("second.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200106 Flag {
107 id: "foo".to_string(),
108 description: "desc".to_string(),
109 values: vec![Value::default(false)],
110 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200111 )
112 .unwrap_err();
113 assert_eq!(
114 &format!("{:?}", error),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200115 "failed to add flag foo from second.txt: flag already defined"
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200116 );
117 }
118
119 #[test]
120 fn test_add_override() {
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200121 fn check_value(cache: &Cache, id: &str, expected: bool) -> bool {
122 cache.iter().find(|&item| item.id == id).unwrap().value == expected
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200123 }
124
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200125 let mut cache = Cache::new(1);
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200126 let error = cache
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200127 .add_override(Source::Memory, Override { id: "foo".to_string(), value: true })
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200128 .unwrap_err();
129 assert_eq!(&format!("{:?}", error), "failed to override flag foo: unknown flag");
130
131 cache
132 .add_flag(
133 Source::File("first.txt".to_string()),
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200134 Flag {
135 id: "foo".to_string(),
136 description: "desc".to_string(),
137 values: vec![Value::default(true)],
138 },
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200139 )
140 .unwrap();
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200141 assert!(check_value(&cache, "foo", true));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200142
143 cache
144 .add_override(Source::Memory, Override { id: "foo".to_string(), value: false })
145 .unwrap();
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200146 assert!(check_value(&cache, "foo", false));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200147
148 cache
149 .add_override(Source::Memory, Override { id: "foo".to_string(), value: true })
150 .unwrap();
Mårten Kongstad09c28d12023-05-04 13:29:26 +0200151 assert!(check_value(&cache, "foo", true));
Mårten Kongstad4d2b4b02023-04-27 16:05:58 +0200152 }
153}