@@ -411,6 +411,100 @@ def test_validate_corrupted_intermediate_backups(self):
411411 # Clean after yourself
412412 self .del_test_dir (module_name , fname )
413413
414+ # @unittest.skip("skip")
415+ def test_validate_error_intermediate_backups (self ):
416+ """
417+ make archive node, take FULL, PAGE1, PAGE2 backups,
418+ change backup status of FULL and PAGE1 to ERROR,
419+ run validate on PAGE1
420+ purpouse of this test is to be sure that not only
421+ CORRUPT backup descendants can be orphanized
422+ """
423+ fname = self .id ().split ('.' )[3 ]
424+ node = self .make_simple_node (
425+ base_dir = os .path .join (module_name , fname , 'node' ),
426+ initdb_params = ['--data-checksums' ],
427+ pg_options = {'wal_level' : 'replica' }
428+ )
429+ backup_dir = os .path .join (self .tmp_path , module_name , fname , 'backup' )
430+ self .init_pb (backup_dir )
431+ self .add_instance (backup_dir , 'node' , node )
432+ self .set_archiving (backup_dir , 'node' , node )
433+ node .slow_start ()
434+
435+ # FULL
436+ backup_id_1 = self .backup_node (backup_dir , 'node' , node )
437+
438+ # PAGE1
439+ backup_id_2 = self .backup_node (
440+ backup_dir , 'node' , node , backup_type = 'page' )
441+
442+ # PAGE2
443+ backup_id_3 = self .backup_node (
444+ backup_dir , 'node' , node , backup_type = 'page' )
445+
446+ # Change FULL backup status to ERROR
447+ control_path = os .path .join (
448+ backup_dir , 'backups' , 'node' , backup_id_1 , 'backup.control' )
449+
450+ with open (control_path , 'r' ) as f :
451+ actual_control = f .read ()
452+
453+ print (actual_control )
454+
455+ new_control_file = ''
456+ for line in actual_control .splitlines ():
457+ new_control_file += line .replace (
458+ 'status = OK' , 'status = ERROR' )
459+ new_control_file += '\n '
460+
461+ with open (control_path , 'wt' ) as f :
462+ f .write (new_control_file )
463+ f .flush ()
464+ f .close ()
465+
466+ print ('HELLO' )
467+ print (new_control_file )
468+
469+ # Validate PAGE1
470+ try :
471+ self .validate_pb (
472+ backup_dir , 'node' , backup_id = backup_id_2 )
473+ self .assertEqual (
474+ 1 , 0 ,
475+ "Expecting Error because backup has status ERROR.\n "
476+ "Output: {0} \n CMD: {1}" .format (
477+ repr (self .output ), self .cmd ))
478+ except ProbackupException as e :
479+ self .assertTrue (
480+ 'WARNING: Backup {0} is orphaned because '
481+ 'his parent {1} has status: ERROR' .format (
482+ backup_id_2 , backup_id_1 ) in e .message and
483+ 'INFO: Validating parents for backup {0}' .format (
484+ backup_id_2 ) in e .message and
485+ 'WARNING: Backup {0} has status ERROR. Skip validation.' .format (
486+ backup_id_1 ) and
487+ 'ERROR: Backup {0} is orphan.' .format (backup_id_2 ) in e .message ,
488+ '\n Unexpected Error Message: {0}\n '
489+ 'CMD: {1}' .format (
490+ repr (e .message ), self .cmd ))
491+
492+ self .assertEqual (
493+ 'ERROR' ,
494+ self .show_pb (backup_dir , 'node' , backup_id_1 )['status' ],
495+ 'Backup STATUS should be "ERROR"' )
496+ self .assertEqual (
497+ 'ORPHAN' ,
498+ self .show_pb (backup_dir , 'node' , backup_id_2 )['status' ],
499+ 'Backup STATUS should be "ORPHAN"' )
500+ self .assertEqual (
501+ 'ORPHAN' ,
502+ self .show_pb (backup_dir , 'node' , backup_id_3 )['status' ],
503+ 'Backup STATUS should be "ORPHAN"' )
504+
505+ # Clean after yourself
506+ self .del_test_dir (module_name , fname )
507+
414508 # @unittest.skip("skip")
415509 def test_validate_corrupted_intermediate_backups_1 (self ):
416510 """
0 commit comments