omaha_client/
app_set.rs
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 {
104 name: Some("some-channel".to_string()),
105 ..Cohort::default()
106 };
107 let user_counting = UserCounting::ClientRegulatedByDate(Some(42));
108 let app_responses = vec![
109 AppResponse {
110 app_id: "some_id".to_string(),
111 cohort: cohort.clone(),
112 user_counting: user_counting.clone(),
113 result: Action::Updated,
114 },
115 AppResponse {
116 app_id: "some_other_id".to_string(),
117 cohort: cohort.clone(),
118 user_counting: user_counting.clone(),
119 result: Action::NoUpdate,
120 },
121 ];
122
123 app_set.update_from_omaha(&app_responses);
124 let apps = app_set.get_apps();
125 assert_eq!(cohort, apps[0].cohort);
126 assert_eq!(user_counting, apps[0].user_counting);
127
128 assert_eq!(
129 apps[1],
130 App::builder().id("not_updated_id").version([2]).build()
131 );
132 }
133
134 #[test]
135 fn test_appsetext_valid() {
136 let app_set = VecAppSet::new(vec![App::builder().id("some_id").version([0, 1]).build()]);
137 assert!(app_set.all_valid());
138 let app_set = VecAppSet::new(vec![
139 App::builder().id("some_id").version([0, 1]).build(),
140 App::builder().id("some_id_2").version([1]).build(),
141 ]);
142 assert!(app_set.all_valid());
143 }
144
145 #[test]
146 fn test_appsetext_not_valid() {
147 let app_set = VecAppSet::new(vec![
148 App::builder().id("some_id").version([0, 1]).build(),
149 App::builder().id("").version([0, 1]).build(),
150 ]);
151 assert!(!app_set.all_valid());
152 let app_set = VecAppSet::new(vec![
153 App::builder().id("some_id").version([0]).build(),
154 App::builder().id("some_id_2").version([0, 1]).build(),
155 ]);
156 assert!(!app_set.all_valid());
157 let app_set = VecAppSet::new(vec![
158 App::builder().id("some_id").version([0]).build(),
159 App::builder().id("").version([0, 1]).build(),
160 ]);
161 assert!(!app_set.all_valid());
162 }
163
164 #[test]
165 fn test_get_apps() {
166 let apps = vec![App::builder().id("some_id").version([0, 1]).build()];
167 let app_set = VecAppSet::new(apps.clone());
168 assert_eq!(app_set.get_apps(), apps);
169 }
170
171 #[test]
172 fn test_iter_mut_apps() {
173 let apps = vec![
174 App::builder().id("id1").version([1]).build(),
175 App::builder().id("id2").version([2]).build(),
176 ];
177 let mut app_set = VecAppSet::new(apps);
178 for app in app_set.iter_mut_apps() {
179 app.id += "_mutated";
180 }
181 assert_eq!(
182 app_set.get_apps(),
183 vec![
184 App::builder().id("id1_mutated").version([1]).build(),
185 App::builder().id("id2_mutated").version([2]).build()
186 ]
187 );
188 }
189
190 #[test]
191 fn test_get_system_app_id() {
192 let apps = vec![
193 App::builder().id("id1").version([1]).build(),
194 App::builder().id("id2").version([2]).build(),
195 ];
196 let app_set = VecAppSet::new(apps);
197 assert_eq!(app_set.get_system_app_id(), "id1");
198 }
199}