@@ -267,24 +267,14 @@ def test_prune_ignore_protected(archivers, request):
267267
268268class MockArchive :
269269 def __init__ (self , ts , id ):
270- self .ts = ts
270+ # Real archive objects have UTC zoned timestamps
271+ self .ts = ts .replace (tzinfo = timezone .utc )
271272 self .id = id
272273
273274 def __repr__ (self ):
274275 return f"{ self .id } : { self .ts .isoformat ()} "
275276
276277
277- # This is the local timezone of the system running the tests.
278- # We need this e.g. to construct archive timestamps for the prune tests,
279- # because borg prune operates in the local timezone (it first converts the
280- # archive timestamp to the local timezone). So, if we want the y/m/d/h/m/s
281- # values which prune uses to be exactly the ones we give [and NOT shift them
282- # by tzoffset], we need to give the timestamps in the same local timezone.
283- # Please note that the timestamps in a real borg archive or manifest are
284- # stored in UTC timezone.
285- local_tz = datetime .now (tz = timezone .utc ).astimezone (tz = None ).tzinfo
286-
287-
288278@pytest .mark .parametrize (
289279 "rule,num_to_keep,expected_ids" ,
290280 [
@@ -304,23 +294,23 @@ def subset(lst, ids):
304294
305295 archives = [
306296 # years apart
307- MockArchive (datetime (2015 , 1 , 1 , 10 , 0 , 0 , tzinfo = local_tz ), 1 ),
308- MockArchive (datetime (2016 , 1 , 1 , 10 , 0 , 0 , tzinfo = local_tz ), 2 ),
309- MockArchive (datetime (2017 , 1 , 1 , 10 , 0 , 0 , tzinfo = local_tz ), 3 ),
297+ MockArchive (datetime (2015 , 1 , 1 , 10 , 0 , 0 ), 1 ),
298+ MockArchive (datetime (2016 , 1 , 1 , 10 , 0 , 0 ), 2 ),
299+ MockArchive (datetime (2017 , 1 , 1 , 10 , 0 , 0 ), 3 ),
310300 # months apart
311- MockArchive (datetime (2017 , 2 , 1 , 10 , 0 , 0 , tzinfo = local_tz ), 4 ),
312- MockArchive (datetime (2017 , 3 , 1 , 10 , 0 , 0 , tzinfo = local_tz ), 5 ),
301+ MockArchive (datetime (2017 , 2 , 1 , 10 , 0 , 0 ), 4 ),
302+ MockArchive (datetime (2017 , 3 , 1 , 10 , 0 , 0 ), 5 ),
313303 # days apart
314- MockArchive (datetime (2017 , 3 , 2 , 10 , 0 , 0 , tzinfo = local_tz ), 6 ),
315- MockArchive (datetime (2017 , 3 , 3 , 10 , 0 , 0 , tzinfo = local_tz ), 7 ),
316- MockArchive (datetime (2017 , 3 , 4 , 10 , 0 , 0 , tzinfo = local_tz ), 8 ),
304+ MockArchive (datetime (2017 , 3 , 2 , 10 , 0 , 0 ), 6 ),
305+ MockArchive (datetime (2017 , 3 , 3 , 10 , 0 , 0 ), 7 ),
306+ MockArchive (datetime (2017 , 3 , 4 , 10 , 0 , 0 ), 8 ),
317307 # minutes apart
318- MockArchive (datetime (2017 , 10 , 1 , 9 , 45 , 0 , tzinfo = local_tz ), 9 ),
319- MockArchive (datetime (2017 , 10 , 1 , 9 , 55 , 0 , tzinfo = local_tz ), 10 ),
308+ MockArchive (datetime (2017 , 10 , 1 , 9 , 45 , 0 ), 9 ),
309+ MockArchive (datetime (2017 , 10 , 1 , 9 , 55 , 0 ), 10 ),
320310 # seconds apart
321- MockArchive (datetime (2017 , 10 , 1 , 10 , 0 , 1 , tzinfo = local_tz ), 11 ),
322- MockArchive (datetime (2017 , 10 , 1 , 10 , 0 , 3 , tzinfo = local_tz ), 12 ),
323- MockArchive (datetime (2017 , 10 , 1 , 10 , 0 , 5 , tzinfo = local_tz ), 13 ),
311+ MockArchive (datetime (2017 , 10 , 1 , 10 , 0 , 1 ), 11 ),
312+ MockArchive (datetime (2017 , 10 , 1 , 10 , 0 , 3 ), 12 ),
313+ MockArchive (datetime (2017 , 10 , 1 , 10 , 0 , 5 ), 13 ),
324314 ]
325315 kept_because = {}
326316 keep = prune_split (archives , rule , num_to_keep , None , kept_because )
@@ -336,17 +326,17 @@ def subset(lst, ids):
336326
337327 archives = [
338328 # oldest backup, but not last in its year
339- MockArchive (datetime (2018 , 1 , 1 , 10 , 0 , 0 , tzinfo = local_tz ), 1 ),
329+ MockArchive (datetime (2018 , 1 , 1 , 10 , 0 , 0 ), 1 ),
340330 # an interim backup
341- MockArchive (datetime (2018 , 12 , 30 , 10 , 0 , 0 , tzinfo = local_tz ), 2 ),
331+ MockArchive (datetime (2018 , 12 , 30 , 10 , 0 , 0 ), 2 ),
342332 # year-end backups
343- MockArchive (datetime (2018 , 12 , 31 , 10 , 0 , 0 , tzinfo = local_tz ), 3 ),
344- MockArchive (datetime (2019 , 12 , 31 , 10 , 0 , 0 , tzinfo = local_tz ), 4 ),
333+ MockArchive (datetime (2018 , 12 , 31 , 10 , 0 , 0 ), 3 ),
334+ MockArchive (datetime (2019 , 12 , 31 , 10 , 0 , 0 ), 4 ),
345335 ]
346336
347337 # Keep oldest when retention target can't otherwise be met
348338 kept_because = {}
349- keep = prune_split (archives , "yearly" , 3 , kept_because )
339+ keep = prune_split (archives , "yearly" , 3 , None , kept_because )
350340
351341 assert set (keep ) == subset (archives , [1 , 3 , 4 ])
352342 assert kept_because [1 ][0 ] == "yearly[oldest]"
@@ -355,7 +345,7 @@ def subset(lst, ids):
355345
356346 # Otherwise, prune it
357347 kept_because = {}
358- keep = prune_split (archives , "yearly" , 2 , kept_because )
348+ keep = prune_split (archives , "yearly" , 2 , None , kept_because )
359349
360350 assert set (keep ) == subset (archives , [3 , 4 ])
361351 assert kept_because [3 ][0 ] == "yearly"
@@ -366,11 +356,12 @@ def test_prune_split_no_archives():
366356 archives = []
367357
368358 kept_because = {}
369- keep = prune_split (archives , "yearly" , 3 , kept_because )
359+ keep = prune_split (archives , "yearly" , 3 , None , kept_because )
370360
371361 assert keep == []
372362 assert kept_because == {}
373363
364+
374365def test_prune_keep_last_same_second (archivers , request ):
375366 archiver = request .getfixturevalue (archivers )
376367 cmd (archiver , "repo-create" , RK_ENCRYPTION )
0 commit comments