@@ -748,6 +748,93 @@ def test_validate_instance_with_corrupted_page(self):
748
748
# Clean after yourself
749
749
self .del_test_dir (module_name , fname )
750
750
751
+ # @unittest.skip("skip")
752
+ def test_validate_instance_with_corrupted_full_and_try_restore (self ):
753
+ """make archive node, take FULL, PAGE1, PAGE2, FULL2, PAGE3 backups,
754
+ corrupt file in FULL backup and run validate on instance,
755
+ expect FULL to gain status CORRUPT, PAGE1 and PAGE2 to gain status ORPHAN,
756
+ try to restore backup with --no-validation option"""
757
+ fname = self .id ().split ('.' )[3 ]
758
+ node = self .make_simple_node (base_dir = "{0}/{1}/node" .format (module_name , fname ),
759
+ initdb_params = ['--data-checksums' ],
760
+ pg_options = {'wal_level' : 'replica' }
761
+ )
762
+ backup_dir = os .path .join (self .tmp_path , module_name , fname , 'backup' )
763
+ self .init_pb (backup_dir )
764
+ self .add_instance (backup_dir , 'node' , node )
765
+ self .set_archiving (backup_dir , 'node' , node )
766
+ node .start ()
767
+
768
+ node .safe_psql (
769
+ "postgres" ,
770
+ "create table t_heap as select i as id, md5(i::text) as text, md5(repeat(i::text,10))::tsvector as tsvector from generate_series(0,10000) i" )
771
+ file_path_t_heap = node .safe_psql (
772
+ "postgres" ,
773
+ "select pg_relation_filepath('t_heap')" ).rstrip ()
774
+ # FULL1
775
+ backup_id_1 = self .backup_node (backup_dir , 'node' , node )
776
+
777
+ node .safe_psql (
778
+ "postgres" ,
779
+ "insert into t_heap select i as id, md5(i::text) as text, md5(repeat(i::text,10))::tsvector as tsvector from generate_series(0,10000) i" )
780
+ # PAGE1
781
+ backup_id_2 = self .backup_node (backup_dir , 'node' , node , backup_type = 'page' )
782
+
783
+ # PAGE2
784
+ node .safe_psql (
785
+ "postgres" ,
786
+ "insert into t_heap select i as id, md5(i::text) as text, md5(repeat(i::text,10))::tsvector as tsvector from generate_series(20000,30000) i" )
787
+ backup_id_3 = self .backup_node (backup_dir , 'node' , node , backup_type = 'page' )
788
+
789
+ # FULL1
790
+ backup_id_4 = self .backup_node (backup_dir , 'node' , node )
791
+
792
+ # PAGE3
793
+ node .safe_psql (
794
+ "postgres" ,
795
+ "insert into t_heap select i as id, md5(i::text) as text, md5(repeat(i::text,10))::tsvector as tsvector from generate_series(30000,40000) i" )
796
+ backup_id_5 = self .backup_node (backup_dir , 'node' , node , backup_type = 'page' )
797
+
798
+ # Corrupt some file in FULL backup
799
+ file_full = os .path .join (backup_dir , 'backups/node' , backup_id_1 , 'database' , file_path_t_heap )
800
+ with open (file_full , "rb+" , 0 ) as f :
801
+ f .seek (84 )
802
+ f .write (b"blah" )
803
+ f .flush ()
804
+ f .close
805
+
806
+ # Validate Instance
807
+ try :
808
+ self .validate_pb (backup_dir , 'node' , options = ['--log-level-file=verbose' ])
809
+ self .assertEqual (1 , 0 , "Expecting Error because of data files corruption.\n Output: {0} \n CMD: {1}" .format (
810
+ repr (self .output ), self .cmd ))
811
+ except ProbackupException as e :
812
+ self .assertTrue (
813
+ 'INFO: Validating backup {0}' .format (backup_id_1 ) in e .message
814
+ and "INFO: Validate backups of the instance 'node'" in e .message
815
+ and 'WARNING: Invalid CRC of backup file "{0}"' .format (file_full ) in e .message
816
+ and 'WARNING: Backup {0} data files are corrupted' .format (backup_id_1 ) in e .message ,
817
+ '\n Unexpected Error Message: {0}\n CMD: {1}' .format (repr (e .message ), self .cmd ))
818
+
819
+ self .assertEqual ('CORRUPT' , self .show_pb (backup_dir , 'node' , backup_id_1 )['status' ], 'Backup STATUS should be "CORRUPT"' )
820
+ self .assertEqual ('ORPHAN' , self .show_pb (backup_dir , 'node' , backup_id_2 )['status' ], 'Backup STATUS should be "ORPHAN"' )
821
+ self .assertEqual ('ORPHAN' , self .show_pb (backup_dir , 'node' , backup_id_3 )['status' ], 'Backup STATUS should be "ORPHAN"' )
822
+ self .assertEqual ('OK' , self .show_pb (backup_dir , 'node' , backup_id_4 )['status' ], 'Backup STATUS should be "OK"' )
823
+ self .assertEqual ('OK' , self .show_pb (backup_dir , 'node' , backup_id_5 )['status' ], 'Backup STATUS should be "OK"' )
824
+
825
+ node .cleanup ()
826
+ restore_out = self .restore_node (
827
+ backup_dir , 'node' , node ,
828
+ options = ["--no-validate" ])
829
+ self .assertIn (
830
+ "INFO: Restore of backup {0} completed." .format (backup_id_5 ),
831
+ restore_out ,
832
+ '\n Unexpected Error Message: {0}\n CMD: {1}' .format (
833
+ repr (self .output ), self .cmd ))
834
+
835
+ # Clean after yourself
836
+ self .del_test_dir (module_name , fname )
837
+
751
838
# @unittest.skip("skip")
752
839
def test_validate_instance_with_corrupted_full (self ):
753
840
"""make archive node, take FULL, PAGE1, PAGE2, FULL2, PAGE3 backups,
@@ -1582,3 +1669,62 @@ def test_validate_corrupted_full_1(self):
1582
1669
1583
1670
# Clean after yourself
1584
1671
self .del_test_dir (module_name , fname )
1672
+
1673
+ def test_file_size_corruption_no_validate (self ):
1674
+
1675
+ fname = self .id ().split ('.' )[3 ]
1676
+ node = self .make_simple_node (
1677
+ base_dir = "{0}/{1}/node" .format (module_name , fname ),
1678
+ # initdb_params=['--data-checksums'],
1679
+ pg_options = {'wal_level' : 'replica' }
1680
+ )
1681
+
1682
+ backup_dir = os .path .join (self .tmp_path , module_name , fname , 'backup' )
1683
+
1684
+ self .init_pb (backup_dir )
1685
+ self .add_instance (backup_dir , 'node' , node )
1686
+ self .set_archiving (backup_dir , 'node' , node )
1687
+
1688
+ node .start ()
1689
+
1690
+ node .safe_psql (
1691
+ "postgres" ,
1692
+ "create table t_heap as select 1 as id, md5(i::text) as text, "
1693
+ "md5(repeat(i::text,10))::tsvector as tsvector "
1694
+ "from generate_series(0,1000) i" )
1695
+ node .safe_psql (
1696
+ "postgres" ,
1697
+ "CHECKPOINT;" )
1698
+
1699
+ heap_path = node .safe_psql (
1700
+ "postgres" ,
1701
+ "select pg_relation_filepath('t_heap')" ).rstrip ()
1702
+ heap_size = node .safe_psql (
1703
+ "postgres" ,
1704
+ "select pg_relation_size('t_heap')" )
1705
+
1706
+ backup_id = self .backup_node (
1707
+ backup_dir , 'node' , node , backup_type = "full" ,
1708
+ options = ["-j" , "4" ], async = False , gdb = False )
1709
+
1710
+ node .stop ()
1711
+ node .cleanup ()
1712
+
1713
+ # Let`s do file corruption
1714
+ with open (os .path .join (backup_dir , "backups" , 'node' , backup_id , "database" , heap_path ), "rb+" , 0 ) as f :
1715
+ f .truncate (int (heap_size ) - 4096 )
1716
+ f .flush ()
1717
+ f .close
1718
+
1719
+ node .cleanup ()
1720
+
1721
+ try :
1722
+ self .restore_node (
1723
+ backup_dir , 'node' , node ,
1724
+ options = ["--no-validate" ])
1725
+ except ProbackupException as e :
1726
+ self .assertTrue ("ERROR: Data files restoring failed" in e .message , repr (e .message ))
1727
+ print "\n Expected error: \n " + e .message
1728
+
1729
+ # Clean after yourself
1730
+ self .del_test_dir (module_name , fname )
0 commit comments