1use {
10 crate::{common::App, state_machine::update_check::AppResponse, storage::Storage},
11 futures::{future::LocalBoxFuture, prelude::*},
12};
13
14pub trait AppSet {
16 fn get_apps(&self) -> Vec<App>;
17 fn iter_mut_apps(&mut self) -> Box<dyn Iterator<Item = &mut App> + '_>;
18 fn get_system_app_id(&self) -> &str;
19}
20
21pub trait AppSetExt: AppSet {
22 fn all_valid(&self) -> bool {
24 self.get_apps().iter().all(|app| app.valid())
25 }
26
27 fn update_from_omaha(&mut self, app_responses: &[AppResponse]) {
29 for app in self.iter_mut_apps() {
30 for app_response in app_responses {
31 if app.id == app_response.app_id {
32 app.cohort.update_from_omaha(app_response.cohort.clone());
33 app.user_counting = app_response.user_counting.clone();
34 break;
35 }
36 }
37 }
38 }
39
40 #[must_use]
42 fn load<'a>(&'a mut self, storage: &'a impl Storage) -> LocalBoxFuture<'a, ()> {
43 async move {
44 for app in self.iter_mut_apps() {
45 app.load(storage).await;
46 }
47 }
48 .boxed_local()
49 }
50
51 #[must_use]
55 fn persist<'a>(&'a self, storage: &'a mut impl Storage) -> LocalBoxFuture<'a, ()> {
56 async move {
57 for app in self.get_apps() {
58 app.persist(storage).await;
59 }
60 }
61 .boxed_local()
62 }
63}
64
65impl<T> AppSetExt for T where T: AppSet {}
66
67pub struct VecAppSet {
69 pub apps: Vec<App>,
70}
71
72impl VecAppSet {
73 pub fn new(apps: Vec<App>) -> Self {
75 assert!(!apps.is_empty());
76 Self { apps }
77 }
78}
79
80impl AppSet for VecAppSet {
81 fn get_apps(&self) -> Vec<App> {
82 self.apps.clone()
83 }
84 fn iter_mut_apps(&mut self) -> Box<dyn Iterator<Item = &mut App> + '_> {
85 Box::new(self.apps.iter_mut())
86 }
87 fn get_system_app_id(&self) -> &str {
88 &self.apps[0].id
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95 use crate::{common::UserCounting, protocol::Cohort, state_machine::update_check::Action};
96
97 #[test]
98 fn test_appsetext_update_from_omaha() {
99 let mut app_set = VecAppSet::new(vec![
100 App::builder().id("some_id").version([0, 1]).build(),
101 App::builder().id("not_updated_id").version([2]).build(),
102 ]);
103 let cohort = Cohort { name: Some("some-channel".to_string()), ..Cohort::default() };
104 let user_counting = UserCounting::ClientRegulatedByDate(Some(42));
105 let app_responses = vec![
106 AppResponse {
107 app_id: "some_id".to_string(),
108 cohort: cohort.clone(),
109 user_counting: user_counting.clone(),
110 result: Action::Updated,
111 },
112 AppResponse {
113 app_id: "some_other_id".to_string(),
114 cohort: cohort.clone(),
115 user_counting: user_counting.clone(),
116 result: Action::NoUpdate,
117 },
118 ];
119
120 app_set.update_from_omaha(&app_responses);
121 let apps = app_set.get_apps();
122 assert_eq!(cohort, apps[0].cohort);
123 assert_eq!(user_counting, apps[0].user_counting);
124
125 assert_eq!(apps[1], App::builder().id("not_updated_id").version([2]).build());
126 }
127
128 #[test]
129 fn test_appsetext_valid() {
130 let app_set = VecAppSet::new(vec![App::builder().id("some_id").version([0, 1]).build()]);
131 assert!(app_set.all_valid());
132 let app_set = VecAppSet::new(vec![
133 App::builder().id("some_id").version([0, 1]).build(),
134 App::builder().id("some_id_2").version([1]).build(),
135 ]);
136 assert!(app_set.all_valid());
137 }
138
139 #[test]
140 fn test_appsetext_not_valid() {
141 let app_set = VecAppSet::new(vec![
142 App::builder().id("some_id").version([0, 1]).build(),
143 App::builder().id("").version([0, 1]).build(),
144 ]);
145 assert!(!app_set.all_valid());
146 let app_set = VecAppSet::new(vec![
147 App::builder().id("some_id").version([0]).build(),
148 App::builder().id("some_id_2").version([0, 1]).build(),
149 ]);
150 assert!(!app_set.all_valid());
151 let app_set = VecAppSet::new(vec![
152 App::builder().id("some_id").version([0]).build(),
153 App::builder().id("").version([0, 1]).build(),
154 ]);
155 assert!(!app_set.all_valid());
156 }
157
158 #[test]
159 fn test_get_apps() {
160 let apps = vec![App::builder().id("some_id").version([0, 1]).build()];
161 let app_set = VecAppSet::new(apps.clone());
162 assert_eq!(app_set.get_apps(), apps);
163 }
164
165 #[test]
166 fn test_iter_mut_apps() {
167 let apps = vec![
168 App::builder().id("id1").version([1]).build(),
169 App::builder().id("id2").version([2]).build(),
170 ];
171 let mut app_set = VecAppSet::new(apps);
172 for app in app_set.iter_mut_apps() {
173 app.id += "_mutated";
174 }
175 assert_eq!(
176 app_set.get_apps(),
177 vec![
178 App::builder().id("id1_mutated").version([1]).build(),
179 App::builder().id("id2_mutated").version([2]).build()
180 ]
181 );
182 }
183
184 #[test]
185 fn test_get_system_app_id() {
186 let apps = vec![
187 App::builder().id("id1").version([1]).build(),
188 App::builder().id("id2").version([2]).build(),
189 ];
190 let app_set = VecAppSet::new(apps);
191 assert_eq!(app_set.get_system_app_id(), "id1");
192 }
193}