]> git.proxmox.com Git - pve-storage.git/blob - test/prune_backups_test.pm
Add prune_backups to storage API
[pve-storage.git] / test / prune_backups_test.pm
1 package PVE::Storage::TestPruneBackups;
2
3 use strict;
4 use warnings;
5
6 use lib qw(..);
7
8 use PVE::Storage;
9 use Test::More;
10 use Test::MockModule;
11
12 my $storeid = 'BackTest123';
13 my @vmids = (1234, 9001);
14
15 # only includes the information needed for prune_backups
16 my $mocked_backups_lists = {};
17
18 my $basetime = 1577881101; # 2020_01_01-12_18_21 UTC
19
20 foreach my $vmid (@vmids) {
21 push @{$mocked_backups_lists->{default}}, (
22 {
23 'volid' => "$storeid:backup/vzdump-qemu-$vmid-2018_05_26-11_18_21.tar.zst",
24 'ctime' => $basetime - 585*24*60*60 - 60*60,
25 'vmid' => $vmid,
26 },
27 {
28 'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_18_21.tar.zst",
29 'ctime' => $basetime - 24*60*60 - 60*60,
30 'vmid' => $vmid,
31 },
32 {
33 'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_19_21.tar.zst",
34 'ctime' => $basetime - 24*60*60 - 60*60 + 60,
35 'vmid' => $vmid,
36 },
37 {
38 'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-11_18_21.tar.zst",
39 'ctime' => $basetime - 60*60,
40 'vmid' => $vmid,
41 },
42 {
43 'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-12_18_21.tar.zst",
44 'ctime' => $basetime,
45 'vmid' => $vmid,
46 },
47 {
48 'volid' => "$storeid:backup/vzdump-lxc-$vmid-2020_01_01-12_18_21.tar.zst",
49 'ctime' => $basetime,
50 'vmid' => $vmid,
51 },
52 {
53 'volid' => "$storeid:backup/vzdump-$vmid-renamed.tar.zst",
54 'ctime' => 1234,
55 'vmid' => $vmid,
56 },
57 );
58 }
59 push @{$mocked_backups_lists->{year1970}}, (
60 {
61 'volid' => "$storeid:backup/vzdump-lxc-321-1970_01_01-00_01_23.tar.zst",
62 'ctime' => 83,
63 'vmid' => 321,
64 },
65 {
66 'volid' => "$storeid:backup/vzdump-lxc-321-2070_01_01-00_01_00.tar.zst",
67 'ctime' => 60*60*24 * (365*100 + 25) + 60,
68 'vmid' => 321,
69 },
70 );
71 push @{$mocked_backups_lists->{novmid}}, (
72 {
73 'volid' => "$storeid:backup/vzdump-lxc-novmid.tar.gz",
74 'ctime' => 1234,
75 },
76 );
77 my $current_list;
78 my $mock_plugin = Test::MockModule->new('PVE::Storage::Plugin');
79 $mock_plugin->redefine(list_volumes => sub {
80 my ($class, $storeid, $scfg, $vmid, $content_types) = @_;
81
82 my $list = $mocked_backups_lists->{$current_list};
83
84 return $list if !defined($vmid);
85
86 return [ grep { $_->{vmid} eq $vmid } @{$list} ];
87 });
88
89 sub generate_expected {
90 my ($vmids, $type, $marks) = @_;
91
92 my @expected;
93 foreach my $vmid (@{$vmids}) {
94 push @expected, (
95 {
96 'volid' => "$storeid:backup/vzdump-qemu-$vmid-2018_05_26-11_18_21.tar.zst",
97 'type' => 'qemu',
98 'ctime' => $basetime - 585*24*60*60 - 60*60,
99 'mark' => $marks->[0],
100 'vmid' => $vmid,
101 },
102 {
103 'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_18_21.tar.zst",
104 'type' => 'qemu',
105 'ctime' => $basetime - 24*60*60 - 60*60,
106 'mark' => $marks->[1],
107 'vmid' => $vmid,
108 },
109 {
110 'volid' => "$storeid:backup/vzdump-qemu-$vmid-2019_12_31-11_19_21.tar.zst",
111 'type' => 'qemu',
112 'ctime' => $basetime - 24*60*60 - 60*60 + 60,
113 'mark' => $marks->[2],
114 'vmid' => $vmid,
115 },
116 {
117 'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-11_18_21.tar.zst",
118 'type' => 'qemu',
119 'ctime' => $basetime - 60*60,
120 'mark' => $marks->[3],
121 'vmid' => $vmid,
122 },
123 {
124 'volid' => "$storeid:backup/vzdump-qemu-$vmid-2020_01_01-12_18_21.tar.zst",
125 'type' => 'qemu',
126 'ctime' => $basetime,
127 'mark' => $marks->[4],
128 'vmid' => $vmid,
129 },
130 ) if !defined($type) || $type eq 'qemu';
131 push @expected, (
132 {
133 'volid' => "$storeid:backup/vzdump-lxc-$vmid-2020_01_01-12_18_21.tar.zst",
134 'type' => 'lxc',
135 'ctime' => $basetime,
136 'mark' => $marks->[5],
137 'vmid' => $vmid,
138 },
139 ) if !defined($type) || $type eq 'lxc';
140 push @expected, (
141 {
142 'volid' => "$storeid:backup/vzdump-$vmid-renamed.tar.zst",
143 'type' => 'unknown',
144 'ctime' => 1234,
145 'mark' => 'protected',
146 'vmid' => $vmid,
147 },
148 ) if !defined($type);
149 }
150 return [ sort { $a->{volid} cmp $b->{volid} } @expected ];
151 }
152
153 # an array of test cases, each test is comprised of the following keys:
154 # description => to identify a single test
155 # vmid => VMID or undef for all
156 # type => 'qemu' or 'lxc' or undef for all
157 # keep => options describing what to keep
158 # list => backups list to use. defaults to 'default'
159 # expected => what prune_backups should return
160 #
161 # most of them are created further below
162 my $tests = [
163 {
164 description => 'last=3, multiple IDs',
165 keep => {
166 'keep-last' => 3,
167 },
168 expected => generate_expected(\@vmids, undef, ['remove', 'remove', 'keep', 'keep', 'keep', 'keep']),
169 },
170 {
171 description => 'weekly=2, one ID',
172 vmid => $vmids[0],
173 keep => {
174 'keep-weekly' => 2,
175 },
176 expected => generate_expected([$vmids[0]], undef, ['keep', 'remove', 'remove', 'remove', 'keep', 'keep']),
177 },
178 {
179 description => 'daily=weekly=monthly=1, multiple IDs',
180 keep => {
181 'keep-hourly' => 0,
182 'keep-daily' => 1,
183 'keep-weekly' => 1,
184 'keep-monthly' => 1,
185 },
186 expected => generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
187 },
188 {
189 description => 'hourly=4, one ID',
190 vmid => $vmids[0],
191 keep => {
192 'keep-hourly' => 4,
193 'keep-daily' => 0,
194 },
195 expected => generate_expected([$vmids[0]], undef, ['keep', 'remove', 'keep', 'keep', 'keep', 'keep']),
196 },
197 {
198 description => 'yearly=2, multiple IDs',
199 keep => {
200 'keep-hourly' => 0,
201 'keep-daily' => 0,
202 'keep-weekly' => 0,
203 'keep-monthly' => 0,
204 'keep-yearly' => 2,
205 },
206 expected => generate_expected(\@vmids, undef, ['remove', 'remove', 'keep', 'remove', 'keep', 'keep']),
207 },
208 {
209 description => 'last=2,hourly=2 one ID',
210 vmid => $vmids[0],
211 keep => {
212 'keep-last' => 2,
213 'keep-hourly' => 2,
214 },
215 expected => generate_expected([$vmids[0]], undef, ['keep', 'remove', 'keep', 'keep', 'keep', 'keep']),
216 },
217 {
218 description => 'last=1,monthly=2, multiple IDs',
219 keep => {
220 'keep-last' => 1,
221 'keep-monthly' => 2,
222 },
223 expected => generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
224 },
225 {
226 description => 'monthly=3, one ID',
227 vmid => $vmids[0],
228 keep => {
229 'keep-monthly' => 3,
230 },
231 expected => generate_expected([$vmids[0]], undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
232 },
233 {
234 description => 'last=daily=weekly=1, multiple IDs',
235 keep => {
236 'keep-last' => 1,
237 'keep-daily' => 1,
238 'keep-weekly' => 1,
239 },
240 expected => generate_expected(\@vmids, undef, ['keep', 'remove', 'keep', 'remove', 'keep', 'keep']),
241 },
242 {
243 description => 'daily=2, one ID',
244 vmid => $vmids[0],
245 keep => {
246 'keep-daily' => 2,
247 },
248 expected => generate_expected([$vmids[0]], undef, ['remove', 'remove', 'keep', 'remove', 'keep', 'keep']),
249 },
250 {
251 description => 'weekly=monthly=1, multiple IDs',
252 keep => {
253 'keep-weekly' => 1,
254 'keep-monthly' => 1,
255 },
256 expected => generate_expected(\@vmids, undef, ['keep', 'remove', 'remove', 'remove', 'keep', 'keep']),
257 },
258 {
259 description => 'weekly=yearly=1, one ID',
260 vmid => $vmids[0],
261 keep => {
262 'keep-weekly' => 1,
263 'keep-yearly' => 1,
264 },
265 expected => generate_expected([$vmids[0]], undef, ['keep', 'remove', 'remove', 'remove', 'keep', 'keep']),
266 },
267 {
268 description => 'weekly=yearly=1, one ID, type qemu',
269 vmid => $vmids[0],
270 type => 'qemu',
271 keep => {
272 'keep-weekly' => 1,
273 'keep-yearly' => 1,
274 },
275 expected => generate_expected([$vmids[0]], 'qemu', ['keep', 'remove', 'remove', 'remove', 'keep', '']),
276 },
277 {
278 description => 'week=yearly=1, one ID, type lxc',
279 vmid => $vmids[0],
280 type => 'lxc',
281 keep => {
282 'keep-last' => 1,
283 },
284 expected => generate_expected([$vmids[0]], 'lxc', ['', '', '', '', '', 'keep']),
285 },
286 {
287 description => 'yearly=1, year before 2000',
288 keep => {
289 'keep-yearly' => 1,
290 },
291 list => 'year1970',
292 expected => [
293 {
294 'volid' => "$storeid:backup/vzdump-lxc-321-1970_01_01-00_01_23.tar.zst",
295 'ctime' => 83,
296 'mark' => 'remove',
297 'type' => 'lxc',
298 'vmid' => 321,
299 },
300 {
301 'volid' => "$storeid:backup/vzdump-lxc-321-2070_01_01-00_01_00.tar.zst",
302 'ctime' => 60*60*24 * (365*100 + 25) + 60,
303 'mark' => 'keep',
304 'type' => 'lxc',
305 'vmid' => 321,
306 },
307 ],
308 },
309 {
310 description => 'last=1, ne ID, year before 2000',
311 keep => {
312 'keep-last' => 1,
313 },
314 list => 'novmid',
315 expected => [
316 {
317 'volid' => "$storeid:backup/vzdump-lxc-novmid.tar.gz",
318 'ctime' => 1234,
319 'mark' => 'protected',
320 'type' => 'lxc',
321 },
322 ],
323 },
324 ];
325
326 plan tests => scalar @$tests;
327
328 for my $tt (@$tests) {
329
330 my $got = eval {
331 $current_list = $tt->{list} // 'default';
332 my $res = PVE::Storage::Plugin->prune_backups($tt->{scfg}, $storeid, $tt->{keep}, $tt->{vmid}, $tt->{type}, 1);
333 return [ sort { $a->{volid} cmp $b->{volid} } @{$res} ];
334 };
335 $got = $@ if $@;
336
337 is_deeply($got, $tt->{expected}, $tt->{description}) || diag(explain($got));
338 }
339
340 done_testing();
341
342 1;