• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2024 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Representation of a TEST_MAPPING JSON file.
16 
17 use std::collections::BTreeSet;
18 
19 use serde::{Deserialize, Serialize};
20 
21 use crate::Error;
22 
23 #[derive(Serialize, Deserialize, Default, Debug)]
24 pub(crate) struct TestMappingJson {
25     #[serde(default, skip_serializing_if = "Vec::is_empty")]
26     pub imports: Vec<TestMappingPath>,
27     #[serde(default, skip_serializing_if = "Vec::is_empty")]
28     presubmit: Vec<TestMappingName>,
29     #[serde(default, skip_serializing_if = "Vec::is_empty", rename = "presubmit-rust")]
30     presubmit_rust: Vec<TestMappingName>,
31     #[serde(default, skip_serializing_if = "Vec::is_empty")]
32     postsubmit: Vec<TestMappingName>,
33 }
34 
35 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
36 struct TestMappingName {
37     name: String,
38 }
39 
40 #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
41 pub(crate) struct TestMappingPath {
42     pub path: String,
43 }
44 
45 impl TestMappingJson {
parse(mut contents: String) -> Result<TestMappingJson, Error>46     pub fn parse(mut contents: String) -> Result<TestMappingJson, Error> {
47         let contents = contents.as_mut_str();
48         // Comments are not part of the JSON spec (although they are often used), and Serde won't parse them.
49         json_strip_comments::strip(contents).map_err(Error::StripJsonCommentsError)?;
50         let parsed: TestMappingJson = serde_json::from_str(contents)?;
51         Ok(parsed)
52     }
is_empty(&self) -> bool53     pub fn is_empty(&self) -> bool {
54         self.imports.is_empty()
55             && self.presubmit.is_empty()
56             && self.presubmit_rust.is_empty()
57             && self.postsubmit.is_empty()
58     }
remove_unknown_tests(&mut self, tests: &BTreeSet<String>) -> bool59     pub fn remove_unknown_tests(&mut self, tests: &BTreeSet<String>) -> bool {
60         let mut changed = false;
61         if self.presubmit.iter().any(|t| !tests.contains(&t.name)) {
62             self.presubmit.retain(|t| tests.contains(&t.name));
63             changed = true;
64         }
65         if self.presubmit_rust.iter().any(|t| !tests.contains(&t.name)) {
66             self.presubmit_rust.retain(|t| tests.contains(&t.name));
67             changed = true;
68         }
69         if self.postsubmit.iter().any(|t| !tests.contains(&t.name)) {
70             self.postsubmit.retain(|t| tests.contains(&t.name));
71             changed = true;
72         }
73         changed
74     }
set_presubmits(&mut self, tests: &BTreeSet<String>)75     pub fn set_presubmits(&mut self, tests: &BTreeSet<String>) {
76         self.presubmit = tests.iter().map(|t| TestMappingName { name: t.to_string() }).collect();
77         self.presubmit_rust = self.presubmit.clone();
78     }
convert_postsubmit_tests(&mut self) -> bool79     pub fn convert_postsubmit_tests(&mut self) -> bool {
80         let changed = !self.postsubmit.is_empty();
81         self.presubmit.append(&mut self.postsubmit.clone());
82         self.presubmit_rust.append(&mut self.postsubmit);
83         self.presubmit.sort();
84         self.presubmit.dedup();
85         self.presubmit_rust.sort();
86         self.presubmit_rust.dedup();
87         changed
88     }
add_new_tests_to_postsubmit(&mut self, tests: &BTreeSet<String>) -> bool89     pub fn add_new_tests_to_postsubmit(&mut self, tests: &BTreeSet<String>) -> bool {
90         let mut changed = false;
91         self.postsubmit.extend(tests.difference(&self.all_test_names()).map(|test_name| {
92             changed = true;
93             TestMappingName { name: test_name.to_string() }
94         }));
95         self.postsubmit.sort();
96         self.postsubmit.dedup();
97         changed
98     }
all_test_names(&self) -> BTreeSet<String>99     fn all_test_names(&self) -> BTreeSet<String> {
100         let mut tests = BTreeSet::new();
101         tests.extend(self.presubmit.iter().map(|t| t.name.clone()));
102         tests.extend(self.presubmit_rust.iter().map(|t| t.name.clone()));
103         tests.extend(self.postsubmit.iter().map(|t| t.name.clone()));
104         tests
105     }
106 }
107 
108 #[cfg(test)]
109 mod tests {
110     use super::*;
111 
112     static TEST_JSON: &str = r###"{
113   "imports": [
114     {
115       "path": "foo"
116     }
117   ],
118   "presubmit": [
119     {
120       "name": "bar"
121     }
122   ],
123   "presubmit-rust": [
124     {
125       "name": "baz"
126     }
127   ],
128   "postsubmit": [
129     {
130       "name": "qux"
131     }
132   ]
133 }
134 "###;
135 
136     #[test]
parse() -> Result<(), Error>137     fn parse() -> Result<(), Error> {
138         TestMappingJson::parse("{}".to_string())?;
139         TestMappingJson::parse("//comment\n{}".to_string())?;
140         TestMappingJson::parse(TEST_JSON.to_string())?;
141         assert!(TestMappingJson::parse("foo".to_string()).is_err());
142         Ok(())
143     }
144 
145     #[test]
all_test_names() -> Result<(), Error>146     fn all_test_names() -> Result<(), Error> {
147         let json = TestMappingJson::parse(TEST_JSON.to_string())?;
148         assert_eq!(
149             json.all_test_names(),
150             BTreeSet::from(["bar".to_string(), "baz".to_string(), "qux".to_string()])
151         );
152         Ok(())
153     }
154 
155     #[test]
set_presubmits() -> Result<(), Error>156     fn set_presubmits() -> Result<(), Error> {
157         let mut json = TestMappingJson::parse(TEST_JSON.to_string())?;
158         json.set_presubmits(&BTreeSet::from(["asdf".to_string()]));
159         assert_eq!(json.presubmit, vec![TestMappingName { name: "asdf".to_string() }]);
160         assert_eq!(json.presubmit, json.presubmit_rust);
161         Ok(())
162     }
163 
164     #[test]
add_new_tests_to_postsubmit() -> Result<(), Error>165     fn add_new_tests_to_postsubmit() -> Result<(), Error> {
166         let mut json = TestMappingJson::parse(TEST_JSON.to_string())?;
167         assert!(!json.add_new_tests_to_postsubmit(&BTreeSet::from(["bar".to_string()])));
168         assert!(json
169             .add_new_tests_to_postsubmit(&BTreeSet::from(["bar".to_string(), "asdf".to_string()])));
170         assert_eq!(
171             json.postsubmit,
172             vec![
173                 TestMappingName { name: "asdf".to_string() },
174                 TestMappingName { name: "qux".to_string() }
175             ]
176         );
177         Ok(())
178     }
179 
180     #[test]
is_empty() -> Result<(), Error>181     fn is_empty() -> Result<(), Error> {
182         let json = TestMappingJson::parse(TEST_JSON.to_string())?;
183         assert!(!json.is_empty());
184         assert!(TestMappingJson::default().is_empty());
185         Ok(())
186     }
187 }
188