]>
Commit | Line | Data |
---|---|---|
1 | use std::path::PathBuf; | |
2 | ||
3 | use anyhow::Error; | |
4 | ||
5 | use pbs_api_types::PruneJobOptions; | |
6 | use pbs_datastore::manifest::MANIFEST_BLOB_NAME; | |
7 | use pbs_datastore::prune::compute_prune_info; | |
8 | use pbs_datastore::{BackupDir, BackupInfo}; | |
9 | ||
10 | fn get_prune_list( | |
11 | list: Vec<BackupInfo>, | |
12 | return_kept: bool, | |
13 | options: &PruneJobOptions, | |
14 | ) -> Vec<PathBuf> { | |
15 | let mut prune_info = compute_prune_info(list, &options.keep).unwrap(); | |
16 | ||
17 | prune_info.reverse(); | |
18 | ||
19 | prune_info | |
20 | .iter() | |
21 | .filter_map(|(info, mark)| { | |
22 | if mark.keep() != return_kept { | |
23 | None | |
24 | } else { | |
25 | Some(info.backup_dir.relative_path()) | |
26 | } | |
27 | }) | |
28 | .collect() | |
29 | } | |
30 | ||
31 | fn create_info(snapshot: &str, partial: bool) -> BackupInfo { | |
32 | let backup_dir = BackupDir::new_test(snapshot.parse().unwrap()); | |
33 | ||
34 | let mut files = Vec::new(); | |
35 | ||
36 | if !partial { | |
37 | files.push(String::from(MANIFEST_BLOB_NAME)); | |
38 | } | |
39 | ||
40 | BackupInfo { | |
41 | backup_dir, | |
42 | files, | |
43 | protected: false, | |
44 | } | |
45 | } | |
46 | ||
47 | fn create_info_protected(snapshot: &str, partial: bool) -> BackupInfo { | |
48 | let mut info = create_info(snapshot, partial); | |
49 | info.protected = true; | |
50 | info | |
51 | } | |
52 | ||
53 | #[test] | |
54 | fn test_prune_protected() -> Result<(), Error> { | |
55 | let orig_list = vec![ | |
56 | create_info_protected("host/elsa/2019-11-15T09:39:15Z", false), | |
57 | create_info("host/elsa/2019-11-15T10:39:15Z", false), | |
58 | create_info("host/elsa/2019-11-15T10:49:15Z", false), | |
59 | create_info_protected("host/elsa/2019-11-15T10:59:15Z", false), | |
60 | ]; | |
61 | ||
62 | eprintln!("{:?}", orig_list); | |
63 | ||
64 | let mut options = PruneJobOptions::default(); | |
65 | options.keep.keep_last = Some(1); | |
66 | let remove_list = get_prune_list(orig_list.clone(), false, &options); | |
67 | let expect: Vec<PathBuf> = vec![PathBuf::from("host/elsa/2019-11-15T10:39:15Z")]; | |
68 | assert_eq!(remove_list, expect); | |
69 | ||
70 | let mut options = PruneJobOptions::default(); | |
71 | options.keep.keep_hourly = Some(1); | |
72 | let remove_list = get_prune_list(orig_list, false, &options); | |
73 | let expect: Vec<PathBuf> = vec![PathBuf::from("host/elsa/2019-11-15T10:39:15Z")]; | |
74 | assert_eq!(remove_list, expect); | |
75 | Ok(()) | |
76 | } | |
77 | ||
78 | #[test] | |
79 | fn test_prune_hourly() -> Result<(), Error> { | |
80 | let orig_list = vec![ | |
81 | create_info("host/elsa/2019-11-15T09:39:15Z", false), | |
82 | create_info("host/elsa/2019-11-15T10:49:15Z", false), | |
83 | create_info("host/elsa/2019-11-15T10:59:15Z", false), | |
84 | create_info("host/elsa/2019-11-15T11:39:15Z", false), | |
85 | create_info("host/elsa/2019-11-15T11:49:15Z", false), | |
86 | create_info("host/elsa/2019-11-15T11:59:15Z", false), | |
87 | ]; | |
88 | ||
89 | let list = orig_list.clone(); | |
90 | let mut options = PruneJobOptions::default(); | |
91 | options.keep.keep_hourly = Some(3); | |
92 | let remove_list = get_prune_list(list, false, &options); | |
93 | let expect: Vec<PathBuf> = vec![ | |
94 | PathBuf::from("host/elsa/2019-11-15T10:49:15Z"), | |
95 | PathBuf::from("host/elsa/2019-11-15T11:39:15Z"), | |
96 | PathBuf::from("host/elsa/2019-11-15T11:49:15Z"), | |
97 | ]; | |
98 | assert_eq!(remove_list, expect); | |
99 | ||
100 | let list = orig_list; | |
101 | let mut options = PruneJobOptions::default(); | |
102 | options.keep.keep_hourly = Some(2); | |
103 | let remove_list = get_prune_list(list, true, &options); | |
104 | let expect: Vec<PathBuf> = vec![ | |
105 | PathBuf::from("host/elsa/2019-11-15T10:59:15Z"), | |
106 | PathBuf::from("host/elsa/2019-11-15T11:59:15Z"), | |
107 | ]; | |
108 | assert_eq!(remove_list, expect); | |
109 | ||
110 | Ok(()) | |
111 | } | |
112 | ||
113 | #[test] | |
114 | fn test_prune_simple2() -> Result<(), Error> { | |
115 | let orig_list = vec![ | |
116 | create_info("host/elsa/2018-11-15T11:59:15Z", false), | |
117 | create_info("host/elsa/2019-11-15T11:59:15Z", false), | |
118 | create_info("host/elsa/2019-11-21T11:59:15Z", false), | |
119 | create_info("host/elsa/2019-11-22T11:59:15Z", false), | |
120 | create_info("host/elsa/2019-11-29T11:59:15Z", false), | |
121 | create_info("host/elsa/2019-12-01T11:59:15Z", false), | |
122 | create_info("host/elsa/2019-12-02T11:59:15Z", false), | |
123 | create_info("host/elsa/2019-12-03T11:59:15Z", false), | |
124 | create_info("host/elsa/2019-12-04T11:59:15Z", false), | |
125 | ]; | |
126 | ||
127 | let list = orig_list.clone(); | |
128 | let mut options = PruneJobOptions::default(); | |
129 | options.keep.keep_daily = Some(1); | |
130 | let remove_list = get_prune_list(list, true, &options); | |
131 | let expect: Vec<PathBuf> = vec![PathBuf::from("host/elsa/2019-12-04T11:59:15Z")]; | |
132 | assert_eq!(remove_list, expect); | |
133 | ||
134 | let list = orig_list.clone(); | |
135 | let mut options = PruneJobOptions::default(); | |
136 | options.keep.keep_last = Some(1); | |
137 | options.keep.keep_daily = Some(1); | |
138 | let remove_list = get_prune_list(list, true, &options); | |
139 | let expect: Vec<PathBuf> = vec![ | |
140 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
141 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
142 | ]; | |
143 | assert_eq!(remove_list, expect); | |
144 | ||
145 | let list = orig_list.clone(); | |
146 | let mut options = PruneJobOptions::default(); | |
147 | options.keep.keep_daily = Some(1); | |
148 | options.keep.keep_weekly = Some(1); | |
149 | let remove_list = get_prune_list(list, true, &options); | |
150 | let expect: Vec<PathBuf> = vec![ | |
151 | PathBuf::from("host/elsa/2019-12-01T11:59:15Z"), | |
152 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
153 | ]; | |
154 | assert_eq!(remove_list, expect); | |
155 | ||
156 | let list = orig_list.clone(); | |
157 | let mut options = PruneJobOptions::default(); | |
158 | options.keep.keep_daily = Some(1); | |
159 | options.keep.keep_weekly = Some(1); | |
160 | options.keep.keep_monthly = Some(1); | |
161 | let remove_list = get_prune_list(list, true, &options); | |
162 | let expect: Vec<PathBuf> = vec![ | |
163 | PathBuf::from("host/elsa/2019-11-22T11:59:15Z"), | |
164 | PathBuf::from("host/elsa/2019-12-01T11:59:15Z"), | |
165 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
166 | ]; | |
167 | assert_eq!(remove_list, expect); | |
168 | ||
169 | let list = orig_list; | |
170 | let mut options = PruneJobOptions::default(); | |
171 | options.keep.keep_monthly = Some(1); | |
172 | options.keep.keep_yearly = Some(1); | |
173 | let remove_list = get_prune_list(list, true, &options); | |
174 | let expect: Vec<PathBuf> = vec![ | |
175 | PathBuf::from("host/elsa/2018-11-15T11:59:15Z"), | |
176 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
177 | ]; | |
178 | assert_eq!(remove_list, expect); | |
179 | ||
180 | Ok(()) | |
181 | } | |
182 | ||
183 | #[test] | |
184 | fn test_prune_simple() -> Result<(), Error> { | |
185 | let orig_list = vec![ | |
186 | create_info("host/elsa/2019-12-02T11:59:15Z", false), | |
187 | create_info("host/elsa/2019-12-03T11:59:15Z", false), | |
188 | create_info("host/elsa/2019-12-04T11:59:15Z", false), | |
189 | create_info("host/elsa/2019-12-04T12:59:15Z", false), | |
190 | ]; | |
191 | ||
192 | // keep-last tests | |
193 | ||
194 | let list = orig_list.clone(); | |
195 | let mut options = PruneJobOptions::default(); | |
196 | options.keep.keep_last = Some(4); | |
197 | let remove_list = get_prune_list(list, false, &options); | |
198 | let expect: Vec<PathBuf> = Vec::new(); | |
199 | assert_eq!(remove_list, expect); | |
200 | ||
201 | let list = orig_list.clone(); | |
202 | let mut options = PruneJobOptions::default(); | |
203 | options.keep.keep_last = Some(3); | |
204 | let remove_list = get_prune_list(list, false, &options); | |
205 | let expect: Vec<PathBuf> = vec![PathBuf::from("host/elsa/2019-12-02T11:59:15Z")]; | |
206 | assert_eq!(remove_list, expect); | |
207 | ||
208 | let list = orig_list.clone(); | |
209 | let mut options = PruneJobOptions::default(); | |
210 | options.keep.keep_last = Some(2); | |
211 | let remove_list = get_prune_list(list, false, &options); | |
212 | let expect: Vec<PathBuf> = vec![ | |
213 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
214 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
215 | ]; | |
216 | assert_eq!(remove_list, expect); | |
217 | ||
218 | let list = orig_list.clone(); | |
219 | let mut options = PruneJobOptions::default(); | |
220 | options.keep.keep_last = Some(1); | |
221 | let remove_list = get_prune_list(list, false, &options); | |
222 | let expect: Vec<PathBuf> = vec![ | |
223 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
224 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
225 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
226 | ]; | |
227 | assert_eq!(remove_list, expect); | |
228 | ||
229 | let list = orig_list.clone(); | |
230 | let mut options = PruneJobOptions::default(); | |
231 | options.keep.keep_last = Some(0); | |
232 | let remove_list = get_prune_list(list, false, &options); | |
233 | let expect: Vec<PathBuf> = vec![ | |
234 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
235 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
236 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
237 | PathBuf::from("host/elsa/2019-12-04T12:59:15Z"), | |
238 | ]; | |
239 | assert_eq!(remove_list, expect); | |
240 | ||
241 | // keep-last, keep-daily mixed | |
242 | let list = orig_list.clone(); | |
243 | let mut options = PruneJobOptions::default(); | |
244 | options.keep.keep_last = Some(2); | |
245 | options.keep.keep_daily = Some(2); | |
246 | let remove_list = get_prune_list(list, false, &options); | |
247 | let expect: Vec<PathBuf> = vec![]; | |
248 | assert_eq!(remove_list, expect); | |
249 | ||
250 | // keep-daily test | |
251 | let list = orig_list.clone(); | |
252 | let mut options = PruneJobOptions::default(); | |
253 | options.keep.keep_daily = Some(3); | |
254 | let remove_list = get_prune_list(list, false, &options); | |
255 | let expect: Vec<PathBuf> = vec![PathBuf::from("host/elsa/2019-12-04T11:59:15Z")]; | |
256 | assert_eq!(remove_list, expect); | |
257 | ||
258 | // keep-daily test | |
259 | let list = orig_list.clone(); | |
260 | let mut options = PruneJobOptions::default(); | |
261 | options.keep.keep_daily = Some(2); | |
262 | let remove_list = get_prune_list(list, false, &options); | |
263 | let expect: Vec<PathBuf> = vec![ | |
264 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
265 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
266 | ]; | |
267 | assert_eq!(remove_list, expect); | |
268 | ||
269 | // keep-weekly | |
270 | let list = orig_list.clone(); | |
271 | let mut options = PruneJobOptions::default(); | |
272 | options.keep.keep_weekly = Some(5); | |
273 | let remove_list = get_prune_list(list, false, &options); | |
274 | // all backup are within the same week, so we only keep a single file | |
275 | let expect: Vec<PathBuf> = vec![ | |
276 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
277 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
278 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
279 | ]; | |
280 | assert_eq!(remove_list, expect); | |
281 | ||
282 | // keep-daily + keep-weekly | |
283 | let list = orig_list.clone(); | |
284 | let mut options = PruneJobOptions::default(); | |
285 | options.keep.keep_daily = Some(1); | |
286 | options.keep.keep_weekly = Some(5); | |
287 | let remove_list = get_prune_list(list, false, &options); | |
288 | let expect: Vec<PathBuf> = vec![ | |
289 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
290 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
291 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
292 | ]; | |
293 | assert_eq!(remove_list, expect); | |
294 | ||
295 | // keep-monthly | |
296 | let list = orig_list.clone(); | |
297 | let mut options = PruneJobOptions::default(); | |
298 | options.keep.keep_monthly = Some(6); | |
299 | let remove_list = get_prune_list(list, false, &options); | |
300 | // all backup are within the same month, so we only keep a single file | |
301 | let expect: Vec<PathBuf> = vec![ | |
302 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
303 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
304 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
305 | ]; | |
306 | assert_eq!(remove_list, expect); | |
307 | ||
308 | // keep-yearly | |
309 | let list = orig_list.clone(); | |
310 | let mut options = PruneJobOptions::default(); | |
311 | options.keep.keep_yearly = Some(7); | |
312 | let remove_list = get_prune_list(list, false, &options); | |
313 | // all backup are within the same year, so we only keep a single file | |
314 | let expect: Vec<PathBuf> = vec![ | |
315 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
316 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
317 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
318 | ]; | |
319 | assert_eq!(remove_list, expect); | |
320 | ||
321 | // keep-weekly + keep-monthly + keep-yearly | |
322 | let list = orig_list; | |
323 | let mut options = PruneJobOptions::default(); | |
324 | options.keep.keep_weekly = Some(5); | |
325 | options.keep.keep_monthly = Some(6); | |
326 | options.keep.keep_yearly = Some(7); | |
327 | let remove_list = get_prune_list(list, false, &options); | |
328 | // all backup are within one week, so we only keep a single file | |
329 | let expect: Vec<PathBuf> = vec![ | |
330 | PathBuf::from("host/elsa/2019-12-02T11:59:15Z"), | |
331 | PathBuf::from("host/elsa/2019-12-03T11:59:15Z"), | |
332 | PathBuf::from("host/elsa/2019-12-04T11:59:15Z"), | |
333 | ]; | |
334 | assert_eq!(remove_list, expect); | |
335 | ||
336 | Ok(()) | |
337 | } |