@@ -1743,6 +1743,188 @@ def test_merge_backup_from_future(self):
1743
1743
# Clean after yourself
1744
1744
self .del_test_dir (module_name ,fname )
1745
1745
1746
+ # @unittest.skip("skip")
1747
+ def test_merge_multiple_descendants (self ):
1748
+ """
1749
+ PAGEb3
1750
+ | PAGEa3
1751
+ PAGEb2 /
1752
+ | PAGEa2 /
1753
+ PAGEb1 \ /
1754
+ | PAGEa1
1755
+ FULLb |
1756
+ FULLa
1757
+ """
1758
+ fname = self .id ().split ('.' )[3 ]
1759
+ node = self .make_simple_node (
1760
+ base_dir = os .path .join (module_name ,fname ,'node' ),
1761
+ initdb_params = ['--data-checksums' ])
1762
+
1763
+ backup_dir = os .path .join (self .tmp_path ,module_name ,fname ,'backup' )
1764
+ self .init_pb (backup_dir )
1765
+ self .add_instance (backup_dir ,'node' ,node )
1766
+ self .set_archiving (backup_dir ,'node' ,node )
1767
+ node .slow_start ()
1768
+
1769
+ # Take FULL BACKUPs
1770
+ backup_id_a = self .backup_node (backup_dir ,'node' ,node )
1771
+
1772
+ backup_id_b = self .backup_node (backup_dir ,'node' ,node )
1773
+
1774
+ # Change FULLb backup status to ERROR
1775
+ self .change_backup_status (backup_dir ,'node' ,backup_id_b ,'ERROR' )
1776
+
1777
+ page_id_a1 = self .backup_node (
1778
+ backup_dir ,'node' ,node ,backup_type = 'page' )
1779
+
1780
+ # Change FULLb backup status to OK
1781
+ self .change_backup_status (backup_dir ,'node' ,backup_id_b ,'OK' )
1782
+
1783
+ # Change PAGEa1 backup status to ERROR
1784
+ self .change_backup_status (backup_dir ,'node' ,page_id_a1 ,'ERROR' )
1785
+
1786
+ # PAGEa1 ERROR
1787
+ # FULLb OK
1788
+ # FULLa OK
1789
+
1790
+ page_id_b1 = self .backup_node (
1791
+ backup_dir ,'node' ,node ,backup_type = 'page' )
1792
+
1793
+ # PAGEb1 OK
1794
+ # PAGEa1 ERROR
1795
+ # FULLb OK
1796
+ # FULLa OK
1797
+
1798
+ # Change PAGEa1 backup status to OK
1799
+ self .change_backup_status (backup_dir ,'node' ,page_id_a1 ,'OK' )
1800
+
1801
+ # Change PAGEb1 backup status to ERROR
1802
+ self .change_backup_status (backup_dir ,'node' ,page_id_b1 ,'ERROR' )
1803
+
1804
+ # PAGEb1 ERROR
1805
+ # PAGEa1 OK
1806
+ # FULLb OK
1807
+ # FULLa OK
1808
+
1809
+ page_id_a2 = self .backup_node (
1810
+ backup_dir ,'node' ,node ,backup_type = 'page' )
1811
+
1812
+ # PAGEa2 OK
1813
+ # PAGEb1 ERROR
1814
+ # PAGEa1 OK
1815
+ # FULLb OK
1816
+ # FULLa OK
1817
+
1818
+ # Change PAGEb1 backup status to OK
1819
+ self .change_backup_status (backup_dir ,'node' ,page_id_b1 ,'OK' )
1820
+
1821
+ # Change PAGEa2 backup status to ERROR
1822
+ self .change_backup_status (backup_dir ,'node' ,page_id_a2 ,'ERROR' )
1823
+
1824
+ # PAGEa2 ERROR
1825
+ # PAGEb1 OK
1826
+ # PAGEa1 OK
1827
+ # FULLb OK
1828
+ # FULLa OK
1829
+
1830
+ page_id_b2 = self .backup_node (
1831
+ backup_dir ,'node' ,node ,backup_type = 'page' )
1832
+
1833
+ # PAGEb2 OK
1834
+ # PAGEa2 ERROR
1835
+ # PAGEb1 OK
1836
+ # PAGEa1 OK
1837
+ # FULLb OK
1838
+ # FULLa OK
1839
+
1840
+ # Change PAGEb2 and PAGEb1 status to ERROR
1841
+ self .change_backup_status (backup_dir ,'node' ,page_id_b2 ,'ERROR' )
1842
+ self .change_backup_status (backup_dir ,'node' ,page_id_b1 ,'ERROR' )
1843
+
1844
+ # PAGEb2 ERROR
1845
+ # PAGEa2 ERROR
1846
+ # PAGEb1 ERROR
1847
+ # PAGEa1 OK
1848
+ # FULLb OK
1849
+ # FULLa OK
1850
+
1851
+ page_id_a3 = self .backup_node (
1852
+ backup_dir ,'node' ,node ,backup_type = 'page' )
1853
+
1854
+ # PAGEa3 OK
1855
+ # PAGEb2 ERROR
1856
+ # PAGEa2 ERROR
1857
+ # PAGEb1 ERROR
1858
+ # PAGEa1 OK
1859
+ # FULLb OK
1860
+ # FULLa OK
1861
+
1862
+ # Change PAGEa3 status to ERROR
1863
+ self .change_backup_status (backup_dir ,'node' ,page_id_a3 ,'ERROR' )
1864
+
1865
+ # Change PAGEb2 status to OK
1866
+ self .change_backup_status (backup_dir ,'node' ,page_id_b2 ,'OK' )
1867
+
1868
+ page_id_b3 = self .backup_node (
1869
+ backup_dir ,'node' ,node ,backup_type = 'page' )
1870
+
1871
+ # PAGEb3 OK
1872
+ # PAGEa3 ERROR
1873
+ # PAGEb2 OK
1874
+ # PAGEa2 ERROR
1875
+ # PAGEb1 ERROR
1876
+ # PAGEa1 OK
1877
+ # FULLb OK
1878
+ # FULLa OK
1879
+
1880
+ # Change PAGEa3, PAGEa2 and PAGEb1 status to OK
1881
+ self .change_backup_status (backup_dir ,'node' ,page_id_a3 ,'OK' )
1882
+ self .change_backup_status (backup_dir ,'node' ,page_id_a2 ,'OK' )
1883
+ self .change_backup_status (backup_dir ,'node' ,page_id_b1 ,'OK' )
1884
+
1885
+ # PAGEb3 OK
1886
+ # PAGEa3 OK
1887
+ # PAGEb2 OK
1888
+ # PAGEa2 OK
1889
+ # PAGEb1 OK
1890
+ # PAGEa1 OK
1891
+ # FULLb OK
1892
+ # FULLa OK
1893
+
1894
+ # Check that page_id_a3 and page_id_a2 are both direct descendants of page_id_a1
1895
+ self .assertEqual (
1896
+ self .show_pb (backup_dir ,'node' ,backup_id = page_id_a3 )['parent-backup-id' ],
1897
+ page_id_a1 )
1898
+
1899
+ self .assertEqual (
1900
+ self .show_pb (backup_dir ,'node' ,backup_id = page_id_a2 )['parent-backup-id' ],
1901
+ page_id_a1 )
1902
+
1903
+ self .merge_backup (
1904
+ backup_dir ,'node' ,page_id_a2 ,
1905
+ options = ['--merge-expired' ,'--log-level-console=log' ])
1906
+
1907
+ try :
1908
+ self .merge_backup (
1909
+ backup_dir ,'node' ,page_id_a3 ,
1910
+ options = ['--merge-expired' ,'--log-level-console=log' ])
1911
+ self .assertEqual (
1912
+ 1 ,0 ,
1913
+ "Expecting Error because of parent FULL backup is missing.\n "
1914
+ "Output: {0}\n CMD: {1}" .format (
1915
+ repr (self .output ),self .cmd ))
1916
+ except ProbackupException as e :
1917
+ self .assertTrue (
1918
+ "ERROR: Parent full backup for the given "
1919
+ "backup {0} was not found" .format (
1920
+ page_id_a3 )in e .message ,
1921
+ '\n Unexpected Error Message: {0}\n CMD: {1}' .format (
1922
+ repr (e .message ),self .cmd ))
1923
+
1924
+ # Clean after yourself
1925
+ self .del_test_dir (module_name ,fname )
1926
+
1927
+
1746
1928
# 1. always use parent link when merging (intermediates may be from different chain)
1747
1929
# 2. page backup we are merging with may disappear after failed merge,
1748
1930
# it should not be possible to continue merge after that