2
2
import os
3
3
import shutil
4
4
import unittest
5
+
6
+ from datetime import datetime , timezone
5
7
from unittest .mock import MagicMock , Mock , call , patch
6
8
from .gutest_helpers import create_side_effect_dict , Files
7
9
@@ -206,7 +208,7 @@ def test_list_checkpoints__checkpoints_dir_exist_but_no_files__empty_list(self):
206
208
# 'assertCountEqual' does check same count, same elements ignoring order
207
209
self .assertCountEqual (expected , actual )
208
210
209
- def test_list_checkpoints__checkpoints_dir_has_multiple_files__multiple_files (self ):
211
+ def test_list_checkpoints__checkpoints_dir_has_multiple_files (self ):
210
212
# Arrange
211
213
self .create_checkpoints_dir ()
212
214
self .add_checkpoint (self .any_checkpoint_name , self .any_config )
@@ -221,7 +223,25 @@ def test_list_checkpoints__checkpoints_dir_has_multiple_files__multiple_files(se
221
223
# 'assertCountEqual' does check same count, same elements ignoring order
222
224
self .assertCountEqual (expected , actual )
223
225
224
- def test_list_checkpoints__checkpoints_names_have_special_characters__multiple_files (self ):
226
+ def test_list_checkpoints__checkpoints_dir_has_multiple_files_with_time (self ):
227
+ # Arrange
228
+ self .create_checkpoints_dir ()
229
+ mod_time1 = self .add_checkpoint (self .any_checkpoint_name , self .any_config )
230
+ mod_time2 = self .add_checkpoint (self .any_other_checkpoint_name , self .any_config )
231
+ rollbacker = self .create_rollbacker ()
232
+ expected = [
233
+ {"name" : self .any_checkpoint_name , "time" : mod_time1 },
234
+ {"name" : self .any_other_checkpoint_name , "time" : mod_time2 }
235
+ ]
236
+
237
+ # Act
238
+ actual = rollbacker .list_checkpoints (includes_time = True )
239
+
240
+ # Assert
241
+ # 'assertCountEqual' does check same count, same elements ignoring order
242
+ self .assertCountEqual (expected , actual )
243
+
244
+ def test_list_checkpoints__checkpoints_names_have_special_characters_multiple_files (self ):
225
245
# Arrange
226
246
self .create_checkpoints_dir ()
227
247
self .add_checkpoint ("check.point1" , self .any_config )
@@ -237,6 +257,26 @@ def test_list_checkpoints__checkpoints_names_have_special_characters__multiple_f
237
257
# 'assertCountEqual' does check same count, same elements ignoring order
238
258
self .assertCountEqual (expected , actual )
239
259
260
+ def test_list_checkpoints__checkpoints_names_have_special_characters_multiple_files_with_time (self ):
261
+ # Arrange
262
+ self .create_checkpoints_dir ()
263
+ mod_time1 = self .add_checkpoint ("check.point1" , self .any_config )
264
+ mod_time2 = self .add_checkpoint (".checkpoint2" , self .any_config )
265
+ mod_time3 = self .add_checkpoint ("checkpoint3." , self .any_config )
266
+ rollbacker = self .create_rollbacker ()
267
+ expected = [
268
+ {"name" : "check.point1" , "time" : mod_time1 },
269
+ {"name" : ".checkpoint2" , "time" : mod_time2 },
270
+ {"name" : "checkpoint3." , "time" : mod_time3 }
271
+ ]
272
+
273
+ # Act
274
+ actual = rollbacker .list_checkpoints (includes_time = True )
275
+
276
+ # Assert
277
+ # 'assertCountEqual' does check same count, same elements ignoring order
278
+ self .assertCountEqual (expected , actual )
279
+
240
280
def test_delete_checkpoint__checkpoint_does_not_exist__failure (self ):
241
281
# Arrange
242
282
rollbacker = self .create_rollbacker ()
@@ -279,18 +319,60 @@ def test_multiple_operations(self):
279
319
rollbacker .delete_checkpoint (self .any_other_checkpoint_name )
280
320
self .assertCountEqual ([], rollbacker .list_checkpoints ())
281
321
322
+ def test_multiple_operations_with_time (self ):
323
+ rollbacker = self .create_rollbacker ()
324
+
325
+ # 'assertCountEqual' does check same count, same elements ignoring order
326
+ self .assertCountEqual ([], rollbacker .list_checkpoints (includes_time = True ))
327
+
328
+ rollbacker .checkpoint (self .any_checkpoint_name )
329
+ self .assertCountEqual (
330
+ [self .any_checkpoint_name ],
331
+ self .extract_checkpoint_names (rollbacker .list_checkpoints (includes_time = True ))
332
+ )
333
+ self .assertEqual (self .any_config , self .get_checkpoint (self .any_checkpoint_name ))
334
+
335
+ rollbacker .rollback (self .any_checkpoint_name )
336
+ rollbacker .config_replacer .replace .assert_has_calls ([call (self .any_config )])
337
+
338
+ rollbacker .checkpoint (self .any_other_checkpoint_name )
339
+ self .assertCountEqual (
340
+ [self .any_checkpoint_name , self .any_other_checkpoint_name ],
341
+ self .extract_checkpoint_names (rollbacker .list_checkpoints (includes_time = True ))
342
+ )
343
+ self .assertEqual (self .any_config , self .get_checkpoint (self .any_other_checkpoint_name ))
344
+
345
+ rollbacker .delete_checkpoint (self .any_checkpoint_name )
346
+ self .assertCountEqual (
347
+ [self .any_other_checkpoint_name ],
348
+ self .extract_checkpoint_names (rollbacker .list_checkpoints (includes_time = True ))
349
+ )
350
+
351
+ rollbacker .delete_checkpoint (self .any_other_checkpoint_name )
352
+ self .assertCountEqual ([], rollbacker .list_checkpoints (includes_time = True ))
353
+
354
+ def extract_checkpoint_names (self , checkpoint_list ):
355
+ """Extract checkpoint names from the list of dictionaries."""
356
+ return [checkpoint ["name" ] for checkpoint in checkpoint_list ]
357
+
282
358
def clean_up (self ):
283
359
if os .path .isdir (self .checkpoints_dir ):
284
360
shutil .rmtree (self .checkpoints_dir )
285
361
286
362
def create_checkpoints_dir (self ):
287
363
os .makedirs (self .checkpoints_dir )
288
364
289
- def add_checkpoint (self , name , json_content ):
365
+ def add_checkpoint (self , name , json_content , mod_time = None ):
290
366
path = os .path .join (self .checkpoints_dir , f"{ name } { self .checkpoint_ext } " )
291
367
with open (path , "w" ) as fh :
292
368
fh .write (json .dumps (json_content ))
293
369
370
+ if mod_time is None :
371
+ mod_time = datetime .now (timezone .utc ).timestamp ()
372
+ os .utime (path , (mod_time , mod_time ))
373
+
374
+ return datetime .fromtimestamp (mod_time , tz = timezone .utc ).isoformat ()
375
+
294
376
def get_checkpoint (self , name ):
295
377
path = os .path .join (self .checkpoints_dir , f"{ name } { self .checkpoint_ext } " )
296
378
with open (path ) as fh :
@@ -519,8 +601,14 @@ def setUp(self):
519
601
self .any_checkpoint_name = "anycheckpoint"
520
602
self .any_other_checkpoint_name = "anyothercheckpoint"
521
603
self .any_checkpoints_list = [self .any_checkpoint_name , self .any_other_checkpoint_name ]
604
+ self .any_checkpoints_list_with_time = [
605
+ {"name" : self .any_checkpoint_name , "time" : datetime .now (timezone .utc ).isoformat ()},
606
+ {"name" : self .any_other_checkpoint_name , "time" : datetime .now (timezone .utc ).isoformat ()}
607
+ ]
608
+
522
609
self .any_config_format = gu .ConfigFormat .SONICYANG
523
610
self .any_verbose = True
611
+ self .list_checkpoints_includes_time = True
524
612
self .any_dry_run = True
525
613
self .any_ignore_non_yang_tables = True
526
614
self .any_ignore_paths = ["" , "/ACL_TABLE" ]
@@ -651,7 +739,26 @@ def test_list_checkpoints__creates_rollbacker_and_list_checkpoints(self):
651
739
expected = self .any_checkpoints_list
652
740
653
741
# Act
654
- actual = generic_updater .list_checkpoints (self .any_verbose )
742
+ actual = generic_updater .list_checkpoints (False , self .any_verbose )
743
+
744
+ # Assert
745
+ self .assertCountEqual (expected , actual )
746
+
747
+ def test_list_checkpoints__creates_rollbacker_and_list_checkpoints_with_time (self ):
748
+ # Arrange
749
+ config_rollbacker = Mock ()
750
+ config_rollbacker .list_checkpoints .return_value = self .any_checkpoints_list_with_time
751
+
752
+ factory = Mock ()
753
+ factory .create_config_rollbacker .side_effect = \
754
+ create_side_effect_dict ({(str (self .any_verbose ),): config_rollbacker })
755
+
756
+ generic_updater = gu .GenericUpdater (factory )
757
+
758
+ expected = self .any_checkpoints_list_with_time
759
+
760
+ # Act
761
+ actual = generic_updater .list_checkpoints (self .list_checkpoints_includes_time , self .any_verbose )
655
762
656
763
# Assert
657
764
self .assertCountEqual (expected , actual )
@@ -710,7 +817,7 @@ def test_list_checkpoints__calls_decorated_rollbacker(self):
710
817
expected = self .any_checkpoints_list
711
818
712
819
# Act
713
- actual = self .decorator .list_checkpoints ()
820
+ actual = self .decorator .list_checkpoints (includes_time = False )
714
821
715
822
# Assert
716
823
self .decorated_config_rollbacker .list_checkpoints .assert_called_once ()
0 commit comments